From f757c84c0e49440d1a8728d6d31bcf985c1a7f19 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 19 Apr 2023 21:35:12 +0200 Subject: [PATCH 01/95] :sparkles: Added customization to rewards and requirements * changed reward/requirement deletion button from middle click to shift+left click * added shift+right click to requirement edition to put custom requirement reason * added right click to requirement and reward edition to set custom description shown in menu --- .../quests/api/objects/QuestObject.java | 100 ++++++++++++++-- .../api/objects/QuestObjectClickEvent.java | 3 +- .../api/objects/QuestObjectLoreBuilder.java | 66 +++++++++++ .../api/requirements/AbstractRequirement.java | 111 +++++++++++++++++- .../requirements/TargetNumberRequirement.java | 31 +++-- .../quests/api/rewards/AbstractReward.java | 22 +++- .../quests/api/stages/AbstractStage.java | 10 +- .../fr/skytasul/quests/editors/Editor.java | 7 -- .../quests/gui/creation/QuestObjectGUI.java | 12 +- .../quests/gui/templates/ListGUI.java | 6 +- .../quests/requirements/ClassRequirement.java | 20 ++-- .../requirements/EquipmentRequirement.java | 21 ++-- .../requirements/FactionRequirement.java | 20 ++-- .../requirements/JobLevelRequirement.java | 24 ++-- .../quests/requirements/LevelRequirement.java | 19 ++- .../McCombatLevelRequirement.java | 18 +-- .../requirements/McMMOSkillRequirement.java | 21 ++-- .../quests/requirements/MoneyRequirement.java | 20 ++-- .../requirements/PermissionsRequirement.java | 38 +++--- .../requirements/PlaceholderRequirement.java | 32 +++-- .../quests/requirements/QuestRequirement.java | 23 ++-- .../requirements/RegionRequirement.java | 29 +++-- .../requirements/ScoreboardRequirement.java | 16 +-- .../SkillAPILevelRequirement.java | 18 +-- .../logical/LogicalOrRequirement.java | 17 +-- .../quests/rewards/CheckpointReward.java | 14 ++- .../quests/rewards/CommandReward.java | 15 +-- .../skytasul/quests/rewards/ItemReward.java | 19 +-- .../quests/rewards/MessageReward.java | 13 +- .../skytasul/quests/rewards/MoneyReward.java | 17 +-- .../quests/rewards/PermissionReward.java | 16 +-- .../quests/rewards/QuestStopReward.java | 4 + .../skytasul/quests/rewards/RandomReward.java | 30 +++-- .../quests/rewards/RemoveItemsReward.java | 29 +++-- .../rewards/RequirementDependentReward.java | 18 +-- .../quests/rewards/TeleportationReward.java | 13 +- .../skytasul/quests/rewards/TitleReward.java | 16 +-- .../skytasul/quests/rewards/WaitReward.java | 17 ++- .../fr/skytasul/quests/rewards/XPReward.java | 15 +-- .../fr/skytasul/quests/structure/Quest.java | 11 +- .../quests/structure/pools/QuestPool.java | 13 +- .../java/fr/skytasul/quests/utils/Lang.java | 8 ++ .../java/fr/skytasul/quests/utils/Utils.java | 37 ++++++ core/src/main/resources/locales/en_US.yml | 11 ++ core/src/main/resources/plugin.yml | 4 +- 45 files changed, 698 insertions(+), 326 deletions(-) create mode 100644 core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index acaddd4c..7b8f8cf3 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -2,12 +2,13 @@ import java.util.HashMap; import java.util.Map; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.serializable.SerializableObject; +import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.structure.Quest; import fr.skytasul.quests.utils.Lang; @@ -15,10 +16,14 @@ public abstract class QuestObject extends SerializableObject implements Cloneable { + protected static final String CUSTOM_DESCRIPTION_KEY = "customDescription"; + private Quest quest; + private String customDescription; - protected QuestObject(QuestObjectsRegistry registry) { + protected QuestObject(QuestObjectsRegistry registry, String customDescription) { super(registry); + this.customDescription = customDescription; } @Override @@ -38,10 +43,22 @@ public Quest getAttachedQuest() { return quest; } + public String getCustomDescription() { + return customDescription; + } + + public void setCustomDescription(String customDescription) { + this.customDescription = customDescription; + } + public String debugName() { return getClass().getSimpleName() + (quest == null ? ", unknown quest" : (", quest " + quest.getID())); } + public boolean isValid() { + return true; + } + @Override public abstract QuestObject clone(); @@ -56,25 +73,92 @@ public void save(ConfigurationSection section) { Map<String, Object> datas = new HashMap<>(); save(datas); Utils.setConfigurationSectionContent(section, datas); + + if (customDescription != null) + section.set(CUSTOM_DESCRIPTION_KEY, customDescription); } @Override public void load(ConfigurationSection section) { load(section.getValues(false)); + + if (section.contains(CUSTOM_DESCRIPTION_KEY)) + customDescription = section.getString(CUSTOM_DESCRIPTION_KEY); } - public String getDescription(Player p) { // will maybe eventually be abstract (and therefore needs to be implemented) + public final String getDescription(Player player) { + return customDescription == null ? getDefaultDescription(player) : customDescription; + } + + /** + * Gets the description shown in the GUIs for this quest object. + * + * @param player player to get the description for + * @return the description of this object (nullable) + */ + protected String getDefaultDescription(Player p) { return null; } - public String[] getLore() { - return new String[] { Lang.RemoveMid.toString() }; + @Deprecated + public String[] getLore() { // backward compatibility from 0.20.1 - TODO REMOVE + return null; + } + + public String[] getItemLore() { + String[] legacyLore = getLore(); + if (legacyLore != null) + return legacyLore; + + QuestObjectLoreBuilder lore = new QuestObjectLoreBuilder(); + addLore(lore); + return lore.toLoreArray(); } + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + loreBuilder.addClick(getRemoveClick(), "§c" + Lang.Remove.toString()); + loreBuilder.addClick(getCustomDescriptionClick(), Lang.object_description_set.toString()); + + String description; + try { + description = getDescription(null); + } catch (Exception ex) { + description = "§cerror"; + BeautyQuests.logger.warning("Could not get quest object description during edition", ex); + } + loreBuilder.addDescription( + Lang.object_description.format(description + (customDescription == null ? " " + Lang.defaultValue : ""))); + } + public ItemStack getItemStack() { - return ItemUtils.lore(getCreator().getItem().clone(), getLore()); + return ItemUtils.lore(getCreator().getItem().clone(), getItemLore()); } - public abstract void itemClick(QuestObjectClickEvent event); + public ClickType getRemoveClick() { + return ClickType.SHIFT_LEFT; + } + + protected ClickType getCustomDescriptionClick() { + return ClickType.RIGHT; + } + + protected abstract void sendCustomDescriptionHelpMessage(Player p); + + public final void click(QuestObjectClickEvent event) { + if (event.getClick() == getRemoveClick()) + return; + + if (event.getClick() == getCustomDescriptionClick()) { + sendCustomDescriptionHelpMessage(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopenGUI, msg -> { + setCustomDescription(msg); + event.reopenGUI(); + }).enter(); + } else { + clickInternal(event); + } + } + protected abstract void clickInternal(QuestObjectClickEvent event); + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java index c33235cc..63146aa6 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java @@ -3,7 +3,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.QuestObjectGUI; @@ -66,7 +65,7 @@ public void updateItemLore(String... lore) { } public void updateItemLore() { - ItemUtils.lore(item, clickedObject.getLore()); + ItemUtils.lore(item, clickedObject.getItemLore()); } } diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java new file mode 100644 index 00000000..97e1eaff --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java @@ -0,0 +1,66 @@ +package fr.skytasul.quests.api.objects; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import org.bukkit.event.inventory.ClickType; +import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.utils.Utils; + +public class QuestObjectLoreBuilder { + + private static final List<ClickType> ORDERED_CLICKS = + Arrays.asList(ClickType.RIGHT, ClickType.LEFT, ClickType.SHIFT_RIGHT, ClickType.SHIFT_LEFT); + private static final Comparator<ClickType> CLICKS_COMPARATOR = Comparator.comparingInt(click -> { + int i = ORDERED_CLICKS.indexOf(click); + if (i != -1) + return i; + return click.ordinal() + ORDERED_CLICKS.size(); + }); + + private List<String> description = new ArrayList<>(5); + private Map<ClickType, String> clicks = new TreeMap<>(CLICKS_COMPARATOR); + + public QuestObjectLoreBuilder() {} + + public void addDescriptionRaw(String line) { + description.add(line); + } + + public void addDescription(String line) { + addDescriptionRaw(QuestOption.formatDescription(line)); + } + + public void addDescriptionAsValue(Object value) { + addDescription(QuestOption.formatNullableValue(value == null ? null : value.toString())); + } + + public void addClick(ClickType click, String action) { + if (click == null) + return; + + clicks.put(click, action); + } + + public String[] toLoreArray() { + String[] lore = new String[description.size() + 1 + clicks.size()]; + int i = 0; + + // we iterate in the reverse order + for (int j = description.size() - 1; j >= 0; j--) { + lore[i++] = description.get(j); + } + + lore[i++] = ""; + for (Entry<ClickType, String> entry : clicks.entrySet()) { + lore[i++] = "§8" + Utils.clickName(entry.getKey()) + " > §7" + entry.getValue(); + } + + return lore; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index b7499656..9be4c9f2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -1,18 +1,40 @@ package fr.skytasul.quests.api.requirements; import java.util.Map; - +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - +import org.bukkit.event.inventory.ClickType; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObject; +import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.editors.TextEditor; +import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.utils.Utils; public abstract class AbstractRequirement extends QuestObject { + protected static final String CUSTOM_REASON_KEY = "customReason"; + + private String customReason; + protected AbstractRequirement() { - super(QuestsAPI.getRequirements()); + this(null, null); + } + + protected AbstractRequirement(String customDescription, String customReason) { + super(QuestsAPI.getRequirements(), customDescription); + this.customReason = customReason; } + public String getCustomReason() { + return customReason; + } + + public void setCustomReason(String customReason) { + this.customReason = customReason; + } + /** * Called when the plugin has to check if a player can start a quest with this requirement * @param p Player to test @@ -24,11 +46,92 @@ protected AbstractRequirement() { * Called if the condition if not filled and if the plugin allows to send a message to the player * @param p Player to send the reason */ - public void sendReason(Player p) {} + public final boolean sendReason(Player player) { + String reason; + + if (!isValid()) + reason = "§cerror: " + getInvalidReason(); + else if (customReason != null) + reason = customReason; + else + reason = getDefaultReason(player); + + if (reason != null && !reason.isEmpty() && !"none".equals(reason)) { + Utils.sendMessage(player, reason); + return true; + } + + return false; + } + + /** + * Gets the reason sent to the player in the chat if it does not meet the requirements and the user + * has not set a particular requirement reason. + * + * @param player player to get the message for + * @return the reason of the requirement (nullable) + */ + protected String getDefaultReason(Player player) { + return null; + } + protected String getInvalidReason() { + return "invalid requirement"; + } + + protected ClickType getCustomReasonClick() { + return ClickType.SHIFT_RIGHT; + } + + protected void sendCustomReasonHelpMessage(Player p) { + Lang.CHOOSE_REQUIREMENT_CUSTOM_REASON.send(p); + } + + @Override + protected void sendCustomDescriptionHelpMessage(Player p) { + Lang.CHOOSE_REQUIREMENT_CUSTOM_DESCRIPTION.send(p); + } + + @Override + protected final void clickInternal(QuestObjectClickEvent event) { + if (event.getClick() == getCustomReasonClick()) { + sendCustomReasonHelpMessage(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopenGUI, msg -> { + setCustomReason(msg); + event.reopenGUI(); + }).enter(); + } else { + itemClick(event); + } + } + + protected abstract void itemClick(QuestObjectClickEvent event); + + @Override + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder + .addDescription(Lang.requirementReason.format(customReason == null ? Lang.NotSet.toString() : customReason)); + loreBuilder.addClick(getCustomReasonClick(), Lang.setRequirementReason.toString()); + } + @Override public abstract AbstractRequirement clone(); + @Override + public void save(ConfigurationSection section) { + super.save(section); + if (customReason != null) + section.set(CUSTOM_REASON_KEY, customReason); + } + + @Override + public void load(ConfigurationSection section) { + super.load(section); + if (section.contains(CUSTOM_REASON_KEY)) + customReason = section.getString(CUSTOM_REASON_KEY); + } + public static AbstractRequirement deserialize(Map<String, Object> map) { return QuestObject.deserialize(map, QuestsAPI.getRequirements()); } diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java b/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java index 3847b78a..00b3f1a9 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java @@ -1,11 +1,11 @@ package fr.skytasul.quests.api.requirements; import java.text.NumberFormat; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.NumberParser; import fr.skytasul.quests.utils.ComparisonMethod; @@ -13,12 +13,12 @@ public abstract class TargetNumberRequirement extends AbstractRequirement { - private static NumberFormat numberFormat = NumberFormat.getInstance(); - protected ComparisonMethod comparison; protected double target; - protected TargetNumberRequirement(double target, ComparisonMethod comparison) { + protected TargetNumberRequirement(String customDescription, String customReason, double target, + ComparisonMethod comparison) { + super(customDescription, customReason); this.target = target; this.comparison = comparison; } @@ -37,17 +37,22 @@ public boolean test(Player p) { return comparison.test(diff); } + public String getShortFormattedValue() { + return comparison.getSymbol() + " " + getNumberFormat().format(target); + } + public String getFormattedValue() { - return comparison.getTitle().format(numberFormat.format(target)); + return comparison.getTitle().format(getNumberFormat().format(target)); } - - protected String getValueLore() { - return "§8> §7" + getFormattedValue(); + + protected NumberFormat getNumberFormat() { + return numberClass() == Integer.class ? NumberFormat.getIntegerInstance() : NumberFormat.getInstance(); } - + @Override - public String[] getLore() { - return new String[] { getValueLore(), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(QuestOption.formatNullableValue(getFormattedValue())); } public abstract double getPlayerTarget(Player p); @@ -58,12 +63,14 @@ public String[] getLore() { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("comparison", comparison.name()); section.set("target", target); } @Override public void load(ConfigurationSection section) { + super.load(section); if (section.contains("comparison")) comparison = ComparisonMethod.valueOf(section.getString("comparison")); target = section.getDouble("target"); } diff --git a/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java b/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java index f08fb49b..451078d2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java +++ b/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java @@ -5,11 +5,17 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObject; +import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.utils.Lang; public abstract class AbstractReward extends QuestObject { protected AbstractReward() { - super(QuestsAPI.getRewards()); + this(null); + } + + protected AbstractReward(String customDescription) { + super(QuestsAPI.getRewards(), customDescription); } @Override @@ -23,7 +29,19 @@ public RewardCreator getCreator() { * @return title of all the subsequent reward (for instance : "4 gold") */ public abstract List<String> give(Player p) throws InterruptingBranchException; + + @Override + protected void sendCustomDescriptionHelpMessage(Player p) { + Lang.CHOOSE_REWARD_CUSTOM_DESCRIPTION.send(p); + } + @Override + protected final void clickInternal(QuestObjectClickEvent event) { + itemClick(event); + } + + protected abstract void itemClick(QuestObjectClickEvent event); + @Override public abstract AbstractReward clone(); @@ -34,5 +52,5 @@ public static AbstractReward deserialize(Map<String, Object> map) { public boolean isAsync() { return false; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 8757bcd7..4ca18ad6 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -8,7 +8,6 @@ import java.util.Optional; import java.util.function.Consumer; import java.util.stream.Collectors; - import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; @@ -16,7 +15,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; @@ -144,13 +142,7 @@ protected boolean canUpdate(Player p) { } protected boolean canUpdate(Player p, boolean msg) { - for (AbstractRequirement requirement : validationRequirements) { - if (!requirement.test(p)) { - if (msg) requirement.sendReason(p); - return false; - } - } - return true; + return Utils.testRequirements(p, validationRequirements, msg); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/editors/Editor.java b/core/src/main/java/fr/skytasul/quests/editors/Editor.java index 134ae438..691c2930 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/Editor.java +++ b/core/src/main/java/fr/skytasul/quests/editors/Editor.java @@ -2,7 +2,6 @@ import java.util.HashMap; import java.util.Map; - import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -13,7 +12,6 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerQuitEvent; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.bossbar.BQBossBarManager.BQBossBar; @@ -123,11 +121,6 @@ public void onChat(AsyncPlayerChatEvent e){ public void onQuit(PlayerQuitEvent e) { if (e.getPlayer() == p) leave(p); } - - @Deprecated - public static <T extends Editor> T enterOrLeave(Player p, T editor) { - return editor.enterOrLeave(p); - } public static boolean hasEditor(Player player){ return players.containsKey(player); diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java index 6b4f7004..9dd2a539 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java @@ -53,7 +53,12 @@ public QuestObjectGUI(String name, QuestObjectLocation objectLocation, Collectio public ItemStack getObjectItemStack(QuestObject object) { return object.getItemStack(); } - + + @Override + protected ClickType getRemoveClick(T object) { + return object.getRemoveClick(); + } + @Override protected void removed(T object) { if (!object.getCreator().canBeMultiple()) creators.add(object.getCreator()); @@ -72,7 +77,8 @@ public ItemStack getItemStack(QuestObjectCreator<T> object) { public void click(QuestObjectCreator<T> existing, ItemStack item, ClickType clickType) { T object = existing.newObject(); if (!existing.canBeMultiple()) creators.remove(existing); - object.itemClick(new QuestObjectClickEvent(p, QuestObjectGUI.this, callback.apply(object), clickType, true, object)); + object.click( + new QuestObjectClickEvent(p, QuestObjectGUI.this, callback.apply(object), clickType, true, object)); } @Override @@ -86,7 +92,7 @@ public CloseBehavior onClose(Player p, Inventory inv) { @Override public void clickObject(QuestObject existing, ItemStack item, ClickType clickType) { - existing.itemClick(new QuestObjectClickEvent(p, this, item, clickType, false, existing)); + existing.click(new QuestObjectClickEvent(p, this, item, clickType, false, existing)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java index 361781a9..fcfcf04b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java @@ -42,7 +42,7 @@ public final ItemStack getItemStack(T object) { @Override public final void click(T existing, ItemStack item, ClickType clickType) { - if (clickType == ClickType.MIDDLE) { + if (clickType == getRemoveClick(existing)) { remove(existing); }else { if (existing == null) { @@ -51,6 +51,10 @@ public final void click(T existing, ItemStack item, ClickType clickType) { } } + protected ClickType getRemoveClick(T object) { + return ClickType.MIDDLE; + } + public boolean remove(T object) { int index = objects.indexOf(object); if (index == -1) return false; diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java index fc9e142c..ecb3225a 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java @@ -4,18 +4,16 @@ 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.BeautyQuests; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.ListGUI; @@ -28,10 +26,11 @@ public class ClassRequirement extends AbstractRequirement { public List<RPGClass> classes; public ClassRequirement() { - this(new ArrayList<>()); + this(null, null, new ArrayList<>()); } - public ClassRequirement(List<RPGClass> classes) { + public ClassRequirement(String customDescription, String customReason, List<RPGClass> classes) { + super(customDescription, customReason); this.classes = classes; } @@ -56,13 +55,14 @@ public boolean test(Player p) { } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Lang.RDClass.format(String.join(" " + Lang.Or.toString() + " ", (Iterable<String>) () -> classes.stream().map(RPGClass::getName).iterator())); } @Override - public String[] getLore() { - return new String[] { "§8> §7" + classes.size() + " classes", "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(classes.size() + " classes"); } @Override @@ -101,17 +101,19 @@ public void finish(List<RPGClass> objects) { @Override public AbstractRequirement clone() { - return new ClassRequirement(new ArrayList<>(classes)); + return new ClassRequirement(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())); } @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()); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java index 8887b304..f1cb22e8 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java @@ -10,7 +10,7 @@ import com.google.common.collect.ImmutableMap; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; @@ -27,7 +27,9 @@ public class EquipmentRequirement extends AbstractRequirement { public EquipmentRequirement() {} - public EquipmentRequirement(EquipmentSlot slot, ItemStack item, ItemComparisonMap comparisons) { + public EquipmentRequirement(String customDescription, String customReason, EquipmentSlot slot, ItemStack item, + ItemComparisonMap comparisons) { + super(customDescription, customReason); this.slot = slot; this.item = item; this.comparisons = comparisons; @@ -41,16 +43,15 @@ public boolean test(Player p) { @Override public AbstractRequirement clone() { - return new EquipmentRequirement(slot, item, comparisons); + return new EquipmentRequirement(getCustomDescription(), getCustomReason(), slot, item, comparisons); } @Override - public String[] getLore() { - if (slot == null) return null; - return new String[] { - QuestOption.formatNullableValue(slot.name() + " > " + ItemUtils.getName(item)), - "", - Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + if (slot != null) { + loreBuilder.addDescription(slot.name() + ": " + ItemUtils.getName(item)); + } } @Override @@ -76,6 +77,7 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("slot", slot.name()); section.set("item", item); if (!comparisons.isDefault()) section.set("comparisons", comparisons.getNotDefault()); @@ -83,6 +85,7 @@ public void save(ConfigurationSection section) { @Override public void load(ConfigurationSection section) { + super.load(section); slot = EquipmentSlot.valueOf(section.getString("slot")); item = section.getItemStack("item"); comparisons = section.contains("comparisons") ? new ItemComparisonMap(section.getConfigurationSection("comparisons")) : new ItemComparisonMap(); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java index f0a76ecd..5d61d92f 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java @@ -4,20 +4,18 @@ 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.massivecraft.factions.FactionsIndex; import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.FactionColl; import com.massivecraft.factions.entity.MPlayer; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.ListGUI; @@ -31,10 +29,11 @@ public class FactionRequirement extends AbstractRequirement { public List<Faction> factions; public FactionRequirement() { - this(new ArrayList<>()); + this(null, null, new ArrayList<>()); } - public FactionRequirement(List<Faction> factions) { + public FactionRequirement(String customDescription, String customReason, List<Faction> factions) { + super(customDescription, customReason); this.factions = factions; } @@ -43,7 +42,7 @@ public void addFaction(Object faction){ } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Lang.RDFaction.format(String.join(" " + Lang.Or.toString() + " ", (Iterable<String>) () -> factions.stream().map(Faction::getName).iterator())); } @@ -57,8 +56,9 @@ public boolean test(Player p) { } @Override - public String[] getLore() { - return new String[] { "§8> §7" + factions.size() + " factions", "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(factions.size() + " factions"); } @Override @@ -97,16 +97,18 @@ public void finish(List<Faction> objects) { @Override public AbstractRequirement clone() { - return new FactionRequirement(new ArrayList<>(factions)); + return new FactionRequirement(getCustomDescription(), getCustomReason(), new ArrayList<>(factions)); } @Override public void save(ConfigurationSection section) { + super.save(section); section.set("factions", factions.stream().map(Faction::getId).collect(Collectors.toList())); } @Override public void load(ConfigurationSection section) { + super.load(section); for (String s : section.getStringList("factions")) { if (!FactionColl.get().containsId(s)) { BeautyQuests.getInstance().getLogger().warning("Faction with ID " + s + " no longer exists."); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java index 1ffb32b5..94d8620b 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java @@ -2,8 +2,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.editors.TextEditor; @@ -16,11 +16,12 @@ public class JobLevelRequirement extends TargetNumberRequirement { public String jobName; public JobLevelRequirement() { - this(null, 0, ComparisonMethod.GREATER_OR_EQUAL); + this(null, null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - public JobLevelRequirement(String jobName, double target, ComparisonMethod comparison) { - super(target, comparison); + public JobLevelRequirement(String customDescription, String customReason, String jobName, double target, + ComparisonMethod comparison) { + super(customDescription, customReason, target, comparison); this.jobName = jobName; } @@ -40,23 +41,24 @@ public void sendHelpString(Player p) { } @Override - public void sendReason(Player p){ - Lang.REQUIREMENT_JOB.send(p, getFormattedValue(), jobName); + protected String getDefaultReason(Player player) { + return Lang.REQUIREMENT_JOB.format(getFormattedValue(), jobName); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Lang.RDJobLevel.format(Integer.toString((int) target), jobName); } - + @Override public AbstractRequirement clone() { - return new JobLevelRequirement(jobName, target, comparison); + return new JobLevelRequirement(getCustomDescription(), getCustomReason(), jobName, target, comparison); } @Override - public String[] getLore() { - return new String[] { getValueLore(), "§8>Job name: §7" + jobName, "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription("§8Job name: §7" + jobName); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java index 13198c6a..36890f75 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.requirements; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.utils.ComparisonMethod; @@ -10,11 +9,11 @@ public class LevelRequirement extends TargetNumberRequirement { public LevelRequirement() { - this(0, ComparisonMethod.GREATER_OR_EQUAL); + this(null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - public LevelRequirement(double target, ComparisonMethod comparison) { - super(target, comparison); + public LevelRequirement(String customDescription, String customReason, double target, ComparisonMethod comparison) { + super(customDescription, customReason, target, comparison); } @Override @@ -23,8 +22,8 @@ public double getPlayerTarget(Player p) { } @Override - public void sendReason(Player p){ - Lang.REQUIREMENT_LEVEL.send(p, getFormattedValue()); + protected String getDefaultReason(Player player) { + return Lang.REQUIREMENT_LEVEL.format(getFormattedValue()); } @Override @@ -38,13 +37,13 @@ public void sendHelpString(Player p) { } @Override - public String getDescription(Player p) { - return Lang.RDLevel.format(Integer.toString((int) target)); + public String getDefaultDescription(Player p) { + return Lang.RDLevel.format(getShortFormattedValue()); } - + @Override public AbstractRequirement clone() { - return new LevelRequirement(target, comparison); + return new LevelRequirement(getCustomDescription(), getCustomReason(), target, comparison); } } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java index 61ba636f..46642534 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.requirements; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.utils.ComparisonMethod; @@ -11,11 +10,12 @@ public class McCombatLevelRequirement extends TargetNumberRequirement { public McCombatLevelRequirement(){ - this(0, ComparisonMethod.GREATER_OR_EQUAL); + this(null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - public McCombatLevelRequirement(double target, ComparisonMethod comparison) { - super(target, comparison); + public McCombatLevelRequirement(String customDescription, String customReason, double target, + ComparisonMethod comparison) { + super(customDescription, customReason, target, comparison); } @Override @@ -24,12 +24,12 @@ public double getPlayerTarget(Player p) { } @Override - public void sendReason(Player p){ - Lang.REQUIREMENT_COMBAT_LEVEL.send(p, getFormattedValue()); + protected String getDefaultReason(Player player) { + return Lang.REQUIREMENT_COMBAT_LEVEL.format(getFormattedValue()); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Lang.RDCombatLevel.format(Integer.toString((int) target)); } @@ -42,10 +42,10 @@ public Class<? extends Number> numberClass() { public void sendHelpString(Player p) { Lang.CHOOSE_XP_REQUIRED.send(p); } - + @Override public AbstractRequirement clone() { - return new McCombatLevelRequirement(target, comparison); + return new McCombatLevelRequirement(getCustomDescription(), getCustomReason(), target, comparison); } } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java index 78f04261..a3e134b7 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java @@ -2,8 +2,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.editors.TextEditor; @@ -16,11 +16,11 @@ public class McMMOSkillRequirement extends TargetNumberRequirement { public String skillName; public McMMOSkillRequirement(){ - this(0, ComparisonMethod.GREATER_OR_EQUAL); + this(null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - public McMMOSkillRequirement(double target, ComparisonMethod comparison) { - super(target, comparison); + public McMMOSkillRequirement(String customDescription, String customReason, double target, ComparisonMethod comparison) { + super(customDescription, customReason, target, comparison); } @Override @@ -29,12 +29,12 @@ public double getPlayerTarget(Player p) { } @Override - public void sendReason(Player p){ - Lang.REQUIREMENT_SKILL.send(p, getFormattedValue(), skillName); + protected String getDefaultReason(Player player) { + return Lang.REQUIREMENT_SKILL.format(getFormattedValue(), skillName); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Lang.RDSkillLevel.format(Integer.toString((int) target), skillName); } @@ -49,8 +49,9 @@ public void sendHelpString(Player p) { } @Override - public String[] getLore() { - return new String[] { getValueLore(), "§8> Skill name: §7" + skillName, "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription("§8Skill name: §7" + skillName); } @Override @@ -79,7 +80,7 @@ public void load(ConfigurationSection section) { @Override public AbstractRequirement clone() { - return new McMMOSkillRequirement(target, comparison); + return new McMMOSkillRequirement(getCustomDescription(), getCustomReason(), target, comparison); } } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java index 8790ec67..88393c1c 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java @@ -2,8 +2,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.Actionnable; import fr.skytasul.quests.editors.TextEditor; @@ -17,7 +17,8 @@ public class MoneyRequirement extends AbstractRequirement implements Actionnable public MoneyRequirement() {} - public MoneyRequirement(double money) { + public MoneyRequirement(String customDescription, String customReason, double money) { + super(customDescription, customReason); this.money = money; } @@ -32,23 +33,24 @@ public void trigger(Player p) { } @Override - public void sendReason(Player p) { - Lang.REQUIREMENT_MONEY.send(p, Vault.format(money)); + protected String getDefaultReason(Player player) { + return Lang.REQUIREMENT_MONEY.format(Vault.format(money)); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Vault.format(money); } @Override public AbstractRequirement clone() { - return new MoneyRequirement(money); + return new MoneyRequirement(getCustomDescription(), getCustomReason(), money); } @Override - public String[] getLore() { - return new String[] { Lang.optionValue.format(money), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.optionValue.format(money)); } @Override @@ -62,11 +64,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("money", money); } @Override public void load(ConfigurationSection section) { + super.load(section); money = section.getDouble("money"); } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java index c44ba0b5..28ce38ee 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java @@ -4,33 +4,30 @@ 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.inventory.ItemStack; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.ListGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.XMaterial; public class PermissionsRequirement extends AbstractRequirement { - public List<Permission> permissions; - public String message; + private List<Permission> permissions; public PermissionsRequirement() { - this(new ArrayList<>(), null); + this(null, null, new ArrayList<>()); } - public PermissionsRequirement(List<Permission> permissions, String message) { + public PermissionsRequirement(String customDescription, String customReason, List<Permission> permissions) { + super(customDescription, customReason); this.permissions = permissions; - this.message = message; } @Override @@ -40,17 +37,18 @@ public boolean test(Player p) { } return true; } - - @Override - public void sendReason(Player p){ - if (message != null) Utils.IsendMessage(p, message, true); - } @Override - public String[] getLore() { - return new String[] { "§8> §7" + Lang.AmountPermissions.format(permissions.size()), "§8> Message: §7" + (message == null ? Lang.NotSet.toString() : message), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.AmountPermissions.format(permissions.size())); } + @Override + protected void sendCustomReasonHelpMessage(Player p) { + Lang.CHOOSE_PERM_REQUIRED_MESSAGE.send(p); + } + @Override public void itemClick(QuestObjectClickEvent event) { new ListGUI<Permission>(Lang.INVENTORY_PERMISSION_LIST.toString(), DyeColor.PURPLE, permissions) { @@ -73,7 +71,7 @@ public void finish(List<Permission> objects) { permissions = objects; Lang.CHOOSE_PERM_REQUIRED_MESSAGE.send(p); new TextEditor<String>(p, event::reopenGUI, obj -> { - message = obj; + setCustomReason(obj); event.reopenGUI(); }).passNullIntoEndConsumer().enter(); } @@ -83,19 +81,21 @@ public void finish(List<Permission> objects) { @Override public AbstractRequirement clone() { - return new PermissionsRequirement(new ArrayList<>(permissions), message); + return new PermissionsRequirement(getCustomDescription(), getCustomReason(), new ArrayList<>(permissions)); } @Override public void save(ConfigurationSection section) { + super.save(section); section.set("permissions", permissions.stream().map(Permission::toString).collect(Collectors.toList())); - if (message != null) section.set("message", message); } @Override public void load(ConfigurationSection section) { + super.load(section); permissions = section.getStringList("permissions").stream().map(Permission::fromString).collect(Collectors.toList()); - if (section.contains("message")) message = section.getString("message"); + if (section.contains("message")) // migration from 0.20.1 and before, TODO delete + setCustomReason(section.getString("message")); } public static class Permission { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java index b2886129..099fa6ea 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java @@ -1,12 +1,12 @@ package fr.skytasul.quests.requirements; import java.math.BigDecimal; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.utils.ComparisonMethod; @@ -14,7 +14,6 @@ import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; - import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; @@ -30,10 +29,12 @@ public class PlaceholderRequirement extends AbstractRequirement { private boolean parseValue = false; public PlaceholderRequirement(){ - this(null, null, ComparisonMethod.EQUALS); + this(null, null, null, null, ComparisonMethod.EQUALS); } - public PlaceholderRequirement(String placeholder, String value, ComparisonMethod comparison) { + public PlaceholderRequirement(String customDescription, String customReason, String placeholder, String value, + ComparisonMethod comparison) { + super(customDescription, customReason); if (placeholder != null) setPlaceholder(placeholder); this.value = value; this.comparison = comparison; @@ -63,8 +64,13 @@ public boolean test(Player p){ } @Override - public void sendReason(Player p) { - if (hook == null) p.sendMessage("§cError: unknown placeholder " + rawPlaceholder); + public boolean isValid() { + return hook != null; + } + + @Override + protected String getInvalidReason() { + return "unknown placeholder " + rawPlaceholder; } public void setPlaceholder(String placeholder){ @@ -102,6 +108,7 @@ public String getValue(){ @Override public void save(ConfigurationSection section) { + super.save(section); section.set("placeholder", rawPlaceholder); section.set("value", value); section.set("comparison", comparison.name()); @@ -110,6 +117,7 @@ public void save(ConfigurationSection section) { @Override public void load(ConfigurationSection section){ + super.load(section); setPlaceholder(section.getString("placeholder")); this.value = section.getString("value"); if (section.contains("comparison")) this.comparison = ComparisonMethod.valueOf(section.getString("comparison")); @@ -117,10 +125,12 @@ public void load(ConfigurationSection section){ } @Override - public String[] getLore() { - return new String[] { "§8> §7" + rawPlaceholder, "§8> §7" + comparison.getTitle().format(value), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(QuestOption.formatNullableValue(rawPlaceholder)); + loreBuilder.addDescription(comparison.getTitle().format(value)); } - + @Override public void itemClick(QuestObjectClickEvent event) { Lang.CHOOSE_PLACEHOLDER_REQUIRED_IDENTIFIER.send(event.getPlayer()); @@ -148,7 +158,7 @@ public void itemClick(QuestObjectClickEvent event) { @Override public AbstractRequirement clone() { - return new PlaceholderRequirement(rawPlaceholder, value, comparison); + return new PlaceholderRequirement(getCustomDescription(), getCustomReason(), rawPlaceholder, value, comparison); } } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java index b337c8d1..07c305d2 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java @@ -2,9 +2,10 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; import fr.skytasul.quests.players.PlayersManager; @@ -18,10 +19,11 @@ public class QuestRequirement extends AbstractRequirement { private Quest cached; public QuestRequirement() { - this(-1); + this(null, null, -1); } - public QuestRequirement(int questId) { + public QuestRequirement(String customDescription, String customReason, int questId) { + super(customDescription, customReason); this.questId = questId; } @@ -32,12 +34,12 @@ public boolean test(Player p) { } @Override - public void sendReason(Player p){ - if (exists()) Lang.REQUIREMENT_QUEST.send(p, cached.getName()); + protected String getDefaultReason(Player player) { + return exists() ? Lang.REQUIREMENT_QUEST.format(cached.getName()) : null; } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Lang.RDQuest.format(exists() ? cached.getName() : questId); } @@ -47,8 +49,9 @@ private boolean exists(){ } @Override - public String[] getLore() { - return new String[] { "§8> §7" + (exists() ? cached.getName() : Lang.NotSet.toString()), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(QuestOption.formatNullableValue(exists() ? cached.getName() : null)); } @Override @@ -73,16 +76,18 @@ public fr.skytasul.quests.gui.CustomInventory.CloseBehavior onClose(Player p, or @Override public AbstractRequirement clone() { - return new QuestRequirement(questId); + return new QuestRequirement(getCustomDescription(), getCustomReason(), questId); } @Override public void save(ConfigurationSection section) { + super.save(section); section.set("questID", questId); } @Override public void load(ConfigurationSection section) { + super.load(section); questId = section.getInt("questID"); } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java index e941737c..b6d6497d 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java @@ -3,11 +3,11 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import com.sk89q.worldguard.protection.regions.ProtectedRegion; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.utils.Lang; @@ -21,10 +21,11 @@ public class RegionRequirement extends AbstractRequirement { private ProtectedRegion region; public RegionRequirement() { - this(null, null); + this(null, null, null, null); } - public RegionRequirement(String worldName, String regionName) { + public RegionRequirement(String customDescription, String customReason, String worldName, String regionName) { + super(customDescription, customReason); this.worldName = worldName; setRegionName(regionName); } @@ -38,8 +39,9 @@ private void setRegionName(String regionName) { } @Override - public String[] getLore() { - return new String[] { Lang.optionValue.format(regionName), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(QuestOption.formatNullableValue(regionName)); } @Override @@ -70,23 +72,30 @@ public boolean test(Player p) { } @Override - public void sendReason(Player p) { - if (region == null) Lang.ERROR_OCCURED.send(p, "required region does not exist"); + protected String getInvalidReason() { + return "required region " + regionName + " in " + worldName + " does not exist"; } - + + @Override + public boolean isValid() { + return region != null; + } + @Override public AbstractRequirement clone() { - return new RegionRequirement(worldName, regionName); + return new RegionRequirement(getCustomDescription(), getCustomReason(), worldName, regionName); } @Override public void save(ConfigurationSection section) { + super.save(section); section.set("world", worldName); section.set("region", regionName); } @Override public void load(ConfigurationSection section) { + super.load(section); worldName = section.getString("world"); setRegionName(section.getString("region")); } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java index e0ee7a89..a16c41a6 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java @@ -4,8 +4,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.scoreboard.Objective; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.editors.TextEditor; @@ -19,11 +19,12 @@ public class ScoreboardRequirement extends TargetNumberRequirement { private String objectiveName; public ScoreboardRequirement() { - this(null, 0, ComparisonMethod.GREATER_OR_EQUAL); + this(null, null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - public ScoreboardRequirement(String objectiveName, double target, ComparisonMethod comparison) { - super(target, comparison); + public ScoreboardRequirement(String customDescription, String customReason, String objectiveName, double target, + ComparisonMethod comparison) { + super(customDescription, customReason, target, comparison); if (objectiveName != null) this.objectiveName = objectiveName; } @@ -48,8 +49,9 @@ public void sendHelpString(Player p) { } @Override - public String[] getLore() { - return new String[] { getValueLore(), "§8>Objective name: §7" + objectiveName, "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription("§8Objective name: §7" + objectiveName); } @Override @@ -82,7 +84,7 @@ public void load(ConfigurationSection section) { @Override public AbstractRequirement clone() { - return new ScoreboardRequirement(objectiveName, target, comparison); + return new ScoreboardRequirement(getCustomDescription(), getCustomReason(), objectiveName, target, comparison); } } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java index 4f7a821c..a4a41f21 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.requirements; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.utils.ComparisonMethod; @@ -11,11 +10,12 @@ public class SkillAPILevelRequirement extends TargetNumberRequirement { public SkillAPILevelRequirement() { - this(0, ComparisonMethod.GREATER_OR_EQUAL); + this(null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - public SkillAPILevelRequirement(double target, ComparisonMethod comparison) { - super(target, comparison); + public SkillAPILevelRequirement(String customDescription, String customReason, double target, + ComparisonMethod comparison) { + super(customDescription, customReason, target, comparison); } @Override @@ -24,8 +24,8 @@ public double getPlayerTarget(Player p) { } @Override - public void sendReason(Player p){ - Lang.REQUIREMENT_LEVEL.send(p, getFormattedValue()); + protected String getDefaultReason(Player player) { + return Lang.REQUIREMENT_LEVEL.format(getFormattedValue()); } @Override @@ -39,13 +39,13 @@ public void sendHelpString(Player p) { } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Lang.RDLevel.format(Integer.toString((int) target)); } - + @Override public AbstractRequirement clone() { - return new SkillAPILevelRequirement(target, comparison); + return new SkillAPILevelRequirement(getCustomDescription(), getCustomReason(), target, comparison); } } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java index c603a7cc..8ebf3fef 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java @@ -2,13 +2,12 @@ import java.util.ArrayList; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.structure.Quest; @@ -19,10 +18,11 @@ public class LogicalOrRequirement extends AbstractRequirement { private List<AbstractRequirement> requirements; public LogicalOrRequirement() { - this(new ArrayList<>()); + this(null, null, new ArrayList<>()); } - public LogicalOrRequirement(List<AbstractRequirement> requirements) { + public LogicalOrRequirement(String customDescription, String customReason, List<AbstractRequirement> requirements) { + super(customDescription, customReason); this.requirements = requirements; } @@ -39,8 +39,9 @@ public void detach() { } @Override - public String[] getLore() { - return new String[] { Lang.requirements.format(requirements.size()), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.requirements.format(requirements.size())); } @Override @@ -58,16 +59,18 @@ public boolean test(Player p) { @Override public AbstractRequirement clone() { - return new LogicalOrRequirement(new ArrayList<>(requirements)); + return new LogicalOrRequirement(getCustomDescription(), getCustomReason(), new ArrayList<>(requirements)); } @Override public void save(ConfigurationSection section) { + super.save(section); section.set("requirements", SerializableObject.serializeList(requirements)); } @Override public void load(ConfigurationSection section) { + super.load(section); requirements = SerializableObject.deserializeList(section.getMapList("requirements"), AbstractRequirement::deserialize); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java index e933a75b..3aa2be24 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java @@ -8,7 +8,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.serializable.SerializableObject; @@ -21,10 +21,11 @@ public class CheckpointReward extends AbstractReward { private List<AbstractReward> actions; public CheckpointReward() { - this(new ArrayList<>()); + this(null, new ArrayList<>()); } - public CheckpointReward(List<AbstractReward> actions) { + public CheckpointReward(String customDescription, List<AbstractReward> actions) { + super(customDescription); this.actions = actions; } @@ -56,12 +57,13 @@ public void applies(Player p) { @Override public AbstractReward clone() { - return new CheckpointReward(new ArrayList<>(actions)); + return new CheckpointReward(getCustomDescription(), new ArrayList<>(actions)); } @Override - public String[] getLore() { - return new String[] { QuestOption.formatDescription(Lang.actions.format(actions.size())), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.actions.format(actions.size())); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index 9d244794..5d17ad3f 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -3,14 +3,13 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Function; - 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 fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; @@ -27,7 +26,8 @@ public class CommandReward extends AbstractReward { public CommandReward() {} - public CommandReward(List<Command> list){ + public CommandReward(String customDescription, List<Command> list) { + super(customDescription); if (list != null) this.commands.addAll(list); } @@ -42,14 +42,15 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new CommandReward(commands); + return new CommandReward(getCustomDescription(), commands); } @Override - public String[] getLore() { - return new String[] { "§8> §7" + Lang.commands.format(commands.size()), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.commands.format(commands.size())); } - + @Override public void itemClick(QuestObjectClickEvent event) { Inventories.create(event.getPlayer(), new ListGUI<Command>(Lang.INVENTORY_COMMANDS_LIST.toString(), DyeColor.ORANGE, commands) { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java index 667b6868..753c50bd 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java @@ -3,12 +3,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.gui.creation.ItemsGUI; import fr.skytasul.quests.utils.Lang; @@ -19,10 +18,11 @@ public class ItemReward extends AbstractReward { public List<ItemStack> items; public ItemReward(){ - this(new ArrayList<>()); + this(null, new ArrayList<>()); } - public ItemReward(List<ItemStack> items){ + public ItemReward(String customDescription, List<ItemStack> items) { + super(customDescription); this.items = items; } @@ -35,19 +35,20 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new ItemReward(items); + return new ItemReward(getCustomDescription(), items); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return items.stream().mapToInt(ItemStack::getAmount).sum() + " " + Lang.Item.toString(); } @Override - public String[] getLore() { - return new String[] { "§8> §7" + items.size() + " " + Lang.Item.toString(), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(items.size() + " " + Lang.Item.toString()); } - + @Override public void itemClick(QuestObjectClickEvent event) { new ItemsGUI(items -> { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java index 5f9d17d5..9ff66916 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java @@ -1,11 +1,10 @@ package fr.skytasul.quests.rewards; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.utils.Lang; @@ -17,7 +16,8 @@ public class MessageReward extends AbstractReward { public MessageReward() {} - public MessageReward(String text){ + public MessageReward(String customDescription, String text) { + super(customDescription); this.text = text; } @@ -29,12 +29,13 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new MessageReward(text); + return new MessageReward(getCustomDescription(), text); } @Override - public String[] getLore() { - return new String[] { Lang.optionValue.format(text), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(text); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java index 6e8db9af..89fc62eb 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java @@ -2,11 +2,10 @@ import java.util.Arrays; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.NumberParser; @@ -19,7 +18,8 @@ public class MoneyReward extends AbstractReward { public MoneyReward() {} - public MoneyReward(double money) { + public MoneyReward(String customDescription, double money) { + super(customDescription); this.money = money; } @@ -33,19 +33,20 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new MoneyReward(money); + return new MoneyReward(getCustomDescription(), money); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return Vault.format(money); } @Override - public String[] getLore() { - return new String[] { Lang.optionValue.format(money), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(money); } - + @Override public void itemClick(QuestObjectClickEvent event) { Lang.CHOOSE_MONEY_REWARD.send(event.getPlayer()); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java index d777329c..a10d6e6f 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java @@ -2,14 +2,12 @@ import java.util.ArrayList; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.gui.permissions.PermissionListGUI; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.types.Permission; @@ -18,10 +16,11 @@ public class PermissionReward extends AbstractReward { public List<Permission> permissions; public PermissionReward(){ - this(new ArrayList<>()); + this(null, new ArrayList<>()); } - public PermissionReward(List<Permission> permissions) { + public PermissionReward(String customDescription, List<Permission> permissions) { + super(customDescription); this.permissions = permissions; } @@ -35,12 +34,13 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new PermissionReward(new ArrayList<>(permissions)); + return new PermissionReward(getCustomDescription(), new ArrayList<>(permissions)); } @Override - public String[] getLore() { - return new String[] { "§8> §7" + permissions.size() + " permissions", "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(permissions.size() + " permissions"); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java b/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java index 2436074d..1d4d17ec 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java @@ -12,6 +12,10 @@ public class QuestStopReward extends AbstractReward { public QuestStopReward() {} + public QuestStopReward(String customDescription) { + super(customDescription); + } + @Override public void itemClick(QuestObjectClickEvent event) {} diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java index 8a639d64..841dbe26 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java @@ -5,15 +5,14 @@ import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - +import org.bukkit.event.inventory.ClickType; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.editors.TextEditor; @@ -26,10 +25,11 @@ public class RandomReward extends AbstractReward { private int min, max; public RandomReward() { - this(new ArrayList<>(), 1, 1); + this(null, new ArrayList<>(), 1, 1); } - public RandomReward(List<AbstractReward> rewards, int min, int max) { + public RandomReward(String customDescription, List<AbstractReward> rewards, int min, int max) { + super(customDescription); this.rewards = rewards; this.min = min; this.max = max; @@ -72,11 +72,11 @@ public boolean isAsync() { @Override public AbstractReward clone() { - return new RandomReward(new ArrayList<>(rewards), min, max); + return new RandomReward(getCustomDescription(), new ArrayList<>(rewards), min, max); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return rewards .stream() .map(req -> req.getDescription(p)) @@ -85,16 +85,14 @@ public String getDescription(Player p) { } @Override - public String[] getLore() { - return new String[] { - QuestOption.formatDescription(Lang.actions.format(rewards.size())), - "§8 | min: §7" + min + "§8 | max: §7" + max, - "", - "§7" + Lang.ClickLeft + " > §7" + Lang.rewardRandomRewards, - "§7" + Lang.ClickRight + " > §7" + Lang.rewardRandomMinMax, - "§7" + Lang.ClickMiddle + " > §c" + Lang.Remove }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.actions.format(rewards.size())); + loreBuilder.addDescriptionRaw("§8 | min: §7" + min + "§8 | max: §7" + max); + loreBuilder.addClick(ClickType.LEFT, Lang.rewardRandomRewards.toString()); + loreBuilder.addClick(ClickType.RIGHT, Lang.rewardRandomMinMax.toString()); } - + @Override public void itemClick(QuestObjectClickEvent event) { if (event.isInCreation() || event.getClick().isLeftClick()) { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java index e09ba2b9..7d89a2b5 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java @@ -3,14 +3,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.gui.creation.ItemsGUI; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; @@ -23,10 +23,11 @@ public class RemoveItemsReward extends AbstractReward { private ItemComparisonMap comparisons; public RemoveItemsReward(){ - this(new ArrayList<>(), new ItemComparisonMap()); + this(null, new ArrayList<>(), new ItemComparisonMap()); } - public RemoveItemsReward(List<ItemStack> items, ItemComparisonMap comparisons) { + public RemoveItemsReward(String customDescription, List<ItemStack> items, ItemComparisonMap comparisons) { + super(customDescription); this.items = items; this.comparisons = comparisons; } @@ -44,25 +45,23 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new RemoveItemsReward(items, comparisons); + return new RemoveItemsReward(getCustomDescription(), items, comparisons); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return items.stream().mapToInt(ItemStack::getAmount).sum() + " " + Lang.Item.toString(); } @Override - public String[] getLore() { - return new String[] { - "§7" + Lang.AmountItems.format(items.size()), - "§7" + Lang.AmountComparisons.format(comparisons.getEffective().size()), - "", - "§7" + Lang.ClickLeft.toString() + " > " + Lang.stageItems.toString(), - "§7" + Lang.ClickRight.toString() + " > " + Lang.stageItemsComparison.toString(), - "§7" + Lang.ClickMiddle.toString() + " > §c" + Lang.Remove.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.AmountItems.format(items.size())); + loreBuilder.addDescription(Lang.AmountComparisons.format(comparisons.getEffective().size())); + loreBuilder.addClick(ClickType.LEFT, Lang.stageItems.toString()); + loreBuilder.addClick(ClickType.RIGHT, Lang.stageItemsComparison.toString()); } - + @Override public void itemClick(QuestObjectClickEvent event) { if (event.isInCreation() || event.getClick().isLeftClick()) { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 344e72df..cd33e6f5 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -14,7 +14,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; @@ -33,10 +33,12 @@ public class RequirementDependentReward extends AbstractReward { private List<AbstractReward> rewards; public RequirementDependentReward() { - this(new ArrayList<>(), new ArrayList<>()); + this(null, new ArrayList<>(), new ArrayList<>()); } - public RequirementDependentReward(List<AbstractRequirement> requirements, List<AbstractReward> rewards) { + public RequirementDependentReward(String customDescription, List<AbstractRequirement> requirements, + List<AbstractReward> rewards) { + super(customDescription); this.requirements = requirements; this.rewards = rewards; } @@ -68,11 +70,12 @@ public boolean isAsync() { @Override public AbstractReward clone() { - return new RequirementDependentReward(new ArrayList<>(requirements), new ArrayList<>(rewards)); + return new RequirementDependentReward(getCustomDescription(), new ArrayList<>(requirements), + new ArrayList<>(rewards)); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return requirements.stream().allMatch(req -> req.test(p)) ? rewards .stream() @@ -83,8 +86,9 @@ public String getDescription(Player p) { } @Override - public String[] getLore() { - return new String[] { QuestOption.formatDescription(Lang.requirements.format(requirements.size()) + ", " + Lang.actions.format(rewards.size())), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.requirements.format(requirements.size())); } @Override 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 7e737be7..b70127d9 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java @@ -1,12 +1,11 @@ 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.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.editors.WaitClick; import fr.skytasul.quests.gui.npc.NPCGUI; @@ -19,7 +18,8 @@ public class TeleportationReward extends AbstractReward { public TeleportationReward() {} - public TeleportationReward(Location teleportation){ + public TeleportationReward(String customDescription, Location teleportation) { + super(customDescription); this.teleportation = teleportation; } @@ -31,12 +31,13 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new TeleportationReward(teleportation.clone()); + return new TeleportationReward(getCustomDescription(), teleportation.clone()); } @Override - public String[] getLore() { - return new String[] { "§8> §7" + Utils.locationToString(teleportation), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(Utils.locationToString(teleportation)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java index cdd3e2c2..fddf16db 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java @@ -1,14 +1,12 @@ package fr.skytasul.quests.rewards; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.gui.misc.TitleGUI; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.Title; public class TitleReward extends AbstractReward { @@ -17,15 +15,17 @@ public class TitleReward extends AbstractReward { public TitleReward() {} - public TitleReward(Title title) { + public TitleReward(String customDescription, Title title) { + super(customDescription); this.title = title; } @Override - public String[] getLore() { - return new String[] { title == null ? Lang.NotSet.toString() : Lang.optionValue.format(title.toString()), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(title); } - + @Override public void itemClick(QuestObjectClickEvent event) { new TitleGUI(newTitle -> { @@ -47,7 +47,7 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new TitleReward(title); + return new TitleReward(getCustomDescription(), title); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java index 12df3bbb..ca772fea 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java @@ -1,11 +1,10 @@ package fr.skytasul.quests.rewards; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.NumberParser; @@ -15,11 +14,10 @@ public class WaitReward extends AbstractReward { private int delay; - public WaitReward() { - this(0); - } + public WaitReward() {} - public WaitReward(int delay) { + public WaitReward(String customDescription, int delay) { + super(customDescription); this.delay = delay; } @@ -29,8 +27,9 @@ public boolean isAsync() { } @Override - public String[] getLore() { - return new String[] { Lang.optionValue.format(Lang.Ticks.format(delay)), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(Lang.Ticks.format(delay)); } @Override @@ -54,7 +53,7 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new WaitReward(delay); + return new WaitReward(getCustomDescription(), delay); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index 94f1cd29..9a76a675 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -2,12 +2,11 @@ import java.util.Arrays; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.NumberParser; @@ -22,7 +21,8 @@ public class XPReward extends AbstractReward { public XPReward() {} - public XPReward(int exp) { + public XPReward(String customDescription, int exp) { + super(customDescription); this.exp = exp; } @@ -36,17 +36,18 @@ public List<String> give(Player p) { @Override public AbstractReward clone() { - return new XPReward(exp); + return new XPReward(getCustomDescription(), exp); } @Override - public String getDescription(Player p) { + public String getDefaultDescription(Player p) { return exp + " " + Lang.Exp.toString(); } @Override - public String[] getLore() { - return new String[] { "§8> §7" + exp + " " + Lang.Exp.toString(), "", Lang.RemoveMid.toString() }; + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(exp + " " + Lang.Exp.toString()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/structure/Quest.java b/core/src/main/java/fr/skytasul/quests/structure/Quest.java index d1127b85..81618171 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/Quest.java +++ b/core/src/main/java/fr/skytasul/quests/structure/Quest.java @@ -31,7 +31,6 @@ import fr.skytasul.quests.api.options.QuestOptionCreator; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.Actionnable; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.gui.Inventories; @@ -262,13 +261,7 @@ public boolean testRequirements(Player p, PlayerAccount acc, boolean sendMessage if (!p.hasPermission("beautyquests.start")) return false; if (!testQuestLimit(p, acc, sendMessage)) return false; sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) || (QuestsConfiguration.isRequirementReasonSentOnMultipleQuests() || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); - for (AbstractRequirement ar : getOptionValueOrDef(OptionRequirements.class)) { - if (!ar.test(p)) { - if (sendMessage) ar.sendReason(p); - return false; - } - } - return true; + return Utils.testRequirements(p, getOptionValueOrDef(OptionRequirements.class), sendMessage); } public boolean testQuestLimit(Player p, PlayerAccount acc, boolean sendMessage) { @@ -566,7 +559,7 @@ private static Quest deserialize(File file, ConfigurationSection map) { rewards = qu.getOption(OptionEndRewards.class); }else { rewards = (OptionEndRewards) QuestOptionCreator.creators.get(OptionEndRewards.class).optionSupplier.get(); - rewards.getValue().add(new MessageReward(endMessage)); + rewards.getValue().add(new MessageReward(null, endMessage)); qu.addOption(rewards); } } diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java index 507e2f79..0d43dd9a 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java @@ -176,15 +176,12 @@ public String give(Player p) { List<Quest> started = new ArrayList<>(questsPerLaunch); for (int i = 0; i < questsPerLaunch; i++) { - for (AbstractRequirement requirement : requirements) { - try { - if (requirement.test(p)) continue; - requirement.sendReason(p); - }catch (Exception ex) { - BeautyQuests.logger.severe("Cannot test requirement " + requirement.getClass().getSimpleName() + " in pool " + id + " for player " + p.getName(), ex); + if (!Utils.testRequirements(p, requirements, started.isEmpty())) { + if (started.isEmpty()) { + return null; + } else { + break; } - if (started.isEmpty()) return null; - break; } List<Quest> notCompleted = avoidDuplicates ? quests.stream().filter(quest -> !datas.getCompletedQuests().contains(quest.getID())).collect(Collectors.toList()) : quests; diff --git a/core/src/main/java/fr/skytasul/quests/utils/Lang.java b/core/src/main/java/fr/skytasul/quests/utils/Lang.java index c0eea28e..b86b0569 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Lang.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Lang.java @@ -259,6 +259,9 @@ public enum Lang implements Locale { CHOOSE_SCOREBOARD_OBJECTIVE("msg.editor.text.chooseObjectiveRequired"), CHOOSE_SCOREBOARD_TARGET("msg.editor.text.chooseObjectiveTargetScore"), CHOOSE_REGION_REQUIRED("msg.editor.text.chooseRegionRequired"), + CHOOSE_REQUIREMENT_CUSTOM_REASON("msg.editor.text.chooseRequirementCustomReason", EditorPrefix), + CHOOSE_REQUIREMENT_CUSTOM_DESCRIPTION("msg.editor.text.chooseRequirementCustomDescription", EditorPrefix), + CHOOSE_REWARD_CUSTOM_DESCRIPTION("msg.editor.text.chooseRewardCustomDescription", EditorPrefix), // rewards CHOOSE_PERM_REWARD("msg.editor.text.reward.permissionName"), @@ -542,6 +545,8 @@ public enum Lang implements Locale { command("inv.stageEnding.command"), INVENTORY_REQUIREMENTS("inv.requirements.name"), + setRequirementReason("inv.requirements.setReason"), + requirementReason("inv.requirements.reason"), // 0: message INVENTORY_REWARDS("inv.rewards.name"), commands("inv.rewards.commands"), @@ -693,6 +698,9 @@ public enum Lang implements Locale { INVENTORY_EQUIPMENT_SLOTS("inv.equipmentSlots.name"), + object_description_set("inv.questObjects.setCustomDescription"), + object_description("inv.questObjects.description"), // 0: description + BOOK_NAME("inv.listBook.questName"), BOOK_STARTER("inv.listBook.questStarter"), BOOK_REWARDS("inv.listBook.questRewards"), diff --git a/core/src/main/java/fr/skytasul/quests/utils/Utils.java b/core/src/main/java/fr/skytasul/quests/utils/Utils.java index 561cb5c1..feb033c6 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Utils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Utils.java @@ -38,6 +38,7 @@ import org.bukkit.entity.Firework; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; @@ -45,6 +46,7 @@ import org.bukkit.scoreboard.DisplaySlot; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.gui.ItemUtils; @@ -121,6 +123,24 @@ public static List<String> giveRewards(Player p, List<AbstractReward> rewards) t return msg; } + public static boolean testRequirements(Player p, List<AbstractRequirement> requirements, boolean message) { + for (AbstractRequirement requirement : requirements) { + try { + if (!requirement.test(p)) { + if (message && !requirement.sendReason(p)) + continue; // means a reason has not yet been sent + return false; + } + } catch (Exception ex) { + BeautyQuests.logger.severe( + "Cannot test requirement " + requirement.getClass().getSimpleName() + " for player " + p.getName(), + ex); + return false; + } + } + return true; + } + public static String ticksToElapsedTime(int ticks) { int i = ticks / 20; int j = i / 60; @@ -573,4 +593,21 @@ public static XMaterial mobItem(EntityType type) { return XMaterial.SPONGE; } + public static String clickName(ClickType click) { + switch (click) { + case LEFT: + return Lang.ClickLeft.toString(); + case RIGHT: + return Lang.ClickRight.toString(); + case SHIFT_LEFT: + return Lang.ClickShiftLeft.toString(); + case SHIFT_RIGHT: + return Lang.ClickShiftRight.toString(); + case MIDDLE: + return Lang.ClickMiddle.toString(); + default: + return click.name().toLowerCase(); + } + } + } \ No newline at end of file diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 4d5f0af0..9a9a4af8 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -252,6 +252,12 @@ msg: chooseObjectiveRequired: §aWrite the objective name. chooseObjectiveTargetScore: §aWrite the target score for the objective. chooseRegionRequired: §aWrite the name of the required region (you must be in the same world). + chooseRequirementCustomReason: 'Write the custom reason for this requirement. If the player does + not meet the requirement but tries to start the quest anyway, this message will appear in the chat.' + chooseRequirementCustomDescription: 'Write the custom description for this requirement. It will appear + in the description of the quest in the menu.' + chooseRewardCustomDescription: 'Write the custom description for this reward. It will appear + in the description of the quest in the menu.' selectWantedBlock: §aClick with the stick on the wanted block for the stage. itemCreator: itemType: '§aWrite the name of the wanted item type:' @@ -567,6 +573,8 @@ inv: command: §eEdit executed command requirements: name: Requirements + setReason: Set custom reason + reason: '§8Custom reason: §7{0}' rewards: name: Rewards commands: 'Commands: {0}' @@ -734,6 +742,9 @@ inv: maps: 'Maps (such as dynmap or BlueMap)' equipmentSlots: name: Equipment slots + questObjects: + setCustomDescription: 'Set custom description' + description: '§8Description: §7{0}' scoreboard: name: §6§lQuests diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index 819eb591..e3653010 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: BeautyQuests author: SkytAsul -#version: "${human.version}_BUILD${build.number}" -version: "${human.version}" +version: "${human.version}_BUILD${build.number}" +#version: "${human.version}" description: Quests system with a simple graphical interface. website: https://www.spigotmc.org/resources/beautyquests.39255/ api-version: 1.13 From 1380bbe43bd1341f0a412cda3b78b018df44a888 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 19 Apr 2023 21:35:35 +0200 Subject: [PATCH 02/95] :bookmark: 0.21-SNAPSHOT --- core/pom.xml | 2 +- dist/pom.xml | 2 +- pom.xml | 4 ++-- v1_12_R1/pom.xml | 2 +- v1_15_R1/pom.xml | 2 +- v1_16_R1/pom.xml | 2 +- v1_16_R2/pom.xml | 2 +- v1_16_R3/pom.xml | 2 +- v1_17_R1/pom.xml | 2 +- v1_18_R1/pom.xml | 2 +- v1_18_R2/pom.xml | 2 +- v1_19_R1/pom.xml | 2 +- v1_19_R2/pom.xml | 2 +- v1_19_R3/pom.xml | 2 +- v1_9_R1/pom.xml | 2 +- v1_9_R2/pom.xml | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 5765a2e3..4e8dd39c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <build> diff --git a/dist/pom.xml b/dist/pom.xml index a86275d8..3c2874ea 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <build> diff --git a/pom.xml b/pom.xml index 2b243938..ebe06c7b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> <packaging>pom</packaging> <name>beautyquests</name> @@ -18,7 +18,7 @@ <maven.compiler.target>1.8</maven.compiler.target> <maven.javadoc.skip>true</maven.javadoc.skip> <build.number>unknown</build.number> - <human.version>0.20.1</human.version> + <human.version>0.21</human.version> </properties> <repositories> diff --git a/v1_12_R1/pom.xml b/v1_12_R1/pom.xml index 6fd7bae5..d1836a69 100644 --- a/v1_12_R1/pom.xml +++ b/v1_12_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_15_R1/pom.xml b/v1_15_R1/pom.xml index de5f1f8e..e47b78c5 100644 --- a/v1_15_R1/pom.xml +++ b/v1_15_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R1/pom.xml b/v1_16_R1/pom.xml index 122ba1f8..535d1457 100644 --- a/v1_16_R1/pom.xml +++ b/v1_16_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R2/pom.xml b/v1_16_R2/pom.xml index 1cc2292d..2b1dceaa 100644 --- a/v1_16_R2/pom.xml +++ b/v1_16_R2/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R3/pom.xml b/v1_16_R3/pom.xml index 0d963ed5..8fa9439e 100644 --- a/v1_16_R3/pom.xml +++ b/v1_16_R3/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml index 2f2a7b3d..d7fe83a0 100644 --- a/v1_17_R1/pom.xml +++ b/v1_17_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties> diff --git a/v1_18_R1/pom.xml b/v1_18_R1/pom.xml index 5c0f19a4..577cadce 100644 --- a/v1_18_R1/pom.xml +++ b/v1_18_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties> diff --git a/v1_18_R2/pom.xml b/v1_18_R2/pom.xml index 092e67a1..3fc0c2ac 100644 --- a/v1_18_R2/pom.xml +++ b/v1_18_R2/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties> diff --git a/v1_19_R1/pom.xml b/v1_19_R1/pom.xml index ffb4aba7..4926c528 100644 --- a/v1_19_R1/pom.xml +++ b/v1_19_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties> diff --git a/v1_19_R2/pom.xml b/v1_19_R2/pom.xml index d98731b1..fe850f75 100644 --- a/v1_19_R2/pom.xml +++ b/v1_19_R2/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties> diff --git a/v1_19_R3/pom.xml b/v1_19_R3/pom.xml index 39ab908e..44db70d1 100644 --- a/v1_19_R3/pom.xml +++ b/v1_19_R3/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties> diff --git a/v1_9_R1/pom.xml b/v1_9_R1/pom.xml index cf4f1f7c..4262b438 100644 --- a/v1_9_R1/pom.xml +++ b/v1_9_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_9_R2/pom.xml b/v1_9_R2/pom.xml index b9c68177..9d616afa 100644 --- a/v1_9_R2/pom.xml +++ b/v1_9_R2/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.20.1</version> + <version>0.21-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> From e2dd5a6d3b07567b733a03a4735161f584a0cf7c Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 19 Apr 2023 21:53:11 +0200 Subject: [PATCH 03/95] :construction: Finished work on quest objects --- .../main/java/fr/skytasul/quests/api/objects/QuestObject.java | 2 +- .../skytasul/quests/api/requirements/AbstractRequirement.java | 2 +- .../main/java/fr/skytasul/quests/rewards/CheckpointReward.java | 2 ++ .../src/main/java/fr/skytasul/quests/rewards/CommandReward.java | 2 ++ core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java | 2 ++ .../src/main/java/fr/skytasul/quests/rewards/MessageReward.java | 2 ++ core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java | 2 ++ .../main/java/fr/skytasul/quests/rewards/PermissionReward.java | 2 ++ .../main/java/fr/skytasul/quests/rewards/QuestStopReward.java | 2 +- core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java | 2 ++ .../main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java | 2 ++ .../fr/skytasul/quests/rewards/RequirementDependentReward.java | 2 ++ .../java/fr/skytasul/quests/rewards/TeleportationReward.java | 2 ++ core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java | 2 ++ core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java | 2 ++ core/src/main/java/fr/skytasul/quests/rewards/XPReward.java | 2 ++ 16 files changed, 29 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index 7b8f8cf3..93017ad1 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -153,7 +153,7 @@ public final void click(QuestObjectClickEvent event) { new TextEditor<String>(event.getPlayer(), event::reopenGUI, msg -> { setCustomDescription(msg); event.reopenGUI(); - }).enter(); + }).passNullIntoEndConsumer().enter(); } else { clickInternal(event); } diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index 9be4c9f2..435a6801 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -99,7 +99,7 @@ protected final void clickInternal(QuestObjectClickEvent event) { new TextEditor<String>(event.getPlayer(), event::reopenGUI, msg -> { setCustomReason(msg); event.reopenGUI(); - }).enter(); + }).passNullIntoEndConsumer().enter(); } else { itemClick(event); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java index 3aa2be24..96bfae57 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java @@ -76,11 +76,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("actions", SerializableObject.serializeList(actions)); } @Override public void load(ConfigurationSection section) { + super.load(section); actions = SerializableObject.deserializeList(section.getMapList("actions"), AbstractReward::deserialize); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index 5d17ad3f..872fe09b 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -84,11 +84,13 @@ public void finish(List<Command> objects) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("commands", Utils.serializeList(commands, Command::serialize)); } @Override public void load(ConfigurationSection section){ + super.load(section); commands.addAll(Utils.deserializeList(section.getMapList("commands"), Command::deserialize)); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java index 753c50bd..0ca67b2e 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java @@ -59,11 +59,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("items", Utils.serializeList(items, ItemStack::serialize)); } @Override public void load(ConfigurationSection section){ + super.load(section); items.addAll(Utils.deserializeList(section.getMapList("items"), ItemStack::deserialize)); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java index 9ff66916..0e08bf43 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java @@ -49,11 +49,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("text", text); } @Override public void load(ConfigurationSection section) { + super.load(section); text = section.getString("text"); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java index 89fc62eb..42128c7b 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java @@ -58,11 +58,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("money", money); } @Override public void load(ConfigurationSection section) { + super.load(section); money = section.getDouble("money"); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java index a10d6e6f..e55e1396 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java @@ -53,11 +53,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("perms", Utils.serializeList(permissions, Permission::serialize)); } @Override public void load(ConfigurationSection section){ + super.load(section); permissions.addAll(Utils.deserializeList(section.getMapList("perms"), Permission::deserialize)); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java b/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java index 1d4d17ec..67d35b77 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java @@ -32,7 +32,7 @@ public List<String> give(Player p) throws InterruptingBranchException { @Override public AbstractReward clone() { - return new QuestStopReward(); + return new QuestStopReward(getCustomDescription()); } } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java index 841dbe26..f3c99d14 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java @@ -114,6 +114,7 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("rewards", SerializableObject.serializeList(rewards)); section.set("min", min); section.set("max", max); @@ -121,6 +122,7 @@ public void save(ConfigurationSection section) { @Override public void load(ConfigurationSection section) { + super.load(section); rewards = SerializableObject.deserializeList(section.getMapList("rewards"), AbstractReward::deserialize); setMinMax(section.getInt("min"), section.getInt("max")); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java index 7d89a2b5..876a65cc 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java @@ -76,12 +76,14 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("items", Utils.serializeList(items, ItemStack::serialize)); if (!comparisons.getNotDefault().isEmpty()) section.createSection("comparisons", comparisons.getNotDefault()); } @Override public void load(ConfigurationSection section){ + super.load(section); items.addAll(Utils.deserializeList(section.getMapList("items"), ItemStack::deserialize)); if (section.contains("comparisons")) comparisons.setNotDefaultComparisons(section.getConfigurationSection("comparisons")); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index cd33e6f5..bf526fde 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -142,12 +142,14 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli @Override public void save(ConfigurationSection section) { + super.save(section); section.set("requirements", SerializableObject.serializeList(requirements)); section.set("rewards", SerializableObject.serializeList(rewards)); } @Override public void load(ConfigurationSection section) { + super.load(section); requirements = SerializableObject.deserializeList(section.getMapList("requirements"), AbstractRequirement::deserialize); rewards = SerializableObject.deserializeList(section.getMapList("rewards"), AbstractReward::deserialize); } 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 b70127d9..4caab831 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java @@ -51,11 +51,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("tp", teleportation.serialize()); } @Override public void load(ConfigurationSection section) { + super.load(section); teleportation = Location.deserialize(section.getConfigurationSection("tp").getValues(false)); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java index fddf16db..adc1aab9 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java @@ -52,11 +52,13 @@ public AbstractReward clone() { @Override public void save(ConfigurationSection section) { + super.save(section); if (title != null) title.serialize(section.createSection("title")); } @Override public void load(ConfigurationSection section) { + super.load(section); title = section.contains("title") ? Title.deserialize(section.getConfigurationSection("title")) : null; } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java index ca772fea..216b4dc9 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java @@ -58,11 +58,13 @@ public AbstractReward clone() { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("delay", delay); } @Override public void load(ConfigurationSection section) { + super.load(section); delay = section.getInt("delay"); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index 9a76a675..f85f0208 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -62,11 +62,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { + super.save(section); section.set("xp", exp); } @Override public void load(ConfigurationSection section) { + super.load(section); exp = section.getInt("xp"); } From 6c0ad46f9ef11474f4b5035cb4a2de43d76571ca Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 20 Apr 2023 15:20:12 +0200 Subject: [PATCH 04/95] :arrow_up: Upgraded some dependencies --- core/pom.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 4e8dd39c..c0c16706 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -154,20 +154,20 @@ <dependency> <groupId>io.papermc.paper</groupId> <artifactId>paper-api</artifactId> - <version>1.19.2-R0.1-SNAPSHOT</version> + <version>1.19.4-R0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> <groupId>net.citizensnpcs</groupId> <artifactId>citizens-main</artifactId> - <version>2.0.30-SNAPSHOT</version> + <version>2.0.31-SNAPSHOT</version> <type>jar</type> <scope>provided</scope> </dependency> <dependency> <groupId>org.mcmonkey</groupId> <artifactId>sentinel</artifactId> - <version>2.6.0-SNAPSHOT</version> + <version>2.7.3-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> @@ -185,7 +185,7 @@ <dependency> <groupId>me.clip</groupId> <artifactId>placeholderapi</artifactId> - <version>2.10.11</version> + <version>2.11.3</version> <scope>provided</scope> </dependency> <dependency> @@ -197,13 +197,13 @@ <dependency> <groupId>me.filoghost.holographicdisplays</groupId> <artifactId>holographicdisplays-api</artifactId> - <version>3.0.0-SNAPSHOT</version> + <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.sk89q.worldguard</groupId> <artifactId>worldguard-bukkit</artifactId> - <version>7.0.6</version> + <version>7.0.7</version> <scope>provided</scope> <exclusions> <exclusion> @@ -221,7 +221,7 @@ <dependency> <groupId>org.bstats</groupId> <artifactId>bstats-bukkit</artifactId> - <version>2.2.1</version> + <version>3.0.2</version> <scope>compile</scope> </dependency> <dependency> @@ -256,7 +256,7 @@ <dependency> <groupId>com.github.BlueMap-Minecraft</groupId> <artifactId>BlueMapAPI</artifactId> - <version>v2.1.0</version> + <version>v2.5.0</version> <scope>provided</scope> </dependency> <dependency> @@ -274,7 +274,7 @@ <dependency> <groupId>com.github.decentsoftware-eu</groupId> <artifactId>decentholograms</artifactId> - <version>2.7.5</version> + <version>2.8.1</version> <scope>provided</scope> </dependency> <dependency> From b654885021ecf17d8b3a185241ebefec82e6cdf6 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 21 Apr 2023 12:47:38 +0200 Subject: [PATCH 05/95] :recycle: Changed quest pool give logic --- .../quests/gui/quests/PlayerListGUI.java | 4 +- .../quests/options/OptionStartDialog.java | 3 +- .../quests/players/PlayerPoolDatas.java | 12 -- .../fr/skytasul/quests/structure/Quest.java | 15 +- .../quests/structure/pools/QuestPool.java | 133 ++++++++++++------ 5 files changed, 104 insertions(+), 63 deletions(-) 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 49b57960..da51c8eb 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 @@ -3,7 +3,6 @@ import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.enchantments.Enchantment; @@ -12,7 +11,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; @@ -221,7 +219,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli Player target = acc.getPlayer(); if (qu.isLauncheable(target, acc, true)) { p.closeInventory(); - qu.attemptStart(target, null); + qu.attemptStart(target); } }else { if (click.isRightClick()) { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java index 3aba0cd1..19604407 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java @@ -5,7 +5,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; @@ -91,7 +90,7 @@ public void detach() { public DialogRunner getDialogRunner() { if (runner == null) { runner = new DialogRunner(getValue(), getNPC()); - runner.addEndAction(p -> getAttachedQuest().attemptStart(p, null)); + runner.addEndAction(p -> getAttachedQuest().attemptStart(p)); } return runner; } diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatas.java b/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatas.java index b3da94d7..c82d7f2e 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatas.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatas.java @@ -4,9 +4,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; - import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.structure.Quest; import fr.skytasul.quests.structure.pools.QuestPool; import fr.skytasul.quests.utils.Utils; @@ -18,8 +16,6 @@ public class PlayerPoolDatas { private long lastGive; private Set<Integer> completedQuests; - private Quest tempStartQuest; - public PlayerPoolDatas(PlayerAccount acc, int poolID) { this(acc, poolID, 0, new HashSet<>()); } @@ -62,14 +58,6 @@ public void setCompletedQuests(Set<Integer> completedQuests) { public void updatedCompletedQuests() {} - public Quest getTempStartQuest() { - return tempStartQuest; - } - - public void setTempStartQuest(Quest tempStartQuest) { - this.tempStartQuest = tempStartQuest; - } - public Map<String, Object> serialize() { Map<String, Object> map = new HashMap<>(); diff --git a/core/src/main/java/fr/skytasul/quests/structure/Quest.java b/core/src/main/java/fr/skytasul/quests/structure/Quest.java index 81618171..e72be394 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/Quest.java +++ b/core/src/main/java/fr/skytasul/quests/structure/Quest.java @@ -306,7 +306,8 @@ public boolean isInDialog(Player p) { public void clickNPC(Player p){ if (hasOption(OptionStartDialog.class)) { getOption(OptionStartDialog.class).getDialogRunner().onClick(p); - }else attemptStart(p, null); + } else + attemptStart(p); } public void leave(Player p) { @@ -342,17 +343,21 @@ public double getDescriptionPriority() { return 15; } - public void attemptStart(Player p, Runnable atStart) { - if (!isLauncheable(p, PlayersManager.getPlayerAccount(p), true)) return; + public CompletableFuture<Boolean> attemptStart(Player p) { + if (!isLauncheable(p, PlayersManager.getPlayerAccount(p), true)) + return CompletableFuture.completedFuture(false); + String confirm; if (QuestsConfiguration.questConfirmGUI() && !"none".equals(confirm = getOptionValueOrDef(OptionConfirmMessage.class))) { + CompletableFuture<Boolean> future = new CompletableFuture<>(); new ConfirmGUI(() -> { start(p); - if (atStart != null) atStart.run(); + future.complete(true); }, () -> Inventories.closeAndExit(p), Lang.INDICATION_START.format(getName()), confirm).create(p); + return future; }else { start(p); - if (atStart != null) atStart.run(); + return CompletableFuture.completedFuture(true); } } diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java index 0d43dd9a..415218ac 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java @@ -4,6 +4,7 @@ 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; @@ -19,6 +20,7 @@ import fr.skytasul.quests.players.PlayerPoolDatas; import fr.skytasul.quests.players.PlayersManager; import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.XMaterial; @@ -172,53 +174,80 @@ public String give(Player p) { PlayerPoolDatas datas = acc.getPoolDatas(this); long time = (datas.getLastGive() + timeDiff) - System.currentTimeMillis(); - if (time > 0) return Lang.POOL_NO_TIME.format(Utils.millisToHumanString(time)); - + if (time > 0) + return Lang.POOL_NO_TIME.format(Utils.millisToHumanString(time)); + List<Quest> started = new ArrayList<>(questsPerLaunch); - for (int i = 0; i < questsPerLaunch; i++) { - if (!Utils.testRequirements(p, requirements, started.isEmpty())) { - if (started.isEmpty()) { - return null; - } else { - break; - } - } - - List<Quest> notCompleted = avoidDuplicates ? quests.stream().filter(quest -> !datas.getCompletedQuests().contains(quest.getID())).collect(Collectors.toList()) : quests; - if (notCompleted.isEmpty()) { // all quests completed - notCompleted = replenishQuests(datas); - if (notCompleted.isEmpty()) { - if (started.isEmpty()) return Lang.POOL_ALL_COMPLETED.toString(); - break; - } - }else if (acc.getQuestsDatas().stream().filter(quest -> quest.hasStarted() && quests.contains(quest.getQuest())).count() >= maxQuests) { - if (started.isEmpty()) return Lang.POOL_MAX_QUESTS.format(maxQuests); - break; - } - - List<Quest> notStarted = notCompleted.stream().filter(quest -> !quest.hasStarted(acc)).collect(Collectors.toList()); - if (notStarted.isEmpty()) notStarted = replenishQuests(datas); - - List<Quest> available = notStarted.stream().filter(quest -> quest.isLauncheable(p, acc, false)).collect(Collectors.toList()); - if (available.isEmpty()) { - if (started.isEmpty()) return Lang.POOL_NO_AVAILABLE.toString(); - break; - }else { - Quest quest = datas.getTempStartQuest(); - if (quest == null || !quest.isLauncheable(p, acc, false)) { - quest = available.get(ThreadLocalRandom.current().nextInt(available.size())); - datas.setTempStartQuest(quest); - } - started.add(quest); - quest.attemptStart(p, () -> { + try { + for (int i = 0; i < questsPerLaunch; i++) { + PoolGiveResult result = giveOne(p, acc, datas, !started.isEmpty()).get(); + if (result.quest != null) { + started.add(result.quest); datas.setLastGive(System.currentTimeMillis()); - datas.setTempStartQuest(null); - }); + } else if (!result.forceContinue) { + if (started.isEmpty()) + return result.reason; + else + break; + } } + } catch (InterruptedException ex) { + BeautyQuests.logger.severe("Interrupted!", ex); + Thread.currentThread().interrupt(); + } catch (ExecutionException ex) { + BeautyQuests.logger.severe("Failed to give quests to player " + p.getName() + " from pool " + id, ex); } + return "started quest(s) " + started.stream().map(x -> "#" + x.getID()).collect(Collectors.joining(", ")); } - + + private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, PlayerPoolDatas datas, boolean hadOne) { + if (!Utils.testRequirements(p, requirements, !hadOne)) + return CompletableFuture.completedFuture(new PoolGiveResult("")); + + List<Quest> notCompleted = avoidDuplicates ? quests.stream() + .filter(quest -> !datas.getCompletedQuests().contains(quest.getID())).collect(Collectors.toList()) : quests; + if (notCompleted.isEmpty()) { + // all quests completed: we check if the player can redo some of them + notCompleted = replenishQuests(datas); + if (notCompleted.isEmpty()) + return CompletableFuture.completedFuture(new PoolGiveResult(Lang.POOL_ALL_COMPLETED.toString())); + } else if (acc.getQuestsDatas().stream().filter(quest -> quest.hasStarted() && quests.contains(quest.getQuest())) + .count() >= maxQuests) { + // player has too much quests in this pool to be able to start one more + return CompletableFuture.completedFuture(new PoolGiveResult(Lang.POOL_MAX_QUESTS.format(maxQuests))); + } + + List<Quest> notStarted = notCompleted.stream().filter(quest -> !quest.hasStarted(acc)).collect(Collectors.toList()); + if (notStarted.isEmpty()) { + // means all quests that are not yet completed are already started. + // we should then check if the player can redo some of the quests it has completed + notStarted = replenishQuests(datas); + } + + List<Quest> available = + notStarted.stream().filter(quest -> quest.isLauncheable(p, acc, false)).collect(Collectors.toList()); + // at this point, "available" contains all quests that the player has not yet completed, that it is + // not currently doing and that meet the requirements to launch + + if (available.isEmpty()) { + return CompletableFuture.completedFuture(new PoolGiveResult(Lang.POOL_NO_AVAILABLE.toString())); + } else { + CompletableFuture<PoolGiveResult> future = new CompletableFuture<>(); + Utils.runOrSync(() -> { + Quest quest = available.get(ThreadLocalRandom.current().nextInt(available.size())); + quest.attemptStart(p).whenComplete((result, exception) -> { + if (exception != null) { + future.completeExceptionally(exception); + } else { + future.complete(result ? new PoolGiveResult(quest) : new PoolGiveResult("").forceContinue()); + } + }); + }); + return future; + } + } + private List<Quest> replenishQuests(PlayerPoolDatas datas) { if (!redoAllowed) return Collections.emptyList(); List<Quest> notDoneQuests = quests.stream() @@ -232,6 +261,7 @@ private List<Quest> replenishQuests(PlayerPoolDatas datas) { .map(Quest::getID) .collect(Collectors.toSet())); } + DebugUtils.logMessage("Replenished available quests of " + datas.getAccount().getNameAndID() + " for pool " + id); return notDoneQuests; } @@ -259,4 +289,25 @@ public static QuestPool deserialize(int id, ConfigurationSection config) { return new QuestPool(id, config.getInt("npcID"), config.getString("hologram"), config.getInt("maxQuests"), config.getInt("questsPerLaunch", 1), config.getBoolean("redoAllowed"), config.getLong("timeDiff"), config.getBoolean("avoidDuplicates", true), requirements); } + private static class PoolGiveResult { + private final Quest quest; + private final String reason; + private boolean forceContinue = false; + + public PoolGiveResult(Quest quest) { + this.quest = quest; + this.reason = null; + } + + public PoolGiveResult(String reason) { + this.quest = null; + this.reason = reason; + } + + public PoolGiveResult forceContinue() { + forceContinue = true; + return this; + } + } + } From 9b12771f42fed1955bfb67ee7db95585150b7418 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 22 Apr 2023 16:09:21 +0200 Subject: [PATCH 06/95] :technologist: Added nullability annotations to most API code --- core/pom.xml | 7 ++ .../java/fr/skytasul/quests/BeautyQuests.java | 22 ++--- .../fr/skytasul/quests/QuestsListener.java | 6 +- .../quests/api/AbstractHolograms.java | 19 +++-- .../java/fr/skytasul/quests/api/Locale.java | 22 +++-- .../fr/skytasul/quests/api/QuestsAPI.java | 46 +++++----- .../quests/api/bossbar/BQBossBarManager.java | 14 ++-- .../quests/api/comparison/ItemComparison.java | 10 ++- .../api/comparison/ItemComparisonMap.java | 25 +++--- .../quests/api/events/DialogSendEvent.java | 13 +-- .../api/events/DialogSendMessageEvent.java | 20 ++--- .../api/events/PlayerAccountQuestEvent.java | 26 ------ .../quests/api/events/PlayerQuestEvent.java | 27 +++--- .../api/events/PlayerQuestResetEvent.java | 7 +- .../api/events/PlayerSetStageEvent.java | 13 +-- .../quests/api/events/QuestCreateEvent.java | 7 +- .../quests/api/events/QuestEvent.java | 13 +-- .../quests/api/events/QuestFinishEvent.java | 5 +- .../quests/api/events/QuestLaunchEvent.java | 5 +- .../api/events/QuestPreLaunchEvent.java | 7 +- .../quests/api/events/QuestRemoveEvent.java | 3 +- .../events/accounts/PlayerAccountEvent.java | 20 +++-- .../accounts/PlayerAccountJoinEvent.java | 7 +- .../accounts/PlayerAccountLeaveEvent.java | 7 +- .../accounts/PlayerAccountResetEvent.java | 7 +- .../{ => internal}/BQBlockBreakEvent.java | 10 +-- .../events/{ => internal}/BQCraftEvent.java | 13 +-- .../{ => internal}/BQNPCClickEvent.java | 14 ++-- .../quests/api/mobs/LeveledMobFactory.java | 3 +- .../java/fr/skytasul/quests/api/mobs/Mob.java | 26 +++--- .../skytasul/quests/api/mobs/MobFactory.java | 27 +++--- .../skytasul/quests/api/mobs/MobStacker.java | 3 +- .../fr/skytasul/quests/api/npcs/BQNPC.java | 12 +-- .../quests/api/npcs/BQNPCsManager.java | 26 +++--- .../quests/api/objects/QuestObject.java | 40 ++++----- .../api/objects/QuestObjectClickEvent.java | 22 ++--- .../api/objects/QuestObjectCreator.java | 18 ++-- .../api/objects/QuestObjectLoreBuilder.java | 12 +-- .../api/objects/QuestObjectsRegistry.java | 21 +++-- .../quests/api/options/OptionSet.java | 6 +- .../quests/api/options/QuestOption.java | 60 +++++++------- .../api/options/QuestOptionCreator.java | 7 +- .../description/QuestDescriptionContext.java | 20 +++-- .../description/QuestDescriptionProvider.java | 6 +- .../api/requirements/AbstractRequirement.java | 39 +++++---- .../quests/api/requirements/Actionnable.java | 3 +- .../api/requirements/RequirementCreator.java | 10 ++- .../requirements/TargetNumberRequirement.java | 33 ++++---- .../quests/api/rewards/AbstractReward.java | 21 +++-- .../quests/api/rewards/RewardCreator.java | 12 +-- .../api/serializable/SerializableCreator.java | 29 ++++--- .../api/serializable/SerializableObject.java | 34 ++++---- .../serializable/SerializableRegistry.java | 15 ++-- .../quests/api/stages/AbstractStage.java | 83 ++++++++++--------- .../quests/api/stages/StageCreation.java | 15 ++-- .../skytasul/quests/api/stages/StageType.java | 42 +++++----- .../quests/api/stages/StageTypeRegistry.java | 13 ++- .../api/stages/options/StageOption.java | 11 +-- .../types/AbstractCountableBlockStage.java | 12 +-- .../stages/types/AbstractCountableStage.java | 56 +++++++------ .../api/stages/types/AbstractEntityStage.java | 26 +++--- .../api/stages/types/AbstractItemStage.java | 28 ++++--- .../quests/api/stages/types/Dialogable.java | 4 + .../quests/api/stages/types/Locatable.java | 43 ++++++---- .../commands/CommandsPlayerManagement.java | 2 +- .../fr/skytasul/quests/editors/SelectNPC.java | 3 +- .../quests/gui/creation/QuestObjectGUI.java | 8 +- .../quests/gui/templates/ListGUI.java | 3 +- .../quests/players/PlayerAccount.java | 59 +++++++------ .../quests/players/PlayersManager.java | 49 ++++++----- .../players/accounts/AbstractAccount.java | 24 ++++-- .../fr/skytasul/quests/stages/StageCraft.java | 2 +- .../fr/skytasul/quests/stages/StageMine.java | 2 +- .../fr/skytasul/quests/stages/StageNPC.java | 2 +- .../quests/structure/BranchesManager.java | 40 ++++----- .../fr/skytasul/quests/structure/Quest.java | 80 +++++++++--------- .../quests/structure/QuestBranch.java | 53 ++++++------ .../quests/structure/QuestsManager.java | 32 +++---- .../structure/pools/QuestPoolsManager.java | 53 +++++++----- .../fr/skytasul/quests/utils/ChatUtils.java | 21 +++-- .../java/fr/skytasul/quests/utils/Lang.java | 21 +++-- .../java/fr/skytasul/quests/utils/Utils.java | 8 +- .../utils/compatibility/BQTokenEnchant.java | 3 +- .../utils/compatibility/BQUltimateTimber.java | 3 +- .../quests/utils/compatibility/Post1_16.java | 3 +- .../utils/compatibility/npcs/BQCitizens.java | 18 ++-- .../quests/utils/logger/LoggerExpanded.java | 23 ++--- .../skytasul/quests/utils/types/BQBlock.java | 31 +++---- .../quests/utils/types/CountableObject.java | 22 +++-- 89 files changed, 974 insertions(+), 824 deletions(-) delete mode 100644 core/src/main/java/fr/skytasul/quests/api/events/PlayerAccountQuestEvent.java rename core/src/main/java/fr/skytasul/quests/api/events/{ => internal}/BQBlockBreakEvent.java (67%) rename core/src/main/java/fr/skytasul/quests/api/events/{ => internal}/BQCraftEvent.java (65%) rename core/src/main/java/fr/skytasul/quests/api/events/{ => internal}/BQNPCClickEvent.java (71%) diff --git a/core/pom.xml b/core/pom.xml index c0c16706..4a76f0e2 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -151,6 +151,13 @@ </repositories> <dependencies> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>24.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>io.papermc.paper</groupId> <artifactId>paper-api</artifactId> diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index f7b6959b..37bec606 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -28,6 +28,8 @@ import org.bukkit.entity.Player; 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; @@ -660,39 +662,39 @@ public void run() { }.runTaskLater(BeautyQuests.getInstance(), 20L); } - public CommandsManager getCommand() { + public @NotNull CommandsManager getCommand() { return command; } - public QuestsConfiguration getConfiguration() { + public @NotNull QuestsConfiguration getConfiguration() { return config; } - public FileConfiguration getDataFile(){ + public @NotNull FileConfiguration getDataFile() { return data; } - public Database getBQDatabase() { + public @Nullable Database getBQDatabase() { return db; } - public ScoreboardManager getScoreboardManager(){ + public @Nullable ScoreboardManager getScoreboardManager() { return scoreboards; } - public QuestsManager getQuestsManager() { + public @NotNull QuestsManager getQuestsManager() { return quests; } - public QuestPoolsManager getPoolsManager() { + public @NotNull QuestPoolsManager getPoolsManager() { return pools; } - public PlayersManager getPlayersManager() { + public @NotNull PlayersManager getPlayersManager() { return players; } - public ILoggerHandler getLoggerHandler() { + public @NotNull ILoggerHandler getLoggerHandler() { return loggerHandler == null ? ILoggerHandler.EMPTY_LOGGER : loggerHandler; } @@ -701,7 +703,7 @@ public boolean isRunningPaper() { } - public static BeautyQuests getInstance(){ + public static @NotNull BeautyQuests getInstance() { return instance; } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 30e131b8..b4c15ec9 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -26,11 +26,11 @@ import org.bukkit.inventory.ComplexRecipe; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.events.BQBlockBreakEvent; -import fr.skytasul.quests.api.events.BQCraftEvent; -import fr.skytasul.quests.api.events.BQNPCClickEvent; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; +import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; +import fr.skytasul.quests.api.events.internal.BQCraftEvent; +import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.gui.Inventories; diff --git a/core/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java b/core/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java index d18165e1..f69c9171 100644 --- a/core/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java +++ b/core/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java @@ -1,10 +1,11 @@ package fr.skytasul.quests.api; import java.util.List; - import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class AbstractHolograms<T> { @@ -12,30 +13,30 @@ public abstract class AbstractHolograms<T> { public abstract boolean supportItems(); - public abstract BQHologram createHologram(Location lc, boolean defaultVisible); + public abstract @NotNull BQHologram createHologram(@NotNull Location lc, boolean defaultVisible); public abstract class BQHologram { - protected T hologram; + protected @NotNull T hologram; - protected BQHologram(T hologram) { + protected BQHologram(@NotNull T hologram) { this.hologram = hologram; } - public void setPlayersVisible(List<Player> players) { + public void setPlayersVisible(@NotNull List<Player> players) { players.forEach(p -> setPlayerVisibility(p, true)); } - public void setPlayerVisibility(Player p, boolean visible) { + public void setPlayerVisibility(@NotNull Player p, boolean visible) { throw new UnsupportedOperationException(); } - public void appendItem(ItemStack item) { + public void appendItem(@NotNull ItemStack item) { throw new UnsupportedOperationException(); } - public abstract void appendTextLine(String text); + public abstract void appendTextLine(@Nullable String text); - public abstract void teleport(Location lc); + public abstract void teleport(@NotNull Location lc); public abstract void delete(); } diff --git a/core/src/main/java/fr/skytasul/quests/api/Locale.java b/core/src/main/java/fr/skytasul/quests/api/Locale.java index 21ca0eb6..3c71dd28 100644 --- a/core/src/main/java/fr/skytasul/quests/api/Locale.java +++ b/core/src/main/java/fr/skytasul/quests/api/Locale.java @@ -8,41 +8,44 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.function.Supplier; - import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.Plugin; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.utils.ChatUtils; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Utils; public interface Locale { + @NotNull String getPath(); + @NotNull String getValue(); - void setValue(String value); + void setValue(@NotNull String value); - default String format(Object... replace) { + default @NotNull String format(@Nullable Object @Nullable... replace) { return Utils.format(getValue(), replace); } - default String format(Supplier<Object>... replace) { + default @NotNull String format(@NotNull Supplier<Object> @Nullable... replace) { return Utils.format(getValue(), replace); } - default void send(CommandSender sender, Object... args) { + default void send(@NotNull CommandSender sender, @Nullable Object @Nullable... args) { Utils.sendMessage(sender, getValue(), args); } - default void sendWP(CommandSender p, Object... args) { + default void sendWP(@NotNull CommandSender p, @Nullable Object @Nullable... args) { Utils.sendMessageWP(p, getValue(), args); } - public static void loadStrings(Locale[] locales, YamlConfiguration defaultConfig, YamlConfiguration config) { + public static void loadStrings(@NotNull Locale @NotNull [] locales, @NotNull YamlConfiguration defaultConfig, + @NotNull YamlConfiguration config) { for (Locale l : locales) { String value = config.getString(l.getPath(), null); if (value == null) value = defaultConfig.getString(l.getPath(), null); @@ -51,7 +54,8 @@ public static void loadStrings(Locale[] locales, YamlConfiguration defaultConfig } } - public static YamlConfiguration loadLang(Plugin plugin, Locale[] locales, String loadedLanguage) throws IOException, URISyntaxException { + public static YamlConfiguration loadLang(@NotNull Plugin plugin, @NotNull Locale @NotNull [] locales, + @NotNull String loadedLanguage) throws IOException, URISyntaxException { long lastMillis = System.currentTimeMillis(); Utils.walkResources(plugin.getClass(), "/locales", 1, path -> { diff --git a/core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java index 4569a289..aba5df4a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ b/core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -10,6 +10,8 @@ import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.bossbar.BQBossBarManager; import fr.skytasul.quests.api.comparison.ItemComparison; @@ -60,7 +62,7 @@ public static <T extends AbstractStage> void registerStage(StageType<T> type) { stages.register(type); } - public static StageTypeRegistry getStages() { + public static @NotNull StageTypeRegistry getStages() { return stages; } @@ -68,57 +70,57 @@ public static StageTypeRegistry getStages() { * Register new mob factory * @param factory MobFactory instance */ - public static void registerMobFactory(MobFactory<?> factory) { + public static void registerMobFactory(@NotNull MobFactory<?> factory) { MobFactory.factories.add(factory); Bukkit.getPluginManager().registerEvents(factory, BeautyQuests.getInstance()); DebugUtils.logMessage("Mob factory registered (id: " + factory.getID() + ")"); } - public static void registerQuestOption(QuestOptionCreator<?, ?> creator) { + public static void registerQuestOption(@NotNull QuestOptionCreator<?, ?> creator) { Validate.notNull(creator); Validate.isTrue(!QuestOptionCreator.creators.containsKey(creator.optionClass), "This quest option was already registered"); QuestOptionCreator.creators.put(creator.optionClass, creator); DebugUtils.logMessage("Quest option registered (id: " + creator.id + ")"); } - public static List<ItemComparison> getItemComparisons() { + public static @NotNull List<@NotNull ItemComparison> getItemComparisons() { return itemComparisons; } - public static void registerItemComparison(ItemComparison comparison) { + public static void registerItemComparison(@NotNull ItemComparison comparison) { Validate.isTrue(itemComparisons.stream().noneMatch(x -> x.getID().equals(comparison.getID())), "This item comparison was already registered"); itemComparisons.add(comparison); DebugUtils.logMessage("Item comparison registered (id: " + comparison.getID() + ")"); } - public static void unregisterItemComparison(ItemComparison comparison) { + public static void unregisterItemComparison(@NotNull ItemComparison comparison) { Validate.isTrue(itemComparisons.remove(comparison), "This item comparison was not registered"); DebugUtils.logMessage("Item comparison unregistered (id: " + comparison.getID() + ")"); } - public static List<MobStacker> getMobStackers() { + public static @NotNull List<@NotNull MobStacker> getMobStackers() { return mobStackers; } - public static void registerMobStacker(MobStacker stacker) { + public static void registerMobStacker(@NotNull MobStacker stacker) { mobStackers.add(stacker); DebugUtils.logMessage("Added " + stacker.toString() + " mob stacker"); } - public static QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getRequirements() { + public static @NotNull QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getRequirements() { return requirements; } - public static QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards() { + public static @NotNull QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards() { return rewards; } - public static BQNPCsManager getNPCsManager() { + public static @NotNull BQNPCsManager getNPCsManager() { return npcsManager; } - public static void setNPCsManager(BQNPCsManager newNpcsManager) { + public static void setNPCsManager(@NotNull BQNPCsManager newNpcsManager) { if (npcsManager != null) { BeautyQuests.logger.warning(newNpcsManager.getClass().getSimpleName() + " will replace " + npcsManager.getClass().getSimpleName() + " as the new NPCs manager."); HandlerList.unregisterAll(npcsManager); @@ -131,11 +133,11 @@ public static boolean hasHologramsManager() { return hologramsManager != null; } - public static AbstractHolograms<?> getHologramsManager() { + public static @Nullable AbstractHolograms<?> getHologramsManager() { return hologramsManager; } - public static void setHologramsManager(AbstractHolograms<?> newHologramsManager) { + public static void setHologramsManager(@NotNull AbstractHolograms<?> newHologramsManager) { Validate.notNull(newHologramsManager); if (hologramsManager != null) BeautyQuests.logger.warning(newHologramsManager.getClass().getSimpleName() + " will replace " + hologramsManager.getClass().getSimpleName() + " as the new holograms manager."); hologramsManager = newHologramsManager; @@ -146,32 +148,32 @@ public static boolean hasBossBarManager() { return bossBarManager != null; } - public static BQBossBarManager getBossBarManager() { + public static @Nullable BQBossBarManager getBossBarManager() { return bossBarManager; } - public static void setBossBarManager(BQBossBarManager newBossBarManager) { + public static void setBossBarManager(@NotNull BQBossBarManager newBossBarManager) { Validate.notNull(newBossBarManager); if (bossBarManager != null) BeautyQuests.logger.warning(newBossBarManager.getClass().getSimpleName() + " will replace " + hologramsManager.getClass().getSimpleName() + " as the new boss bar manager."); bossBarManager = newBossBarManager; DebugUtils.logMessage("Bossbars manager has been registered: " + newBossBarManager.getClass().getName()); } - public static void registerQuestsHandler(QuestsHandler handler) { + public static void registerQuestsHandler(@NotNull QuestsHandler handler) { Validate.notNull(handler); if (handlers.add(handler) && BeautyQuests.loaded) handler.load(); // if BeautyQuests not loaded so far, it will automatically call the load method } - public static void unregisterQuestsHandler(QuestsHandler handler) { + public static void unregisterQuestsHandler(@NotNull QuestsHandler handler) { if (handlers.remove(handler)) handler.unload(); } - public static Collection<QuestsHandler> getQuestsHandlers() { + public static @NotNull Collection<@NotNull QuestsHandler> getQuestsHandlers() { return handlers; } - public static void propagateQuestsHandlers(Consumer<QuestsHandler> consumer) { + public static void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> consumer) { handlers.forEach(handler -> { try { consumer.accept(handler); @@ -181,11 +183,11 @@ public static void propagateQuestsHandlers(Consumer<QuestsHandler> consumer) { }); } - public static QuestsManager getQuests() { + public static @NotNull QuestsManager getQuests() { return BeautyQuests.getInstance().getQuestsManager(); } - public static QuestPoolsManager getQuestPools() { + public static @NotNull QuestPoolsManager getQuestPools() { return BeautyQuests.getInstance().getPoolsManager(); } diff --git a/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java b/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java index ce45666d..985911a2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java +++ b/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java @@ -3,26 +3,28 @@ import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; public interface BQBossBarManager { - BQBossBar buildBossBar(String name, BarColor color, BarStyle style); + @NotNull + BQBossBar buildBossBar(@NotNull String name, @NotNull BarColor color, @NotNull BarStyle style); - default BQBossBar buildBossBar(String name, String color, String style) { + default @NotNull BQBossBar buildBossBar(@NotNull String name, @NotNull String color, @NotNull String style) { return buildBossBar(name, BarColor.valueOf(color), BarStyle.valueOf(style)); } public interface BQBossBar { - void setTitle(String name); + void setTitle(@NotNull String name); void setProgress(double progress); - void setStyle(BarStyle style); + void setStyle(@NotNull BarStyle style); - void addPlayer(Player player); + void addPlayer(@NotNull Player player); - void removePlayer(Player player); + void removePlayer(@NotNull Player player); void removeAll(); diff --git a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java b/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java index d449855c..78140c70 100644 --- a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java +++ b/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java @@ -2,14 +2,16 @@ import java.util.function.BiPredicate; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; public class ItemComparison { - private final String id, itemName, itemDescription; - private final BiPredicate<ItemStack, ItemStack> comparator; + private final @NotNull String id, itemName, itemDescription; + private final @NotNull BiPredicate<@NotNull ItemStack, @NotNull ItemStack> comparator; private boolean enabledByDefault, needsMeta, hasPriority; - public ItemComparison(String id, String itemName, String itemDescription, BiPredicate<ItemStack, ItemStack> comparator) { + public ItemComparison(@NotNull String id, @NotNull String itemName, @NotNull String itemDescription, + @NotNull BiPredicate<@NotNull ItemStack, @NotNull ItemStack> comparator) { this.id = id; this.itemName = itemName; this.itemDescription = itemDescription; @@ -58,7 +60,7 @@ public boolean hasPriority() { /** * This must <i>not</i> check the amount of the item. The function call must not affect the item in any way. */ - public boolean isSimilar(ItemStack item1, ItemStack item2) { + public boolean isSimilar(@NotNull ItemStack item1, @NotNull ItemStack item2) { return comparator.test(item1, item2); } diff --git a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java b/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java index ac6d81b4..f6d92aee 100644 --- a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java +++ b/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java @@ -10,6 +10,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; public class ItemComparisonMap implements Cloneable { @@ -21,15 +22,15 @@ public ItemComparisonMap() { this(new HashMap<>()); } - public ItemComparisonMap(ConfigurationSection notDefault) { + public ItemComparisonMap(@NotNull ConfigurationSection notDefault) { setNotDefaultComparisons(notDefault); } - public ItemComparisonMap(Map<String, Boolean> notDefault) { + public ItemComparisonMap(@NotNull Map<String, Boolean> notDefault) { setNotDefaultComparisons(notDefault); } - public void setNotDefaultComparisons(ConfigurationSection section) { + public void setNotDefaultComparisons(@NotNull ConfigurationSection section) { this.notDefault = (Map) section.getValues(false); effective = new ArrayList<>(3); @@ -40,7 +41,7 @@ public void setNotDefaultComparisons(ConfigurationSection section) { updated(); } - public void setNotDefaultComparisons(Map<String, Boolean> comparisons) { + public void setNotDefaultComparisons(@NotNull Map<String, Boolean> comparisons) { this.notDefault = comparisons; effective = new ArrayList<>(3); @@ -53,7 +54,7 @@ public void setNotDefaultComparisons(Map<String, Boolean> comparisons) { updated(); } - public Map<String, Boolean> getNotDefault() { + public @NotNull Map<String, Boolean> getNotDefault() { return notDefault; } @@ -61,15 +62,15 @@ public boolean isDefault() { return notDefault.isEmpty(); } - public List<ItemComparison> getEffective() { + public @NotNull List<@NotNull ItemComparison> getEffective() { return effective; } - public boolean isEnabled(ItemComparison comparison) { + public boolean isEnabled(@NotNull ItemComparison comparison) { return effective.contains(comparison); } - public boolean toggle(ItemComparison comparison) { + public boolean toggle(@NotNull ItemComparison comparison) { Boolean bool = notDefault.get(comparison.getID()); if (bool == null) { bool = !comparison.isEnabledByDefault(); @@ -94,7 +95,7 @@ private void updated() { Collections.sort(effective, Comparator.comparing(ItemComparison::hasPriority)); } - public boolean isSimilar(ItemStack item1, ItemStack item2) { + public boolean isSimilar(@NotNull ItemStack item1, @NotNull ItemStack item2) { boolean meta1 = item1.hasItemMeta(); boolean meta2 = item2.hasItemMeta(); @@ -129,7 +130,7 @@ else if (!meta1) return lastResult; } - public boolean containsItems(Inventory inv, ItemStack i, int amount) { + public boolean containsItems(@NotNull Inventory inv, @NotNull ItemStack i, int amount) { for (ItemStack item : inv.getContents()) { if (item == null) continue; if (isSimilar(item, i)) { @@ -146,7 +147,7 @@ public boolean containsItems(Inventory inv, ItemStack i, int amount) { return false; } - public void removeItems(Inventory inv, ItemStack i) { + public void removeItems(@NotNull Inventory inv, @NotNull ItemStack i) { int amount = i.getAmount(); if (amount <= 0) return; ItemStack[] items = inv.getContents(); @@ -170,7 +171,7 @@ public void removeItems(Inventory inv, ItemStack i) { } @Override - public ItemComparisonMap clone() { + public @NotNull ItemComparisonMap clone() { return new ItemComparisonMap(new HashMap<>(notDefault)); } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java index 560709cb..5ad1c6ca 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.utils.types.Dialog; @@ -12,16 +12,17 @@ public class DialogSendEvent extends Event implements Cancellable { private boolean cancelled = false; - private Dialog dialog; - private BQNPC npc; - private Player player; - private Runnable runnable; + private final @NotNull Dialog dialog; + private final @NotNull BQNPC npc; + private final @NotNull Player player; + private final @NotNull Runnable runnable; - public DialogSendEvent(Dialog dialog, BQNPC npc, Player player, Runnable runnable) { + public DialogSendEvent(@NotNull Dialog dialog, @NotNull BQNPC npc, @NotNull Player player, @NotNull Runnable runnable) { this.dialog = dialog; this.npc = npc; this.player = player; this.runnable = runnable; + // TODO change this "runnable" thing } @Override diff --git a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java index a0e49e55..25c93849 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.utils.types.Dialog; import fr.skytasul.quests.utils.types.Message; @@ -13,12 +13,12 @@ public class DialogSendMessageEvent extends Event implements Cancellable { private boolean cancelled = false; - private Dialog dialog; - private Message msg; - private BQNPC npc; - private Player player; + private final @NotNull Dialog dialog; + private final @NotNull Message msg; + private final @NotNull BQNPC npc; + private final @NotNull Player player; - public DialogSendMessageEvent(Dialog dialog, Message msg, BQNPC npc, Player player) { + public DialogSendMessageEvent(@NotNull Dialog dialog, @NotNull Message msg, @NotNull BQNPC npc, @NotNull Player player) { this.dialog = dialog; this.msg = msg; this.npc = npc; @@ -35,19 +35,19 @@ public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } - public Dialog getDialog() { + public @NotNull Dialog getDialog() { return dialog; } - public Message getMessage() { + public @NotNull Message getMessage() { return msg; } - public BQNPC getNPC() { + public @NotNull BQNPC getNPC() { return npc; } - public Player getPlayer(){ + public @NotNull Player getPlayer() { return player; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/PlayerAccountQuestEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/PlayerAccountQuestEvent.java deleted file mode 100644 index 76958883..00000000 --- a/core/src/main/java/fr/skytasul/quests/api/events/PlayerAccountQuestEvent.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.skytasul.quests.api.events; - -import org.bukkit.event.Event; - -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.Quest; - -public abstract class PlayerAccountQuestEvent extends Event { - - protected Quest qu; - protected PlayerAccount acc; - - public PlayerAccountQuestEvent(PlayerAccount account, Quest quest) { - this.acc = account; - this.qu = quest; - } - - public Quest getQuest() { - return qu; - } - - public PlayerAccount getPlayerAccount() { - return acc; - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java index 956aeb32..8bd567ba 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java @@ -1,29 +1,28 @@ package fr.skytasul.quests.api.events; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerEvent; - +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.events.accounts.PlayerAccountEvent; import fr.skytasul.quests.players.PlayerAccount; import fr.skytasul.quests.players.PlayersManager; import fr.skytasul.quests.structure.Quest; -public abstract class PlayerQuestEvent extends PlayerEvent{ +public abstract class PlayerQuestEvent extends PlayerAccountEvent { - protected Quest qu; - protected PlayerAccount acc; + protected final @NotNull Quest quest; - public PlayerQuestEvent(Player who, Quest quest){ - super(who); - this.qu = quest; - this.acc = PlayersManager.getPlayerAccount(who); + protected PlayerQuestEvent(@NotNull Player who, @NotNull Quest quest) { + super(PlayersManager.getPlayerAccount(who)); + this.quest = quest; } - public Quest getQuest(){ - return qu; + protected PlayerQuestEvent(@NotNull PlayerAccount acc, @NotNull Quest quest) { + super(acc); + this.quest = quest; } - - public PlayerAccount getPlayerAccount(){ - return acc; + + public @NotNull Quest getQuest() { + return quest; } } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java index 7ea44293..bcd2d8a0 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java @@ -1,19 +1,20 @@ package fr.skytasul.quests.api.events; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.players.PlayerAccount; import fr.skytasul.quests.structure.Quest; /** * Called when the stage of a player is cancelled */ -public class PlayerQuestResetEvent extends PlayerAccountQuestEvent { +public class PlayerQuestResetEvent extends PlayerQuestEvent { - public PlayerQuestResetEvent(PlayerAccount account, Quest quest) { + public PlayerQuestResetEvent(@NotNull PlayerAccount account, @NotNull Quest quest) { super(account, quest); } + @Override public HandlerList getHandlers() { return handlers; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java index e0ad96b1..59c0d77f 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java @@ -1,7 +1,7 @@ package fr.skytasul.quests.api.events; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.players.PlayerAccount; import fr.skytasul.quests.structure.BranchesManager; @@ -10,23 +10,24 @@ /** * Called when a player finish a stage */ -public class PlayerSetStageEvent extends PlayerAccountQuestEvent{ +public class PlayerSetStageEvent extends PlayerQuestEvent { - private AbstractStage stage; + private final @NotNull AbstractStage stage; - public PlayerSetStageEvent(PlayerAccount account, Quest quest, AbstractStage stage){ + public PlayerSetStageEvent(@NotNull PlayerAccount account, @NotNull Quest quest, @NotNull AbstractStage stage) { super(account, quest); this.stage = stage; } - public AbstractStage getStage(){ + public @NotNull AbstractStage getStage() { return stage; } public BranchesManager getStageManager(){ - return qu.getBranchesManager(); + return quest.getBranchesManager(); } + @Override public HandlerList getHandlers() { return handlers; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java index 6fced797..7da6e507 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java @@ -3,7 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.structure.Quest; /** @@ -13,15 +13,17 @@ public class QuestCreateEvent extends PlayerQuestEvent implements Cancellable{ private boolean cancel, edit = false; - public QuestCreateEvent(Player who, Quest quest, boolean edit){ + public QuestCreateEvent(@NotNull Player who, @NotNull Quest quest, boolean edit) { super(who, quest); this.edit = edit; } + @Override public boolean isCancelled(){ return cancel; } + @Override public void setCancelled(boolean paramBoolean){ this.cancel = paramBoolean; } @@ -30,6 +32,7 @@ public boolean isEdited(){ return edit; } + @Override public HandlerList getHandlers() { return handlers; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java index 7e32a2c4..26bd2a8a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java @@ -2,21 +2,22 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.structure.Quest; public abstract class QuestEvent extends Event { - protected Quest qu; + protected final @NotNull Quest quest; - public QuestEvent(Quest quest){ - this.qu = quest; + protected QuestEvent(@NotNull Quest quest) { + this.quest = quest; } - public Quest getQuest(){ - return qu; + public @NotNull Quest getQuest() { + return quest; } + @Override public HandlerList getHandlers(){ return handlers; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java index c1b372ee..679d92fd 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java @@ -2,7 +2,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.structure.Quest; /** @@ -10,10 +10,11 @@ */ public class QuestFinishEvent extends PlayerQuestEvent{ - public QuestFinishEvent(Player who, Quest quest){ + public QuestFinishEvent(@NotNull Player who, @NotNull Quest quest) { super(who, quest); } + @Override public HandlerList getHandlers() { return handlers; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java index e833770d..b9944578 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java @@ -2,7 +2,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.structure.Quest; /** @@ -10,10 +10,11 @@ */ public class QuestLaunchEvent extends PlayerQuestEvent { - public QuestLaunchEvent(Player who, Quest quest){ + public QuestLaunchEvent(@NotNull Player who, @NotNull Quest quest) { super(who, quest); } + @Override public HandlerList getHandlers() { return handlers; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java index 7e5f9e3e..a2a72004 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java @@ -3,7 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.structure.Quest; /** @@ -13,18 +13,21 @@ public class QuestPreLaunchEvent extends PlayerQuestEvent implements Cancellable private boolean cancel = false; - public QuestPreLaunchEvent(Player who, Quest quest){ + public QuestPreLaunchEvent(@NotNull Player who, @NotNull Quest quest) { super(who, quest); } + @Override public boolean isCancelled(){ return cancel; } + @Override public void setCancelled(boolean paramBoolean){ this.cancel = paramBoolean; } + @Override public HandlerList getHandlers() { return handlers; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java index da2c4f6a..ea9888b7 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.api.events; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.structure.Quest; /** @@ -8,7 +9,7 @@ */ public class QuestRemoveEvent extends QuestEvent{ - public QuestRemoveEvent(Quest quest) { + public QuestRemoveEvent(@NotNull Quest quest) { super(quest); } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java index 26be1092..f985c609 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java @@ -2,28 +2,30 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.players.PlayerAccount; public abstract class PlayerAccountEvent extends Event { - private Player who; - private PlayerAccount account; + protected final @NotNull PlayerAccount account; - protected PlayerAccountEvent(Player who, PlayerAccount account) { - this.who = who; + protected PlayerAccountEvent(@NotNull PlayerAccount account) { this.account = account; } public boolean isAccountCurrent() { - return who != null; + return account.isCurrent(); } - public Player getPlayer() { - return who; + public @Nullable Player getPlayer() { + if (!account.isCurrent()) + throw new IllegalStateException("Account is not currently used"); + + return account.getPlayer(); } - public PlayerAccount getPlayerAccount() { + public @NotNull PlayerAccount getPlayerAccount() { return account; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java index 264c4862..e977be80 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java @@ -1,16 +1,15 @@ package fr.skytasul.quests.api.events.accounts; -import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.players.PlayerAccount; public class PlayerAccountJoinEvent extends PlayerAccountEvent { private boolean firstJoin; - public PlayerAccountJoinEvent(Player who, PlayerAccount account, boolean firstJoin) { - super(who, account); + public PlayerAccountJoinEvent(@NotNull PlayerAccount account, boolean firstJoin) { + super(account); this.firstJoin = firstJoin; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java index 5c304316..853dc0a7 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java @@ -1,14 +1,13 @@ package fr.skytasul.quests.api.events.accounts; -import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.players.PlayerAccount; public class PlayerAccountLeaveEvent extends PlayerAccountEvent { - public PlayerAccountLeaveEvent(Player who, PlayerAccount account) { - super(who, account); + public PlayerAccountLeaveEvent(@NotNull PlayerAccount account) { + super(account); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java index fa2de5cc..61c5813f 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java @@ -1,14 +1,13 @@ package fr.skytasul.quests.api.events.accounts; -import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.players.PlayerAccount; public class PlayerAccountResetEvent extends PlayerAccountEvent { - public PlayerAccountResetEvent(Player who, PlayerAccount account) { - super(who, account); + public PlayerAccountResetEvent(@NotNull PlayerAccount account) { + super(account); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/api/events/BQBlockBreakEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java similarity index 67% rename from core/src/main/java/fr/skytasul/quests/api/events/BQBlockBreakEvent.java rename to core/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java index 6d518759..ea7428d7 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/BQBlockBreakEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java @@ -1,25 +1,25 @@ -package fr.skytasul.quests.api.events; +package fr.skytasul.quests.api.events.internal; import java.util.List; - import org.apache.commons.lang.Validate; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; public class BQBlockBreakEvent extends PlayerEvent { - private final List<Block> blocks; + private final @NotNull List<@NotNull Block> blocks; - public BQBlockBreakEvent(Player player, List<Block> blocks) { + public BQBlockBreakEvent(@NotNull Player player, @NotNull List<@NotNull Block> blocks) { super(player); Validate.notNull(player); Validate.notNull(blocks); this.blocks = blocks; } - public List<Block> getBlocks() { + public @NotNull List<@NotNull Block> getBlocks() { return blocks; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/BQCraftEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java similarity index 65% rename from core/src/main/java/fr/skytasul/quests/api/events/BQCraftEvent.java rename to core/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java index da6d2eed..6567b57a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/BQCraftEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java @@ -1,29 +1,30 @@ -package fr.skytasul.quests.api.events; +package fr.skytasul.quests.api.events.internal; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerEvent; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; public class BQCraftEvent extends PlayerEvent { - private final InventoryClickEvent clickEvent; - private final ItemStack result; + private final @NotNull InventoryClickEvent clickEvent; + private final @NotNull ItemStack result; private final int maxCraftable; - public BQCraftEvent(InventoryClickEvent clickEvent, ItemStack result, int maxCraftable) { + public BQCraftEvent(@NotNull InventoryClickEvent clickEvent, @NotNull ItemStack result, int maxCraftable) { super((Player) clickEvent.getView().getPlayer()); this.clickEvent = clickEvent; this.result = result; this.maxCraftable = maxCraftable; } - public InventoryClickEvent getClickEvent() { + public @NotNull InventoryClickEvent getClickEvent() { return clickEvent; } - public ItemStack getResult() { + public @NotNull ItemStack getResult() { return result; } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/BQNPCClickEvent.java b/core/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java similarity index 71% rename from core/src/main/java/fr/skytasul/quests/api/events/BQNPCClickEvent.java rename to core/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java index b9ca4c6c..c5d9ef41 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/BQNPCClickEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java @@ -1,21 +1,21 @@ -package fr.skytasul.quests.api.events; +package fr.skytasul.quests.api.events.internal; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.QuestsConfiguration.ClickType; import fr.skytasul.quests.api.npcs.BQNPC; public class BQNPCClickEvent extends PlayerEvent implements Cancellable { - private final BQNPC npc; - private final ClickType click; + private final @NotNull BQNPC npc; + private final @NotNull ClickType click; private boolean cancelled = false; - public BQNPCClickEvent(BQNPC npc, Player p, ClickType click) { + public BQNPCClickEvent(@NotNull BQNPC npc, @NotNull Player p, @NotNull ClickType click) { super(p); this.npc = npc; this.click = click; @@ -31,11 +31,11 @@ public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } - public BQNPC getNPC() { + public @NotNull BQNPC getNPC() { return npc; } - public ClickType getClick() { + public @NotNull ClickType getClick() { return click; } diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java b/core/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java index 01e356aa..563176c1 100644 --- a/core/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java +++ b/core/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java @@ -1,9 +1,10 @@ package fr.skytasul.quests.api.mobs; import org.bukkit.entity.Entity; +import org.jetbrains.annotations.NotNull; public interface LeveledMobFactory<T> extends MobFactory<T> { - double getMobLevel(T type, Entity entity); + double getMobLevel(@NotNull T type, @NotNull Entity entity); } diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java b/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java index 5ad50345..bb3de279 100644 --- a/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java +++ b/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java @@ -7,6 +7,8 @@ import java.util.Map; import org.apache.commons.lang.Validate; import org.bukkit.entity.Entity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.XMaterial; @@ -22,22 +24,22 @@ public class Mob<D> implements Cloneable { private String formattedName; - public Mob(MobFactory<D> factory, D data) { + public Mob(@NotNull MobFactory<D> factory, @NotNull D data) { Validate.notNull(factory, "Mob factory cannot be null"); Validate.notNull(data, "Mob data cannot be null"); this.factory = factory; this.data = data; } - public MobFactory<D> getFactory() { + public @NotNull MobFactory<D> getFactory() { return factory; } - public D getData() { + public @NotNull D getData() { return data; } - public String getName() { + public @NotNull String getName() { if (formattedName == null) { if (customName != null) { formattedName = customName; @@ -51,23 +53,23 @@ public String getName() { return formattedName; } - public List<String> getDescriptiveLore() { + public @NotNull List<@Nullable String> getDescriptiveLore() { return factory.getDescriptiveLore(data); } - public void setCustomName(String customName) { + public void setCustomName(@Nullable String customName) { this.customName = customName; } - public Double getMinLevel() { + public @Nullable Double getMinLevel() { return minLevel; } - public void setMinLevel(Double minLevel) { + public void setMinLevel(@Nullable Double minLevel) { this.minLevel = minLevel; } - public XMaterial getMobItem() { + public @NotNull XMaterial getMobItem() { try { return Utils.mobItem(factory.getEntityType(data)); }catch (Exception ex) { @@ -76,15 +78,15 @@ public XMaterial getMobItem() { } } - public boolean applies(Object data) { + public boolean applies(@Nullable Object data) { return factory.mobApplies(this.data, data); } - public boolean appliesEntity(Entity entity) { + public boolean appliesEntity(@NotNull Entity entity) { return factory.bukkitMobApplies(data, entity); } - public double getLevel(Entity entity) { + public double getLevel(@NotNull Entity entity) { if (!(factory instanceof LeveledMobFactory)) throw new UnsupportedOperationException( "Cannot get the level of a mob from an unleveled mob factory: " + factory.getID()); diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java b/core/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java index a8f96782..099ee2f1 100644 --- a/core/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java +++ b/core/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java @@ -16,6 +16,8 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import fr.skytasul.quests.BeautyQuests; @@ -33,57 +35,57 @@ public abstract interface MobFactory<T> extends Listener { /** * @return internal ID of this Mob Factory */ - public abstract String getID(); + public abstract @NotNull String getID(); /** * @return item which will represent this Mob Factory in the Mobs Create GUI */ - public abstract ItemStack getFactoryItem(); + public abstract @NotNull ItemStack getFactoryItem(); /** * Called when a player click on the {@link #getFactoryItem()} * @param p Player who clicked on the item * @param run */ - public abstract void itemClick(Player p, Consumer<T> run); + public abstract void itemClick(@NotNull Player p, @NotNull Consumer<@Nullable T> run); /** * @param value value returned from {@link #getValue(Object)} * @return object created with the value */ - public abstract T fromValue(String value); + public abstract @NotNull T fromValue(@NotNull String value); /** * @param data object to get a String value from * @return String value */ - public abstract String getValue(T data); + public abstract @NotNull String getValue(@NotNull T data); /** * @param data object to get a name from * @return name of the object */ - public abstract String getName(T data); + public abstract @NotNull String getName(@NotNull T data); /** * @param data object to get the entity type from * @return entity type of the object */ - public abstract EntityType getEntityType(T data); + public abstract @NotNull EntityType getEntityType(@NotNull T data); /** * @param data object to get a description from * @return list of string which will be displayed as the lore of the mob item */ - public default List<String> getDescriptiveLore(T data) { + public default @NotNull List<@Nullable String> getDescriptiveLore(@NotNull T data) { return Collections.emptyList(); } - public default boolean mobApplies(T first, Object other) { + public default boolean mobApplies(@Nullable T first, @Nullable Object other) { return Objects.equals(first, other); } - public default boolean bukkitMobApplies(T first, Entity entity) { // TODO abstract (introduced in 0.20) + public default boolean bukkitMobApplies(@NotNull T first, @NotNull Entity entity) { // TODO abstract (introduced in 0.20) BeautyQuests.logger.warning("The mob factory " + getID() + " has not been updated. Nag its author about it!"); return false; } @@ -96,7 +98,8 @@ public default boolean bukkitMobApplies(T first, Entity entity) { // TODO abstra * @param entity bukkit entity killed * @param player killer */ - public default void callEvent(Event originalEvent, T pluginMob, Entity entity, Player player) { + public default void callEvent(@Nullable Event originalEvent, @NotNull T pluginMob, @NotNull Entity entity, + @NotNull Player player) { Validate.notNull(pluginMob, "Plugin mob object cannot be null"); Validate.notNull(player, "Player cannot be null"); if (originalEvent != null) { @@ -118,7 +121,7 @@ public default void callEvent(Event originalEvent, T pluginMob, Entity entity, P static final Cache<Event, CompatMobDeathEvent> eventsCache = CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build(); public static final List<MobFactory<?>> factories = new ArrayList<>(); - public static MobFactory<?> getMobFactory(String id) { + public static @Nullable MobFactory<?> getMobFactory(@NotNull String id) { for (MobFactory<?> factory : factories) { if (factory.getID().equals(id)) return factory; } diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java b/core/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java index f8f804a8..b5561877 100644 --- a/core/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java +++ b/core/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java @@ -1,9 +1,10 @@ package fr.skytasul.quests.api.mobs; import org.bukkit.entity.Entity; +import org.jetbrains.annotations.NotNull; public interface MobStacker { - int getEntityStackSize(Entity entity); + int getEntityStackSize(@NotNull Entity entity); } diff --git a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java b/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java index 286faad3..30d1f4b9 100644 --- a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java +++ b/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java @@ -3,7 +3,6 @@ import java.util.*; import java.util.Map.Entry; import java.util.function.BiPredicate; - import org.apache.commons.lang.StringUtils; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -12,7 +11,8 @@ 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.QuestsConfiguration; import fr.skytasul.quests.api.AbstractHolograms; @@ -62,17 +62,17 @@ protected BQNPC() { public abstract int getId(); - public abstract String getName(); + public abstract @NotNull String getName(); public abstract boolean isSpawned(); @Override - public abstract Entity getEntity(); + public abstract @NotNull Entity getEntity(); @Override - public abstract Location getLocation(); + public abstract @NotNull Location getLocation(); - public abstract void setSkin(String skin); + public abstract void setSkin(@Nullable String skin); /** * Sets the "paused" state of the NPC navigation diff --git a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java b/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java index 345006ea..e3c9a809 100644 --- a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java +++ b/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java @@ -3,7 +3,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; - import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -11,9 +10,11 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Listener; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration.ClickType; -import fr.skytasul.quests.api.events.BQNPCClickEvent; +import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; public abstract class BQNPCsManager implements Listener { @@ -21,30 +22,31 @@ public abstract class BQNPCsManager implements Listener { public abstract int getTimeToWaitForNPCs(); - public abstract Collection<Integer> getIDs(); + public abstract @NotNull Collection<@NotNull Integer> getIDs(); - public abstract boolean isNPC(Entity entity); + public abstract boolean isNPC(@NotNull Entity entity); - public final BQNPC createNPC(Location location, EntityType type, String name, String skin) { + public final @NotNull BQNPC createNPC(@NotNull Location location, @NotNull EntityType type, @NotNull String name, + @Nullable String skin) { BQNPC npc = create(location, type, name); try { if (type == EntityType.PLAYER) npc.setSkin(skin); }catch (Exception ex) { - ex.printStackTrace(); + BeautyQuests.logger.severe("Failed to set NPC skin", ex); } npcs.put(npc.getId(), npc); return npc; } - public abstract boolean isValidEntityType(EntityType type); + public abstract boolean isValidEntityType(@NotNull EntityType type); - protected abstract BQNPC create(Location location, EntityType type, String name); + protected abstract @NotNull BQNPC create(@NotNull Location location, @NotNull EntityType type, @NotNull String name); - public final BQNPC getById(int id) { + public final @Nullable BQNPC getById(int id) { return npcs.computeIfAbsent(id, this::fetchNPC); } - protected abstract BQNPC fetchNPC(int id); + protected abstract @Nullable BQNPC fetchNPC(int id); protected final void removeEvent(int id) { BQNPC npc = npcs.get(id); @@ -53,7 +55,7 @@ protected final void removeEvent(int id) { npcs.remove(id); } - protected final void clickEvent(Cancellable event, int npcID, Player p, ClickType click) { + protected final void clickEvent(@NotNull Cancellable event, int npcID, @NotNull Player p, @NotNull ClickType click) { if (event != null && event.isCancelled()) return; BQNPCClickEvent newEvent = new BQNPCClickEvent(getById(npcID), p, click); Bukkit.getPluginManager().callEvent(newEvent); diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index 93017ad1..888190e9 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -6,6 +6,8 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; 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.serializable.SerializableObject; import fr.skytasul.quests.editors.TextEditor; @@ -21,7 +23,7 @@ public abstract class QuestObject extends SerializableObject implements Cloneabl private Quest quest; private String customDescription; - protected QuestObject(QuestObjectsRegistry registry, String customDescription) { + protected QuestObject(@NotNull QuestObjectsRegistry registry, @Nullable String customDescription) { super(registry); this.customDescription = customDescription; } @@ -31,7 +33,7 @@ public QuestObjectCreator getCreator() { return (QuestObjectCreator) super.getCreator(); } - public void attach(Quest quest) { + public void attach(@NotNull Quest quest) { this.quest = quest; } @@ -39,19 +41,19 @@ public void detach() { this.quest = null; } - public Quest getAttachedQuest() { + public @Nullable Quest getAttachedQuest() { return quest; } - public String getCustomDescription() { + public @Nullable String getCustomDescription() { return customDescription; } - public void setCustomDescription(String customDescription) { + public void setCustomDescription(@Nullable String customDescription) { this.customDescription = customDescription; } - public String debugName() { + public @NotNull String debugName() { return getClass().getSimpleName() + (quest == null ? ", unknown quest" : (", quest " + quest.getID())); } @@ -60,7 +62,7 @@ public boolean isValid() { } @Override - public abstract QuestObject clone(); + public abstract @NotNull QuestObject clone(); @Deprecated protected void save(Map<String, Object> datas) {} @@ -69,7 +71,7 @@ protected void save(Map<String, Object> datas) {} protected void load(Map<String, Object> savedDatas) {} @Override - public void save(ConfigurationSection section) { + public void save(@NotNull ConfigurationSection section) { Map<String, Object> datas = new HashMap<>(); save(datas); Utils.setConfigurationSectionContent(section, datas); @@ -79,14 +81,14 @@ public void save(ConfigurationSection section) { } @Override - public void load(ConfigurationSection section) { + public void load(@NotNull ConfigurationSection section) { load(section.getValues(false)); if (section.contains(CUSTOM_DESCRIPTION_KEY)) customDescription = section.getString(CUSTOM_DESCRIPTION_KEY); } - public final String getDescription(Player player) { + public final @Nullable String getDescription(Player player) { return customDescription == null ? getDefaultDescription(player) : customDescription; } @@ -96,7 +98,7 @@ public final String getDescription(Player player) { * @param player player to get the description for * @return the description of this object (nullable) */ - protected String getDefaultDescription(Player p) { + protected @Nullable String getDefaultDescription(@NotNull Player p) { return null; } @@ -105,7 +107,7 @@ public String[] getLore() { // backward compatibility from 0.20.1 - TODO REMOVE return null; } - public String[] getItemLore() { + public @NotNull String @Nullable [] getItemLore() { String[] legacyLore = getLore(); if (legacyLore != null) return legacyLore; @@ -115,7 +117,7 @@ public String[] getItemLore() { return lore.toLoreArray(); } - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { loreBuilder.addClick(getRemoveClick(), "§c" + Lang.Remove.toString()); loreBuilder.addClick(getCustomDescriptionClick(), Lang.object_description_set.toString()); @@ -130,21 +132,21 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { Lang.object_description.format(description + (customDescription == null ? " " + Lang.defaultValue : ""))); } - public ItemStack getItemStack() { + public @NotNull ItemStack getItemStack() { return ItemUtils.lore(getCreator().getItem().clone(), getItemLore()); } - public ClickType getRemoveClick() { + public @Nullable ClickType getRemoveClick() { return ClickType.SHIFT_LEFT; } - protected ClickType getCustomDescriptionClick() { + protected @Nullable ClickType getCustomDescriptionClick() { return ClickType.RIGHT; } - protected abstract void sendCustomDescriptionHelpMessage(Player p); + protected abstract void sendCustomDescriptionHelpMessage(@NotNull Player p); - public final void click(QuestObjectClickEvent event) { + public final void click(@NotNull QuestObjectClickEvent event) { if (event.getClick() == getRemoveClick()) return; @@ -159,6 +161,6 @@ public final void click(QuestObjectClickEvent event) { } } - protected abstract void clickInternal(QuestObjectClickEvent event); + protected abstract void clickInternal(@NotNull QuestObjectClickEvent event); } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java index 63146aa6..542b46f0 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java @@ -3,19 +3,21 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.QuestObjectGUI; public class QuestObjectClickEvent { - private final Player player; - private final QuestObjectGUI gui; - private final ItemStack item; - private final ClickType click; + private final @NotNull Player player; + private final @NotNull QuestObjectGUI gui; + private final @NotNull ItemStack item; + private final @NotNull ClickType click; + private final @NotNull QuestObject clickedObject; private final boolean creation; - private final QuestObject clickedObject; - public QuestObjectClickEvent(Player player, QuestObjectGUI gui, ItemStack item, ClickType click, boolean creation, QuestObject clickedObject) { + public QuestObjectClickEvent(@NotNull Player player, @NotNull QuestObjectGUI gui, @NotNull ItemStack item, + @NotNull ClickType click, boolean creation, @NotNull QuestObject clickedObject) { this.player = player; this.gui = gui; this.item = item; @@ -24,19 +26,19 @@ public QuestObjectClickEvent(Player player, QuestObjectGUI gui, ItemStack item, this.clickedObject = clickedObject; } - public Player getPlayer() { + public @NotNull Player getPlayer() { return player; } - public QuestObjectGUI getGUI() { + public @NotNull QuestObjectGUI getGUI() { return gui; } - public ItemStack getItem() { + public @NotNull ItemStack getItem() { return item; } - public ClickType getClick() { + public @NotNull ClickType getClick() { return click; } diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java index ded73102..453e39fa 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java @@ -1,17 +1,16 @@ package fr.skytasul.quests.api.objects; import java.util.function.Supplier; - import org.bukkit.inventory.ItemStack; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.gui.creation.QuestObjectGUI; public class QuestObjectCreator<T extends QuestObject> extends SerializableCreator<T> { - private final ItemStack item; + private final @NotNull ItemStack item; private final boolean multiple; - private QuestObjectLocation[] allowedLocations; + private @NotNull QuestObjectLocation @NotNull [] allowedLocations; /** * @param id unique identifier for the object @@ -19,7 +18,8 @@ public class QuestObjectCreator<T extends QuestObject> extends SerializableCreat * @param item ItemStack shown in {@link QuestObjectGUI} * @param newObjectSupplier lambda returning an instance of this Object ({@link T}::new) */ - public QuestObjectCreator(String id, Class<? extends T> clazz, ItemStack item, Supplier<T> newObjectSupplier) { + public QuestObjectCreator(@NotNull String id, @NotNull Class<? extends T> clazz, @NotNull ItemStack item, + @NotNull Supplier<@NotNull T> newObjectSupplier) { this(id, clazz, item, newObjectSupplier, true); } @@ -32,14 +32,16 @@ public QuestObjectCreator(String id, Class<? extends T> clazz, ItemStack item, S * @param allowedLocations if present, specifies where the object can be used. * If no location is specified, then all locations are accepted. */ - public QuestObjectCreator(String id, Class<? extends T> clazz, ItemStack item, Supplier<T> newObjectSupplier, boolean multiple, QuestObjectLocation... allowedLocations) { + public QuestObjectCreator(@NotNull String id, @NotNull Class<? extends T> clazz, @NotNull ItemStack item, + @NotNull Supplier<@NotNull T> newObjectSupplier, boolean multiple, + @NotNull QuestObjectLocation @NotNull... allowedLocations) { super(id, clazz, newObjectSupplier); this.item = item; this.multiple = multiple; this.allowedLocations = allowedLocations; } - public ItemStack getItem() { + public @NotNull ItemStack getItem() { return item; } @@ -47,7 +49,7 @@ public boolean canBeMultiple() { return multiple; } - public boolean isAllowed(QuestObjectLocation location) { + public boolean isAllowed(@NotNull QuestObjectLocation location) { if (allowedLocations.length == 0) return true; for (QuestObjectLocation allowed : allowedLocations) { if (allowed == location) return true; diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java index 97e1eaff..97a8f973 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java @@ -8,6 +8,8 @@ import java.util.Map.Entry; import java.util.TreeMap; import org.bukkit.event.inventory.ClickType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.utils.Utils; @@ -27,26 +29,26 @@ public class QuestObjectLoreBuilder { public QuestObjectLoreBuilder() {} - public void addDescriptionRaw(String line) { + public void addDescriptionRaw(@Nullable String line) { description.add(line); } - public void addDescription(String line) { + public void addDescription(@Nullable String line) { addDescriptionRaw(QuestOption.formatDescription(line)); } - public void addDescriptionAsValue(Object value) { + public void addDescriptionAsValue(@Nullable Object value) { addDescription(QuestOption.formatNullableValue(value == null ? null : value.toString())); } - public void addClick(ClickType click, String action) { + public void addClick(@Nullable ClickType click, @NotNull String action) { if (click == null) return; clicks.put(click, action); } - public String[] toLoreArray() { + public @NotNull String @Nullable [] toLoreArray() { String[] lore = new String[description.size() + 1 + clicks.size()]; int i = 0; diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java index 7149ae00..01d93e6f 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java +++ b/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java @@ -5,36 +5,41 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.serializable.SerializableRegistry; import fr.skytasul.quests.gui.creation.QuestObjectGUI; public class QuestObjectsRegistry<T extends QuestObject, C extends QuestObjectCreator<T>> extends SerializableRegistry<T, C> { - private final String inventoryName; + private final @NotNull String inventoryName; - public QuestObjectsRegistry(String id, String inventoryName) { + public QuestObjectsRegistry(@NotNull String id, @NotNull String inventoryName) { super(id); this.inventoryName = inventoryName; } - public String getInventoryName() { + public @NotNull String getInventoryName() { return inventoryName; } - public QuestObjectGUI<T> createGUI(QuestObjectLocation location, Consumer<List<T>> end, List<T> objects) { + public QuestObjectGUI<T> createGUI(@NotNull QuestObjectLocation location, @NotNull Consumer<@NotNull List<T>> end, + @NotNull List<T> objects) { return createGUI(inventoryName, location, end, objects, null); } - public QuestObjectGUI<T> createGUI(QuestObjectLocation location, Consumer<List<T>> end, List<T> objects, Predicate<C> filter) { + public QuestObjectGUI<T> createGUI(@NotNull QuestObjectLocation location, @NotNull Consumer<@NotNull List<T>> end, + @NotNull List<T> objects, @Nullable Predicate<C> filter) { return createGUI(inventoryName, location, end, objects, filter); } - public QuestObjectGUI<T> createGUI(String name, QuestObjectLocation location, Consumer<List<T>> end, List<T> objects) { + public QuestObjectGUI<T> createGUI(@NotNull String name, @NotNull QuestObjectLocation location, + @NotNull Consumer<@NotNull List<T>> end, @NotNull List<T> objects) { return createGUI(name, location, end, objects, null); } - public QuestObjectGUI<T> createGUI(String name, QuestObjectLocation location, Consumer<List<T>> end, List<T> objects, Predicate<C> filter) { + public QuestObjectGUI<T> createGUI(@NotNull String name, @NotNull QuestObjectLocation location, + @NotNull Consumer<@NotNull List<T>> end, @NotNull List<@NotNull T> objects, @Nullable Predicate<C> filter) { return new QuestObjectGUI<>(name, location, (Collection<QuestObjectCreator<T>>) (filter == null ? creators : creators.stream().filter(filter).collect(Collectors.toList())), end, objects); } diff --git a/core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java b/core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java index 046fa7a3..4fa5a6c9 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java @@ -1,10 +1,12 @@ package fr.skytasul.quests.api.options; +import org.jetbrains.annotations.NotNull; + @SuppressWarnings ("rawtypes") public interface OptionSet extends Iterable<QuestOption> { - <T extends QuestOption<?>> T getOption(Class<T> optionClass); + <T extends QuestOption<?>> @NotNull T getOption(@NotNull Class<T> optionClass); - boolean hasOption(Class<? extends QuestOption<?>> clazz); + boolean hasOption(@NotNull Class<? extends QuestOption<?>> clazz); } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/core/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index da651bb8..b60faa3e 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.api.options; import java.util.Objects; - import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; @@ -10,7 +9,8 @@ import org.bukkit.event.Listener; import org.bukkit.event.inventory.ClickType; 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.options.description.QuestDescriptionProvider; import fr.skytasul.quests.gui.creation.FinishGUI; @@ -19,15 +19,15 @@ public abstract class QuestOption<T> implements Cloneable { - private final QuestOptionCreator<T, QuestOption<T>> creator; + private final @NotNull QuestOptionCreator<T, QuestOption<T>> creator; - private T value; - private Quest attachedQuest; + private @Nullable T value; + private @Nullable Quest attachedQuest; - private final Class<? extends QuestOption<?>>[] requiredQuestOptions; - private Runnable valueUpdateListener; + private final @NotNull Class<? extends QuestOption<?>> @NotNull [] requiredQuestOptions; + private @Nullable Runnable valueUpdateListener; - public QuestOption(Class<? extends QuestOption<?>>... requiredQuestOptions) { + protected QuestOption(@NotNull Class<? extends QuestOption<?>> @NotNull... requiredQuestOptions) { this.requiredQuestOptions = requiredQuestOptions; this.creator = (QuestOptionCreator<T, QuestOption<T>>) QuestOptionCreator.creators.get(getClass()); @@ -36,7 +36,7 @@ public QuestOption(Class<? extends QuestOption<?>>... requiredQuestOptions) { setValue(creator.defaultValue == null ? null : cloneValue(creator.defaultValue)); } - public QuestOptionCreator<T, QuestOption<T>> getOptionCreator() { + public @NotNull QuestOptionCreator<T, QuestOption<T>> getOptionCreator() { return creator; } @@ -44,11 +44,11 @@ public final boolean hasCustomValue() { return !Objects.equals(this.value, creator.defaultValue); } - public final T getValue() { + public final @Nullable T getValue() { return value; } - public void setValue(T value) { + public void setValue(@Nullable T value) { this.value = value; valueUpdated(); } @@ -61,19 +61,19 @@ protected void valueUpdated() { if (valueUpdateListener != null) valueUpdateListener.run(); } - public void setValueUpdaterListener(Runnable listener) { + public void setValueUpdaterListener(@Nullable Runnable listener) { this.valueUpdateListener = listener; } - public Class<? extends QuestOption<?>>[] getRequiredQuestOptions() { + public @NotNull Class<? extends QuestOption<?>> @NotNull [] getRequiredQuestOptions() { return requiredQuestOptions; } - public Quest getAttachedQuest() { + public @Nullable Quest getAttachedQuest() { return attachedQuest; } - public void attach(Quest quest) { + public void attach(@NotNull Quest quest) { Validate.notNull(quest, "Attached quest cannot be null"); if (this.attachedQuest != null) throw new IllegalStateException("This option is already attached to " + attachedQuest.getID()); this.attachedQuest = quest; @@ -96,50 +96,52 @@ public void detach() { } if (previous != null && this instanceof QuestDescriptionProvider) { - previous.getDescriptions().remove((QuestDescriptionProvider) this); + previous.getDescriptions().remove(this); } } - public abstract Object save(); + public abstract @Nullable Object save(); - public abstract void load(ConfigurationSection config, String key); + public abstract void load(@NotNull ConfigurationSection config, @NotNull String key); - public abstract T cloneValue(T value); + public abstract @Nullable T cloneValue(@Nullable T value); @Override - public QuestOption<T> clone() { + public @NotNull QuestOption<T> clone() { QuestOption<T> clone = creator.optionSupplier.get(); clone.setValue(value == null ? null : cloneValue(value)); return clone; } - public boolean shouldDisplay(OptionSet options) { + public boolean shouldDisplay(@NotNull OptionSet options) { return true; } - public void updatedDependencies(OptionSet options, ItemStack item) {} + public void updatedDependencies(@NotNull OptionSet options, @NotNull ItemStack item) {} - public abstract ItemStack getItemStack(OptionSet options); + public abstract @NotNull ItemStack getItemStack(@NotNull OptionSet options); - public abstract void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click); + public abstract void click(@NotNull FinishGUI gui, @NotNull Player p, @NotNull ItemStack item, int slot, + @NotNull ClickType click); - public boolean clickCursor(FinishGUI gui, Player p, ItemStack item, ItemStack cursor, int slot) { + public boolean clickCursor(@NotNull FinishGUI gui, @NotNull Player p, @NotNull ItemStack item, @NotNull ItemStack cursor, + int slot) { return true; } - public String formatValue(String valueString) { + public @NotNull String formatValue(@Nullable String valueString) { return formatNullableValue(valueString, !hasCustomValue()); } - public static String formatDescription(String description) { + public static @Nullable String formatDescription(@Nullable String description) { return description == null ? null : "§8> §7" + description; } - public static String formatNullableValue(String valueString) { + public static @NotNull String formatNullableValue(@Nullable String valueString) { return formatNullableValue(valueString, false); } - public static String formatNullableValue(String valueString, boolean defaultValue) { + public static @NotNull String formatNullableValue(@Nullable String valueString, boolean defaultValue) { valueString = Lang.optionValue.format(valueString == null ? Lang.NotSet.toString() : valueString); if (defaultValue) valueString += " " + Lang.defaultValue.toString(); return valueString; diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java index 8f6b0944..184220f1 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java @@ -4,6 +4,8 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class QuestOptionCreator<D, T extends QuestOption<D>> { @@ -17,7 +19,8 @@ public class QuestOptionCreator<D, T extends QuestOption<D>> { public int slot = -1; - public QuestOptionCreator(String id, int preferedSlot, Class<T> optionClass, Supplier<T> optionSupplier, D defaultValue, String... oldNames) { + public QuestOptionCreator(@NotNull String id, int preferedSlot, @NotNull Class<T> optionClass, + @NotNull Supplier<@NotNull T> optionSupplier, @Nullable D defaultValue, @NotNull String @NotNull... oldNames) { this.id = id; this.optionClass = optionClass; this.optionSupplier = optionSupplier; @@ -39,7 +42,7 @@ public static int calculateSlot(int preferedSlot) { return prevSlot == preferedSlot ? prevSlot + 1 : preferedSlot; } - public boolean applies(String key) { + public boolean applies(@NotNull String key) { return id.equals(key) || Arrays.stream(oldNames).anyMatch(key::equals); } diff --git a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java b/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java index 858b11e6..3181e534 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; import fr.skytasul.quests.players.PlayerAccount; @@ -20,8 +22,8 @@ public class QuestDescriptionContext { private PlayerQuestDatas cachedDatas; - public QuestDescriptionContext(QuestDescription descriptionOptions, Quest quest, PlayerAccount acc, - PlayerListGUI.Category category, Source source) { + public QuestDescriptionContext(@NotNull QuestDescription descriptionOptions, @NotNull Quest quest, + @NotNull PlayerAccount acc, @NotNull PlayerListGUI.Category category, @NotNull Source source) { this.descriptionOptions = descriptionOptions; this.quest = quest; this.acc = acc; @@ -29,32 +31,32 @@ public QuestDescriptionContext(QuestDescription descriptionOptions, Quest quest, this.source = source; } - public QuestDescription getDescriptionOptions() { + public @NotNull QuestDescription getDescriptionOptions() { return descriptionOptions; } - public Quest getQuest() { + public @NotNull Quest getQuest() { return quest; } - public PlayerAccount getPlayerAccount() { + public @NotNull PlayerAccount getPlayerAccount() { return acc; } - public Category getCategory() { + public @NotNull Category getCategory() { return category; } - public Source getSource() { + public @NotNull Source getSource() { return source; } - public PlayerQuestDatas getQuestDatas() { + public @Nullable PlayerQuestDatas getQuestDatas() { if (cachedDatas == null) cachedDatas = acc.getQuestDatasIfPresent(quest); return cachedDatas; } - public List<String> formatDescription() { + public @NotNull List<@Nullable String> formatDescription() { List<String> list = new ArrayList<>(); quest.getDescriptions() diff --git a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java b/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java index 0b968a7a..0cab02be 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java @@ -2,13 +2,17 @@ import java.util.Comparator; import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface QuestDescriptionProvider { public static final Comparator<QuestDescriptionProvider> COMPARATOR = Comparator.comparingDouble(QuestDescriptionProvider::getDescriptionPriority); - List<String> provideDescription(QuestDescriptionContext context); + @NotNull + List<@Nullable String> provideDescription(@NotNull QuestDescriptionContext context); + @NotNull String getDescriptionId(); double getDescriptionPriority(); diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index 435a6801..d3ae3ab8 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -4,10 +4,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; @@ -22,16 +25,16 @@ protected AbstractRequirement() { this(null, null); } - protected AbstractRequirement(String customDescription, String customReason) { + protected AbstractRequirement(@Nullable String customDescription, @Nullable String customReason) { super(QuestsAPI.getRequirements(), customDescription); this.customReason = customReason; } - public String getCustomReason() { + public @Nullable String getCustomReason() { return customReason; } - public void setCustomReason(String customReason) { + public void setCustomReason(@Nullable String customReason) { this.customReason = customReason; } @@ -40,13 +43,13 @@ public void setCustomReason(String customReason) { * @param p Player to test * @return if the player fills conditions of this requirement */ - public abstract boolean test(Player p); + public abstract boolean test(@NotNull Player p); /** * Called if the condition if not filled and if the plugin allows to send a message to the player * @param p Player to send the reason */ - public final boolean sendReason(Player player) { + public final boolean sendReason(@NotNull Player player) { String reason; if (!isValid()) @@ -71,29 +74,29 @@ else if (customReason != null) * @param player player to get the message for * @return the reason of the requirement (nullable) */ - protected String getDefaultReason(Player player) { + protected @Nullable String getDefaultReason(@NotNull Player player) { return null; } - protected String getInvalidReason() { + protected @NotNull String getInvalidReason() { return "invalid requirement"; } - protected ClickType getCustomReasonClick() { + protected @Nullable ClickType getCustomReasonClick() { return ClickType.SHIFT_RIGHT; } - protected void sendCustomReasonHelpMessage(Player p) { + protected void sendCustomReasonHelpMessage(@NotNull Player p) { Lang.CHOOSE_REQUIREMENT_CUSTOM_REASON.send(p); } @Override - protected void sendCustomDescriptionHelpMessage(Player p) { + protected void sendCustomDescriptionHelpMessage(@NotNull Player p) { Lang.CHOOSE_REQUIREMENT_CUSTOM_DESCRIPTION.send(p); } @Override - protected final void clickInternal(QuestObjectClickEvent event) { + protected final void clickInternal(@NotNull QuestObjectClickEvent event) { if (event.getClick() == getCustomReasonClick()) { sendCustomReasonHelpMessage(event.getPlayer()); new TextEditor<String>(event.getPlayer(), event::reopenGUI, msg -> { @@ -105,10 +108,10 @@ protected final void clickInternal(QuestObjectClickEvent event) { } } - protected abstract void itemClick(QuestObjectClickEvent event); + protected abstract void itemClick(@NotNull QuestObjectClickEvent event); @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder .addDescription(Lang.requirementReason.format(customReason == null ? Lang.NotSet.toString() : customReason)); @@ -116,24 +119,24 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { } @Override - public abstract AbstractRequirement clone(); + public abstract @NotNull AbstractRequirement clone(); @Override - public void save(ConfigurationSection section) { + public void save(@NotNull ConfigurationSection section) { super.save(section); if (customReason != null) section.set(CUSTOM_REASON_KEY, customReason); } @Override - public void load(ConfigurationSection section) { + public void load(@NotNull ConfigurationSection section) { super.load(section); if (section.contains(CUSTOM_REASON_KEY)) customReason = section.getString(CUSTOM_REASON_KEY); } - public static AbstractRequirement deserialize(Map<String, Object> map) { - return QuestObject.deserialize(map, QuestsAPI.getRequirements()); + public static @NotNull AbstractRequirement deserialize(Map<String, Object> map) { + return SerializableObject.deserialize(map, QuestsAPI.getRequirements()); } } diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java b/core/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java index c12af8a3..981fb495 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java +++ b/core/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java @@ -1,9 +1,10 @@ package fr.skytasul.quests.api.requirements; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; public interface Actionnable { - public void trigger(Player p); + public void trigger(@NotNull Player p); } diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java b/core/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java index 7963f1a5..6470bae2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java +++ b/core/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java @@ -1,19 +1,21 @@ package fr.skytasul.quests.api.requirements; import java.util.function.Supplier; - import org.bukkit.inventory.ItemStack; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.objects.QuestObjectCreator; import fr.skytasul.quests.api.objects.QuestObjectLocation; public class RequirementCreator extends QuestObjectCreator<AbstractRequirement> { - public RequirementCreator(String id, Class<? extends AbstractRequirement> clazz, ItemStack is, Supplier<AbstractRequirement> newObjectSupplier) { + public RequirementCreator(@NotNull String id, @NotNull Class<? extends AbstractRequirement> clazz, @NotNull ItemStack is, + @NotNull Supplier<@NotNull AbstractRequirement> newObjectSupplier) { super(id, clazz, is, newObjectSupplier); } - public RequirementCreator(String id, Class<? extends AbstractRequirement> clazz, ItemStack is, Supplier<AbstractRequirement> newObjectSupplier, boolean multiple, QuestObjectLocation... allowedLocations) { + public RequirementCreator(@NotNull String id, @NotNull Class<? extends AbstractRequirement> clazz, @NotNull ItemStack is, + @NotNull Supplier<@NotNull AbstractRequirement> newObjectSupplier, boolean multiple, + @NotNull QuestObjectLocation @NotNull... allowedLocations) { super(id, clazz, is, newObjectSupplier, multiple, allowedLocations); } diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java b/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java index 00b3f1a9..e543de27 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java @@ -1,8 +1,11 @@ package fr.skytasul.quests.api.requirements; import java.text.NumberFormat; +import java.util.Objects; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; @@ -16,67 +19,67 @@ public abstract class TargetNumberRequirement extends AbstractRequirement { protected ComparisonMethod comparison; protected double target; - protected TargetNumberRequirement(String customDescription, String customReason, double target, - ComparisonMethod comparison) { + protected TargetNumberRequirement(@Nullable String customDescription, @Nullable String customReason, double target, + @NotNull ComparisonMethod comparison) { super(customDescription, customReason); this.target = target; - this.comparison = comparison; + this.comparison = Objects.requireNonNull(comparison); } public double getTarget(){ return target; } - public ComparisonMethod getComparisonMethod() { + public @NotNull ComparisonMethod getComparisonMethod() { return comparison; } @Override - public boolean test(Player p) { + public boolean test(@NotNull Player p) { double diff = getPlayerTarget(p) - target; return comparison.test(diff); } - public String getShortFormattedValue() { + public @NotNull String getShortFormattedValue() { return comparison.getSymbol() + " " + getNumberFormat().format(target); } - public String getFormattedValue() { + public @NotNull String getFormattedValue() { return comparison.getTitle().format(getNumberFormat().format(target)); } - protected NumberFormat getNumberFormat() { + protected @NotNull NumberFormat getNumberFormat() { return numberClass() == Integer.class ? NumberFormat.getIntegerInstance() : NumberFormat.getInstance(); } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(getFormattedValue())); } - public abstract double getPlayerTarget(Player p); + public abstract double getPlayerTarget(@NotNull Player p); - public abstract Class<? extends Number> numberClass(); + public abstract @NotNull Class<? extends Number> numberClass(); - public abstract void sendHelpString(Player p); + public abstract void sendHelpString(@NotNull Player p); @Override - public void save(ConfigurationSection section) { + public void save(@NotNull ConfigurationSection section) { super.save(section); section.set("comparison", comparison.name()); section.set("target", target); } @Override - public void load(ConfigurationSection section) { + public void load(@NotNull ConfigurationSection section) { super.load(section); if (section.contains("comparison")) comparison = ComparisonMethod.valueOf(section.getString("comparison")); target = section.getDouble("target"); } @Override - public void itemClick(QuestObjectClickEvent event) { + public void itemClick(@NotNull QuestObjectClickEvent event) { sendHelpString(event.getPlayer()); new TextEditor<>(event.getPlayer(), () -> { if (target == 0) event.getGUI().remove(this); diff --git a/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java b/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java index 451078d2..49090b04 100644 --- a/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java +++ b/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java @@ -3,9 +3,12 @@ import java.util.List; import java.util.Map; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.utils.Lang; public abstract class AbstractReward extends QuestObject { @@ -14,12 +17,12 @@ protected AbstractReward() { this(null); } - protected AbstractReward(String customDescription) { + protected AbstractReward(@Nullable String customDescription) { super(QuestsAPI.getRewards(), customDescription); } @Override - public RewardCreator getCreator() { + public @NotNull RewardCreator getCreator() { return (RewardCreator) super.getCreator(); } @@ -28,25 +31,25 @@ public RewardCreator getCreator() { * @param p Player to give the reward * @return title of all the subsequent reward (for instance : "4 gold") */ - public abstract List<String> give(Player p) throws InterruptingBranchException; + public abstract @Nullable List<@NotNull String> give(Player p) throws InterruptingBranchException; @Override - protected void sendCustomDescriptionHelpMessage(Player p) { + protected void sendCustomDescriptionHelpMessage(@NotNull Player p) { Lang.CHOOSE_REWARD_CUSTOM_DESCRIPTION.send(p); } @Override - protected final void clickInternal(QuestObjectClickEvent event) { + protected final void clickInternal(@NotNull QuestObjectClickEvent event) { itemClick(event); } - protected abstract void itemClick(QuestObjectClickEvent event); + protected abstract void itemClick(@NotNull QuestObjectClickEvent event); @Override - public abstract AbstractReward clone(); + public abstract @NotNull AbstractReward clone(); - public static AbstractReward deserialize(Map<String, Object> map) { - return QuestObject.deserialize(map, QuestsAPI.getRewards()); + public static @NotNull AbstractReward deserialize(Map<String, Object> map) { + return SerializableObject.deserialize(map, QuestsAPI.getRewards()); } public boolean isAsync() { diff --git a/core/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java b/core/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java index b4ac4de0..e8fb496e 100644 --- a/core/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java +++ b/core/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java @@ -1,9 +1,8 @@ package fr.skytasul.quests.api.rewards; import java.util.function.Supplier; - import org.bukkit.inventory.ItemStack; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.objects.QuestObjectCreator; import fr.skytasul.quests.api.objects.QuestObjectLocation; @@ -11,11 +10,14 @@ public class RewardCreator extends QuestObjectCreator<AbstractReward> { private boolean async = false; - public RewardCreator(String id, Class<? extends AbstractReward> clazz, ItemStack is, Supplier<AbstractReward> newObjectSupplier) { + public RewardCreator(@NotNull String id, @NotNull Class<? extends AbstractReward> clazz, @NotNull ItemStack is, + @NotNull Supplier<AbstractReward> newObjectSupplier) { super(id, clazz, is, newObjectSupplier); } - public RewardCreator(String id, Class<? extends AbstractReward> clazz, ItemStack is, Supplier<AbstractReward> newObjectSupplier, boolean multiple, QuestObjectLocation... allowedLocations) { + public RewardCreator(@NotNull String id, @NotNull Class<? extends AbstractReward> clazz, @NotNull ItemStack is, + @NotNull Supplier<AbstractReward> newObjectSupplier, boolean multiple, + @NotNull QuestObjectLocation @NotNull... allowedLocations) { super(id, clazz, is, newObjectSupplier, multiple, allowedLocations); } @@ -23,7 +25,7 @@ public boolean canBeAsync() { return async; } - public RewardCreator setCanBeAsync(boolean async) { + public @NotNull RewardCreator setCanBeAsync(boolean async) { this.async = async; return this; } diff --git a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java b/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java index 611a3f5b..54a18ce2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java +++ b/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java @@ -1,35 +1,38 @@ package fr.skytasul.quests.api.serializable; import java.util.function.Supplier; +import org.jetbrains.annotations.NotNull; public class SerializableCreator<T extends SerializableObject> { - - private final String id; - private final Class<? extends T> clazz; - private final Supplier<T> newObjectSupplier; + + private final @NotNull String id; + private final @NotNull Class<? extends T> clazz; + private final @NotNull Supplier<@NotNull T> newObjectSupplier; /** * Creates a new creator for the serializable object of type <code><T></code> + * * @param id unique string id for the serializable object type * @param clazz class of the serializable object type * @param newObjectSupplier function used to instanciate a serializable object */ - public SerializableCreator(String id, Class<? extends T> clazz, Supplier<T> newObjectSupplier) { + public SerializableCreator(@NotNull String id, @NotNull Class<? extends T> clazz, + Supplier<@NotNull T> newObjectSupplier) { this.id = id; this.clazz = clazz; this.newObjectSupplier = newObjectSupplier; } - - public String getID() { + + public @NotNull String getID() { return id; } - - public Class<? extends T> getSerializableClass() { + + public @NotNull Class<? extends T> getSerializableClass() { return clazz; } - - public T newObject() { + + public @NotNull T newObject() { return newObjectSupplier.get(); } - -} \ No newline at end of file + +} diff --git a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java b/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java index 6ebcc93c..4ca78d42 100644 --- a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java +++ b/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java @@ -5,52 +5,53 @@ import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemoryConfiguration; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.Utils; public abstract class SerializableObject { - protected final SerializableCreator creator; + protected final @NotNull SerializableCreator creator; - protected SerializableObject(SerializableRegistry registry) { + protected SerializableObject(@NotNull SerializableRegistry registry) { this.creator = registry.getByClass(getClass()); if (creator == null) throw new IllegalArgumentException(getClass().getName() + " has not been registered as an object."); } - protected SerializableObject(SerializableCreator creator) { + protected SerializableObject(@NotNull SerializableCreator creator) { this.creator = creator; if (creator == null) throw new IllegalArgumentException("Creator cannot be null."); } - public SerializableCreator getCreator() { + public @NotNull SerializableCreator getCreator() { return creator; } - public String getName() { - return getCreator().getID(); + public @NotNull String getName() { + return creator.getID(); } @Override - public abstract SerializableObject clone(); + public abstract @NotNull SerializableObject clone(); - public abstract void save(ConfigurationSection section); + public abstract void save(@NotNull ConfigurationSection section); - public abstract void load(ConfigurationSection section); + public abstract void load(@NotNull ConfigurationSection section); - public final void serialize(ConfigurationSection section) { + public final void serialize(@NotNull ConfigurationSection section) { section.set("id", creator.getID()); save(section); } - public static <T extends SerializableObject, C extends SerializableCreator<T>> T deserialize(Map<String, Object> map, SerializableRegistry<T, C> registry) { + public static <T extends SerializableObject, C extends SerializableCreator<T>> T deserialize( + @NotNull Map<String, Object> map, @NotNull SerializableRegistry<T, C> registry) { return deserialize(Utils.createConfigurationSection(map), registry); } - public static <T extends SerializableObject, C extends SerializableCreator<T>> T deserialize(ConfigurationSection section, SerializableRegistry<T, C> registry) { + public static <T extends SerializableObject, C extends SerializableCreator<T>> @NotNull T deserialize( + @NotNull ConfigurationSection section, @NotNull SerializableRegistry<T, C> registry) { SerializableCreator<T> creator = null; String id = section.getString("id"); @@ -76,7 +77,8 @@ public static <T extends SerializableObject, C extends SerializableCreator<T>> T return reward; } - public static <T extends SerializableObject> List<T> deserializeList(List<Map<?, ?>> objectList, Function<Map<String, Object>, T> deserializeFunction) { + public static <T extends SerializableObject> @NotNull List<T> deserializeList(@NotNull List<Map<?, ?>> objectList, + @NotNull Function<Map<String, Object>, T> deserializeFunction) { List<T> objects = new ArrayList<>(objectList.size()); for (Map<?, ?> objectMap : objectList) { try { @@ -93,7 +95,7 @@ public static <T extends SerializableObject> List<T> deserializeList(List<Map<?, return objects; } - public static List<Map<String, Object>> serializeList(List<? extends SerializableObject> objects) { + public static @NotNull List<Map<String, Object>> serializeList(@NotNull List<? extends SerializableObject> objects) { return objects.stream().map(object -> { MemoryConfiguration section = new MemoryConfiguration(); object.serialize(section); diff --git a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java b/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java index 058eb347..82f73f17 100644 --- a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java +++ b/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java @@ -3,7 +3,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.utils.DebugUtils; /** @@ -18,11 +19,11 @@ public class SerializableRegistry<T extends SerializableObject, C extends Serial protected final String id; protected final List<C> creators = new ArrayList<>(); - public SerializableRegistry(String id) { + public SerializableRegistry(@NotNull String id) { this.id = id; } - public String getID() { + public @NotNull String getID() { return id; } @@ -30,14 +31,14 @@ public String getID() { * Registers a new type of serializable object. * @param creator object that will be used to instanciate objects of type <code><T></code> */ - public void register(C creator) { + public void register(@NotNull C creator) { if (creators.stream().anyMatch(x -> x.getID().equals(creator.getID()))) throw new IllegalStateException("A creator with the same id " + creator.getID() + " has been registered."); creators.add(creator); DebugUtils.logMessage("Quest object registered in registry " + id + " (id: " + creator.getID() + ", class: " + creator.getSerializableClass().getName() + ")"); } - public C getByClass(Class<?> clazz) { + public @Nullable C getByClass(@NotNull Class<?> clazz) { return creators .stream() .filter(creator -> creator.getSerializableClass().equals(clazz)) @@ -45,7 +46,7 @@ public C getByClass(Class<?> clazz) { .orElse(null); } - public C getByID(String id) { + public @Nullable C getByID(@NotNull String id) { return creators .stream() .filter(creator -> creator.getID().equals(id)) @@ -53,7 +54,7 @@ public C getByID(String id) { .orElse(null); } - public List<C> getCreators() { + public @NotNull List<C> getCreators() { return creators; } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 4ca18ad6..8abe45d2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -15,6 +15,8 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; @@ -34,69 +36,69 @@ public abstract class AbstractStage implements Listener { - private final StageType<?> type; - protected boolean asyncEnd = false; + private final @NotNull StageType<?> type; - protected final QuestBranch branch; + protected final @NotNull QuestBranch branch; - private String startMessage = null; - private String customText = null; - private List<AbstractReward> rewards = new ArrayList<>(); - private List<AbstractRequirement> validationRequirements = new ArrayList<>(); + private @Nullable String startMessage = null; + private @Nullable String customText = null; + private @NotNull List<@NotNull AbstractReward> rewards = new ArrayList<>(); + private @NotNull List<@NotNull AbstractRequirement> validationRequirements = new ArrayList<>(); - private List<StageOption> options; + private @NotNull List<@NotNull StageOption> options; + protected boolean asyncEnd = false; - protected AbstractStage(QuestBranch branch) { + protected AbstractStage(@NotNull QuestBranch branch) { this.branch = branch; this.type = QuestsAPI.getStages().getType(getClass()).orElseThrow(() -> new IllegalArgumentException(getClass().getName() + "has not been registered as a stage type via the API.")); Bukkit.getPluginManager().registerEvents(this, BeautyQuests.getInstance()); } - public QuestBranch getQuestBranch(){ + public @NotNull QuestBranch getQuestBranch() { return branch; } - public void setStartMessage(String text){ + public void setStartMessage(@Nullable String text) { this.startMessage = text; } - public String getStartMessage(){ + public @Nullable String getStartMessage() { return startMessage; } - public List<AbstractReward> getRewards(){ + public @NotNull List<@NotNull AbstractReward> getRewards() { return rewards; } - public void setRewards(List<AbstractReward> rewards){ + public void setRewards(@NotNull List<@NotNull AbstractReward> rewards) { this.rewards = rewards; rewards.forEach(reward -> reward.attach(branch.getQuest())); checkAsync(); } - public List<AbstractRequirement> getValidationRequirements() { + public @NotNull List<@NotNull AbstractRequirement> getValidationRequirements() { return validationRequirements; } - public void setValidationRequirements(List<AbstractRequirement> validationRequirements) { + public void setValidationRequirements(@NotNull List<@NotNull AbstractRequirement> validationRequirements) { this.validationRequirements = validationRequirements; validationRequirements.forEach(requirement -> requirement.attach(branch.getQuest())); } - public List<StageOption> getOptions() { + public @NotNull List<@NotNull StageOption> getOptions() { return options; } - public void setOptions(List<StageOption> options) { + public void setOptions(@NotNull List<@NotNull StageOption> options) { this.options = options; } - public String getCustomText(){ + public @Nullable String getCustomText() { return customText; } - public void setCustomText(String message) { + public void setCustomText(@Nullable String message) { this.customText = message; } @@ -104,7 +106,7 @@ public boolean sendStartMessage(){ return startMessage == null && QuestsConfiguration.sendStageStartMessage(); } - public StageType<?> getType() { + public @NotNull StageType<?> getType() { return type; } @@ -137,11 +139,11 @@ public int getStoredID(){ return index; } - protected boolean canUpdate(Player p) { + protected boolean canUpdate(@NotNull Player p) { return canUpdate(p, false); } - protected boolean canUpdate(Player p, boolean msg) { + protected boolean canUpdate(@NotNull Player p, boolean msg) { return Utils.testRequirements(p, validationRequirements, msg); } @@ -150,7 +152,7 @@ public String toString() { return "stage " + getID() + "(" + type.getID() + ") of quest " + branch.getQuest().getID() + ", branch " + branch.getID(); } - private void propagateStageHandlers(Consumer<StageHandler> consumer) { + private void propagateStageHandlers(@NotNull Consumer<@NotNull StageHandler> consumer) { Consumer<StageHandler> newConsumer = handler -> { try { consumer.accept(handler); @@ -166,7 +168,7 @@ private void propagateStageHandlers(Consumer<StageHandler> consumer) { * Called internally when a player finish stage's objectives * @param p Player who finish the stage */ - protected final void finishStage(Player p) { + protected final void finishStage(@NotNull Player p) { Utils.runSync(() -> branch.finishStage(p, this)); } @@ -175,7 +177,7 @@ protected final void finishStage(Player p) { * @param p Player to test * @see QuestBranch#hasStageLaunched(PlayerAccount, AbstractStage) */ - protected final boolean hasStarted(Player p){ + protected final boolean hasStarted(@NotNull Player p) { return branch.hasStageLaunched(PlayersManager.getPlayerAccount(p), this); } @@ -183,7 +185,7 @@ protected final boolean hasStarted(Player p){ * Called when the stage starts (player can be offline) * @param acc PlayerAccount for which the stage starts */ - public void start(PlayerAccount acc) { + public void start(@NotNull PlayerAccount acc) { if (acc.isCurrent()) Utils.sendOffMessage(acc.getPlayer(), startMessage); Map<String, Object> datas = new HashMap<>(); initPlayerDatas(acc, datas); @@ -191,13 +193,13 @@ public void start(PlayerAccount acc) { propagateStageHandlers(handler -> handler.stageStart(acc, this)); } - protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) {} + protected void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) {} /** * Called when the stage ends (player can be offline) * @param acc PlayerAccount for which the stage ends */ - public void end(PlayerAccount acc) { + public void end(@NotNull PlayerAccount acc) { acc.getQuestDatas(branch.getQuest()).setStageDatas(getStoredID(), null); propagateStageHandlers(handler -> handler.stageEnd(acc, this)); } @@ -206,7 +208,7 @@ public void end(PlayerAccount acc) { * Called when an account with this stage launched joins * @param acc PlayerAccount which just joined */ - public void joins(PlayerAccount acc, Player p) { + public void joins(@NotNull PlayerAccount acc, @NotNull Player p) { propagateStageHandlers(handler -> handler.stageJoin(acc, p, this)); } @@ -214,11 +216,11 @@ public void joins(PlayerAccount acc, Player p) { * Called when an account with this stage launched leaves * @param acc PlayerAccount which just left */ - public void leaves(PlayerAccount acc, Player p) { + public void leaves(@NotNull PlayerAccount acc, @NotNull Player p) { propagateStageHandlers(handler -> handler.stageLeave(acc, p, this)); } - public final String getDescriptionLine(PlayerAccount acc, Source source){ + public final @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { if (customText != null) return "§e" + Utils.format(customText, descriptionFormat(acc, source)); try{ return descriptionLine(acc, source); @@ -233,7 +235,7 @@ public final String getDescriptionLine(PlayerAccount acc, Source source){ * @param source source of the description request * @return the progress of the stage for the player */ - protected abstract String descriptionLine(PlayerAccount acc, Source source); + protected abstract @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull Source source); /** * Will be called only if there is a {@link #customText} @@ -241,9 +243,12 @@ public final String getDescriptionLine(PlayerAccount acc, Source source){ * @param source source of the description request * @return all strings that can be used to format the custom description text */ - protected Object[] descriptionFormat(PlayerAccount acc, Source source) {return null;} + protected @Nullable Object @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull Source source) { + return null; + } - public void updateObjective(PlayerAccount acc, Player p, String dataKey, Object dataValue) { + public void updateObjective(@NotNull PlayerAccount acc, @NotNull Player p, @NotNull String dataKey, + @Nullable Object dataValue) { Map<String, Object> datas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStoredID()); Validate.notNull(datas, "Account " + acc.debugName() + " does not have datas for " + toString()); datas.put(dataKey, dataValue); @@ -251,7 +256,7 @@ public void updateObjective(PlayerAccount acc, Player p, String dataKey, Object branch.getBranchesManager().objectiveUpdated(p, acc); } - protected <T> T getData(PlayerAccount acc, String dataKey) { + protected <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { Map<String, Object> stageDatas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStoredID()); return stageDatas == null ? null : (T) stageDatas.get(dataKey); } @@ -294,13 +299,13 @@ public void onLeave(PlayerAccountLeaveEvent e) { @Deprecated protected void serialize(Map<String, Object> map) {} - protected void serialize(ConfigurationSection section) { + protected void serialize(@NotNull ConfigurationSection section) { Map<String, Object> map = new HashMap<>(); serialize(map); Utils.setConfigurationSectionContent(section, map); } - public final void save(ConfigurationSection section) { + public final void save(@NotNull ConfigurationSection section) { serialize(section); section.set("stageType", type.getID()); @@ -313,7 +318,7 @@ public final void save(ConfigurationSection section) { options.stream().filter(StageOption::shouldSave).forEach(option -> option.save(section.createSection("options." + option.getCreator().getID()))); } - public static AbstractStage deserialize(ConfigurationSection section, QuestBranch branch) { + public static @NotNull AbstractStage deserialize(@NotNull ConfigurationSection section, @NotNull QuestBranch branch) { String typeID = section.getString("stageType"); Optional<StageType<?>> stageTypeOptional = QuestsAPI.getStages().getType(typeID); diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java b/core/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java index 45eaba72..dd5823d5 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java @@ -3,9 +3,8 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; - import org.bukkit.entity.Player; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOption; @@ -35,7 +34,7 @@ public abstract class StageCreation<T extends AbstractStage> { private StagesGUI leadingBranch; - public StageCreation(Line line, boolean ending) { + protected StageCreation(Line line, boolean ending) { this.line = line; this.ending = ending; @@ -139,7 +138,7 @@ public void setLeadingBranch(StagesGUI leadingBranch) { this.leadingBranch = leadingBranch; } - public final void setup(StageType<T> type) { + public final void setup(@NotNull StageType<T> type) { this.type = type; } @@ -147,7 +146,7 @@ public final void setup(StageType<T> type) { * Called when stage item clicked * @param p player who click on the item */ - public void start(Player p) { + public void start(@NotNull Player p) { setRewards(new ArrayList<>()); setRequirements(new ArrayList<>()); setCustomDescription(null); @@ -161,7 +160,7 @@ public void start(Player p) { * Called when quest edition started * @param stage Existing stage */ - public void edit(T stage) { + public void edit(@NotNull T stage) { setRewards(stage.getRewards()); setRequirements(stage.getValidationRequirements()); setStartMessage(stage.getStartMessage()); @@ -171,7 +170,7 @@ public void edit(T stage) { options.forEach(option -> option.startEdition(this)); } - public final T finish(QuestBranch branch) { + public final @NotNull T finish(@NotNull QuestBranch branch) { T stage = finishStage(branch); stage.setRewards(rewards); stage.setValidationRequirements(requirements); @@ -186,6 +185,6 @@ public final T finish(QuestBranch branch) { * @param branch quest created * @return AsbtractStage created */ - protected abstract T finishStage(QuestBranch branch); + protected abstract @NotNull T finishStage(@NotNull QuestBranch branch); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageType.java b/core/src/main/java/fr/skytasul/quests/api/stages/StageType.java index d3c07897..3c854a91 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageType.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/StageType.java @@ -1,11 +1,10 @@ package fr.skytasul.quests.api.stages; import java.util.Map; - import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.serializable.SerializableRegistry; @@ -15,16 +14,16 @@ public class StageType<T extends AbstractStage> { - private final String id; - private final Class<T> clazz; - private final String name; - private final StageLoader<T> loader; - private final ItemStack item; - private final StageCreationSupplier<T> creationSupplier; + private final @NotNull String id; + private final @NotNull Class<T> clazz; + private final @NotNull String name; + private final @NotNull StageLoader<T> loader; + private final @NotNull ItemStack item; + private final @NotNull StageCreationSupplier<T> creationSupplier; @Deprecated - public final String[] dependencies; + public final String[] dependencies; // TODO remove - private final SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> optionsRegistry; + private final @NotNull SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> optionsRegistry; /** * Creates a stage type. @@ -36,7 +35,8 @@ public class StageType<T extends AbstractStage> { * @param item item representing this stage in the Stages GUI * @param creationSupplier function creating a stage creation context */ - public StageType(String id, Class<T> clazz, String name, StageLoader<T> loader, ItemStack item, StageCreationSupplier<T> creationSupplier) { + public StageType(@NotNull String id, @NotNull Class<T> clazz, @NotNull String name, @NotNull StageLoader<T> loader, + @NotNull ItemStack item, @NotNull StageCreationSupplier<T> creationSupplier) { this(id, clazz, name, loader, item, creationSupplier, new String[0]); } @@ -60,31 +60,31 @@ public StageType(String id, Class<T> clazz, String name, StageLoader<T> loader, if (dependencies.length != 0) BeautyQuests.logger.warning("Nag author of the " + id + " stage type about its use of the deprecated \"dependencies\" feature."); } - public String getID() { + public @NotNull String getID() { return id; } - public Class<T> getStageClass() { + public @NotNull Class<T> getStageClass() { return clazz; } - public String getName() { + public @NotNull String getName() { return name; } - public StageLoader<T> getLoader() { + public @NotNull StageLoader<T> getLoader() { return loader; } - public ItemStack getItem() { + public @NotNull ItemStack getItem() { return item; } - public StageCreationSupplier<T> getCreationSupplier() { + public @NotNull StageCreationSupplier<T> getCreationSupplier() { return creationSupplier; } - public SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> getOptionsRegistry() { + public @NotNull SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> getOptionsRegistry() { return optionsRegistry; } @@ -99,7 +99,8 @@ public boolean isValid() { @FunctionalInterface public static interface StageCreationSupplier<T extends AbstractStage> { - StageCreation<T> supply(Line line, boolean endingStage); + @NotNull + StageCreation<T> supply(@NotNull Line line, boolean endingStage); } @@ -123,7 +124,8 @@ default T supply(ConfigurationSection section, QuestBranch branch) { @FunctionalInterface public static interface StageLoader<T extends AbstractStage> { - T supply(ConfigurationSection section, QuestBranch branch); + @NotNull + T supply(@NotNull ConfigurationSection section, @NotNull QuestBranch branch); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java b/core/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java index 4143f385..349d2d38 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java @@ -4,30 +4,29 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; - import org.apache.commons.lang.Validate; - +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.utils.DebugUtils; public class StageTypeRegistry implements Iterable<StageType<?>> { - private List<StageType<?>> types = new LinkedList<>(); + private @NotNull List<@NotNull StageType<?>> types = new LinkedList<>(); /** * Registers new stage type into the plugin. * @param type StageType instance */ - public void register(StageType<? extends AbstractStage> type) { + public void register(@NotNull StageType<? extends AbstractStage> type) { Validate.notNull(type); types.add(type); DebugUtils.logMessage("Stage registered (" + type.getName() + ", " + (types.size() - 1) + ")"); } - public List<StageType<?>> getTypes() { + public @NotNull List<@NotNull StageType<?>> getTypes() { return types; } - public <T extends AbstractStage> Optional<StageType<T>> getType(Class<T> stageClass) { + public <T extends AbstractStage> @NotNull Optional<StageType<T>> getType(@NotNull Class<T> stageClass) { return types .stream() .filter(type -> type.getStageClass() == stageClass) @@ -35,7 +34,7 @@ public <T extends AbstractStage> Optional<StageType<T>> getType(Class<T> stageCl .findAny(); } - public Optional<StageType<?>> getType(String id) { + public @NotNull Optional<StageType<?>> getType(@NotNull String id) { return types .stream() .filter(type -> type.getID().equals(id)) diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java b/core/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java index c132cd48..b488d149 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.api.stages.options; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.api.stages.AbstractStage; @@ -8,9 +9,9 @@ public abstract class StageOption<T extends AbstractStage> extends SerializableObject implements StageHandler { - private final Class<T> stageClass; + private final @NotNull Class<T> stageClass; - protected StageOption(Class<T> stageClass) { + protected StageOption(@NotNull Class<T> stageClass) { super(QuestsAPI.getStages() .getType(stageClass) .orElseThrow(() -> new IllegalArgumentException(stageClass.getName() + "has not been registered as a stage type via the API.")) @@ -18,14 +19,14 @@ protected StageOption(Class<T> stageClass) { this.stageClass = stageClass; } - public Class<T> getStageClass() { + public @NotNull Class<T> getStageClass() { return stageClass; } @Override - public abstract StageOption<T> clone(); + public abstract @NotNull StageOption<T> clone(); - public abstract void startEdition(StageCreation<T> creation); + public abstract void startEdition(@NotNull StageCreation<T> creation); public abstract boolean shouldSave(); diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java index cb623b2a..541b1f9b 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java @@ -6,6 +6,7 @@ import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.blocks.BlocksGUI; @@ -18,28 +19,29 @@ public abstract class AbstractCountableBlockStage extends AbstractCountableStage<BQBlock> { - protected AbstractCountableBlockStage(QuestBranch branch, List<CountableObject<BQBlock>> objects) { + protected AbstractCountableBlockStage(@NotNull QuestBranch branch, + @NotNull List<@NotNull CountableObject<BQBlock>> objects) { super(branch, objects); } @Override - protected boolean objectApplies(BQBlock object, Object other) { + protected boolean objectApplies(@NotNull BQBlock object, Object other) { if (other instanceof Block) return object.applies((Block) other); return super.objectApplies(object, other); } @Override - protected String getName(BQBlock object) { + protected @NotNull String getName(@NotNull BQBlock object) { return object.getName(); } @Override - protected Object serialize(BQBlock object) { + protected @NotNull Object serialize(@NotNull BQBlock object) { return object.getAsString(); } @Override - protected BQBlock deserialize(Object object) { + protected @NotNull BQBlock deserialize(@NotNull Object object) { return BQBlock.fromString((String) object); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index cd451ae3..695f0918 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -15,6 +15,9 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; @@ -30,13 +33,13 @@ public abstract class AbstractCountableStage<T> extends AbstractStage { - protected final List<CountableObject<T>> objects; + protected final @NotNull List<@NotNull CountableObject<T>> objects; - protected Map<Player, BossBar> bars = new HashMap<>(); + protected @NotNull Map<Player, BossBar> bars = new HashMap<>(); private boolean barsEnabled = false; private int cachedSize = 0; - protected AbstractCountableStage(QuestBranch branch, List<CountableObject<T>> objects) { + protected AbstractCountableStage(@NotNull QuestBranch branch, @NotNull List<@NotNull CountableObject<T>> objects) { super(branch); this.objects = objects; calculateSize(); @@ -53,16 +56,16 @@ protected AbstractCountableStage(QuestBranch branch, Map<Integer, Entry<T, Integ + " uses an outdated way to store player datas. Please notice its author."); } - public List<CountableObject<T>> getObjects() { + public @NotNull List<@NotNull CountableObject<T>> getObjects() { return objects; } - public List<MutableCountableObject<T>> getMutableObjects() { + public @NotNull List<@NotNull MutableCountableObject<T>> getMutableObjects() { return objects.stream().map(countable -> CountableObject.createMutable(countable.getUUID(), cloneObject(countable.getObject()), countable.getAmount())).collect(Collectors.toList()); } - public Optional<CountableObject<T>> getObject(UUID uuid) { + public @NotNull Optional<CountableObject<T>> getObject(@NotNull UUID uuid) { return objects.stream().filter(object -> object.getUUID().equals(uuid)).findAny(); } @@ -77,7 +80,7 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { } @SuppressWarnings("rawtypes") - public Map<UUID, Integer> getPlayerRemainings(PlayerAccount acc, boolean warnNull) { + public @NotNull Map<@NotNull UUID, @NotNull Integer> getPlayerRemainings(@NotNull PlayerAccount acc, boolean warnNull) { Map<?, Integer> remaining = getData(acc, "remaining"); if (warnNull && remaining == null) BeautyQuests.logger.severe("Cannot retrieve stage datas for " + acc.getNameAndID() + " on " + super.toString()); @@ -109,7 +112,8 @@ public Map<UUID, Integer> getPlayerRemainings(PlayerAccount acc, boolean warnNul throw new UnsupportedOperationException(object.getClass().getName()); } - protected void updatePlayerRemaining(PlayerAccount acc, Player player, Map<UUID, Integer> remaining) { + protected void updatePlayerRemaining(@NotNull PlayerAccount acc, @NotNull Player player, + @NotNull Map<@NotNull UUID, @NotNull Integer> remaining) { updateObjective(acc, player, "remaining", remaining.entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toString(), Entry::getValue))); } @@ -120,16 +124,16 @@ protected void calculateSize() { } @Override - protected String descriptionLine(PlayerAccount acc, Source source){ + protected @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { return Utils.descriptionLines(source, buildRemainingArray(acc, source)); } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, Source source) { + protected @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull Source source) { return new Supplier[] { () -> Utils.descriptionLines(source, buildRemainingArray(acc, source)) }; } - private String[] buildRemainingArray(PlayerAccount acc, Source source) { + private @NotNull String @NotNull [] buildRemainingArray(@NotNull PlayerAccount acc, @NotNull Source source) { Map<UUID, Integer> playerAmounts = getPlayerRemainings(acc, true); if (playerAmounts == null) return new String[] { "§4§lerror" }; String[] elements = new String[playerAmounts.size()]; @@ -146,7 +150,7 @@ private String[] buildRemainingArray(PlayerAccount acc, Source source) { } @Override - protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { + protected void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { super.initPlayerDatas(acc, datas); datas.put("remaining", objects.stream() .collect(Collectors.toMap(object -> object.getUUID().toString(), CountableObject::getAmount))); @@ -162,7 +166,7 @@ protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { * @param amount amount completed * @return <code>true</code> if there is no need to call this method again in the same game tick. */ - public boolean event(PlayerAccount acc, Player p, Object object, int amount) { + public boolean event(@NotNull PlayerAccount acc, @NotNull Player p, @UnknownNullability Object object, int amount) { if (amount < 0) throw new IllegalArgumentException("Event amount must be positive (" + amount + ")"); if (!canUpdate(p)) return true; @@ -200,13 +204,13 @@ public boolean event(PlayerAccount acc, Player p, Object object, int amount) { } @Override - public void start(PlayerAccount acc) { + public void start(@NotNull PlayerAccount acc) { super.start(acc); if (acc.isCurrent()) createBar(acc.getPlayer(), cachedSize); } @Override - public void end(PlayerAccount acc) { + public void end(@NotNull PlayerAccount acc) { super.end(acc); if (acc.isCurrent()) removeBar(acc.getPlayer()); } @@ -218,7 +222,7 @@ public void unload() { } @Override - public void joins(PlayerAccount acc, Player p) { + public void joins(@NotNull PlayerAccount acc, @NotNull Player p) { super.joins(acc, p); Map<UUID, Integer> remainings = getPlayerRemainings(acc, true); if (remainings == null) return; @@ -226,12 +230,12 @@ public void joins(PlayerAccount acc, Player p) { } @Override - public void leaves(PlayerAccount acc, Player p) { + public void leaves(@NotNull PlayerAccount acc, @NotNull Player p) { super.leaves(acc, p); removeBar(p); } - protected void createBar(Player p, int amount) { + protected void createBar(@NotNull Player p, int amount) { if (barsEnabled) { if (bars.containsKey(p)) { // NOSONAR Map#computeIfAbsent cannot be used here as we should log the issue BeautyQuests.logger.warning("Trying to create an already existing bossbar for player " + p.getName()); @@ -241,23 +245,23 @@ protected void createBar(Player p, int amount) { } } - protected void removeBar(Player p) { + protected void removeBar(@NotNull Player p) { if (bars.containsKey(p)) bars.remove(p).remove(); } - protected boolean objectApplies(T object, Object other) { + protected boolean objectApplies(@NotNull T object, @UnknownNullability Object other) { return object.equals(other); } - protected T cloneObject(T object) { + protected @NotNull T cloneObject(@NotNull T object) { return object; } - protected abstract String getName(T object); + protected abstract @NotNull String getName(@NotNull T object); - protected abstract Object serialize(T object); + protected abstract @NotNull Object serialize(@NotNull T object); - protected abstract T deserialize(Object object); + protected abstract @NotNull T deserialize(@NotNull Object object); /** * @deprecated for removal, {@link #serialize(ConfigurationSection)} should be used instead. @@ -267,7 +271,7 @@ protected T cloneObject(T object) { protected void serialize(Map<String, Object> map) {} @Override - protected void serialize(ConfigurationSection section) { + protected void serialize(@NotNull ConfigurationSection section) { ConfigurationSection objectsSection = section.createSection("objects"); for (CountableObject<T> obj : objects) { ConfigurationSection objectSection = objectsSection.createSection(obj.getUUID().toString()); @@ -288,7 +292,7 @@ protected void deserialize(Map<String, Object> serializedDatas) { deserialize(Utils.createConfigurationSection(serializedDatas)); } - protected void deserialize(ConfigurationSection section) { + protected void deserialize(@NotNull ConfigurationSection section) { ConfigurationSection objectsSection = section.getConfigurationSection("objects"); if (objectsSection != null) { for (String key : objectsSection.getKeys(false)) { diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index 2151eabf..849210f6 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -8,11 +8,11 @@ import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Supplier; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.stages.AbstractStage; @@ -36,16 +36,16 @@ @LocatableType (types = LocatedType.ENTITY) public abstract class AbstractEntityStage extends AbstractStage implements Locatable.MultipleLocatable { - protected EntityType entity; - protected int amount; + protected final @NotNull EntityType entity; + protected final int amount; - public AbstractEntityStage(QuestBranch branch, EntityType entity, int amount) { + protected AbstractEntityStage(@NotNull QuestBranch branch, @NotNull EntityType entity, int amount) { super(branch); this.entity = entity; this.amount = amount; } - protected void event(Player p, EntityType type) { + protected void event(@NotNull Player p, @NotNull EntityType type) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); if (branch.hasStageLaunched(acc, this) && canUpdate(p)) { if (entity == null || type.equals(entity)) { @@ -61,23 +61,23 @@ protected void event(Player p, EntityType type) { } } - protected Integer getPlayerAmount(PlayerAccount acc) { + protected @Nullable Integer getPlayerAmount(@NotNull PlayerAccount acc) { return getData(acc, "amount"); } @Override - protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { + protected void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { super.initPlayerDatas(acc, datas); datas.put("amount", amount); } @Override - protected void serialize(ConfigurationSection section) { + protected void serialize(@NotNull ConfigurationSection section) { section.set("entityType", entity == null ? "any" : entity.name()); section.set("amount", amount); } - protected String getMobsLeft(PlayerAccount acc) { + protected @NotNull String getMobsLeft(@NotNull PlayerAccount acc) { Integer playerAmount = getPlayerAmount(acc); if (playerAmount == null) return "§cerror: no datas"; @@ -85,7 +85,7 @@ protected String getMobsLeft(PlayerAccount acc) { } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, Source source) { + protected @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull Source source) { return new Supplier[] { () -> getMobsLeft(acc) }; } @@ -95,7 +95,7 @@ public boolean canBeFetchedAsynchronously() { } @Override - public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { + public @NotNull Spliterator<@NotNull Located> getNearbyLocated(@NotNull NearbyFetcher fetcher) { if (!fetcher.isTargeting(LocatedType.ENTITY)) return Spliterators.emptySpliterator(); return fetcher.getCenter().getWorld() .getEntitiesByClass(entity.getEntityClass()) @@ -163,7 +163,7 @@ protected boolean canBeAnyEntity() { return true; } - protected abstract boolean canUseEntity(EntityType type); + protected abstract boolean canUseEntity(@NotNull EntityType type); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java index 6f87844b..423c5154 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java @@ -9,6 +9,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.gui.ItemUtils; @@ -23,15 +24,15 @@ public abstract class AbstractItemStage extends AbstractCountableStage<ItemStack> { - protected final ItemComparisonMap comparisons; + protected final @NotNull ItemComparisonMap comparisons; - protected AbstractItemStage(QuestBranch branch, List<CountableObject<ItemStack>> objects, + protected AbstractItemStage(@NotNull QuestBranch branch, @NotNull List<@NotNull CountableObject<ItemStack>> objects, ItemComparisonMap comparisons) { super(branch, objects); this.comparisons = comparisons; } - protected AbstractItemStage(QuestBranch branch, ConfigurationSection section) { + protected AbstractItemStage(@NotNull QuestBranch branch, @NotNull ConfigurationSection section) { super(branch, new ArrayList<>()); if (section.contains("itemComparisons")) { @@ -42,32 +43,32 @@ protected AbstractItemStage(QuestBranch branch, ConfigurationSection section) { } @Override - protected ItemStack cloneObject(ItemStack object) { + protected @NotNull ItemStack cloneObject(@NotNull ItemStack object) { return object.clone(); } @Override - protected boolean objectApplies(ItemStack object, Object other) { + protected boolean objectApplies(@NotNull ItemStack object, @NotNull Object other) { return comparisons.isSimilar(object, (ItemStack) other); } @Override - protected String getName(ItemStack object) { + protected @NotNull String getName(@NotNull ItemStack object) { return ItemUtils.getName(object, true); } @Override - protected Object serialize(ItemStack object) { + protected @NotNull Object serialize(@NotNull ItemStack object) { return object.serialize(); } @Override - protected ItemStack deserialize(Object object) { + protected @NotNull ItemStack deserialize(@NotNull Object object) { return ItemStack.deserialize((Map<String, Object>) object); } @Override - protected void serialize(ConfigurationSection section) { + protected void serialize(@NotNull ConfigurationSection section) { super.serialize(section); if (!comparisons.getNotDefault().isEmpty()) section.createSection("itemComparisons", comparisons.getNotDefault()); } @@ -76,8 +77,8 @@ public abstract static class Creator<T extends AbstractItemStage> extends StageC private static final ItemStack stageComparison = ItemUtils.item(XMaterial.PRISMARINE_SHARD, Lang.stageItemsComparison.toString()); - private List<ItemStack> items; - private ItemComparisonMap comparisons = new ItemComparisonMap(); + private @NotNull List<ItemStack> items; + private @NotNull ItemComparisonMap comparisons = new ItemComparisonMap(); protected Creator(Line line, boolean ending) { super(line, ending); @@ -96,7 +97,7 @@ protected Creator(Line line, boolean ending) { }); } - protected abstract ItemStack getEditItem(); + protected abstract @NotNull ItemStack getEditItem(); public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); @@ -140,7 +141,8 @@ public final T finishStage(QuestBranch branch) { return finishStage(branch, itemsMap, comparisons); } - protected abstract T finishStage(QuestBranch branch, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons); + protected abstract T finishStage(@NotNull QuestBranch branch, + @NotNull List<@NotNull CountableObject<ItemStack>> items, @NotNull ItemComparisonMap comparisons); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java index 4e9bd201..f115ad2c 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java @@ -1,15 +1,19 @@ package fr.skytasul.quests.api.stages.types; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.utils.types.Dialog; import fr.skytasul.quests.utils.types.DialogRunner; public interface Dialogable { + @Nullable Dialog getDialog(); + @Nullable DialogRunner getDialogRunner(); + @Nullable BQNPC getNPC(); default boolean hasDialog() { diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java index b3d7a6c1..f6b100cc 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java @@ -12,7 +12,8 @@ import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; -import fr.skytasul.quests.api.stages.types.Locatable.MultipleLocatable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.utils.DebugUtils; /** @@ -36,7 +37,7 @@ public interface Locatable { * @return <code>true</code> if location indications should be displayed * to the player, <code>false</code> otherwise. */ - default boolean isShown(Player player) { + default boolean isShown(@NotNull Player player) { return true; } @@ -65,6 +66,7 @@ interface PreciseLocatable extends Locatable { * having something else changed in the game state would return the same value. * @return the located object */ + @NotNull Located getLocated(); } @@ -81,7 +83,8 @@ interface MultipleLocatable extends Locatable { * @param fetcher describes the region from where the targets must be found * @return a Spliterator which allows iterating through the targets */ - Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher); + @NotNull + Spliterator<@NotNull Located> getNearbyLocated(@NotNull NearbyFetcher fetcher); /** * This POJO contains informations on the region from where @@ -89,6 +92,7 @@ interface MultipleLocatable extends Locatable { */ interface NearbyFetcher { + @NotNull Location getCenter(); double getMaxDistance(); @@ -97,15 +101,16 @@ default double getMaxDistanceSquared() { return getMaxDistance() * getMaxDistance(); } - default boolean isTargeting(LocatedType type) { + default boolean isTargeting(@NotNull LocatedType type) { return true; } - static NearbyFetcher create(Location location, double maxDistance) { + static @NotNull NearbyFetcher create(@NotNull Location location, double maxDistance) { return new NearbyFetcherImpl(location, maxDistance, null); } - static NearbyFetcher create(Location location, double maxDistance, LocatedType targetType) { + static @NotNull NearbyFetcher create(@NotNull Location location, double maxDistance, + @Nullable LocatedType targetType) { return new NearbyFetcherImpl(location, maxDistance, targetType); } @@ -153,7 +158,8 @@ public boolean isTargeting(LocatedType type) { * @return an array of {@link LocatedType} that can be retrieved * from the class attached to this annotation. */ - LocatedType[] types() default { LocatedType.ENTITY, LocatedType.BLOCK, LocatedType.OTHER }; + @NotNull + LocatedType @NotNull [] types() default {LocatedType.ENTITY, LocatedType.BLOCK, LocatedType.OTHER}; } /** @@ -161,11 +167,13 @@ public boolean isTargeting(LocatedType type) { */ interface Located { + @NotNull Location getLocation(); + @NotNull LocatedType getType(); - static Located create(Location location) { + static @NotNull Located create(@NotNull Location location) { return new LocatedImpl(location); } @@ -202,20 +210,21 @@ public boolean equals(Object obj) { interface LocatedEntity extends Located { + @NotNull Entity getEntity(); @Override - default Location getLocation() { + default @NotNull Location getLocation() { Entity entity = getEntity(); return entity == null ? null : entity.getLocation(); } @Override - default LocatedType getType() { + default @NotNull LocatedType getType() { return LocatedType.ENTITY; } - static LocatedEntity create(Entity entity) { + static @NotNull LocatedEntity create(Entity entity) { return new LocatedEntityImpl(entity); } @@ -249,11 +258,11 @@ public boolean equals(Object obj) { interface LocatedBlock extends Located { - default Block getBlock() { + default @NotNull Block getBlock() { return getLocation().getBlock(); } - default Block getBlockNullable() { + default @Nullable Block getBlockNullable() { Location location = getLocation(); if (location == null || location.getWorld() == null) return null; @@ -261,15 +270,15 @@ default Block getBlockNullable() { } @Override - default LocatedType getType() { + default @NotNull LocatedType getType() { return LocatedType.BLOCK; } - static LocatedBlock create(Block block) { + static @NotNull LocatedBlock create(@NotNull Block block) { return new LocatedBlockImpl(block); } - static LocatedBlock create(Location location) { + static @NotNull LocatedBlock create(@NotNull Location location) { return new LocatedBlockLocationImpl(location); } @@ -341,7 +350,7 @@ enum LocatedType { * <b>OR</b> if the clazz does not have a {@link LocatableType} annotation attached, * <code>false</code> otherwise. */ - static boolean hasLocatedTypes(Class<? extends Locatable> clazz, LocatedType... types) { + static boolean hasLocatedTypes(@NotNull Class<? extends Locatable> clazz, @NotNull LocatedType @NotNull... types) { Set<LocatedType> toTest = new HashSet<>(Arrays.asList(types)); boolean foundAnnotation = false; 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 4ee1d8f8..0c5a6c7c 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java @@ -205,7 +205,7 @@ public void resetPlayer(BukkitCommandActor actor, EntitySelector<Player> players final int questsFinal = quests; final int poolsFinal = pools; CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).whenComplete(Utils.runSyncConsumer(() -> { - Bukkit.getPluginManager().callEvent(new PlayerAccountResetEvent(player, acc)); + Bukkit.getPluginManager().callEvent(new PlayerAccountResetEvent(acc)); if (acc.isCurrent()) Lang.DATA_REMOVED.send(player, questsFinal, actor.getName(), poolsFinal); Lang.DATA_REMOVED_INFO.send(actor.getSender(), questsFinal, player.getName(), poolsFinal); diff --git a/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java b/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java index 180640b9..3c5b7b85 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java +++ b/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java @@ -5,8 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; - -import fr.skytasul.quests.api.events.BQNPCClickEvent; +import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java index 9dd2a539..bc738e6d 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java @@ -10,6 +10,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -39,12 +40,15 @@ public class QuestObjectGUI<T extends QuestObject> extends ListGUI<T> { private Collection<QuestObjectCreator<T>> creators; private Consumer<List<T>> end; - public QuestObjectGUI(String name, QuestObjectLocation objectLocation, Collection<QuestObjectCreator<T>> creators, Consumer<List<T>> end, List<T> objects) { + public QuestObjectGUI(@NotNull String name, @NotNull QuestObjectLocation objectLocation, + @NotNull Collection<@NotNull QuestObjectCreator<T>> creators, @NotNull Consumer<@NotNull List<T>> end, + @NotNull List<T> objects) { super(name, DyeColor.CYAN, (List<T>) objects.stream().map(QuestObject::clone).collect(Collectors.toList())); this.name = name; this.creators = creators.stream() .filter(creator -> creator.isAllowed(objectLocation)) - .filter(creator -> creator.canBeMultiple() || objects.stream().noneMatch(object -> object.getCreator() == creator)) + .filter(creator -> creator.canBeMultiple() + || objects.stream().noneMatch(object -> object.getCreator() == creator)) .collect(Collectors.toList()); this.end = end; } diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java index fcfcf04b..e51bc4cf 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java @@ -9,6 +9,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.XMaterial; @@ -23,7 +24,7 @@ public abstract class ListGUI<T> extends PagedGUI<T> { private ItemStack create = ItemUtils.item(XMaterial.SLIME_BALL, Lang.addObject.toString()); - public ListGUI(String name, DyeColor color, Collection<T> objects) { + protected ListGUI(@NotNull String name, @NotNull DyeColor color, @NotNull Collection<T> objects) { super(name, color, objects); if (objects.contains(null)) throw new IllegalArgumentException("Object cannot be null in a list GUI"); diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerAccount.java b/core/src/main/java/fr/skytasul/quests/players/PlayerAccount.java index 01220c52..ecc96b88 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerAccount.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerAccount.java @@ -9,6 +9,9 @@ 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.players.accounts.AbstractAccount; @@ -26,7 +29,7 @@ public class PlayerAccount { protected final Map<SavableData<?>, Object> additionalDatas = new HashMap<>(); protected final int index; - protected PlayerAccount(AbstractAccount account, int index) { + protected PlayerAccount(@NotNull AbstractAccount account, int index) { this.abstractAcc = account; this.index = index; } @@ -41,26 +44,26 @@ public boolean isCurrent() { /** * @return the OfflinePlayer instance attached to this account (no matter if the player is online or not, or if the account is the currently used) */ - public OfflinePlayer getOfflinePlayer(){ + public @NotNull OfflinePlayer getOfflinePlayer() { return abstractAcc.getOfflinePlayer(); } /** * @return the Player instance who own this account. If the account is not which in use by the player ({@link #isCurrent()}), this will return null. */ - public Player getPlayer(){ + public @Nullable Player getPlayer() { return abstractAcc.getPlayer(); } - public boolean hasQuestDatas(Quest quest) { + public boolean hasQuestDatas(@NotNull Quest quest) { return questDatas.containsKey(quest.getID()); } - public PlayerQuestDatas getQuestDatasIfPresent(Quest quest) { + public @Nullable PlayerQuestDatas getQuestDatasIfPresent(@NotNull Quest quest) { return questDatas.get(quest.getID()); } - public PlayerQuestDatas getQuestDatas(Quest quest) { + public @NotNull PlayerQuestDatas getQuestDatas(@NotNull Quest quest) { PlayerQuestDatas datas = questDatas.get(quest.getID()); if (datas == null) { datas = BeautyQuests.getInstance().getPlayersManager().createPlayerQuestDatas(this, quest); @@ -69,11 +72,11 @@ public PlayerQuestDatas getQuestDatas(Quest quest) { return datas; } - public CompletableFuture<PlayerQuestDatas> removeQuestDatas(Quest quest) { + public @NotNull CompletableFuture<PlayerQuestDatas> removeQuestDatas(@NotNull Quest quest) { return removeQuestDatas(quest.getID()); } - public CompletableFuture<PlayerQuestDatas> removeQuestDatas(int id) { + public @NotNull CompletableFuture<PlayerQuestDatas> removeQuestDatas(int id) { PlayerQuestDatas removed = questDatas.remove(id); if (removed == null) return CompletableFuture.completedFuture(null); @@ -81,19 +84,19 @@ public CompletableFuture<PlayerQuestDatas> removeQuestDatas(int id) { return BeautyQuests.getInstance().getPlayersManager().playerQuestDataRemoved(removed).thenApply(__ -> removed); } - protected PlayerQuestDatas removeQuestDatasSilently(int id) { + protected @Nullable PlayerQuestDatas removeQuestDatasSilently(int id) { return questDatas.remove(id); } - public Collection<PlayerQuestDatas> getQuestsDatas() { + public @UnmodifiableView @NotNull Collection<@NotNull PlayerQuestDatas> getQuestsDatas() { return questDatas.values(); } - public boolean hasPoolDatas(QuestPool pool) { + public boolean hasPoolDatas(@NotNull QuestPool pool) { return poolDatas.containsKey(pool.getID()); } - public PlayerPoolDatas getPoolDatas(QuestPool pool) { + public @NotNull PlayerPoolDatas getPoolDatas(@NotNull QuestPool pool) { PlayerPoolDatas datas = poolDatas.get(pool.getID()); if (datas == null) { datas = BeautyQuests.getInstance().getPlayersManager().createPlayerPoolDatas(this, pool); @@ -102,11 +105,11 @@ public PlayerPoolDatas getPoolDatas(QuestPool pool) { return datas; } - public CompletableFuture<PlayerPoolDatas> removePoolDatas(QuestPool pool) { + public @NotNull CompletableFuture<PlayerPoolDatas> removePoolDatas(@NotNull QuestPool pool) { return removePoolDatas(pool.getID()); } - public CompletableFuture<PlayerPoolDatas> removePoolDatas(int id) { + public @NotNull CompletableFuture<PlayerPoolDatas> removePoolDatas(int id) { PlayerPoolDatas removed = poolDatas.remove(id); if (removed == null) return CompletableFuture.completedFuture(null); @@ -114,17 +117,17 @@ public CompletableFuture<PlayerPoolDatas> removePoolDatas(int id) { return BeautyQuests.getInstance().getPlayersManager().playerPoolDataRemoved(removed).thenApply(__ -> removed); } - public Collection<PlayerPoolDatas> getPoolDatas() { + public @UnmodifiableView @NotNull Collection<@NotNull PlayerPoolDatas> getPoolDatas() { return poolDatas.values(); } - public <T> T getData(SavableData<T> data) { + public <T> @Nullable T getData(@NotNull SavableData<T> data) { if (!BeautyQuests.getInstance().getPlayersManager().getAccountDatas().contains(data)) throw new IllegalArgumentException("The " + data.getId() + " account data has not been registered."); return (T) additionalDatas.getOrDefault(data, data.getDefaultValue()); } - public <T> void setData(SavableData<T> data, T value) { + public <T> void setData(@NotNull SavableData<T> data, @Nullable T value) { if (!BeautyQuests.getInstance().getPlayersManager().getAccountDatas().contains(data)) throw new IllegalArgumentException("The " + data.getId() + " account data has not been registered."); additionalDatas.put(data, value); @@ -135,12 +138,14 @@ public void resetDatas() { } @Override - public boolean equals(Object arg0) { - if (arg0 == this) return true; - if (arg0.getClass() != this.getClass()) return false; - PlayerAccount otherAccount = (PlayerAccount) arg0; - if (!abstractAcc.equals(otherAccount.abstractAcc)) return false; - return true; + public boolean equals(Object object) { + if (object == this) + return true; + if (object == null) + return false; + if (object.getClass() != this.getClass()) + return false; + return abstractAcc.equals(((PlayerAccount) object).abstractAcc); } @Override @@ -153,21 +158,21 @@ public int hashCode() { return hash; } - public String getName() { + public @NotNull String getName() { Player p = getPlayer(); return p == null ? debugName() : p.getName(); } - public String getNameAndID() { + public @NotNull String getNameAndID() { Player p = getPlayer(); return p == null ? debugName() : p.getName() + " (# " + index + ")"; } - public String debugName() { + public @NotNull String debugName() { return abstractAcc.getIdentifier() + " (#" + index + ")"; } - public void serialize(ConfigurationSection config) { + public void serialize(@NotNull ConfigurationSection config) { config.set("identifier", abstractAcc.getIdentifier()); config.set("quests", questDatas.isEmpty() ? null : Utils.serializeList(questDatas.values(), PlayerQuestDatas::serialize)); config.set("pools", poolDatas.isEmpty() ? null : Utils.serializeList(poolDatas.values(), PlayerPoolDatas::serialize)); diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayersManager.java b/core/src/main/java/fr/skytasul/quests/players/PlayersManager.java index f984b15f..97684e5d 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManager.java @@ -14,6 +14,9 @@ import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -33,27 +36,27 @@ public abstract class PlayersManager { - protected final Map<Player, PlayerAccount> cachedAccounts = new HashMap<>(); - protected final Set<SavableData<?>> accountDatas = new HashSet<>(); + protected final @NotNull Map<Player, PlayerAccount> cachedAccounts = new HashMap<>(); + protected final @NotNull Set<@NotNull SavableData<?>> accountDatas = new HashSet<>(); private boolean loaded = false; - public abstract void load(AccountFetchRequest request); + public abstract void load(@NotNull AccountFetchRequest request); - public abstract void unloadAccount(PlayerAccount acc); + public abstract void unloadAccount(@NotNull PlayerAccount acc); - protected abstract CompletableFuture<Void> removeAccount(PlayerAccount acc); + protected abstract @NotNull CompletableFuture<Void> removeAccount(@NotNull PlayerAccount acc); - public abstract CompletableFuture<Integer> removeQuestDatas(Quest quest); + public abstract @NotNull CompletableFuture<Integer> removeQuestDatas(@NotNull Quest quest); - public abstract PlayerQuestDatas createPlayerQuestDatas(PlayerAccount acc, Quest quest); + public abstract @NotNull PlayerQuestDatas createPlayerQuestDatas(@NotNull PlayerAccount acc, @NotNull Quest quest); - public abstract PlayerPoolDatas createPlayerPoolDatas(PlayerAccount acc, QuestPool pool); + public abstract @NotNull PlayerPoolDatas createPlayerPoolDatas(@NotNull PlayerAccount acc, @NotNull QuestPool pool); - public CompletableFuture<Void> playerQuestDataRemoved(PlayerQuestDatas datas) { + public @NotNull CompletableFuture<Void> playerQuestDataRemoved(@NotNull PlayerQuestDatas datas) { return CompletableFuture.completedFuture(null); } - public CompletableFuture<Void> playerPoolDataRemoved(PlayerPoolDatas datas) { + public @NotNull CompletableFuture<Void> playerPoolDataRemoved(@NotNull PlayerPoolDatas datas) { return CompletableFuture.completedFuture(null); } @@ -68,7 +71,7 @@ public boolean isLoaded() { public abstract void save(); - public void addAccountData(SavableData<?> data) { + public void addAccountData(@NotNull SavableData<?> data) { if (loaded) throw new IllegalStateException("Cannot add account data after players manager has been loaded"); if (PlayerAccount.FORBIDDEN_DATA_ID.contains(data.getId())) @@ -81,15 +84,15 @@ public void addAccountData(SavableData<?> data) { DebugUtils.logMessage("Registered account data " + data.getId()); } - public Collection<SavableData<?>> getAccountDatas() { + public @NotNull Collection<@NotNull SavableData<?>> getAccountDatas() { return accountDatas; } - protected AbstractAccount createAbstractAccount(Player p) { + protected @NotNull AbstractAccount createAbstractAccount(@NotNull Player p) { return QuestsConfiguration.hookAccounts() ? Accounts.getPlayerAccount(p) : new UUIDAccount(p.getUniqueId()); } - protected String getIdentifier(OfflinePlayer p) { + protected @NotNull String getIdentifier(@NotNull OfflinePlayer p) { if (QuestsConfiguration.hookAccounts()) { if (!p.isOnline()) throw new IllegalArgumentException("Cannot fetch player identifier of an offline player with AccountsHook"); @@ -98,7 +101,7 @@ protected String getIdentifier(OfflinePlayer p) { return p.getUniqueId().toString(); } - protected AbstractAccount createAccountFromIdentifier(String identifier) { + protected @Nullable AbstractAccount createAccountFromIdentifier(@NotNull String identifier) { if (identifier.startsWith("Hooked|")){ if (!QuestsConfiguration.hookAccounts()) throw new MissingDependencyException("AccountsHook is not enabled or config parameter is disabled, but saved datas need it."); String nidentifier = identifier.substring(7); @@ -124,7 +127,7 @@ protected AbstractAccount createAccountFromIdentifier(String identifier) { return null; } - public synchronized void loadPlayer(Player p) { + public synchronized void loadPlayer(@NotNull Player p) { cachedPlayerNames.put(p.getUniqueId(), p.getName()); long time = System.currentTimeMillis(); @@ -145,7 +148,7 @@ public synchronized void loadPlayer(Player p) { }); } - private boolean tryLoad(Player p, long time) { + private boolean tryLoad(@NotNull Player p, long time) { if (!p.isOnline()) { BeautyQuests.logger .warning("Player " + p.getName() + " has quit the server while loading its datas. This may be a bug."); @@ -189,7 +192,7 @@ private boolean tryLoad(Player p, long time) { if (p.isOnline()) { Bukkit.getPluginManager() - .callEvent(new PlayerAccountJoinEvent(p, request.getAccount(), request.isAccountCreated())); + .callEvent(new PlayerAccountJoinEvent(request.getAccount(), request.isAccountCreated())); } else { BeautyQuests.logger.warning( "Player " + p.getName() + " has quit the server while loading its datas. This may be a bug."); @@ -202,16 +205,16 @@ private boolean tryLoad(Player p, long time) { return false; } - public synchronized void unloadPlayer(Player p) { + public synchronized void unloadPlayer(@NotNull Player p) { PlayerAccount acc = cachedAccounts.get(p); if (acc == null) return; DebugUtils.logMessage("Unloading player " + p.getName() + "... (" + acc.getQuestsDatas().size() + " quests, " + acc.getPoolDatas().size() + " pools)"); - Bukkit.getPluginManager().callEvent(new PlayerAccountLeaveEvent(p, acc)); + Bukkit.getPluginManager().callEvent(new PlayerAccountLeaveEvent(acc)); unloadAccount(acc); cachedAccounts.remove(p); } - public PlayerAccount getAccount(Player p) { + public @UnknownNullability PlayerAccount getAccount(@NotNull Player p) { if (QuestsAPI.getNPCsManager().isNPC(p)) return null; if (!p.isOnline()) { BeautyQuests.logger.severe("Trying to fetch the account of an offline player (" + p.getName() + ")"); @@ -231,11 +234,11 @@ public PlayerAccount getAccount(Player p) { @Deprecated public static PlayersManager manager; // TODO remove, changed in 0.20.1 - public static PlayerAccount getPlayerAccount(Player p) { + public static @UnknownNullability PlayerAccount getPlayerAccount(@NotNull Player p) { return BeautyQuests.getInstance().getPlayersManager().getAccount(p); } - public static synchronized String getPlayerName(UUID uuid) { + public static synchronized @Nullable String getPlayerName(@NotNull UUID uuid) { if (cachedPlayerNames.containsKey(uuid)) return cachedPlayerNames.get(uuid); diff --git a/core/src/main/java/fr/skytasul/quests/players/accounts/AbstractAccount.java b/core/src/main/java/fr/skytasul/quests/players/accounts/AbstractAccount.java index e8bd780e..7d50d9d6 100644 --- a/core/src/main/java/fr/skytasul/quests/players/accounts/AbstractAccount.java +++ b/core/src/main/java/fr/skytasul/quests/players/accounts/AbstractAccount.java @@ -2,27 +2,35 @@ import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class AbstractAccount { protected AbstractAccount(){} - public abstract OfflinePlayer getOfflinePlayer(); + public abstract @NotNull OfflinePlayer getOfflinePlayer(); - public abstract Player getPlayer(); + public abstract @Nullable Player getPlayer(); public abstract boolean isCurrent(); - public abstract String getIdentifier(); + public abstract @NotNull String getIdentifier(); - protected abstract boolean equalsAccount(AbstractAccount acc); + protected abstract boolean equalsAccount(@NotNull AbstractAccount acc); + @Override public abstract int hashCode(); - public boolean equals(Object arg0) { - if (arg0 == this) return true; - if (arg0.getClass() != this.getClass()) return false; - return equalsAccount((AbstractAccount) arg0); + @Override + public boolean equals(Object object) { + if (object == this) + return true; + if (object == null) + return false; + if (object.getClass() != this.getClass()) + return false; + return equalsAccount((AbstractAccount) object); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index 60f72069..1860fdb1 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -14,7 +14,7 @@ import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; -import fr.skytasul.quests.api.events.BQCraftEvent; +import fr.skytasul.quests.api.events.internal.BQCraftEvent; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.gui.ItemUtils; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index 4a7a81e4..70b3e969 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -18,7 +18,7 @@ import com.gestankbratwurst.playerblocktracker.PlayerBlockTracker; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.api.events.BQBlockBreakEvent; +import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; 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 8c525703..84d1c9c6 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -18,7 +18,7 @@ import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.AbstractHolograms; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.events.BQNPCClickEvent; +import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; diff --git a/core/src/main/java/fr/skytasul/quests/structure/BranchesManager.java b/core/src/main/java/fr/skytasul/quests/structure/BranchesManager.java index db942f25..45c3ba77 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/BranchesManager.java +++ b/core/src/main/java/fr/skytasul/quests/structure/BranchesManager.java @@ -1,15 +1,17 @@ package fr.skytasul.quests.structure; -import java.util.Comparator; +import java.util.Collection; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.stream.Collectors; +import java.util.TreeMap; import org.apache.commons.lang.Validate; 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.QuestsAPI; import fr.skytasul.quests.players.PlayerAccount; @@ -17,15 +19,15 @@ public class BranchesManager{ - private Map<Integer, QuestBranch> branches = new LinkedHashMap<>(); + private @NotNull Map<Integer, QuestBranch> branches = new TreeMap<>(Integer::compare); - private final Quest quest; + private final @NotNull Quest quest; - public BranchesManager(Quest quest){ + public BranchesManager(@NotNull Quest quest) { this.quest = quest; } - public Quest getQuest(){ + public @NotNull Quest getQuest() { return quest; } @@ -33,12 +35,12 @@ public int getBranchesAmount(){ return branches.size(); } - public void addBranch(QuestBranch branch){ + public void addBranch(@NotNull QuestBranch branch) { Validate.notNull(branch, "Branch cannot be null !"); branches.put(branches.size(), branch); } - public int getID(QuestBranch branch){ + public int getID(@NotNull QuestBranch branch) { for (Entry<Integer, QuestBranch> en : branches.entrySet()){ if (en.getValue() == branch) return en.getKey(); } @@ -46,20 +48,20 @@ public int getID(QuestBranch branch){ return -1; } - public List<QuestBranch> getBranches() { - return branches.entrySet().stream().sorted(Comparator.comparingInt(Entry::getKey)).map(Entry::getValue).collect(Collectors.toList()); + public @UnmodifiableView @NotNull Collection<@NotNull QuestBranch> getBranches() { + return branches.values(); } - public QuestBranch getBranch(int id){ + public @NotNull QuestBranch getBranch(int id) { return branches.get(id); } - public QuestBranch getPlayerBranch(PlayerAccount acc) { + public @Nullable QuestBranch getPlayerBranch(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(quest)) return null; return branches.get(acc.getQuestDatas(quest).getBranch()); } - public boolean hasBranchStarted(PlayerAccount acc, QuestBranch branch){ + public boolean hasBranchStarted(@NotNull PlayerAccount acc, @NotNull QuestBranch branch) { if (!acc.hasQuestDatas(quest)) return false; return acc.getQuestDatas(quest).getBranch() == branch.getID(); } @@ -68,20 +70,20 @@ public boolean hasBranchStarted(PlayerAccount acc, QuestBranch branch){ * Called internally when the quest is updated for the player * @param p Player */ - public final void objectiveUpdated(Player p, PlayerAccount acc) { + public final void objectiveUpdated(@NotNull Player p, @NotNull PlayerAccount acc) { if (quest.hasStarted(acc)) { QuestsAPI.propagateQuestsHandlers(x -> x.questUpdated(acc, p, quest)); } } - public void startPlayer(PlayerAccount acc){ + public void startPlayer(@NotNull PlayerAccount acc) { PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); datas.resetQuestFlow(); datas.setStartingTime(System.currentTimeMillis()); branches.get(0).start(acc); } - public void remove(PlayerAccount acc) { + public void remove(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(quest)) return; QuestBranch branch = getPlayerBranch(acc); if (branch != null) branch.remove(acc, true); @@ -94,7 +96,7 @@ public void remove(){ branches.clear(); } - public void save(ConfigurationSection section) { + public void save(@NotNull ConfigurationSection section) { ConfigurationSection branchesSection = section.createSection("branches"); branches.forEach((id, branch) -> { try { @@ -111,7 +113,7 @@ public String toString() { return "BranchesManager{branches=" + branches.size() + "}"; } - public static BranchesManager deserialize(ConfigurationSection section, Quest qu) { + public static @NotNull BranchesManager deserialize(@NotNull ConfigurationSection section, @NotNull Quest qu) { BranchesManager bm = new BranchesManager(qu); ConfigurationSection branchesSection; diff --git a/core/src/main/java/fr/skytasul/quests/structure/Quest.java b/core/src/main/java/fr/skytasul/quests/structure/Quest.java index e72be394..f5f03f33 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/Quest.java +++ b/core/src/main/java/fr/skytasul/quests/structure/Quest.java @@ -18,6 +18,8 @@ import org.bukkit.configuration.file.YamlConfiguration; 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.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; @@ -67,7 +69,7 @@ public Quest(int id) { this(id, new File(BeautyQuests.getInstance().getQuestsManager().getSaveFolder(), id + ".yml")); } - public Quest(int id, File file) { + public Quest(int id, @NotNull File file) { this.id = id; this.file = file; this.manager = new BranchesManager(this); @@ -78,7 +80,7 @@ public void load() { QuestsAPI.propagateQuestsHandlers(handler -> handler.questLoaded(this)); } - public List<QuestDescriptionProvider> getDescriptions() { + public @NotNull List<QuestDescriptionProvider> getDescriptions() { return descriptions; } @@ -87,7 +89,7 @@ public Iterator<QuestOption> iterator() { return (Iterator) options.iterator(); } - public <D> D getOptionValueOrDef(Class<? extends QuestOption<D>> clazz) { + public @Nullable <D> D getOptionValueOrDef(@NotNull Class<? extends QuestOption<D>> clazz) { for (QuestOption<?> option : options) { if (clazz.isInstance(option)) return (D) option.getValue(); } @@ -95,7 +97,7 @@ public <D> D getOptionValueOrDef(Class<? extends QuestOption<D>> clazz) { } @Override - public <T extends QuestOption<?>> T getOption(Class<T> clazz) { + public @NotNull <T extends QuestOption<?>> T getOption(@NotNull Class<T> clazz) { for (QuestOption<?> option : options) { if (clazz.isInstance(option)) return (T) option; } @@ -103,14 +105,14 @@ public <T extends QuestOption<?>> T getOption(Class<T> clazz) { } @Override - public boolean hasOption(Class<? extends QuestOption<?>> clazz) { + public boolean hasOption(@NotNull Class<? extends QuestOption<?>> clazz) { for (QuestOption<?> option : options) { if (clazz.isInstance(option)) return true; } return false; } - public void addOption(QuestOption<?> option) { + public void addOption(@NotNull QuestOption<?> option) { if (!option.hasCustomValue()) return; options.add(option); option.attach(this); @@ -122,7 +124,7 @@ public void addOption(QuestOption<?> option) { }); } - public void removeOption(Class<? extends QuestOption<?>> clazz) { + public void removeOption(@NotNull Class<? extends QuestOption<?>> clazz) { for (Iterator<QuestOption<?>> iterator = options.iterator(); iterator.hasNext();) { QuestOption<?> option = iterator.next(); if (clazz.isInstance(option)) { @@ -145,15 +147,15 @@ public File getFile(){ return file; } - public String getName(){ + public @Nullable String getName() { return getOptionValueOrDef(OptionName.class); } - public String getDescription() { + public @Nullable String getDescription() { return getOptionValueOrDef(OptionDescription.class); } - public ItemStack getQuestItem() { + public @NotNull ItemStack getQuestItem() { return getOptionValueOrDef(OptionQuestItem.class); } @@ -181,26 +183,26 @@ public boolean canBypassLimit() { return getOptionValueOrDef(OptionBypassLimit.class); } - public BranchesManager getBranchesManager(){ + public @NotNull BranchesManager getBranchesManager() { return manager; } - public String getTimeLeft(PlayerAccount acc) { + public @NotNull String getTimeLeft(@NotNull PlayerAccount acc) { return Utils.millisToHumanString(acc.getQuestDatas(this).getTimer() - System.currentTimeMillis()); } - public boolean hasStarted(PlayerAccount acc){ + public boolean hasStarted(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(this)) return false; if (acc.getQuestDatas(this).hasStarted()) return true; if (acc.isCurrent() && asyncStart != null && asyncStart.contains(acc.getPlayer())) return true; return false; } - public boolean hasFinished(PlayerAccount acc){ + public boolean hasFinished(@NotNull PlayerAccount acc) { return acc.hasQuestDatas(this) && acc.getQuestDatas(this).isFinished(); } - public boolean cancelPlayer(PlayerAccount acc) { + public boolean cancelPlayer(@NotNull PlayerAccount acc) { PlayerQuestDatas datas = acc.getQuestDatasIfPresent(this); if (datas == null || !datas.hasStarted()) return false; @@ -210,7 +212,7 @@ public boolean cancelPlayer(PlayerAccount acc) { return true; } - private void cancelInternal(PlayerAccount acc) { + private void cancelInternal(@NotNull PlayerAccount acc) { manager.remove(acc); QuestsAPI.propagateQuestsHandlers(handler -> handler.questReset(acc, this)); Bukkit.getPluginManager().callEvent(new PlayerQuestResetEvent(acc, this)); @@ -224,10 +226,7 @@ private void cancelInternal(PlayerAccount acc) { } } - public CompletableFuture<Boolean> resetPlayer(PlayerAccount acc){ - if (acc == null) - return CompletableFuture.completedFuture(Boolean.FALSE); - + public @NotNull CompletableFuture<Boolean> resetPlayer(@NotNull PlayerAccount acc) { boolean hadDatas = false; CompletableFuture<?> future = null; @@ -246,7 +245,7 @@ && getOption(OptionStartDialog.class).getDialogRunner().removePlayer(acc.getPlay return future == null ? CompletableFuture.completedFuture(hadDatas) : future.thenApply(__ -> true); } - public boolean isLauncheable(Player p, PlayerAccount acc, boolean sendMessage) { + public boolean isLauncheable(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { if (hasStarted(acc)){ if (sendMessage) Lang.ALREADY_STARTED.send(p); return false; @@ -257,14 +256,14 @@ public boolean isLauncheable(Player p, PlayerAccount acc, boolean sendMessage) { return true; } - public boolean testRequirements(Player p, PlayerAccount acc, boolean sendMessage){ + public boolean testRequirements(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { if (!p.hasPermission("beautyquests.start")) return false; if (!testQuestLimit(p, acc, sendMessage)) return false; sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) || (QuestsConfiguration.isRequirementReasonSentOnMultipleQuests() || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); return Utils.testRequirements(p, getOptionValueOrDef(OptionRequirements.class), sendMessage); } - public boolean testQuestLimit(Player p, PlayerAccount acc, boolean sendMessage) { + public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { if (Boolean.TRUE.equals(getOptionValueOrDef(OptionBypassLimit.class))) return true; int playerMaxLaunchedQuest; @@ -288,7 +287,7 @@ public boolean testQuestLimit(Player p, PlayerAccount acc, boolean sendMessage) return true; } - public boolean testTimer(PlayerAccount acc, boolean sendMessage) { + public boolean testTimer(@NotNull PlayerAccount acc, boolean sendMessage) { if (isRepeatable() && acc.hasQuestDatas(this)) { long time = acc.getQuestDatas(this).getTimer(); if (time > System.currentTimeMillis()) { @@ -299,24 +298,24 @@ public boolean testTimer(PlayerAccount acc, boolean sendMessage) { return true; } - public boolean isInDialog(Player p) { + public boolean isInDialog(@NotNull Player p) { return hasOption(OptionStartDialog.class) && getOption(OptionStartDialog.class).getDialogRunner().isPlayerInDialog(p); } - public void clickNPC(Player p){ + public void clickNPC(@NotNull Player p) { if (hasOption(OptionStartDialog.class)) { getOption(OptionStartDialog.class).getDialogRunner().onClick(p); } else attemptStart(p); } - public void leave(Player p) { + public void leave(@NotNull Player p) { if (hasOption(OptionStartDialog.class)) { getOption(OptionStartDialog.class).getDialogRunner().removePlayer(p); } } - public String getDescriptionLine(PlayerAccount acc, Source source) { + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { if (!acc.hasQuestDatas(this)) throw new IllegalArgumentException("Account does not have quest datas for quest " + id); if (asyncStart != null && acc.isCurrent() && asyncStart.contains(acc.getPlayer())) return "§7x"; PlayerQuestDatas datas = acc.getQuestDatas(this); @@ -327,14 +326,17 @@ public String getDescriptionLine(PlayerAccount acc, Source source) { } @Override - public List<String> provideDescription(QuestDescriptionContext context) { - if (!context.getPlayerAccount().isCurrent()) return null; - if (context.getCategory() != Category.IN_PROGRESS) return null; + public @NotNull List<String> provideDescription(QuestDescriptionContext context) { + if (!context.getPlayerAccount().isCurrent()) + return Collections.emptyList(); + if (context.getCategory() != Category.IN_PROGRESS) + return Collections.emptyList(); + return Arrays.asList(getDescriptionLine(context.getPlayerAccount(), context.getSource())); } @Override - public String getDescriptionId() { + public @NotNull String getDescriptionId() { return "advancement"; } @@ -343,7 +345,7 @@ public double getDescriptionPriority() { return 15; } - public CompletableFuture<Boolean> attemptStart(Player p) { + public @NotNull CompletableFuture<Boolean> attemptStart(@NotNull Player p) { if (!isLauncheable(p, PlayersManager.getPlayerAccount(p), true)) return CompletableFuture.completedFuture(false); @@ -361,11 +363,11 @@ public CompletableFuture<Boolean> attemptStart(Player p) { } } - public void start(Player p){ + public void start(@NotNull Player p) { start(p, false); } - public void start(Player p, boolean silently) { + public void start(@NotNull Player p, boolean silently) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); if (hasStarted(acc)){ if (!silently) Lang.ALREADY_STARTED.send(p); @@ -404,7 +406,7 @@ public void start(Player p, boolean silently) { }else run.run(); } - public void finish(Player p){ + public void finish(@NotNull Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); AdminMode.broadcast(p.getName() + " is completing the quest " + id); PlayerQuestDatas questDatas = acc.getQuestDatas(Quest.this); @@ -506,7 +508,7 @@ public boolean saveToFile() throws Exception { } } - private void save(ConfigurationSection section) throws Exception{ + private void save(@NotNull ConfigurationSection section) throws Exception { for (QuestOption<?> option : options) { try { if (option.hasCustomValue()) section.set(option.getOptionCreator().id, option.save()); @@ -520,7 +522,7 @@ private void save(ConfigurationSection section) throws Exception{ } - public static Quest loadFromFile(File file){ + public static @Nullable Quest loadFromFile(@NotNull File file) { try { YamlConfiguration config = new YamlConfiguration(); config.load(file); @@ -531,7 +533,7 @@ public static Quest loadFromFile(File file){ } } - private static Quest deserialize(File file, ConfigurationSection map) { + private static @Nullable Quest deserialize(@NotNull File file, @NotNull ConfigurationSection map) { if (!map.contains("id")) { BeautyQuests.getInstance().getLogger().severe("Quest doesn't have an id."); return null; diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java index a099f2dd..4332770a 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java @@ -12,6 +12,8 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.events.PlayerSetStageEvent; @@ -29,21 +31,23 @@ public class QuestBranch { private LinkedHashMap<AbstractStage, QuestBranch> endStages = new LinkedHashMap<>(); + // TODO change this LinkedHashMap to a better option using a list + private LinkedList<AbstractStage> regularStages = new LinkedList<>(); private List<PlayerAccount> asyncReward = new ArrayList<>(5); - private final BranchesManager manager; + private final @NotNull BranchesManager manager; - public QuestBranch(BranchesManager manager){ + public QuestBranch(@NotNull BranchesManager manager) { this.manager = manager; } - public Quest getQuest(){ + public @NotNull Quest getQuest() { return manager.getQuest(); } - public BranchesManager getBranchesManager(){ + public @NotNull BranchesManager getBranchesManager() { return manager; } @@ -55,39 +59,39 @@ public int getID(){ return manager.getID(this); } - public void addRegularStage(AbstractStage stage){ + public void addRegularStage(@NotNull AbstractStage stage) { Validate.notNull(stage, "Stage cannot be null !"); regularStages.add(stage); stage.load(); } - public void addEndStage(AbstractStage stage, QuestBranch linked){ + public void addEndStage(@NotNull AbstractStage stage, @NotNull QuestBranch linked) { Validate.notNull(stage, "Stage cannot be null !"); endStages.put(stage, linked); stage.load(); } - public int getID(AbstractStage stage){ + public int getID(@NotNull AbstractStage stage) { return regularStages.indexOf(stage); } - public LinkedList<AbstractStage> getRegularStages(){ + public @NotNull List<@NotNull AbstractStage> getRegularStages() { return regularStages; } - public AbstractStage getRegularStage(int id){ + public @NotNull AbstractStage getRegularStage(int id) { return regularStages.get(id); } - public boolean isRegularStage(AbstractStage stage){ + public boolean isRegularStage(@NotNull AbstractStage stage) { return regularStages.contains(stage); } - public LinkedHashMap<AbstractStage, QuestBranch> getEndingStages() { + public @NotNull LinkedHashMap<AbstractStage, QuestBranch> getEndingStages() { return endStages; } - public AbstractStage getEndingStage(int id) { + public @Nullable AbstractStage getEndingStage(int id) { int i = 0; for (AbstractStage stage : endStages.keySet()) { if (i++ == id) return stage; @@ -95,7 +99,7 @@ public AbstractStage getEndingStage(int id) { return null; } - public String getDescriptionLine(PlayerAccount acc, Source source) { + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { PlayerQuestDatas datas; if (!acc.hasQuestDatas(getQuest()) || (datas = acc.getQuestDatas(getQuest())).getBranch() != getID()) throw new IllegalArgumentException("Account does not have this branch launched"); if (asyncReward.contains(acc)) return Lang.SCOREBOARD_ASYNC_END.toString(); @@ -117,14 +121,15 @@ public String getDescriptionLine(PlayerAccount acc, Source source) { if (datas.getStage() >= regularStages.size()) return "§cerror: datas do not match"; return Utils.format(QuestsConfiguration.getStageDescriptionFormat(), datas.getStage() + 1, regularStages.size(), regularStages.get(datas.getStage()).getDescriptionLine(acc, source)); } + /** * Where do the description request come from */ - public static enum Source{ + public enum Source { SCOREBOARD, MENU, PLACEHOLDER, FORCESPLIT, FORCELINE; } - public boolean hasStageLaunched(PlayerAccount acc, AbstractStage stage){ + public boolean hasStageLaunched(@Nullable PlayerAccount acc, @NotNull AbstractStage stage) { if (acc == null) return false; if (asyncReward.contains(acc)) return false; if (!acc.hasQuestDatas(getQuest())) return false; @@ -134,7 +139,7 @@ public boolean hasStageLaunched(PlayerAccount acc, AbstractStage stage){ return (endStages.keySet().contains(stage)); } - public void remove(PlayerAccount acc, boolean end) { + public void remove(@NotNull PlayerAccount acc, boolean end) { if (!acc.hasQuestDatas(getQuest())) return; PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); if (end) { @@ -146,7 +151,7 @@ public void remove(PlayerAccount acc, boolean end) { datas.setStage(-1); } - public void start(PlayerAccount acc){ + public void start(@NotNull PlayerAccount acc) { acc.getQuestDatas(getQuest()).setBranch(getID()); if (!regularStages.isEmpty()){ setStage(acc, 0); @@ -155,7 +160,7 @@ public void start(PlayerAccount acc){ } } - public void finishStage(Player p, AbstractStage stage){ + public void finishStage(@NotNull Player p, @NotNull AbstractStage stage) { DebugUtils.logMessage("Next stage for player " + p.getName() + " (coming from " + stage.toString() + ") via " + DebugUtils.stackTraces(1, 3)); PlayerAccount acc = PlayersManager.getPlayerAccount(p); PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); @@ -198,7 +203,7 @@ public void finishStage(Player p, AbstractStage stage){ }); } - private void endStage(PlayerAccount acc, AbstractStage stage, Runnable runAfter) { + private void endStage(@NotNull PlayerAccount acc, @NotNull AbstractStage stage, @NotNull Runnable runAfter) { if (acc.isCurrent()){ Player p = acc.getPlayer(); stage.end(acc); @@ -241,7 +246,7 @@ private void endStage(PlayerAccount acc, AbstractStage stage, Runnable runAfter) } } - public void setStage(PlayerAccount acc, int id) { + public void setStage(@NotNull PlayerAccount acc, int id) { AbstractStage stage = regularStages.get(id); Player p = acc.getPlayer(); if (stage == null){ @@ -258,7 +263,7 @@ public void setStage(PlayerAccount acc, int id) { } } - public void setEndingStages(PlayerAccount acc, boolean launchStage) { + public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { Player p = acc.getPlayer(); if (QuestsConfiguration.sendQuestUpdateMessage() && p != null && launchStage) Utils.sendMessage(p, Lang.QUEST_UPDATED.toString(), getQuest().getName()); PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); @@ -270,7 +275,7 @@ public void setEndingStages(PlayerAccount acc, boolean launchStage) { if (p != null && launchStage) playNextStage(p); } - private void playNextStage(Player p) { + private void playNextStage(@NotNull Player p) { Utils.playPluginSound(p.getLocation(), QuestsConfiguration.getNextStageSound(), 0.5F); if (QuestsConfiguration.showNextParticles()) QuestsConfiguration.getParticleNext().send(p, Arrays.asList(p)); } @@ -282,7 +287,7 @@ public void remove(){ endStages.clear(); } - public void save(ConfigurationSection section) { + public void save(@NotNull ConfigurationSection section) { ConfigurationSection stagesSection = section.createSection("stages"); int id = 0; for (AbstractStage stage : regularStages) { @@ -314,7 +319,7 @@ public String toString() { return "QuestBranch{regularStages=" + regularStages.size() + ",endingStages=" + endStages.size() + "}"; } - public boolean load(ConfigurationSection section) { + public boolean load(@NotNull ConfigurationSection section) { ConfigurationSection stagesSection; if (section.isList("stages")) { // migration on 0.19.3: TODO remove List<Map<?, ?>> stages = section.getMapList("stages"); diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestsManager.java b/core/src/main/java/fr/skytasul/quests/structure/QuestsManager.java index e3a6f438..5b611420 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestsManager.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestsManager.java @@ -12,7 +12,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.options.OptionStartable; @@ -70,15 +72,15 @@ public int incrementLastID() { return lastID.incrementAndGet(); } - public BeautyQuests getPlugin() { + public @NotNull BeautyQuests getPlugin() { return plugin; } - public File getSaveFolder() { + public @NotNull File getSaveFolder() { return saveFolder; } - public List<Quest> getQuests() { + public @NotNull List<Quest> getQuests() { return quests; } @@ -87,11 +89,11 @@ public int getQuestsAmount() { } @Override - public Iterator<Quest> iterator() { + public @NotNull Iterator<Quest> iterator() { return quests.iterator(); } - public Quest getQuest(int id) { + public @Nullable Quest getQuest(int id) { return quests.stream().filter(x -> x.getID() == id).findAny().orElse(null); } @@ -105,14 +107,14 @@ public void unloadQuests() { } } - public void removeQuest(Quest quest) { + public void removeQuest(@NotNull Quest quest) { quests.remove(quest); if (quest.hasOption(OptionStarterNPC.class)) { quest.getOption(OptionStarterNPC.class).getValue().removeQuest(quest); } } - public void addQuest(Quest quest) { + public void addQuest(@NotNull Quest quest) { lastID.set(Math.max(lastID.get(), quest.getID())); quests.add(quest); if (quest.hasOption(OptionStarterNPC.class)) { @@ -122,11 +124,12 @@ public void addQuest(Quest quest) { quest.load(); } - public List<Quest> getQuestsStarted(PlayerAccount acc) { + public @NotNull @Unmodifiable List<Quest> getQuestsStarted(PlayerAccount acc) { return getQuestsStarted(acc, false, false); } - public List<Quest> getQuestsStarted(PlayerAccount acc, boolean hide, boolean withoutScoreboard) { + public @NotNull @Unmodifiable List<Quest> getQuestsStarted(@NotNull PlayerAccount acc, boolean hide, + boolean withoutScoreboard) { return acc.getQuestsDatas() .stream() .filter(PlayerQuestDatas::hasStarted) @@ -138,7 +141,7 @@ public List<Quest> getQuestsStarted(PlayerAccount acc, boolean hide, boolean wit .collect(Collectors.toList()); } - public void updateQuestsStarted(PlayerAccount acc, boolean withoutScoreboard, List<Quest> list) { + public void updateQuestsStarted(@NotNull PlayerAccount acc, boolean withoutScoreboard, @NotNull List<Quest> list) { for (Iterator<Quest> iterator = list.iterator(); iterator.hasNext();) { Quest existing = iterator.next(); if (!existing.hasStarted(acc) || (withoutScoreboard && !existing.isScoreboardEnabled())) iterator.remove(); @@ -150,21 +153,22 @@ public void updateQuestsStarted(PlayerAccount acc, boolean withoutScoreboard, Li } } - public int getStartedSize(PlayerAccount acc) { + public int getStartedSize(@NotNull PlayerAccount acc) { return (int) quests .stream() .filter(quest -> !quest.canBypassLimit() && quest.hasStarted(acc)) .count(); } - public List<Quest> getQuestsFinished(PlayerAccount acc, boolean hide) { + public @NotNull @Unmodifiable List<Quest> getQuestsFinished(@NotNull PlayerAccount acc, boolean hide) { return quests .stream() .filter(quest -> !(hide && quest.isHidden(VisibilityLocation.TAB_FINISHED)) && quest.hasFinished(acc)) .collect(Collectors.toList()); } - public List<Quest> getQuestsNotStarted(PlayerAccount acc, boolean hide, boolean clickableAndRedoable) { + public @NotNull @Unmodifiable List<Quest> getQuestsNotStarted(@NotNull PlayerAccount acc, boolean hide, + boolean clickableAndRedoable) { return quests .stream() .filter(quest -> { diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManager.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManager.java index b2bb4969..3c6c1a22 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManager.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManager.java @@ -7,21 +7,22 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; - +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.requirements.AbstractRequirement; import fr.skytasul.quests.options.OptionQuestPool; public class QuestPoolsManager { - + private File file; private YamlConfiguration config; - + private Map<Integer, QuestPool> pools = new HashMap<>(); - + public QuestPoolsManager(File file) throws IOException { this.file = file; if (!file.exists()) { @@ -29,34 +30,41 @@ public QuestPoolsManager(File file) throws IOException { config.options().copyHeader(true); config.options().header("This file describes configuration of the different quest pools. See \"/quests pool\"."); config.save(file); - }else { + } else { config = YamlConfiguration.loadConfiguration(file); for (String key : config.getKeys(false)) { try { int id = Integer.parseInt(key); QuestPool pool = QuestPool.deserialize(id, config.getConfigurationSection(key)); pools.put(id, pool); - }catch (Exception ex) { + } catch (Exception ex) { BeautyQuests.logger.severe("An exception ocurred while loading quest pool " + key, ex); continue; } } } } - - public void save(QuestPool pool) { + + public void save(@NotNull QuestPool pool) { ConfigurationSection section = config.createSection(Integer.toString(pool.getID())); pool.save(section); try { config.save(file); - }catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); } } - - public QuestPool createPool(QuestPool editing, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, List<AbstractRequirement> requirements) { - if (editing != null) editing.unload(); - QuestPool pool = new QuestPool(editing == null ? pools.keySet().stream().mapToInt(Integer::intValue).max().orElse(-1) + 1 : editing.getID(), npcID, hologram, maxQuests, questsPerLaunch, redoAllowed, timeDiff, avoidDuplicates, requirements); + + public @NotNull QuestPool createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, int maxQuests, + int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, + @NotNull List<AbstractRequirement> requirements) { + + if (editing != null) + editing.unload(); + + QuestPool pool = new QuestPool( + editing == null ? pools.keySet().stream().mapToInt(Integer::intValue).max().orElse(-1) + 1 : editing.getID(), + npcID, hologram, maxQuests, questsPerLaunch, redoAllowed, timeDiff, avoidDuplicates, requirements); save(pool); pools.put(pool.getID(), pool); if (editing != null) { @@ -65,26 +73,27 @@ public QuestPool createPool(QuestPool editing, int npcID, String hologram, int m } return pool; } - + public void removePool(int id) { QuestPool pool = pools.remove(id); - if (pool == null) return; + if (pool == null) + return; pool.unload(); new ArrayList<>(pool.quests).forEach(quest -> quest.removeOption(OptionQuestPool.class)); // prevents concurrent config.set(Integer.toString(id), null); try { config.save(file); - }catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); } } - - public QuestPool getPool(int id) { + + public @Nullable QuestPool getPool(int id) { return pools.get(id); } - - public Collection<QuestPool> getPools() { + + public @NotNull @UnmodifiableView Collection<QuestPool> getPools() { return pools.values(); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java b/core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java index f965830e..cc4973ea 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java @@ -7,8 +7,9 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.bukkit.ChatColor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class ChatUtils { @@ -63,11 +64,12 @@ private static void test(String string, int line, int critical, String... expect * @param lineLength The length of a line of text. * @return An array of word-wrapped lines. */ - public static List<String> wordWrap(String rawString, int lineLength) { + public static @NotNull List<@NotNull String> wordWrap(@Nullable String rawString, int lineLength) { return wordWrap(rawString, lineLength, lineLength); } - public static List<String> wordWrap(String rawString, int maxLineLength, int criticalLineLength) { + public static @NotNull List<@NotNull String> wordWrap(@Nullable String rawString, int maxLineLength, + int criticalLineLength) { if (maxLineLength > criticalLineLength) maxLineLength = criticalLineLength; // A null string is a single line if (rawString == null) { @@ -190,7 +192,7 @@ public static List<String> wordWrap(String rawString, int maxLineLength, int cri } } - public static String appendRawColorString(String original, String appended) { + public static @NotNull String appendRawColorString(@NotNull String original, @NotNull String appended) { StringBuilder builder = new StringBuilder(original); StringBuilder hexBuilder = null; for (int colorIndex = 1; colorIndex < appended.length(); colorIndex += 2) { @@ -221,11 +223,12 @@ public static String appendRawColorString(String original, String appended) { return builder.toString(); } - private static String getColorDifference(String oldColors, String newColors) { + private static @NotNull String getColorDifference(@NotNull String oldColors, @NotNull String newColors) { return newColors.startsWith(oldColors) ? newColors.substring(oldColors.length()) : newColors; } - private static List<String> splitColoredWord(String string, int stringLength, int maxLength, int criticalLength, String startColors) { + private static @NotNull List<@NotNull String> splitColoredWord(@NotNull String string, int stringLength, int maxLength, + int criticalLength, @NotNull String startColors) { final String original = string; int loops = 0; List<String> split = new ArrayList<>(); @@ -284,7 +287,7 @@ private static List<String> splitColoredWord(String string, int stringLength, in return split; } - private static int getFirstTextIndex(String string) { + private static int getFirstTextIndex(@NotNull String string) { for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); if (i % 2 == 0) { @@ -296,7 +299,7 @@ private static int getFirstTextIndex(String string) { return string.length(); } - public static String translateHexColorCodes(String message) { + public static @NotNull String translateHexColorCodes(@NotNull String message) { Matcher matcher = HEX_COLOR.matcher(message); StringBuffer buffer = new StringBuffer(message.length() + 4 * 8); while (matcher.find()) { @@ -309,7 +312,7 @@ public static String translateHexColorCodes(String message) { return matcher.appendTail(buffer).toString(); } - public static String getLastColors(String originalColors, String appended) { + public static @NotNull String getLastColors(@NotNull String originalColors, @Nullable String appended) { if (appended == null || appended.length() == 0) return originalColors; StringBuilder builder = originalColors == null ? new StringBuilder() : new StringBuilder(originalColors); StringBuilder hexBuilder = null; diff --git a/core/src/main/java/fr/skytasul/quests/utils/Lang.java b/core/src/main/java/fr/skytasul/quests/utils/Lang.java index b86b0569..d7efcaa5 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Lang.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Lang.java @@ -1,5 +1,8 @@ package fr.skytasul.quests.utils; +import java.util.Objects; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.Locale; /** @@ -855,32 +858,32 @@ public enum Lang implements Locale { private static final String DEFAULT_STRING = "§cnot loaded"; - private final String path; - private final Lang prefix; + private final @NotNull String path; + private final @Nullable Lang prefix; - private String value = DEFAULT_STRING; + private @NotNull String value = DEFAULT_STRING; - private Lang(String path){ + private Lang(@NotNull String path) { this(path, null); } - private Lang(String path, Lang prefix) { + private Lang(@NotNull String path, @Nullable Lang prefix) { this.path = path; this.prefix = prefix; } @Override - public String getPath(){ + public @NotNull String getPath() { return path; } @Override - public void setValue(String value) { - this.value = value; + public void setValue(@NotNull String value) { + this.value = Objects.requireNonNull(value); } @Override - public String getValue() { + public @NotNull String getValue() { return prefix == null ? value : (prefix.toString() + value); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/Utils.java b/core/src/main/java/fr/skytasul/quests/utils/Utils.java index feb033c6..a0a35a10 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Utils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Utils.java @@ -44,6 +44,8 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.scoreboard.DisplaySlot; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.requirements.AbstractRequirement; @@ -300,7 +302,7 @@ public static <T, E> List<T> getKeysByValue(Map<T, E> map, E value) { return list; } - public static String format(String msg, Supplier<Object>... replace) { + public static @NotNull String format(@NotNull String msg, @NotNull Supplier<Object> @Nullable... replace) { if (replace != null && replace.length != 0) { for (int i = 0; i < replace.length; i++) { Supplier<Object> supplier = replace[i]; @@ -310,7 +312,7 @@ public static String format(String msg, Supplier<Object>... replace) { return msg; } - public static String format(String msg, Object... replace){ + public static @NotNull String format(@NotNull String msg, @Nullable Object @Nullable... replace) { if (replace != null && replace.length != 0){ for (int i = 0; i < replace.length; i++){ Object replacement = replace[i]; @@ -327,7 +329,7 @@ public static String format(String msg, Object... replace){ private static final Map<Integer, Pattern> REPLACEMENT_PATTERNS = new HashMap<>(); private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); - public static String format(String msg, int i, Supplier<Object> replace) { + public static String format(@NotNull String msg, int i, @NotNull Supplier<Object> replace) { Pattern pattern = REPLACEMENT_PATTERNS.computeIfAbsent(i, __ -> Pattern.compile("\\{" + i + "\\}")); Matcher matcher = pattern.matcher(msg); StringBuilder output = new StringBuilder(msg.length()); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java index 3e5f50d3..20110ef3 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java @@ -6,8 +6,7 @@ import org.bukkit.event.Listener; import com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent; - -import fr.skytasul.quests.api.events.BQBlockBreakEvent; +import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; public class BQTokenEnchant implements Listener { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java index 815082cd..dc2cbe71 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java @@ -10,8 +10,7 @@ import com.songoda.ultimatetimber.events.TreeFellEvent; import com.songoda.ultimatetimber.tree.ITreeBlock; - -import fr.skytasul.quests.api.events.BQBlockBreakEvent; +import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; public class BQUltimateTimber implements Listener { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_16.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_16.java index 341541cb..3706ee22 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_16.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_16.java @@ -5,8 +5,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.SmithItemEvent; - -import fr.skytasul.quests.api.events.BQCraftEvent; +import fr.skytasul.quests.api.events.internal.BQCraftEvent; public class Post1_16 implements Listener { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java index d81a5960..707756e7 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java @@ -3,18 +3,17 @@ import java.util.Collection; import java.util.stream.Collectors; import java.util.stream.StreamSupport; - import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; - +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration.ClickType; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.npcs.BQNPCsManager; - import net.citizensnpcs.Settings; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.CitizensReloadEvent; @@ -123,18 +122,23 @@ public boolean isSpawned() { } @Override - public Entity getEntity() { + public @NotNull Entity getEntity() { return npc.getEntity(); } @Override - public Location getLocation() { + public @NotNull Location getLocation() { return npc.getStoredLocation(); } @Override - public void setSkin(String skin) { - npc.getOrAddTrait(SkinTrait.class).setSkinName(skin); + public void setSkin(@Nullable String skin) { + if (skin == null) { + if (npc.hasTrait(SkinTrait.class)) + npc.getTraitNullable(SkinTrait.class).clearTexture(); + } else { + npc.getOrAddTrait(SkinTrait.class).setSkinName(skin); + } } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerExpanded.java b/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerExpanded.java index e14e07a0..51c39d46 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerExpanded.java +++ b/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerExpanded.java @@ -6,37 +6,40 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.utils.Lang; public class LoggerExpanded { - private Logger logger; + private final @NotNull Logger logger; - public LoggerExpanded(Logger logger) { + public LoggerExpanded(@NotNull Logger logger) { this.logger = logger; } - public void info(String msg) { + public void info(@Nullable String msg) { logger.info(msg); } - public void warning(String msg) { + public void warning(@Nullable String msg) { logger.log(Level.WARNING, msg); } - public void warning(String msg, Throwable throwable) { + public void warning(@Nullable String msg, @Nullable Throwable throwable) { logger.log(Level.WARNING, msg, throwable); } - public void severe(String msg) { + public void severe(@Nullable String msg) { logger.log(Level.SEVERE, msg); } - public void severe(String msg, Throwable throwable) { + public void severe(@Nullable String msg, @Nullable Throwable throwable) { logger.log(Level.SEVERE, msg, throwable); } - public <T> BiConsumer<T, Throwable> logError(Consumer<T> consumer, String friendlyErrorMessage, CommandSender sender) { + public <T> BiConsumer<T, Throwable> logError(@Nullable Consumer<T> consumer, @Nullable String friendlyErrorMessage, + @Nullable CommandSender sender) { return (object, ex) -> { if (ex == null) { if (consumer != null) @@ -55,11 +58,11 @@ public <T> BiConsumer<T, Throwable> logError(Consumer<T> consumer, String friend }; } - public <T> BiConsumer<T, Throwable> logError(String friendlyErrorMessage, CommandSender sender) { + public <T> BiConsumer<T, Throwable> logError(@Nullable String friendlyErrorMessage, @Nullable CommandSender sender) { return logError(null, friendlyErrorMessage, sender); } - public <T> BiConsumer<T, Throwable> logError(String friendlyErrorMessage) { + public <T> BiConsumer<T, Throwable> logError(@Nullable String friendlyErrorMessage) { return logError(null, friendlyErrorMessage, null); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java b/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java index 87e592ae..fb0a884b 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java @@ -6,6 +6,8 @@ import java.util.Spliterator; import java.util.Spliterators; import org.bukkit.block.Block; +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.Located; import fr.skytasul.quests.api.stages.types.Locatable.Located.LocatedBlock; @@ -21,42 +23,42 @@ public abstract class BQBlock { public static final String TAG_HEADER = "tag:"; public static final String CUSTOM_NAME_FOOTER = "|customname:"; - private final String customName; + private final @Nullable String customName; - private XMaterial cachedMaterial; - private String cachedName; + private @Nullable XMaterial cachedMaterial; + private @Nullable String cachedName; - protected BQBlock(String customName) { + protected BQBlock(@Nullable String customName) { this.customName = customName; } - protected abstract String getDataString(); + protected abstract @NotNull String getDataString(); - public abstract boolean applies(Block block); + public abstract boolean applies(@NotNull Block block); - public abstract XMaterial retrieveMaterial(); + public abstract @NotNull XMaterial retrieveMaterial(); - public final XMaterial getMaterial() { + public final @NotNull XMaterial getMaterial() { if (cachedMaterial == null) cachedMaterial = retrieveMaterial(); return cachedMaterial; } - public String getDefaultName() { + public @NotNull String getDefaultName() { return MinecraftNames.getMaterialName(getMaterial()); } - public final String getName() { + public final @NotNull String getName() { if (cachedName == null) cachedName = customName == null ? getDefaultName() : customName; return cachedName; } - public final String getAsString() { + public final @NotNull String getAsString() { return getDataString() + getFooter(); } - private String getFooter() { + private @NotNull String getFooter() { return customName == null ? "" : CUSTOM_NAME_FOOTER + customName; } @@ -65,7 +67,7 @@ public String toString() { return "BQBlock{" + getAsString() + "}"; } - public static BQBlock fromString(String string) { + public static @NotNull BQBlock fromString(@NotNull String string) { int nameIndex = string.lastIndexOf(CUSTOM_NAME_FOOTER); String customName = nameIndex == -1 ? null : string.substring(nameIndex + CUSTOM_NAME_FOOTER.length()); @@ -78,7 +80,8 @@ public static BQBlock fromString(String string) { return new BQBlockMaterial(customName, XMaterial.valueOf(string.substring(0, dataEnd))); } - public static Spliterator<Locatable.Located> getNearbyBlocks(Locatable.MultipleLocatable.NearbyFetcher fetcher, Collection<BQBlock> types) { + public static @NotNull Spliterator<Locatable.@NotNull Located> getNearbyBlocks( + @NotNull Locatable.MultipleLocatable.NearbyFetcher fetcher, @NotNull Collection<@NotNull BQBlock> types) { if (!fetcher.isTargeting(LocatedType.BLOCK)) return Spliterators.emptySpliterator(); int minY = (int) Math.max(fetcher.getCenter().getWorld().getMinHeight(), fetcher.getCenter().getY() - fetcher.getMaxDistance()); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/CountableObject.java b/core/src/main/java/fr/skytasul/quests/utils/types/CountableObject.java index c0fe101b..a11cea5f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/CountableObject.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/CountableObject.java @@ -1,36 +1,40 @@ package fr.skytasul.quests.utils.types; +import java.util.Objects; import java.util.UUID; +import org.jetbrains.annotations.NotNull; public interface CountableObject<T> { + @NotNull UUID getUUID(); + @NotNull T getObject(); int getAmount(); - default MutableCountableObject<T> toMutable() { + default @NotNull MutableCountableObject<T> toMutable() { return createMutable(getUUID(), getObject(), getAmount()); } public interface MutableCountableObject<T> extends CountableObject<T> { - void setObject(T object); + void setObject(@NotNull T object); void setAmount(int newAmount); - default CountableObject<T> toImmutable() { + default @NotNull CountableObject<T> toImmutable() { return create(getUUID(), getObject(), getAmount()); } } - static <T> CountableObject<T> create(UUID uuid, T object, int amount) { + static <T> @NotNull CountableObject<T> create(@NotNull UUID uuid, @NotNull T object, int amount) { return new DummyCountableObject<>(uuid, object, amount); } - static <T> MutableCountableObject<T> createMutable(UUID uuid, T object, int amount) { + static <T> @NotNull MutableCountableObject<T> createMutable(@NotNull UUID uuid, @NotNull T object, int amount) { return new DummyMutableCountableObject<>(uuid, object, amount); } @@ -41,8 +45,8 @@ class DummyCountableObject<T> implements CountableObject<T> { private final int amount; public DummyCountableObject(UUID uuid, T object, int amount) { - this.uuid = uuid; - this.object = object; + this.uuid = Objects.requireNonNull(uuid); + this.object = Objects.requireNonNull(object); this.amount = amount; } @@ -70,8 +74,8 @@ class DummyMutableCountableObject<T> implements MutableCountableObject<T> { private int amount; public DummyMutableCountableObject(UUID uuid, T object, int amount) { - this.uuid = uuid; - this.object = object; + this.uuid = Objects.requireNonNull(uuid); + this.object = Objects.requireNonNull(object); this.amount = amount; } From a748c1d3a1f73c72111e065c1a660fb64766ec42 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 22 Apr 2023 16:09:59 +0200 Subject: [PATCH 07/95] :coffin: Removed old SpigotUpdater --- .../skytasul/quests/utils/SpigotUpdater.java | 114 ------------------ 1 file changed, 114 deletions(-) delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/SpigotUpdater.java diff --git a/core/src/main/java/fr/skytasul/quests/utils/SpigotUpdater.java b/core/src/main/java/fr/skytasul/quests/utils/SpigotUpdater.java deleted file mode 100644 index 6e61e7cb..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/SpigotUpdater.java +++ /dev/null @@ -1,114 +0,0 @@ -package fr.skytasul.quests.utils; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; - -import org.bukkit.plugin.Plugin; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -import fr.skytasul.quests.BeautyQuests; - -/** - * @author <a href="https://inventivetalent.org">inventivetalent</a>, SkytAsul - */ -public class SpigotUpdater extends Thread { - private final Plugin plugin; - private boolean enabled; - private URL url; - - public SpigotUpdater(Plugin plugin, int resourceID) throws IOException { - this.enabled = true; - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } else if (resourceID == 0) { - throw new IllegalArgumentException("Resource ID cannot be null (0)"); - } else { - this.plugin = plugin; - this.url = new URL("https://api.inventivetalent.org/spigot/resource-simple/" + resourceID); - this.enabled = BeautyQuests.getInstance().getConfig().getBoolean("checkUpdates"); - super.start(); - } - } - - public synchronized void start() { - } - - public void run() { - if (this.plugin.isEnabled()) { - if (this.enabled) { - - HttpURLConnection connection = null; - - try { - connection = (HttpURLConnection) this.url.openConnection(); - connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); - connection.setRequestMethod("GET"); - BufferedReader e = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String e11 = ""; - - for (String line = null; (line = e.readLine()) != null; e11 = e11 + line) { - ; - } - - e.close(); - JSONObject json = null; - - try { - json = (JSONObject) (new JSONParser()).parse(e11); - } catch (ParseException var9) { - ; - } - - String currentVersion = null; - if (json != null && json.containsKey("version")) { - String version = (String) json.get("version"); - if (version != null && !version.isEmpty()) { - currentVersion = version; - } - } - - if (currentVersion == null) return; - - String v = this.plugin.getDescription().getVersion(); - if (v.contains("_")){ - plugin.getLogger().info("You are using a snapshot version! (" + v + ") Current version: " + currentVersion); - }else if (!currentVersion.equals(v)) { - try { - boolean beta = false; - String[] current = currentVersion.split("\\."); - String[] last = this.plugin.getDescription().getVersion().split("\\."); - for (int i = 0;; i++){ - if (i == current.length){ - beta = true; - break; - }else if (i == last.length) break; - int c = Integer.parseInt(current[i]); - int l = Integer.parseInt(last[i]); - if (c > l) break; - if (c < l){ - beta = true; - break; - } - } - if (beta){ - sendNewVersionMessage("Are you a beta-tester ? Current version: " + currentVersion + "!"); - }else sendNewVersionMessage("You are using an old version of plugin. New version: " + currentVersion + "!"); - }catch (Throwable ex){ - sendNewVersionMessage("Found another online version: " + currentVersion + "!"); - } - } - } catch (IOException var10) {} - - } - } - } - - private void sendNewVersionMessage(String msg){ - this.plugin.getLogger().info(msg + " (Your version is " + this.plugin.getDescription().getVersion() + ")"); - } -} \ No newline at end of file From a686fe4af6968f021f0e5ee39ecbe8a6219dd1b0 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 22 Apr 2023 17:37:15 +0200 Subject: [PATCH 08/95] :arrow_up: :art: Upgraded XSeries * upgraded XSeries (XMaterial, XPotion, XBlock) to version 9.3.1 * no longer copying XSeries classes manually, now using maven to shade the classes * updated all imports style --- core/pom.xml | 19 + .../skytasul/quests/QuestsConfiguration.java | 2 +- .../fr/skytasul/quests/QuestsListener.java | 2 +- .../fr/skytasul/quests/api/QuestsHandler.java | 1 - .../quests/api/data/SQLDataSaver.java | 2 - .../java/fr/skytasul/quests/api/mobs/Mob.java | 2 +- .../api/options/QuestOptionBoolean.java | 1 - .../quests/api/options/QuestOptionItem.java | 4 +- .../quests/api/options/QuestOptionObject.java | 4 +- .../api/options/QuestOptionRewards.java | 1 - .../quests/api/options/QuestOptionString.java | 4 +- .../api/options/UpdatableOptionSet.java | 1 - .../api/stages/AbstractCountableStage.java | 1 - .../quests/api/stages/StageHandler.java | 1 - .../api/stages/types/AbstractEntityStage.java | 2 +- .../api/stages/types/AbstractItemStage.java | 2 +- .../quests/api/stages/types/Locatable.java | 1 + .../quests/commands/CommandsPlayer.java | 3 - .../quests/commands/CommandsRoot.java | 1 - .../quests/commands/CommandsScoreboard.java | 2 - .../quests/commands/OutsideEditor.java | 1 - .../quests/editors/CancellableEditor.java | 1 - .../skytasul/quests/editors/DialogEditor.java | 1 - .../fr/skytasul/quests/editors/SelectNPC.java | 1 - .../skytasul/quests/editors/TextEditor.java | 2 - .../quests/editors/TextListEditor.java | 2 - .../quests/editors/WaitBlockClick.java | 2 - .../fr/skytasul/quests/editors/WaitClick.java | 1 - .../editors/checkers/CollectionParser.java | 2 - .../quests/editors/checkers/ColorParser.java | 2 - .../editors/checkers/DurationParser.java | 1 - .../editors/checkers/MaterialParser.java | 3 +- .../quests/editors/checkers/NumberParser.java | 2 - .../editors/checkers/PatternParser.java | 2 - .../checkers/ScoreboardObjectiveParser.java | 1 - .../fr/skytasul/quests/gui/ItemUtils.java | 7 +- .../quests/gui/blocks/SelectBlockGUI.java | 2 +- .../quests/gui/creation/CommandGUI.java | 4 +- .../quests/gui/creation/FinishGUI.java | 2 +- .../quests/gui/creation/ItemsGUI.java | 4 +- .../gui/creation/QuestCreationSession.java | 1 - .../quests/gui/creation/QuestObjectGUI.java | 2 +- .../quests/gui/creation/stages/Line.java | 1 - .../quests/gui/creation/stages/StagesGUI.java | 4 +- .../skytasul/quests/gui/misc/BranchesGUI.java | 4 +- .../skytasul/quests/gui/misc/ConfirmGUI.java | 3 +- .../quests/gui/misc/DamageCausesGUI.java | 4 +- .../quests/gui/misc/ItemComparisonGUI.java | 4 +- .../quests/gui/misc/ItemCreatorGUI.java | 4 +- .../fr/skytasul/quests/gui/misc/ItemGUI.java | 2 - .../fr/skytasul/quests/gui/misc/ListBook.java | 1 - .../fr/skytasul/quests/gui/misc/TitleGUI.java | 4 +- .../quests/gui/mobs/EntityTypeGUI.java | 4 +- .../quests/gui/mobs/MobSelectionGUI.java | 2 - .../fr/skytasul/quests/gui/npc/NPCGUI.java | 4 +- .../fr/skytasul/quests/gui/npc/SelectGUI.java | 4 +- .../gui/particles/ParticleEffectGUI.java | 4 +- .../quests/gui/particles/ParticleListGUI.java | 4 +- .../quests/gui/permissions/PermissionGUI.java | 4 +- .../gui/permissions/PermissionListGUI.java | 4 +- .../quests/gui/pools/PoolEditGUI.java | 4 +- .../quests/gui/pools/PoolsManageGUI.java | 4 +- .../quests/gui/quests/DialogHistoryGUI.java | 4 +- .../quests/gui/quests/PlayerListGUI.java | 2 +- .../quests/gui/quests/QuestsListGUI.java | 2 - .../quests/gui/templates/ChooseGUI.java | 2 - .../quests/gui/templates/ListGUI.java | 2 +- .../quests/gui/templates/PagedGUI.java | 2 +- .../quests/gui/templates/StaticPagedGUI.java | 2 - .../quests/options/OptionCancelRewards.java | 4 +- .../quests/options/OptionConfirmMessage.java | 3 +- .../quests/options/OptionDescription.java | 2 +- .../quests/options/OptionEndMessage.java | 3 +- .../quests/options/OptionEndRewards.java | 2 +- .../quests/options/OptionEndSound.java | 3 +- .../quests/options/OptionFailOnDeath.java | 1 - .../quests/options/OptionFirework.java | 4 +- .../quests/options/OptionHologramLaunch.java | 2 +- .../options/OptionHologramLaunchNo.java | 2 +- .../quests/options/OptionHologramText.java | 3 +- .../skytasul/quests/options/OptionName.java | 3 +- .../quests/options/OptionQuestItem.java | 3 +- .../quests/options/OptionQuestPool.java | 4 +- .../quests/options/OptionRequirements.java | 2 +- .../quests/options/OptionStartDialog.java | 2 +- .../quests/options/OptionStartMessage.java | 3 +- .../quests/options/OptionStartRewards.java | 3 +- .../quests/options/OptionStarterNPC.java | 4 +- .../skytasul/quests/options/OptionTimer.java | 3 +- .../quests/options/OptionVisibility.java | 4 +- .../fr/skytasul/quests/players/AdminMode.java | 2 - .../quests/players/PlayerQuestDatas.java | 1 - .../players/accounts/HookedAccount.java | 1 - .../quests/players/accounts/UUIDAccount.java | 1 - .../requirements/EquipmentRequirement.java | 2 +- .../requirements/FactionRequirement.java | 2 +- .../requirements/PermissionsRequirement.java | 2 +- .../quests/rewards/CommandReward.java | 2 +- .../rewards/RequirementDependentReward.java | 2 +- .../fr/skytasul/quests/stages/StageArea.java | 2 +- .../fr/skytasul/quests/stages/StageBreed.java | 1 - .../quests/stages/StageBringBack.java | 2 +- .../skytasul/quests/stages/StageBucket.java | 2 +- .../fr/skytasul/quests/stages/StageChat.java | 3 +- .../fr/skytasul/quests/stages/StageCraft.java | 4 +- .../quests/stages/StageDealDamage.java | 4 +- .../fr/skytasul/quests/stages/StageDeath.java | 4 +- .../skytasul/quests/stages/StageEatDrink.java | 2 +- .../skytasul/quests/stages/StageEnchant.java | 2 +- .../fr/skytasul/quests/stages/StageFish.java | 2 +- .../skytasul/quests/stages/StageInteract.java | 2 +- .../skytasul/quests/stages/StageLocation.java | 2 +- .../fr/skytasul/quests/stages/StageMelt.java | 2 +- .../fr/skytasul/quests/stages/StageMine.java | 2 +- .../fr/skytasul/quests/stages/StageMobs.java | 2 +- .../fr/skytasul/quests/stages/StageNPC.java | 4 +- .../quests/stages/StagePlaceBlocks.java | 2 +- .../skytasul/quests/stages/StagePlayTime.java | 4 +- .../fr/skytasul/quests/stages/StageTame.java | 1 - .../quests/structure/pools/QuestPool.java | 2 +- .../utils/CustomizedObjectTypeAdapter.java | 1 - .../fr/skytasul/quests/utils/Database.java | 4 - .../skytasul/quests/utils/MinecraftNames.java | 107 +- .../skytasul/quests/utils/ParticleEffect.java | 2 - .../java/fr/skytasul/quests/utils/Utils.java | 1 + .../java/fr/skytasul/quests/utils/XBlock.java | 857 ------- .../fr/skytasul/quests/utils/XMaterial.java | 2238 ----------------- .../fr/skytasul/quests/utils/XPotion.java | 436 ---- .../quests/utils/compatibility/BQCMI.java | 3 - .../compatibility/BQHolographicDisplays2.java | 3 - .../compatibility/BQHolographicDisplays3.java | 3 - .../utils/compatibility/BQTokenEnchant.java | 1 - .../utils/compatibility/BQUltimateTimber.java | 2 - .../compatibility/DependenciesManager.java | 2 +- .../quests/utils/compatibility/Factions.java | 1 - .../quests/utils/compatibility/GPS.java | 2 - .../quests/utils/compatibility/Jobs.java | 1 - .../utils/compatibility/McCombatLevel.java | 1 - .../quests/utils/compatibility/McMMO.java | 1 - .../quests/utils/compatibility/Paper.java | 2 - .../quests/utils/compatibility/Post1_13.java | 2 +- .../compatibility/QuestsPlaceholders.java | 3 - .../quests/utils/compatibility/SkillAPI.java | 2 - .../quests/utils/compatibility/Vault.java | 1 - .../mobs/BQAdvancedSpawners.java | 5 +- .../utils/compatibility/mobs/BQBoss.java | 4 +- .../compatibility/mobs/BQLevelledMobs.java | 2 +- .../mobs/BukkitEntityFactory.java | 4 +- .../compatibility/mobs/CitizensFactory.java | 3 - .../utils/compatibility/mobs/MythicMobs.java | 2 +- .../utils/compatibility/mobs/MythicMobs5.java | 2 +- .../utils/compatibility/npcs/BQSentinel.java | 2 - .../worldguard/BQWorldGuard.java | 2 +- .../worldguard/WorldGuardEntryEvent.java | 2 - .../fr/skytasul/quests/utils/nms/NMS.java | 3 - .../fr/skytasul/quests/utils/nms/NullNMS.java | 2 - .../skytasul/quests/utils/types/BQBlock.java | 4 +- .../skytasul/quests/utils/types/Command.java | 2 - .../skytasul/quests/utils/types/Dialog.java | 2 - .../skytasul/quests/utils/types/Message.java | 3 - .../quests/utils/types/NumberedList.java | 1 - .../quests/utils/types/Permission.java | 2 - .../fr/skytasul/quests/utils/types/Title.java | 1 - 163 files changed, 206 insertions(+), 3831 deletions(-) delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/XBlock.java delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/XMaterial.java delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/XPotion.java diff --git a/core/pom.xml b/core/pom.xml index 4a76f0e2..a99e8825 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -55,7 +55,21 @@ <pattern>com.zaxxer.hikari</pattern> <shadedPattern>fr.skytasul.quests.utils.hikari</shadedPattern> </relocation> + <relocation> + <pattern>com.cryptomorin.xseries</pattern> + <shadedPattern>fr.skytasul.quests.utils</shadedPattern> + </relocation> </relocations> + <filters> + <filter> + <artifact>com.github.cryptomorin:XSeries</artifact> + <includes> + <include>com/cryptomorin/xseries/XMaterial*</include> + <include>com/cryptomorin/xseries/XBlock*</include> + <include>com/cryptomorin/xseries/XPotion*</include> + </includes> + </filter> + </filters> </configuration> <executions> <execution> @@ -323,6 +337,11 @@ <artifactId>HikariCP</artifactId> <version>4.0.3</version> <!-- For Java 8 compatibility --> </dependency> + <dependency> + <groupId>com.github.cryptomorin</groupId> + <artifactId>XSeries</artifactId> + <version>9.3.1</version> + </dependency> <!-- Local JARs --> <dependency> diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java b/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java index 88b140d3..8286e264 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java @@ -15,6 +15,7 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; +import com.cryptomorin.xseries.XMaterial; import com.google.common.collect.Sets; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.options.description.QuestDescription; @@ -25,7 +26,6 @@ import fr.skytasul.quests.utils.MinecraftNames; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Accounts; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.nms.NMS; diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index b4c15ec9..215450cd 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -25,6 +25,7 @@ import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ComplexRecipe; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; @@ -45,7 +46,6 @@ import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Paper; public class QuestsListener implements Listener{ diff --git a/core/src/main/java/fr/skytasul/quests/api/QuestsHandler.java b/core/src/main/java/fr/skytasul/quests/api/QuestsHandler.java index 4d89d34b..176dbc97 100644 --- a/core/src/main/java/fr/skytasul/quests/api/QuestsHandler.java +++ b/core/src/main/java/fr/skytasul/quests/api/QuestsHandler.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.api; import org.bukkit.entity.Player; - import fr.skytasul.quests.api.stages.StageHandler; import fr.skytasul.quests.players.PlayerAccount; import fr.skytasul.quests.structure.Quest; diff --git a/core/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java b/core/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java index aa121302..9b6b4ce4 100644 --- a/core/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java +++ b/core/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java @@ -9,9 +9,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; - import com.google.common.collect.ImmutableMap; - import fr.skytasul.quests.utils.CustomizedObjectTypeAdapter; public class SQLDataSaver<T> { diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java b/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java index bb3de279..0e3d919a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java +++ b/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java @@ -9,9 +9,9 @@ import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class Mob<D> implements Cloneable { diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java index 0606aa7d..dc4aa876 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java @@ -4,7 +4,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java index 66530cd1..b2cf98e7 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java @@ -3,18 +3,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.gui.misc.ItemGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public abstract class QuestOptionItem extends QuestOption<ItemStack> { diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java index b31de3f1..b3a44824 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java @@ -3,12 +3,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectCreator; import fr.skytasul.quests.api.objects.QuestObjectLocation; @@ -17,7 +16,6 @@ import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.XMaterial; public abstract class QuestOptionObject<T extends QuestObject, C extends QuestObjectCreator<T>> extends QuestOption<List<T>> { diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java index 33c6db02..340e141a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.api.options; import java.util.Map; - import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.rewards.AbstractReward; diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java index 0a95ee59..821c1834 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java @@ -4,17 +4,15 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.TextListEditor; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.utils.XMaterial; public abstract class QuestOptionString extends QuestOption<String> { diff --git a/core/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java b/core/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java index e54b52ce..ac9799ee 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java +++ b/core/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java @@ -5,7 +5,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; - import fr.skytasul.quests.api.options.UpdatableOptionSet.Updatable; @SuppressWarnings ("rawtypes") diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java index 6fcbceb2..231bd442 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java @@ -2,7 +2,6 @@ import java.util.Map; import java.util.Map.Entry; - import fr.skytasul.quests.structure.QuestBranch; @Deprecated diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java b/core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java index f153f3c4..66154747 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.api.stages; import org.bukkit.entity.Player; - import fr.skytasul.quests.players.PlayerAccount; public interface StageHandler { diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index 849210f6..ecddeb35 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -13,6 +13,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.stages.AbstractStage; @@ -31,7 +32,6 @@ import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.MinecraftNames; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; @LocatableType (types = LocatedType.ENTITY) public abstract class AbstractEntityStage extends AbstractStage implements Locatable.MultipleLocatable { diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java index 423c5154..78e88f2a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java @@ -10,6 +10,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.gui.ItemUtils; @@ -19,7 +20,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.CountableObject; public abstract class AbstractItemStage extends AbstractCountableStage<ItemStack> { diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java b/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java index f6b100cc..255f724e 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java +++ b/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java @@ -14,6 +14,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.stages.types.Locatable.MultipleLocatable; import fr.skytasul.quests.utils.DebugUtils; /** diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java index fcbca2e4..456e2239 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java @@ -1,9 +1,7 @@ package fr.skytasul.quests.commands; import java.util.Optional; - import org.bukkit.entity.Player; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.gui.quests.PlayerListGUI; @@ -14,7 +12,6 @@ import fr.skytasul.quests.structure.Quest; import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.utils.Lang; - import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Subcommand; import revxrsal.commands.bukkit.BukkitCommandActor; diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java index 554586f2..fc90f428 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java @@ -3,7 +3,6 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; - import revxrsal.commands.annotation.Command; import revxrsal.commands.annotation.Description; import revxrsal.commands.annotation.Subcommand; 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 06e03afc..4ca70c7d 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java @@ -1,11 +1,9 @@ package fr.skytasul.quests.commands; import org.bukkit.entity.Player; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.scoreboards.Scoreboard; import fr.skytasul.quests.utils.Lang; - import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Optional; import revxrsal.commands.annotation.Range; diff --git a/core/src/main/java/fr/skytasul/quests/commands/OutsideEditor.java b/core/src/main/java/fr/skytasul/quests/commands/OutsideEditor.java index d8e8f7fc..6cc75862 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/OutsideEditor.java +++ b/core/src/main/java/fr/skytasul/quests/commands/OutsideEditor.java @@ -2,7 +2,6 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Retention; import java.lang.annotation.Target; diff --git a/core/src/main/java/fr/skytasul/quests/editors/CancellableEditor.java b/core/src/main/java/fr/skytasul/quests/editors/CancellableEditor.java index 6acc8149..edf3d2bc 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/CancellableEditor.java +++ b/core/src/main/java/fr/skytasul/quests/editors/CancellableEditor.java @@ -4,7 +4,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerInteractEvent; - import fr.skytasul.quests.gui.ItemUtils; public abstract class CancellableEditor extends InventoryClear { diff --git a/core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java b/core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java index b1a6427b..2af87d79 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java +++ b/core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.editors; import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.types.Dialog; diff --git a/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java b/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java index 3c5b7b85..4e59f6a3 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java +++ b/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.editors; import java.util.function.Consumer; - import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; diff --git a/core/src/main/java/fr/skytasul/quests/editors/TextEditor.java b/core/src/main/java/fr/skytasul/quests/editors/TextEditor.java index 62c3d015..49a1bdc4 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/TextEditor.java +++ b/core/src/main/java/fr/skytasul/quests/editors/TextEditor.java @@ -1,10 +1,8 @@ package fr.skytasul.quests.editors; import java.util.function.Consumer; - import org.apache.commons.lang.Validate; import org.bukkit.entity.Player; - import fr.skytasul.quests.editors.checkers.AbstractParser; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; diff --git a/core/src/main/java/fr/skytasul/quests/editors/TextListEditor.java b/core/src/main/java/fr/skytasul/quests/editors/TextListEditor.java index a6f24252..86157ebb 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/TextListEditor.java +++ b/core/src/main/java/fr/skytasul/quests/editors/TextListEditor.java @@ -4,10 +4,8 @@ import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Predicate; - import org.apache.commons.lang.Validate; import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; diff --git a/core/src/main/java/fr/skytasul/quests/editors/WaitBlockClick.java b/core/src/main/java/fr/skytasul/quests/editors/WaitBlockClick.java index 5887121a..ad27e7f6 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/WaitBlockClick.java +++ b/core/src/main/java/fr/skytasul/quests/editors/WaitBlockClick.java @@ -1,14 +1,12 @@ package fr.skytasul.quests.editors; import java.util.function.Consumer; - import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.gui.ItemUtils; public class WaitBlockClick extends InventoryClear{ diff --git a/core/src/main/java/fr/skytasul/quests/editors/WaitClick.java b/core/src/main/java/fr/skytasul/quests/editors/WaitClick.java index 849ac1c6..39cdea38 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/WaitClick.java +++ b/core/src/main/java/fr/skytasul/quests/editors/WaitClick.java @@ -6,7 +6,6 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.gui.ItemUtils; public class WaitClick extends InventoryClear{ diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/CollectionParser.java b/core/src/main/java/fr/skytasul/quests/editors/checkers/CollectionParser.java index dd280557..430bd832 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/CollectionParser.java +++ b/core/src/main/java/fr/skytasul/quests/editors/checkers/CollectionParser.java @@ -4,9 +4,7 @@ import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; - import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.Lang; public class CollectionParser<T> implements AbstractParser<T> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/ColorParser.java b/core/src/main/java/fr/skytasul/quests/editors/checkers/ColorParser.java index 18c877c0..e7d9e264 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/ColorParser.java +++ b/core/src/main/java/fr/skytasul/quests/editors/checkers/ColorParser.java @@ -2,11 +2,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.bukkit.ChatColor; import org.bukkit.Color; import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.Lang; public class ColorParser implements AbstractParser<Color> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/DurationParser.java b/core/src/main/java/fr/skytasul/quests/editors/checkers/DurationParser.java index a3fd82fb..46eba6a1 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/DurationParser.java +++ b/core/src/main/java/fr/skytasul/quests/editors/checkers/DurationParser.java @@ -4,7 +4,6 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.apache.commons.lang.StringUtils; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/MaterialParser.java b/core/src/main/java/fr/skytasul/quests/editors/checkers/MaterialParser.java index 7d9fa47c..96c26277 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/MaterialParser.java +++ b/core/src/main/java/fr/skytasul/quests/editors/checkers/MaterialParser.java @@ -2,9 +2,8 @@ import org.bukkit.Material; import org.bukkit.entity.Player; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/NumberParser.java b/core/src/main/java/fr/skytasul/quests/editors/checkers/NumberParser.java index 5ac85b15..46c87322 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/NumberParser.java +++ b/core/src/main/java/fr/skytasul/quests/editors/checkers/NumberParser.java @@ -1,9 +1,7 @@ package fr.skytasul.quests.editors.checkers; import java.math.BigDecimal; - import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.Lang; public class NumberParser<T extends Number> implements AbstractParser<T> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/PatternParser.java b/core/src/main/java/fr/skytasul/quests/editors/checkers/PatternParser.java index 966b3fa2..d11db8d5 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/PatternParser.java +++ b/core/src/main/java/fr/skytasul/quests/editors/checkers/PatternParser.java @@ -2,9 +2,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; - import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.Lang; public class PatternParser implements AbstractParser<Pattern> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/ScoreboardObjectiveParser.java b/core/src/main/java/fr/skytasul/quests/editors/checkers/ScoreboardObjectiveParser.java index ada8f708..4f21b4f0 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/ScoreboardObjectiveParser.java +++ b/core/src/main/java/fr/skytasul/quests/editors/checkers/ScoreboardObjectiveParser.java @@ -3,7 +3,6 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scoreboard.Objective; - import fr.skytasul.quests.utils.Lang; public class ScoreboardObjectiveParser implements AbstractParser<Objective> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java b/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java index e24f0a1f..77b948d9 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java +++ b/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; - import org.apache.commons.lang.Validate; import org.bukkit.DyeColor; import org.bukkit.enchantments.Enchantment; @@ -17,14 +16,12 @@ import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.SkullMeta; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.utils.ChatUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.MinecraftNames; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.nms.NMS; - import net.md_5.bungee.api.ChatColor; public class ItemUtils { @@ -380,7 +377,7 @@ public static ItemStack set(ItemStack itemSwitch, boolean enable) { if (itemSwitch == null) return null; String name = getName(itemSwitch); name(itemSwitch, (enable ? "§a" : "§7") + name.substring(2)); - if (XMaterial.isNewVersion()){ + if (NMS.getMCVersion() >= 13) { itemSwitch.setType(enable ? XMaterial.LIME_DYE.parseMaterial() : XMaterial.GRAY_DYE.parseMaterial()); }else itemSwitch.setDurability((short) (enable ? 10 : 8)); return itemSwitch; 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 fba5aba0..1b65c0d4 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 @@ -10,6 +10,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.MaterialParser; @@ -18,7 +19,6 @@ import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; import fr.skytasul.quests.utils.types.BQBlock; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java index 749d9d23..9abd9894 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java @@ -1,14 +1,13 @@ package fr.skytasul.quests.gui.creation; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.NumberParser; import fr.skytasul.quests.gui.CustomInventory; @@ -16,7 +15,6 @@ import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.types.Command; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java index de900349..da4dd37c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java @@ -10,6 +10,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; @@ -33,7 +34,6 @@ import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.nms.NMS; public class FinishGUI extends UpdatableOptionSet<Updatable> implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java index 651889cd..a068396e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java @@ -5,20 +5,18 @@ import java.util.Map; import java.util.function.Consumer; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.CustomInventory; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.misc.ItemCreatorGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class ItemsGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java index 78414bf8..d66fd7de 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.gui.creation; import org.bukkit.entity.Player; - import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.creation.stages.StagesGUI; import fr.skytasul.quests.structure.Quest; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java index bc738e6d..b34f255f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -31,7 +32,6 @@ import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.nms.NMS; public class QuestObjectGUI<T extends QuestObject> extends ListGUI<T> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java index f766b088..b333cf7c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java @@ -3,7 +3,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.StageRunnable.StageRunnableClick; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index e3633b7e..6c3da616 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -4,13 +4,12 @@ import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; - import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; @@ -26,7 +25,6 @@ import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class StagesGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java index ded4c6c4..34ca9fd4 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java @@ -2,17 +2,15 @@ import java.util.LinkedList; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.CustomInventory; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class BranchesGUI implements CustomInventory { // WIP diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java index 1d896c50..973865ba 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java @@ -6,12 +6,11 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.CustomInventory; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class ConfirmGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java index 795cb533..70344230 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java @@ -5,16 +5,14 @@ import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; - import org.bukkit.DyeColor; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.ListGUI; import fr.skytasul.quests.gui.templates.StaticPagedGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class DamageCausesGUI extends ListGUI<DamageCause> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java index 8054b6ec..e4d6e7b5 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java @@ -14,7 +14,7 @@ import fr.skytasul.quests.gui.templates.PagedGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; +import fr.skytasul.quests.utils.nms.NMS; public class ItemComparisonGUI extends PagedGUI<ItemComparison> { @@ -46,7 +46,7 @@ public static void initialize() { Lang.comparisonMaterialLore.toString(), (item1, item2) -> { if (item2.getType() != item1.getType()) return false; - if (item1.getType().getMaxDurability() > 0 || XMaterial.isNewVersion()) + if (item1.getType().getMaxDurability() > 0 || NMS.getMCVersion() >= 13) return true; return item2.getDurability() == item1.getDurability(); })); diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java index e3b3624d..7a1a40c0 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -12,7 +11,7 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.TextListEditor; import fr.skytasul.quests.editors.checkers.MaterialParser; @@ -21,7 +20,6 @@ import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class ItemCreatorGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java index 659050c6..9d6fd670 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.gui.misc; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.entity.Player; @@ -9,7 +8,6 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.gui.CustomInventory; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.ItemsGUI; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java index e830e0c0..3265d3da 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java @@ -5,7 +5,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; - import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.options.OptionRequirements; import fr.skytasul.quests.options.OptionStarterNPC; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index d33a5651..12ebf95a 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -1,14 +1,13 @@ package fr.skytasul.quests.gui.misc; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.NumberParser; @@ -17,7 +16,6 @@ import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.Title; public class TitleGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java index 5be127a7..2e0c0647 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java @@ -5,20 +5,18 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; - import org.bukkit.DyeColor; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.PagedGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class EntityTypeGUI extends PagedGUI<EntityType>{ diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java index b9e9b655..e1513270 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java @@ -1,13 +1,11 @@ package fr.skytasul.quests.gui.mobs; import java.util.function.Consumer; - import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.mobs.Mob; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.gui.templates.PagedGUI; diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java index 5a07ef14..ddf1a562 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java @@ -1,14 +1,13 @@ package fr.skytasul.quests.gui.npc; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.editors.TextEditor; @@ -19,7 +18,6 @@ import fr.skytasul.quests.gui.mobs.EntityTypeGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class NPCGUI implements CustomInventory{ diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java index 0ca301ed..aa5ba627 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java @@ -1,14 +1,13 @@ package fr.skytasul.quests.gui.npc; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.editors.SelectNPC; import fr.skytasul.quests.gui.CustomInventory; @@ -16,7 +15,6 @@ import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class SelectGUI implements CustomInventory{ diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index 132d675e..25be4d10 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -4,7 +4,6 @@ import java.util.List; import java.util.function.Consumer; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Particle; @@ -12,7 +11,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.ColorParser; import fr.skytasul.quests.gui.CustomInventory; @@ -21,7 +20,6 @@ import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java index 23aa122b..296b17b1 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java @@ -4,17 +4,15 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; - import org.bukkit.DyeColor; import org.bukkit.Particle; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.StaticPagedGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.ParticleEffect; -import fr.skytasul.quests.utils.XMaterial; public class ParticleListGUI extends StaticPagedGUI<Particle> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java index bdea920c..41cc4ff0 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.gui.permissions; import java.util.function.Consumer; - import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -9,13 +8,12 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.editors.checkers.WorldParser; import fr.skytasul.quests.gui.CustomInventory; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.Permission; public class PermissionGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java index f0661da9..c4a8e9dd 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java @@ -3,15 +3,13 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Function; - import org.bukkit.DyeColor; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.ListGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.Permission; public class PermissionListGUI extends ListGUI<Permission> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index 6c6aa9ba..0c2e8c66 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -3,14 +3,13 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; - import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectLocation; @@ -27,7 +26,6 @@ import fr.skytasul.quests.structure.pools.QuestPool; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class PoolEditGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java index 8f523bca..8a425a12 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java @@ -3,19 +3,17 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; - import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.PagedGUI; import fr.skytasul.quests.structure.pools.QuestPool; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class PoolsManageGUI extends PagedGUI<QuestPool> { 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 ade56677..dc095abc 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 @@ -6,7 +6,6 @@ import java.util.LinkedList; import java.util.List; import java.util.stream.Stream; - import org.apache.commons.lang.Validate; import org.bukkit.DyeColor; import org.bukkit.entity.Player; @@ -15,7 +14,7 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.gui.quests.DialogHistoryGUI.WrappedDialogable; import fr.skytasul.quests.gui.templates.PagedGUI; @@ -27,7 +26,6 @@ import fr.skytasul.quests.utils.ChatUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.Message; public class DialogHistoryGUI extends PagedGUI<WrappedDialogable> { 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 da51c8eb..2eb7ac4f 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 @@ -11,6 +11,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; @@ -25,7 +26,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class PlayerListGUI implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java index e82204a1..a8fbfe8c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java @@ -2,13 +2,11 @@ import java.util.ArrayList; import java.util.function.Consumer; - import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java index 5381d543..e3d1eafd 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java @@ -1,13 +1,11 @@ package fr.skytasul.quests.gui.templates; import java.util.List; - import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.gui.CustomInventory; public abstract class ChooseGUI<T> implements CustomInventory { diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java index e51bc4cf..b5ecd412 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java @@ -10,9 +10,9 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; /** * An inventory which has up to 54 slots to store items. Each item is linked in a list to an instance of type T. diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/PagedGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/PagedGUI.java index 548e19cd..e8d128f4 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/PagedGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/templates/PagedGUI.java @@ -13,13 +13,13 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.gui.CustomInventory; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.LevenshteinComparator; -import fr.skytasul.quests.utils.XMaterial; /** * An inventory with an infinite amount of pages of 35 items (integer limit). diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/StaticPagedGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/StaticPagedGUI.java index 5129fb80..67d1a0f4 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/StaticPagedGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/templates/StaticPagedGUI.java @@ -4,13 +4,11 @@ import java.util.Map.Entry; import java.util.function.Consumer; import java.util.function.Function; - import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.utils.Utils; public class StaticPagedGUI<T> extends PagedGUI<Entry<T, ItemStack>> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java index ea287ca8..4adf8761 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java @@ -1,11 +1,10 @@ package fr.skytasul.quests.options; import java.util.stream.Collectors; - import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOptionRewards; @@ -14,7 +13,6 @@ import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.gui.creation.QuestObjectGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionCancelRewards extends QuestOptionRewards { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java index 62018338..8d4bb931 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java @@ -1,12 +1,11 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionConfirmMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java index 229611d5..a388b5f4 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import org.bukkit.entity.Player; +import com.cryptomorin.xseries.XMaterial; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import fr.skytasul.quests.api.options.QuestOptionString; @@ -11,7 +12,6 @@ import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class OptionDescription extends QuestOptionString implements QuestDescriptionProvider { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java index 0535c36f..3be49b39 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java @@ -1,10 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionEndMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java index 3c266836..a6e58bff 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java @@ -4,6 +4,7 @@ import java.util.Objects; import java.util.regex.Pattern; import java.util.stream.Collectors; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; @@ -11,7 +12,6 @@ import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class OptionEndRewards extends QuestOptionRewards implements QuestDescriptionProvider { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java index 28b3b453..52e8f96a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java @@ -1,10 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionEndSound extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java index 4b9320d9..6d1a87e4 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java @@ -3,7 +3,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; - import fr.skytasul.quests.api.options.QuestOptionBoolean; import fr.skytasul.quests.players.PlayerAccount; import fr.skytasul.quests.players.PlayersManager; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java index 8f8d2d61..c18cad7d 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java @@ -2,14 +2,13 @@ import java.util.ArrayList; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; @@ -17,7 +16,6 @@ import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class OptionFirework extends QuestOption<FireworkMeta> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java index 7f589a23..f9c0c698 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.options; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionItem; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionHologramLaunch extends QuestOptionItem { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java index c1555078..b5326465 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.options; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionItem; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionHologramLaunchNo extends QuestOptionItem { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java index d4d7e16e..5e6fd46a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java @@ -1,13 +1,12 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionHologramText extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionName.java b/core/src/main/java/fr/skytasul/quests/options/OptionName.java index f5cd06fd..5353df56 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionName.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionName.java @@ -1,10 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionName extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java index bee8df4f..46bc9276 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java @@ -5,7 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.editors.TextEditor; @@ -14,7 +14,6 @@ import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class OptionQuestItem extends QuestOption<ItemStack> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java index d4b2e6cd..c582cd3b 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; - import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.configuration.ConfigurationSection; @@ -10,7 +9,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; @@ -20,7 +19,6 @@ import fr.skytasul.quests.structure.Quest; import fr.skytasul.quests.structure.pools.QuestPool; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionQuestPool extends QuestOption<QuestPool> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java index 92e0a81b..5f500670 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java @@ -4,6 +4,7 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.options.QuestOptionObject; @@ -14,7 +15,6 @@ import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class OptionRequirements extends QuestOptionObject<AbstractRequirement, RequirementCreator> implements QuestDescriptionProvider { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java index 19604407..b7c428c8 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; @@ -14,7 +15,6 @@ import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.Dialog; import fr.skytasul.quests.utils.types.DialogRunner; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java index 090b1879..7474ab2d 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java @@ -1,10 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionStartMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java index dffcb741..2494374a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java @@ -1,11 +1,10 @@ package fr.skytasul.quests.options; import java.util.ArrayList; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionStartRewards extends QuestOptionRewards { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 71fab696..9c5b8a7a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -2,12 +2,11 @@ import java.util.ArrayList; import java.util.List; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.OptionSet; @@ -16,7 +15,6 @@ import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.gui.npc.SelectGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class OptionStarterNPC extends QuestOption<BQNPC> { 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 2998591d..ec6b49cf 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java @@ -4,7 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.editors.TextEditor; @@ -13,7 +13,6 @@ import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class OptionTimer extends QuestOption<Integer> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java index 4d95e0ff..5ad84173 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map.Entry; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -14,7 +13,7 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.gui.CustomInventory; @@ -23,7 +22,6 @@ import fr.skytasul.quests.options.OptionVisibility.VisibilityLocation; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class OptionVisibility extends QuestOption<List<VisibilityLocation>> { diff --git a/core/src/main/java/fr/skytasul/quests/players/AdminMode.java b/core/src/main/java/fr/skytasul/quests/players/AdminMode.java index a95a4632..0e591c7f 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AdminMode.java +++ b/core/src/main/java/fr/skytasul/quests/players/AdminMode.java @@ -4,11 +4,9 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; - import org.bukkit.Particle; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.ParticleEffect; diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatas.java b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatas.java index ae173521..df9a9cd2 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatas.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatas.java @@ -3,7 +3,6 @@ import java.util.HashMap; import java.util.Map; import java.util.StringJoiner; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.stages.AbstractStage; diff --git a/core/src/main/java/fr/skytasul/quests/players/accounts/HookedAccount.java b/core/src/main/java/fr/skytasul/quests/players/accounts/HookedAccount.java index a1fe6c40..e8d8557c 100644 --- a/core/src/main/java/fr/skytasul/quests/players/accounts/HookedAccount.java +++ b/core/src/main/java/fr/skytasul/quests/players/accounts/HookedAccount.java @@ -3,7 +3,6 @@ import org.apache.commons.lang.Validate; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; - import fr.skytasul.accounts.Account; public class HookedAccount extends AbstractAccount { diff --git a/core/src/main/java/fr/skytasul/quests/players/accounts/UUIDAccount.java b/core/src/main/java/fr/skytasul/quests/players/accounts/UUIDAccount.java index 66e13ef8..416f5743 100644 --- a/core/src/main/java/fr/skytasul/quests/players/accounts/UUIDAccount.java +++ b/core/src/main/java/fr/skytasul/quests/players/accounts/UUIDAccount.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.players.accounts; import java.util.UUID; - import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java index f1cb22e8..6029c1c6 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java @@ -7,6 +7,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import com.google.common.collect.ImmutableMap; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -17,7 +18,6 @@ import fr.skytasul.quests.gui.misc.ItemGUI; import fr.skytasul.quests.gui.templates.StaticPagedGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class EquipmentRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java index 5d61d92f..a7ad8523 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java @@ -9,6 +9,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import com.massivecraft.factions.FactionsIndex; import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.FactionColl; @@ -21,7 +22,6 @@ import fr.skytasul.quests.gui.templates.ListGUI; import fr.skytasul.quests.gui.templates.PagedGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Factions; public class FactionRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java index 28ce38ee..cb9a06c5 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java @@ -8,6 +8,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; @@ -15,7 +16,6 @@ import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.templates.ListGUI; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class PermissionsRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index 872fe09b..ad09b20c 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; @@ -17,7 +18,6 @@ import fr.skytasul.quests.gui.templates.ListGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.Command; public class CommandReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index bf526fde..92ca6b11 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -11,6 +11,7 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; @@ -25,7 +26,6 @@ import fr.skytasul.quests.structure.Quest; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class RequirementDependentReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java index 14f5935f..46fe067c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; +import com.cryptomorin.xseries.XMaterial; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -25,7 +26,6 @@ import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardEntryEvent; import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardExitEvent; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java index 42475175..d954163f 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java @@ -6,7 +6,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityBreedEvent; - import fr.skytasul.quests.api.stages.types.AbstractEntityStage; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.players.PlayerAccount; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 90556af6..2404c72c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -9,6 +9,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.editors.TextEditor; @@ -21,7 +22,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class StageBringBack extends StageNPC{ diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 0124c798..1dfdad00 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -8,6 +8,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; @@ -22,7 +23,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.nms.NMS; public class StageBucket extends AbstractStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index b5c193da..b67bac16 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -6,7 +6,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.editors.TextEditor; @@ -17,7 +17,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class StageChat extends AbstractStage{ diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index 1860fdb1..af27d2af 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -2,7 +2,6 @@ import java.util.Map; import java.util.function.Supplier; - import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -11,7 +10,7 @@ import org.bukkit.event.inventory.FurnaceExtractEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.events.internal.BQCraftEvent; @@ -27,7 +26,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; /** * @author SkytAsul, ezeiger92, TheBusyBiscuit diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index 16e6e2b6..2d099462 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -6,7 +6,6 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; - import org.bukkit.DyeColor; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -16,7 +15,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.projectiles.ProjectileSource; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.mobs.Mob; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; @@ -32,7 +31,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; @SuppressWarnings ("rawtypes") public class StageDealDamage extends AbstractStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java index 95d63aca..073ae63b 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java @@ -3,14 +3,13 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; - import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.PlayerDeathEvent; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.gui.ItemUtils; @@ -20,7 +19,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; public class StageDeath extends AbstractStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java index 01b4bab1..be19d264 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java @@ -5,6 +5,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.gui.ItemUtils; @@ -14,7 +15,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.CountableObject; public class StageEatDrink extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java index 37e585f8..14a39b66 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java @@ -7,6 +7,7 @@ import org.bukkit.event.enchantment.EnchantItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.gui.ItemUtils; @@ -16,7 +17,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.CountableObject; public class StageEnchant extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java index e8f63b98..4c5ee4e2 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java @@ -9,6 +9,7 @@ import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerFishEvent.State; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.gui.ItemUtils; @@ -18,7 +19,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.CountableObject; public class StageFish extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java index d0601ea4..6dfa9d75 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java @@ -15,6 +15,7 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; @@ -32,7 +33,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.nms.NMS; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.BQLocation; 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 e97ff9d4..2c375508 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -6,6 +6,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; @@ -25,7 +26,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.BQLocation; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java index ef111daf..74284d1e 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java @@ -6,6 +6,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.inventory.FurnaceExtractEvent; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.gui.ItemUtils; @@ -15,7 +16,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.CountableObject; public class StageMelt extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index 70b3e969..8295866c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -15,6 +15,7 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; +import com.cryptomorin.xseries.XMaterial; import com.gestankbratwurst.playerblocktracker.PlayerBlockTracker; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; @@ -30,7 +31,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.CountableObject; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index 231072cd..0272b0cf 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -16,6 +16,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.mobs.Mob; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.AbstractCountableStage; @@ -30,7 +31,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.mobs.CompatMobDeathEvent; import fr.skytasul.quests.utils.types.CountableObject; import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; 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 84d1c9c6..4377fa81 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; - import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -13,7 +12,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.AbstractHolograms; @@ -36,7 +35,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.Dialog; import fr.skytasul.quests.utils.types.DialogRunner; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index 1ca748dc..64f189d2 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -8,6 +8,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; @@ -16,7 +17,6 @@ import fr.skytasul.quests.structure.QuestBranch; import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.CountableObject; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index df518d9f..eef0e642 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -4,12 +4,11 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; - import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; @@ -22,7 +21,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class StagePlayTime extends AbstractStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java index 1dcc890a..7e6ebdbd 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java @@ -6,7 +6,6 @@ import org.bukkit.entity.Tameable; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityTameEvent; - import fr.skytasul.quests.api.stages.types.AbstractEntityStage; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.players.PlayerAccount; diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java index 415218ac..84befe06 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java @@ -10,6 +10,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.npcs.BQNPC; @@ -23,7 +24,6 @@ import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class QuestPool implements Comparable<QuestPool> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/CustomizedObjectTypeAdapter.java b/core/src/main/java/fr/skytasul/quests/utils/CustomizedObjectTypeAdapter.java index 5f8b0c04..1001cd14 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/CustomizedObjectTypeAdapter.java +++ b/core/src/main/java/fr/skytasul/quests/utils/CustomizedObjectTypeAdapter.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; - import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapter; diff --git a/core/src/main/java/fr/skytasul/quests/utils/Database.java b/core/src/main/java/fr/skytasul/quests/utils/Database.java index aa29c1d3..c561dd61 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Database.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Database.java @@ -4,14 +4,10 @@ import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; - import javax.sql.DataSource; - import org.bukkit.configuration.ConfigurationSection; - import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; - import fr.skytasul.quests.BeautyQuests; public class Database implements Closeable { diff --git a/core/src/main/java/fr/skytasul/quests/utils/MinecraftNames.java b/core/src/main/java/fr/skytasul/quests/utils/MinecraftNames.java index 22579b23..83d1f5d1 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/MinecraftNames.java +++ b/core/src/main/java/fr/skytasul/quests/utils/MinecraftNames.java @@ -2,7 +2,9 @@ import java.io.File; import java.io.FileReader; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.WordUtils; @@ -10,6 +12,10 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.potion.PotionData; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import com.cryptomorin.xseries.XPotion; import com.google.gson.GsonBuilder; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.nms.NMS; @@ -23,7 +29,7 @@ public class MinecraftNames { private static Map<EntityType, String> cachedEntities = new HashMap<>(); private static Map<XMaterial, String> cachedMaterials = new HashMap<>(); - public static boolean intialize(String fileName){ + public static boolean intialize(@NotNull String fileName) { try { if (!fileName.contains(".")) fileName = fileName + ".json"; File file = new File(BeautyQuests.getInstance().getDataFolder(), fileName); @@ -50,13 +56,13 @@ public static boolean intialize(String fileName){ }else if (key.startsWith("item.minecraft.")) { String item = key.substring(15); if (item.startsWith("potion.effect.")) { - XPotion potion = XPotion.matchFromTranslationKey(item.substring(14)); + PotionMapping potion = PotionMapping.matchFromTranslationKey(item.substring(14)); if (potion != null) potion.normal = (String) en.getValue(); }else if (item.startsWith("splash_potion.effect.")) { - XPotion potion = XPotion.matchFromTranslationKey(item.substring(21)); + PotionMapping potion = PotionMapping.matchFromTranslationKey(item.substring(21)); if (potion != null) potion.splash = (String) en.getValue(); }else if (item.startsWith("lingering_potion.effect.")) { - XPotion potion = XPotion.matchFromTranslationKey(item.substring(24)); + PotionMapping potion = PotionMapping.matchFromTranslationKey(item.substring(24)); if (potion != null) potion.lingering = (String) en.getValue(); }else cachedMaterials.put(XMaterial.matchXMaterial(item).orElse(null), (String) en.getValue()); } @@ -67,11 +73,11 @@ public static boolean intialize(String fileName){ return true; } - public static Object getRaw(String path) { + public static @Nullable Object getRaw(@Nullable String path) { return map.get(path); } - public static String getEntityName(EntityType type) { + public static @NotNull String getEntityName(@NotNull EntityType type) { String defaultName = type.getName(); if (defaultName == null) defaultName = type.name(); if (map == null) return defaultFormat(defaultName); @@ -80,34 +86,107 @@ public static String getEntityName(EntityType type) { return name; } - public static String getMaterialName(ItemStack item) { + public static @NotNull String getMaterialName(ItemStack item) { XMaterial type = XMaterial.matchXMaterial(item); if (NMS.getMCVersion() > 8 && (type == XMaterial.POTION || type == XMaterial.LINGERING_POTION || type == XMaterial.SPLASH_POTION)) { PotionMeta meta = (PotionMeta) item.getItemMeta(); try { PotionData basePotion = meta.getBasePotionData(); - XPotion potion = basePotion.getType().name().equals("TURTLE_MASTER") ? XPotion.TURTLE_MASTER - : XPotion.matchXPotion(basePotion.getType().getEffectType()); - String string = potion.getTranslated(type); + PotionMapping mapping = basePotion.getType().name().equals("TURTLE_MASTER") ? PotionMapping.TURTLE_MASTER + : PotionMapping.matchFromXPotion(XPotion.matchXPotion(basePotion.getType().getEffectType())); + String string = mapping.getTranslated(type); if (basePotion.isUpgraded()) { - string += " II" + potion.strongDuration; - }else if (potion.baseDuration != null) string += basePotion.isExtended() ? potion.extendedDuration : potion.baseDuration; + string += " II" + mapping.strongDuration; + } else if (mapping.baseDuration != null) + string += basePotion.isExtended() ? mapping.extendedDuration : mapping.baseDuration; return string; }catch (NullPointerException ex) {} // happens with potions with no effect } return getMaterialName(type); } - public static String getMaterialName(XMaterial type) { + public static @NotNull String getMaterialName(@NotNull XMaterial type) { if (map == null) return defaultFormat(type.name()); String name = cachedMaterials.get(type); if (name == null) return defaultFormat(type.name()); return name; } - public static String defaultFormat(String value){ + public static @NotNull String defaultFormat(@NotNull String value) { return WordUtils.capitalize(value.toLowerCase().replace('_', ' ')); } + + private static class PotionMapping { + + private static final List<PotionMapping> MAPPINGS = new ArrayList<>(); + public static final PotionMapping TURTLE_MASTER; + + static { + MAPPINGS.add(new PotionMapping(XPotion.FIRE_RESISTANCE, "fire_resistance", 3600, 9600, -1)); + MAPPINGS.add(new PotionMapping(XPotion.HARM, "harming", -1, -1, -1)); + MAPPINGS.add(new PotionMapping(XPotion.HEAL, "healing", -1, -1, -1)); + MAPPINGS.add(new PotionMapping(XPotion.INCREASE_DAMAGE, "strength", 3600, 9600, 1800)); + MAPPINGS.add(new PotionMapping(XPotion.INVISIBILITY, "invisibility", 3600, 9600, -1)); + MAPPINGS.add(new PotionMapping(XPotion.JUMP, "leaping", 3600, 9600, 1800)); + MAPPINGS.add(new PotionMapping(XPotion.LEVITATION, "levitation", -1, -1, -1)); + MAPPINGS.add(new PotionMapping(XPotion.LUCK, "luck", 6000, -1, -1)); + MAPPINGS.add(new PotionMapping(XPotion.NIGHT_VISION, "night_vision", 3600, 9600, -1)); + MAPPINGS.add(new PotionMapping(XPotion.POISON, "poison", 900, 1800, 432)); + MAPPINGS.add(new PotionMapping(XPotion.REGENERATION, "regeneration", 900, 1800, 450)); + MAPPINGS.add(new PotionMapping(XPotion.SLOW, "slowness", 1800, 4800, 400)); + MAPPINGS.add(new PotionMapping(XPotion.SLOW_FALLING, "slow_falling", 1800, 4800, -1)); + MAPPINGS.add(new PotionMapping(XPotion.SPEED, "swiftness", 3600, 9600, 1800)); + MAPPINGS.add(new PotionMapping(XPotion.WATER_BREATHING, "water_breathing", 3600, 9600, -1)); + MAPPINGS.add(new PotionMapping(XPotion.WEAKNESS, "weakness", 1800, 4800, -1)); + MAPPINGS.add(TURTLE_MASTER = new PotionMapping(null, "turtle_master", 400, 800, 400)); + } + + private final @Nullable XPotion mappedPotion; + private final @NotNull String key; + private final @Nullable String baseDuration, extendedDuration, strongDuration; + private @NotNull String normal, splash, lingering; + + private PotionMapping(@Nullable XPotion mappedPotion, @NotNull String key, int baseDuration, int extendedDuration, + int strongDuration) { + this.mappedPotion = mappedPotion; + this.key = key; + this.baseDuration = baseDuration == 0 ? null : " (" + Utils.ticksToElapsedTime(baseDuration) + ")"; + this.extendedDuration = extendedDuration == 0 ? null : " (" + Utils.ticksToElapsedTime(extendedDuration) + ")"; + this.strongDuration = strongDuration == 0 ? "" : " (" + Utils.ticksToElapsedTime(strongDuration) + ")"; + this.normal = "potion of " + key; + this.splash = "splash potion of " + key; + this.lingering = "lingering potion of " + key; + } + + public @NotNull String getTranslated(XMaterial material) { + if (material == XMaterial.POTION) + return normal; + if (material == XMaterial.SPLASH_POTION) + return splash; + if (material == XMaterial.LINGERING_POTION) + return lingering; + throw new IllegalArgumentException("Argument is not a potion material"); + } + + public static @Nullable PotionMapping matchFromTranslationKey(String key) { + for (PotionMapping potion : MAPPINGS) { + if (key.equals(potion.key)) + return potion; + } + return null; + } + + public static @NotNull PotionMapping matchFromXPotion(XPotion xpotion) { + for (PotionMapping potion : MAPPINGS) { + if (xpotion.equals(potion.mappedPotion)) + return potion; + } + PotionMapping potion = new PotionMapping(xpotion, defaultFormat(xpotion.name()), -1, -1, -1); + MAPPINGS.add(potion); + return potion; + } + + } } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java b/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java index 8bd6fcd1..85cfbe54 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java +++ b/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java @@ -2,7 +2,6 @@ import java.util.List; import java.util.Random; - import org.apache.commons.lang.Validate; import org.bukkit.Color; import org.bukkit.Location; @@ -10,7 +9,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; diff --git a/core/src/main/java/fr/skytasul/quests/utils/Utils.java b/core/src/main/java/fr/skytasul/quests/utils/Utils.java index a0a35a10..0b79209b 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Utils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Utils.java @@ -46,6 +46,7 @@ import org.bukkit.scoreboard.DisplaySlot; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.requirements.AbstractRequirement; diff --git a/core/src/main/java/fr/skytasul/quests/utils/XBlock.java b/core/src/main/java/fr/skytasul/quests/utils/XBlock.java deleted file mode 100644 index 2261123d..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/XBlock.java +++ /dev/null @@ -1,857 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2022 Crypto Morin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package fr.skytasul.quests.utils; - -import java.util.*; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.apache.commons.lang.Validate; -import org.bukkit.DyeColor; -import org.bukkit.Material; -import org.bukkit.TreeSpecies; -import org.bukkit.block.Banner; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; -import org.bukkit.block.data.BlockData; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.material.Cake; -import org.bukkit.material.Colorable; -import org.bukkit.material.Directional; -import org.bukkit.material.MaterialData; -import org.bukkit.material.Openable; -import org.bukkit.material.Wood; -import org.bukkit.material.Wool; - -/** - * <b>XBlock</b> - MaterialData/BlockData Support<br> - * BlockState (Old): https://hub.spigotmc.org/javadocs/spigot/org/bukkit/block/BlockState.html - * BlockData (New): https://hub.spigotmc.org/javadocs/spigot/org/bukkit/block/data/BlockData.html - * MaterialData (Old): https://hub.spigotmc.org/javadocs/spigot/org/bukkit/material/MaterialData.html - * <p> - * All the parameters are non-null except the ones marked as nullable. - * This class doesn't and shouldn't support materials that are {@link Material#isLegacy()}. - * - * @author Crypto Morin - * @version 2.2.0 - * @see Block - * @see BlockState - * @see MaterialData - * @see XMaterial - */ -@SuppressWarnings("deprecation") -public final class XBlock { - public static final Set<XMaterial> CROPS = Collections.unmodifiableSet(EnumSet.of( - XMaterial.CARROT, XMaterial.POTATO, XMaterial.NETHER_WART, XMaterial.WHEAT_SEEDS, XMaterial.PUMPKIN_SEEDS, - XMaterial.MELON_SEEDS, XMaterial.BEETROOT_SEEDS, XMaterial.SUGAR_CANE, XMaterial.BAMBOO_SAPLING, XMaterial.CHORUS_PLANT, - XMaterial.KELP, XMaterial.SEA_PICKLE, XMaterial.BROWN_MUSHROOM, XMaterial.RED_MUSHROOM - )); - public static final Set<XMaterial> DANGEROUS = Collections.unmodifiableSet(EnumSet.of(XMaterial.MAGMA_BLOCK, XMaterial.LAVA, XMaterial.CAMPFIRE, XMaterial.FIRE, XMaterial.SOUL_FIRE)); - public static final byte CAKE_SLICES = 6; - private static final boolean ISFLAT = XMaterial.supports(13); - private static final Map<XMaterial, XMaterial> ITEM_TO_BLOCK = new EnumMap<>(XMaterial.class); - - static { - ITEM_TO_BLOCK.put(XMaterial.MELON_SLICE, XMaterial.MELON_STEM); - ITEM_TO_BLOCK.put(XMaterial.MELON_SEEDS, XMaterial.MELON_STEM); - - ITEM_TO_BLOCK.put(XMaterial.CARROT_ON_A_STICK, XMaterial.CARROTS); - ITEM_TO_BLOCK.put(XMaterial.GOLDEN_CARROT, XMaterial.CARROTS); - ITEM_TO_BLOCK.put(XMaterial.CARROT, XMaterial.CARROTS); - - ITEM_TO_BLOCK.put(XMaterial.POTATO, XMaterial.POTATOES); - ITEM_TO_BLOCK.put(XMaterial.BAKED_POTATO, XMaterial.POTATOES); - ITEM_TO_BLOCK.put(XMaterial.POISONOUS_POTATO, XMaterial.POTATOES); - - ITEM_TO_BLOCK.put(XMaterial.PUMPKIN_SEEDS, XMaterial.PUMPKIN_STEM); - ITEM_TO_BLOCK.put(XMaterial.PUMPKIN_PIE, XMaterial.PUMPKIN); - } - - private XBlock() {} - - public static boolean isLit(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Lightable)) return false; - org.bukkit.block.data.Lightable lightable = (org.bukkit.block.data.Lightable) block.getBlockData(); - return lightable.isLit(); - } - - return isMaterial(block, BlockMaterial.REDSTONE_LAMP_ON, BlockMaterial.REDSTONE_TORCH_ON, BlockMaterial.BURNING_FURNACE); - } - - /** - * Checks if the block is a container. - * Containers are chests, hoppers, enderchests and everything that - * has an inventory. - * - * @param block the block to check. - * - * @return true if the block is a container, otherwise false. - */ - public static boolean isContainer(@Nullable Block block) { - return block != null && block.getState() instanceof InventoryHolder; - } - - /** - * Can be furnaces or redstone lamps. - * - * @param block the block to change. - * @param lit if it should be lit or not. - */ - public static void setLit(Block block, boolean lit) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Lightable)) return; - BlockData data = block.getBlockData(); - org.bukkit.block.data.Lightable lightable = (org.bukkit.block.data.Lightable) data; - lightable.setLit(lit); - block.setBlockData(data, false); - return; - } - - String name = block.getType().name(); - if (name.endsWith("FURNACE")) - block.setType(BlockMaterial.BURNING_FURNACE.material); - else if (name.startsWith("REDSTONE_LAMP")) - block.setType(BlockMaterial.REDSTONE_LAMP_ON.material); - else block.setType(BlockMaterial.REDSTONE_TORCH_ON.material); - } - - /** - * Any material that can be planted which is from {@link #CROPS} - * - * @param material the material to check. - * - * @return true if this material is a crop, otherwise false. - */ - public static boolean isCrop(XMaterial material) { - return CROPS.contains(material); - } - - /** - * Any material that can damage players, usually by interacting with the block. - * - * @param material the material to check. - * - * @return true if this material is dangerous, otherwise false. - */ - public static boolean isDangerous(XMaterial material) { - return DANGEROUS.contains(material); - } - - /** - * Wool and Dye. But Dye is not a block itself. - */ - public static DyeColor getColor(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof Colorable)) return null; - Colorable colorable = (Colorable) block.getBlockData(); - return colorable.getColor(); - } - - BlockState state = block.getState(); - MaterialData data = state.getData(); - if (data instanceof Wool) { - Wool wool = (Wool) data; - return wool.getColor(); - } - return null; - } - - public static boolean isCake(@Nullable Material material) { - return material == Material.CAKE || material == BlockMaterial.CAKE_BLOCK.material; - } - - public static boolean isWheat(@Nullable Material material) { - return material == Material.WHEAT || material == BlockMaterial.CROPS.material; - } - - public static boolean isSugarCane(@Nullable Material material) { - return material == Material.SUGAR_CANE || material == BlockMaterial.SUGAR_CANE_BLOCK.material; - } - - public static boolean isBeetroot(@Nullable Material material) { - return material == Material.BEETROOT || material == Material.BEETROOTS || material == BlockMaterial.BEETROOT_BLOCK.material; - } - - public static boolean isNetherWart(@Nullable Material material) { - return material == Material.NETHER_WART || material == BlockMaterial.NETHER_WARTS.material; - } - - public static boolean isCarrot(@Nullable Material material) { - return material == Material.CARROT || material == Material.CARROTS; - } - - public static boolean isMelon(@Nullable Material material) { - return material == Material.MELON || material == Material.MELON_SLICE || material == BlockMaterial.MELON_BLOCK.material; - } - - public static boolean isPotato(@Nullable Material material) { - return material == Material.POTATO || material == Material.POTATOES; - } - - public static BlockFace getDirection(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Directional)) return BlockFace.SELF; - org.bukkit.block.data.Directional direction = (org.bukkit.block.data.Directional) block.getBlockData(); - return direction.getFacing(); - } - - BlockState state = block.getState(); - MaterialData data = state.getData(); - if (data instanceof org.bukkit.material.Directional) return ((org.bukkit.material.Directional) data).getFacing(); - return BlockFace.SELF; - } - - public static boolean setDirection(Block block, BlockFace facing) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Directional)) return false; - BlockData data = block.getBlockData(); - org.bukkit.block.data.Directional direction = (org.bukkit.block.data.Directional) data; - direction.setFacing(facing); - block.setBlockData(data, false); - return true; - } - - BlockState state = block.getState(); - MaterialData data = state.getData(); - if (data instanceof Directional) { - ((Directional) data).setFacingDirection(facing); - state.update(true); - return true; - } - return false; - } - - public static boolean setType(@Nonnull Block block, @Nullable XMaterial material, boolean applyPhysics) { - Objects.requireNonNull(block, "Cannot set type of null block"); - if (material == null) material = XMaterial.AIR; - XMaterial smartConversion = ITEM_TO_BLOCK.get(material); - if (smartConversion != null) material = smartConversion; - if (material.parseMaterial() == null) return false; - - block.setType(material.parseMaterial(), applyPhysics); - if (XMaterial.supports(13)) return false; - - String parsedName = material.parseMaterial().name(); - if (parsedName.endsWith("_ITEM")) { - String blockName = parsedName.substring(0, parsedName.length() - "_ITEM".length()); - Material blockMaterial = Objects.requireNonNull(Material.getMaterial(blockName), () -> "Could not find block material for item '" + parsedName + "' as '" + blockName + '\''); - block.setType(blockMaterial, applyPhysics); - }else if (parsedName.contains("CAKE")) { - Material blockMaterial = Material.getMaterial("CAKE_BLOCK"); - block.setType(blockMaterial, applyPhysics); - } - - LegacyMaterial legacyMaterial = LegacyMaterial.getMaterial(parsedName); - if (legacyMaterial == LegacyMaterial.BANNER) block.setType(LegacyMaterial.STANDING_BANNER.material, applyPhysics); - LegacyMaterial.Handling handling = legacyMaterial == null ? null : legacyMaterial.handling; - - BlockState state = block.getState(); - boolean update = false; - - if (handling == LegacyMaterial.Handling.COLORABLE) { - if (state instanceof Banner) { - Banner banner = (Banner) state; - String xName = material.name(); - int colorIndex = xName.indexOf('_'); - String color = xName.substring(0, colorIndex); - if (color.equals("LIGHT")) color = xName.substring(0, "LIGHT_".length() + 4); - - banner.setBaseColor(DyeColor.valueOf(color)); - }else state.setRawData(material.getData()); - update = true; - }else if (handling == LegacyMaterial.Handling.WOOD_SPECIES) { - // Wood doesn't exist in 1.8 - // https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/material/Wood.java?until=7d83cba0f2575112577ed7a091ed8a193bfc261a&untilPath=src%2Fmain%2Fjava%2Forg%2Fbukkit%2Fmaterial%2FWood.java - // https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/TreeSpecies.java - - String name = material.name(); - int firstIndicator = name.indexOf('_'); - if (firstIndicator < 0) return false; - String woodType = name.substring(0, firstIndicator); - - TreeSpecies species; - switch (woodType) { - case "OAK": - species = TreeSpecies.GENERIC; - break; - case "DARK": - species = TreeSpecies.DARK_OAK; - break; - case "SPRUCE": - species = TreeSpecies.REDWOOD; - break; - default: { - try { - species = TreeSpecies.valueOf(woodType); - }catch (IllegalArgumentException ex) { - throw new AssertionError("Unknown material " + legacyMaterial + " for wood species"); - } - } - } - - // Doesn't handle stairs, slabs, fence and fence gates as they had their own separate materials. - boolean firstType = false; - switch (legacyMaterial) { - case WOOD: - case WOOD_DOUBLE_STEP: - state.setRawData(species.getData()); - update = true; - break; - case LOG: - case LEAVES: - firstType = true; - // fall through to next switch statement below - case LOG_2: - case LEAVES_2: - switch (species) { - case GENERIC: - case REDWOOD: - case BIRCH: - case JUNGLE: - if (!firstType) throw new AssertionError("Invalid tree species " + species + " for block type" + legacyMaterial + ", use block type 2 instead"); - break; - case ACACIA: - case DARK_OAK: - if (firstType) throw new AssertionError("Invalid tree species " + species + " for block type 2 " + legacyMaterial + ", use block type instead"); - break; - } - state.setRawData((byte) ((state.getRawData() & 0xC) | (species.getData() & 0x3))); - update = true; - break; - case SAPLING: - case WOOD_STEP: - state.setRawData((byte) ((state.getRawData() & 0x8) | species.getData())); - update = true; - break; - default: - throw new AssertionError("Unknown block type " + legacyMaterial + " for tree species: " + species); - } - }else if (material.getData() != 0) { - state.setRawData(material.getData()); - update = true; - } - - if (update) state.update(false, applyPhysics); - return update; - } - - public static boolean setType(@Nonnull Block block, @Nullable XMaterial material) { - return setType(block, material, true); - } - - public static int getAge(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Ageable)) return 0; - org.bukkit.block.data.Ageable ageable = (org.bukkit.block.data.Ageable) block.getBlockData(); - return ageable.getAge(); - } - - BlockState state = block.getState(); - MaterialData data = state.getData(); - return data.getData(); - } - - public static void setAge(Block block, int age) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Ageable)) return; - BlockData data = block.getBlockData(); - org.bukkit.block.data.Ageable ageable = (org.bukkit.block.data.Ageable) data; - ageable.setAge(age); - block.setBlockData(data, false); - } - - BlockState state = block.getState(); - MaterialData data = state.getData(); - data.setData((byte) age); - state.update(true); - } - - /** - * Sets the type of any block that can be colored. - * - * @param block the block to color. - * @param color the color to use. - * - * @return true if the block can be colored, otherwise false. - */ - public static boolean setColor(Block block, DyeColor color) { - if (ISFLAT) { - String type = block.getType().name(); - int index = type.indexOf('_'); - if (index == -1) return false; - - String realType = type.substring(index); - Material material = Material.getMaterial(color.name() + '_' + realType); - if (material == null) return false; - block.setType(material); - return true; - } - - BlockState state = block.getState(); - state.setRawData(color.getWoolData()); - state.update(true); - return false; - } - - /** - * Can be used on cauldrons as well. - * - * @param block the block to set the fluid level of. - * @param level the level of fluid. - * - * @return true if this block can have a fluid level, otherwise false. - */ - public static boolean setFluidLevel(Block block, int level) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Levelled)) return false; - BlockData data = block.getBlockData(); - org.bukkit.block.data.Levelled levelled = (org.bukkit.block.data.Levelled) data; - levelled.setLevel(level); - block.setBlockData(data, false); - return true; - } - - BlockState state = block.getState(); - MaterialData data = state.getData(); - data.setData((byte) level); - state.update(true); - return false; - } - - public static int getFluidLevel(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Levelled)) return -1; - org.bukkit.block.data.Levelled levelled = (org.bukkit.block.data.Levelled) block.getBlockData(); - return levelled.getLevel(); - } - - BlockState state = block.getState(); - MaterialData data = state.getData(); - return data.getData(); - } - - public static boolean isWaterStationary(Block block) { - return ISFLAT ? getFluidLevel(block) < 7 : block.getType() == BlockMaterial.STATIONARY_WATER.material; - } - - public static boolean isWater(Material material) { - return material == Material.WATER || material == BlockMaterial.STATIONARY_WATER.material; - } - - public static boolean isLava(Material material) { - return material == Material.LAVA || material == BlockMaterial.STATIONARY_LAVA.material; - } - - public static boolean isOneOf(Block block, Collection<String> blocks) { - if (blocks == null || blocks.isEmpty()) return false; - String name = block.getType().name(); - XMaterial matched = XMaterial.matchXMaterial(block.getType()); - - for (String comp : blocks) { - String checker = comp.toUpperCase(Locale.ENGLISH); - if (checker.startsWith("CONTAINS:")) { - comp = XMaterial.format(checker.substring(9)); - if (name.contains(comp)) return true; - continue; - } - if (checker.startsWith("REGEX:")) { - comp = comp.substring(6); - if (name.matches(comp)) return true; - continue; - } - - // Direct Object Equals - Optional<XMaterial> xMat = XMaterial.matchXMaterial(comp); - if (xMat.isPresent()) { - if (matched == xMat.get() || isType(block, xMat.get())) return true; - } - } - return false; - } - - public static void setCakeSlices(Block block, int amount) { - Validate.isTrue(isCake(block.getType()), "Block is not a cake: " + block.getType()); - if (ISFLAT) { - BlockData data = block.getBlockData(); - org.bukkit.block.data.type.Cake cake = (org.bukkit.block.data.type.Cake) data; - int remaining = cake.getMaximumBites() - (cake.getBites() + amount); - if (remaining > 0) { - cake.setBites(remaining); - block.setBlockData(data); - }else { - block.breakNaturally(); - } - - return; - } - - BlockState state = block.getState(); - Cake cake = (Cake) state.getData(); - if (amount > 0) { - cake.setSlicesRemaining(amount); - state.update(true); - }else { - block.breakNaturally(); - } - } - - public static int addCakeSlices(Block block, int slices) { - Validate.isTrue(isCake(block.getType()), "Block is not a cake: " + block.getType()); - if (ISFLAT) { - BlockData data = block.getBlockData(); - org.bukkit.block.data.type.Cake cake = (org.bukkit.block.data.type.Cake) data; - int bites = cake.getBites() - slices; - int remaining = cake.getMaximumBites() - bites; - - if (remaining > 0) { - cake.setBites(bites); - block.setBlockData(data); - return remaining; - }else { - block.breakNaturally(); - return 0; - } - } - - BlockState state = block.getState(); - Cake cake = (Cake) state.getData(); - int remaining = cake.getSlicesRemaining() + slices; - - if (remaining > 0) { - cake.setSlicesRemaining(remaining); - state.update(true); - return remaining; - }else { - block.breakNaturally(); - return 0; - } - } - - public static void setEnderPearlOnFrame(Block endPortalFrame, boolean eye) { - BlockState state = endPortalFrame.getState(); - if (ISFLAT) { - org.bukkit.block.data.BlockData data = state.getBlockData(); - org.bukkit.block.data.type.EndPortalFrame frame = (org.bukkit.block.data.type.EndPortalFrame) data; - frame.setEye(eye); - state.setBlockData(data); - }else { - state.setRawData((byte) (eye ? 4 : 0)); - } - state.update(true); - } - - /** - * @param block the block to get its XMaterial type. - * - * @return the XMaterial of the block. - * @deprecated Not stable, use {@link #isType(Block, XMaterial)} or {@link #isSimilar(Block, XMaterial)} instead. - * If you want to save a block material somewhere, you need to use {@link XMaterial#matchXMaterial(Material)} - */ - @Deprecated - public static XMaterial getType(Block block) { - if (ISFLAT) return XMaterial.matchXMaterial(block.getType()); - String type = block.getType().name(); - BlockState state = block.getState(); - MaterialData data = state.getData(); - byte dataValue; - - if (data instanceof Wood) { - TreeSpecies species = ((Wood) data).getSpecies(); - dataValue = species.getData(); - }else if (data instanceof Colorable) { - DyeColor color = ((Colorable) data).getColor(); - dataValue = color.getDyeData(); - }else { - dataValue = data.getData(); - } - - return XMaterial.matchDefinedXMaterial(type, dataValue).orElseThrow(() -> new IllegalArgumentException("Unsupported material for block " + dataValue + ": " + block.getType().name())); - } - - /** - * Same as {@link #isType(Block, XMaterial)} except it also does a simple {@link XMaterial#matchXMaterial(Material)} - * comparison with the given block and material. - * - * @param block the block to compare. - * @param material the material to compare with. - * - * @return true if block type is similar to the given material. - * @see #isType(Block, XMaterial) - * @since 1.3.0 - */ - public static boolean isSimilar(Block block, XMaterial material) { - return material == XMaterial.matchXMaterial(block.getType()) || isType(block, material); - } - - /** - * <b>Universal Method</b> - * <p> - * Check if the block type matches the specified XMaterial. - * Note that this method assumes that you've already tried doing {@link XMaterial#matchXMaterial(Material)} using - * {@link Block#getType()} and compared it with the other XMaterial. If not, use {@link #isSimilar(Block, XMaterial)} - * - * @param block the block to check. - * @param material the XMaterial similar to this block type. - * - * @return true if the raw block type matches with the material. - * @see #isSimilar(Block, XMaterial) - */ - public static boolean isType(Block block, XMaterial material) { - Material mat = block.getType(); - switch (material) { - case CAKE: - return isCake(mat); - case NETHER_WART: - return isNetherWart(mat); - case MELON: - case MELON_SLICE: - return isMelon(mat); - case CARROT: - case CARROTS: - return isCarrot(mat); - case POTATO: - case POTATOES: - return isPotato(mat); - case WHEAT: - case WHEAT_SEEDS: - return isWheat(mat); - case BEETROOT: - case BEETROOT_SEEDS: - case BEETROOTS: - return isBeetroot(mat); - case SUGAR_CANE: - return isSugarCane(mat); - case WATER: - return isWater(mat); - case LAVA: - return isLava(mat); - case AIR: - case CAVE_AIR: - case VOID_AIR: - return isAir(mat); - } - return false; - } - - public static boolean isAir(@Nullable Material material) { - if (ISFLAT) { - // material.isAir() doesn't exist for 1.13 - switch (material) { - case AIR: - case CAVE_AIR: - case VOID_AIR: - return true; - default: - return false; - } - } - return material == Material.AIR; - } - - public static boolean isPowered(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Powerable)) return false; - org.bukkit.block.data.Powerable powerable = (org.bukkit.block.data.Powerable) block.getBlockData(); - return powerable.isPowered(); - } - - String name = block.getType().name(); - if (name.startsWith("REDSTONE_COMPARATOR")) return block.getType() == BlockMaterial.REDSTONE_COMPARATOR_ON.material; - return false; - } - - public static void setPowered(Block block, boolean powered) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Powerable)) return; - BlockData data = block.getBlockData(); - org.bukkit.block.data.Powerable powerable = (org.bukkit.block.data.Powerable) data; - powerable.setPowered(powered); - block.setBlockData(data, false); - return; - } - - String name = block.getType().name(); - if (name.startsWith("REDSTONE_COMPARATOR")) block.setType(BlockMaterial.REDSTONE_COMPARATOR_ON.material); - } - - public static boolean isOpen(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Openable)) return false; - org.bukkit.block.data.Openable openable = (org.bukkit.block.data.Openable) block.getBlockData(); - return openable.isOpen(); - } - - BlockState state = block.getState(); - if (!(state instanceof Openable)) return false; - Openable openable = (Openable) state.getData(); - return openable.isOpen(); - } - - public static void setOpened(Block block, boolean opened) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Openable)) return; - // These useless "data" variables are used because JVM doesn't like upcasts/downcasts for - // non-existing classes even if unused. - BlockData data = block.getBlockData(); - org.bukkit.block.data.Openable openable = (org.bukkit.block.data.Openable) data; - openable.setOpen(opened); - block.setBlockData(data, false); - return; - } - - BlockState state = block.getState(); - if (!(state instanceof Openable)) return; - Openable openable = (Openable) state.getData(); - openable.setOpen(opened); - state.setData((MaterialData) openable); - state.update(); - } - - public static BlockFace getRotation(Block block) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Rotatable)) return null; - org.bukkit.block.data.Rotatable rotatable = (org.bukkit.block.data.Rotatable) block.getBlockData(); - return rotatable.getRotation(); - } - - return null; - } - - public static void setRotation(Block block, BlockFace facing) { - if (ISFLAT) { - if (!(block.getBlockData() instanceof org.bukkit.block.data.Rotatable)) return; - BlockData data = block.getBlockData(); - org.bukkit.block.data.Rotatable rotatable = (org.bukkit.block.data.Rotatable) data; - rotatable.setRotation(facing); - block.setBlockData(data, false); - } - } - - private static boolean isMaterial(Block block, BlockMaterial... materials) { - Material type = block.getType(); - for (BlockMaterial material : materials) { - if (type == material.material) return true; - } - return false; - } - - private enum LegacyMaterial { - // Colorable - STANDING_BANNER( - Handling.COLORABLE), - WALL_BANNER( - Handling.COLORABLE), - BANNER( - Handling.COLORABLE), - CARPET( - Handling.COLORABLE), - WOOL( - Handling.COLORABLE), - STAINED_CLAY( - Handling.COLORABLE), - STAINED_GLASS( - Handling.COLORABLE), - STAINED_GLASS_PANE( - Handling.COLORABLE), - THIN_GLASS( - Handling.COLORABLE), - - // Wood Species - WOOD( - Handling.WOOD_SPECIES), - WOOD_STEP( - Handling.WOOD_SPECIES), - WOOD_DOUBLE_STEP( - Handling.WOOD_SPECIES), - LEAVES( - Handling.WOOD_SPECIES), - LEAVES_2( - Handling.WOOD_SPECIES), - LOG( - Handling.WOOD_SPECIES), - LOG_2( - Handling.WOOD_SPECIES), - SAPLING( - Handling.WOOD_SPECIES); - - private static final Map<String, LegacyMaterial> LOOKUP = new HashMap<>(); - - static { - for (LegacyMaterial legacyMaterial : values()) { - LOOKUP.put(legacyMaterial.name(), legacyMaterial); - } - } - - private final Material material = Material.getMaterial(name()); - private final Handling handling; - - LegacyMaterial(Handling handling) { - this.handling = handling; - } - - private static LegacyMaterial getMaterial(String name) { - return LOOKUP.get(name); - } - - private enum Handling { - COLORABLE, WOOD_SPECIES; - } - } - - /** - * An enum with cached legacy materials which can be used when comparing blocks with blocks and blocks with items. - * - * @since 2.0.0 - */ - public enum BlockMaterial { - // Blocks - CAKE_BLOCK, - CROPS, - SUGAR_CANE_BLOCK, - BEETROOT_BLOCK, - NETHER_WARTS, - MELON_BLOCK, - - // Others - BURNING_FURNACE, - STATIONARY_WATER, - STATIONARY_LAVA, - - // Toggleable - REDSTONE_LAMP_ON, - REDSTONE_LAMP_OFF, - REDSTONE_TORCH_ON, - REDSTONE_TORCH_OFF, - REDSTONE_COMPARATOR_ON, - REDSTONE_COMPARATOR_OFF; - - @Nullable - private final Material material; - - BlockMaterial() { - this.material = Material.getMaterial(this.name()); - } - } -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/utils/XMaterial.java b/core/src/main/java/fr/skytasul/quests/utils/XMaterial.java deleted file mode 100644 index 6bde6370..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/XMaterial.java +++ /dev/null @@ -1,2238 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Hex_27 - * Copyright (c) 2022 Crypto Morin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package fr.skytasul.quests.utils; - -import com.google.common.base.Enums; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.SpawnEggMeta; -import org.bukkit.potion.Potion; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import java.util.stream.Collectors; - -/** - * <b>XMaterial</b> - Data Values/Pre-flattening<br> - * 1.13 and above as priority. - * <p> - * This class is mainly designed to support {@link ItemStack}. If you want to use it on blocks, you'll have to use - * <a href="https://github.com/CryptoMorin/XSeries/blob/master/src/main/java/com/cryptomorin/xseries/XBlock.java">XBlock</a> - * <p> - * Pre-flattening: https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening - * Materials: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html - * Materials (1.12): https://helpch.at/docs/1.12.2/index.html?org/bukkit/Material.html - * Material IDs: https://minecraft-ids.grahamedgecombe.com/ - * Material Source Code: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/Material.java - * XMaterial v1: https://www.spigotmc.org/threads/329630/ - * <p> - * This class will throw a "unsupported material" error if someone tries to use an item with an invalid data value which can only happen in 1.12 servers and below or when the - * utility is missing a new material in that specific version. - * To get an invalid item, (aka <a href="https://minecraft.fandom.com/wiki/Missing_Texture_Block">Missing Texture Block</a>) you can use the command - * <b>/give @p minecraft:dirt 1 10</b> where 1 is the item amount, and 10 is the data value. The material {@link #DIRT} with a data value of {@code 10} doesn't exist. - * - * @author Crypto Morin - * @version 11.0.0 - * @see Material - * @see ItemStack - */ -public enum XMaterial { - ACACIA_BOAT("BOAT_ACACIA"), - ACACIA_BUTTON("WOOD_BUTTON"), - ACACIA_CHEST_BOAT, - ACACIA_DOOR("ACACIA_DOOR", "ACACIA_DOOR_ITEM"), - ACACIA_FENCE, - ACACIA_FENCE_GATE, - ACACIA_LEAVES(4, "LEAVES_2"), - ACACIA_LOG(4, "LOG_2"), - ACACIA_PLANKS(4, "WOOD"), - ACACIA_PRESSURE_PLATE("WOOD_PLATE"), - ACACIA_SAPLING(4, "SAPLING"), - ACACIA_SIGN("SIGN_POST", "SIGN"), - ACACIA_SLAB(4, "WOOD_DOUBLE_STEP", "WOOD_STEP", "WOODEN_SLAB"), - ACACIA_STAIRS, - ACACIA_TRAPDOOR("TRAP_DOOR"), - ACACIA_WALL_SIGN("WALL_SIGN"), - ACACIA_WOOD(4, "LOG_2"), - ACTIVATOR_RAIL, - /** - * https://minecraft.gamepedia.com/Air - * {@link Material#isAir()} - * - * @see #VOID_AIR - * @see #CAVE_AIR - */ - AIR, - ALLAY_SPAWN_EGG, - ALLIUM(2, "RED_ROSE"), - AMETHYST_BLOCK, - AMETHYST_CLUSTER, - AMETHYST_SHARD, - ANCIENT_DEBRIS, - ANDESITE(5, "STONE"), - ANDESITE_SLAB, - ANDESITE_STAIRS, - ANDESITE_WALL, - ANVIL, - APPLE, - ARMOR_STAND, - ARROW, - ATTACHED_MELON_STEM(7, "MELON_STEM"), - ATTACHED_PUMPKIN_STEM(7, "PUMPKIN_STEM"), - AXOLOTL_BUCKET, - AXOLOTL_SPAWN_EGG, - AZALEA, - AZALEA_LEAVES, - AZURE_BLUET(3, "RED_ROSE"), - BAKED_POTATO, - BAMBOO, - BAMBOO_SAPLING, - BARREL, - BARRIER, - BASALT, - BAT_SPAWN_EGG(65, "MONSTER_EGG"), - BEACON, - BEDROCK, - BEEF("RAW_BEEF"), - BEEHIVE, - /** - * Beetroot is a known material in pre-1.13 - */ - BEETROOT("BEETROOT_BLOCK"), - BEETROOTS("BEETROOT"), - BEETROOT_SEEDS, - BEETROOT_SOUP, - BEE_NEST, - BEE_SPAWN_EGG, - BELL, - BIG_DRIPLEAF, - BIG_DRIPLEAF_STEM, - BIRCH_BOAT("BOAT_BIRCH"), - BIRCH_BUTTON("WOOD_BUTTON"), - BIRCH_CHEST_BOAT, - BIRCH_DOOR("BIRCH_DOOR", "BIRCH_DOOR_ITEM"), - BIRCH_FENCE, - BIRCH_FENCE_GATE, - BIRCH_LEAVES(2, "LEAVES"), - BIRCH_LOG(2, "LOG"), - BIRCH_PLANKS(2, "WOOD"), - BIRCH_PRESSURE_PLATE("WOOD_PLATE"), - BIRCH_SAPLING(2, "SAPLING"), - BIRCH_SIGN("SIGN_POST", "SIGN"), - BIRCH_SLAB(2, "WOOD_DOUBLE_STEP", "WOOD_STEP", "WOODEN_SLAB"), - BIRCH_STAIRS("BIRCH_WOOD_STAIRS"), - BIRCH_TRAPDOOR("TRAP_DOOR"), - BIRCH_WALL_SIGN("WALL_SIGN"), - BIRCH_WOOD(2, "LOG"), - BLACKSTONE, - BLACKSTONE_SLAB, - BLACKSTONE_STAIRS, - BLACKSTONE_WALL, - BLACK_BANNER("STANDING_BANNER", "BANNER"), - /** - * Version 1.12+ interprets "BED" as BLACK_BED due to enum alphabetic ordering. - */ - BLACK_BED(supports(12) ? 15 : 0, "BED_BLOCK", "BED"), - BLACK_CANDLE, - BLACK_CANDLE_CAKE, - BLACK_CARPET(15, "CARPET"), - BLACK_CONCRETE(15, "CONCRETE"), - BLACK_CONCRETE_POWDER(15, "CONCRETE_POWDER"), - BLACK_DYE, - BLACK_GLAZED_TERRACOTTA, - BLACK_SHULKER_BOX, - BLACK_STAINED_GLASS(15, "STAINED_GLASS"), - BLACK_STAINED_GLASS_PANE(15, "STAINED_GLASS_PANE"), - BLACK_TERRACOTTA(15, "STAINED_CLAY"), - BLACK_WALL_BANNER("WALL_BANNER"), - BLACK_WOOL(15, "WOOL"), - BLAST_FURNACE, - BLAZE_POWDER, - BLAZE_ROD, - BLAZE_SPAWN_EGG(61, "MONSTER_EGG"), - BLUE_BANNER(4, "STANDING_BANNER", "BANNER"), - BLUE_BED(supports(12) ? 11 : 0, "BED_BLOCK", "BED"), - BLUE_CANDLE, - BLUE_CANDLE_CAKE, - BLUE_CARPET(11, "CARPET"), - BLUE_CONCRETE(11, "CONCRETE"), - BLUE_CONCRETE_POWDER(11, "CONCRETE_POWDER"), - BLUE_DYE(4, "INK_SACK", "LAPIS_LAZULI"), - BLUE_GLAZED_TERRACOTTA, - BLUE_ICE, - BLUE_ORCHID(1, "RED_ROSE"), - BLUE_SHULKER_BOX, - BLUE_STAINED_GLASS(11, "STAINED_GLASS"), - BLUE_STAINED_GLASS_PANE(11, "THIN_GLASS", "STAINED_GLASS_PANE"), - BLUE_TERRACOTTA(11, "STAINED_CLAY"), - BLUE_WALL_BANNER(4, "WALL_BANNER"), - BLUE_WOOL(11, "WOOL"), - BONE, - BONE_BLOCK, - BONE_MEAL(15, "INK_SACK"), - BOOK, - BOOKSHELF, - BOW, - BOWL, - BRAIN_CORAL, - BRAIN_CORAL_BLOCK, - BRAIN_CORAL_FAN, - BRAIN_CORAL_WALL_FAN, - BREAD, - BREWING_STAND("BREWING_STAND", "BREWING_STAND_ITEM"), - BRICK("CLAY_BRICK"), - BRICKS("BRICKS", "BRICK"), - BRICK_SLAB(4, "STEP"), - BRICK_STAIRS, - BRICK_WALL, - BROWN_BANNER(3, "STANDING_BANNER", "BANNER"), - BROWN_BED(supports(12) ? 12 : 0, "BED_BLOCK", "BED"), - BROWN_CANDLE, - BROWN_CANDLE_CAKE, - BROWN_CARPET(12, "CARPET"), - BROWN_CONCRETE(12, "CONCRETE"), - BROWN_CONCRETE_POWDER(12, "CONCRETE_POWDER"), - BROWN_DYE(3, "INK_SACK", "DYE", "COCOA_BEANS"), - BROWN_GLAZED_TERRACOTTA, - BROWN_MUSHROOM, - BROWN_MUSHROOM_BLOCK("BROWN_MUSHROOM", "HUGE_MUSHROOM_1"), - BROWN_SHULKER_BOX, - BROWN_STAINED_GLASS(12, "STAINED_GLASS"), - BROWN_STAINED_GLASS_PANE(12, "THIN_GLASS", "STAINED_GLASS_PANE"), - BROWN_TERRACOTTA(12, "STAINED_CLAY"), - BROWN_WALL_BANNER(3, "WALL_BANNER"), - BROWN_WOOL(12, "WOOL"), - BUBBLE_COLUMN, - BUBBLE_CORAL, - BUBBLE_CORAL_BLOCK, - BUBBLE_CORAL_FAN, - BUBBLE_CORAL_WALL_FAN, - BUCKET, - BUDDING_AMETHYST, - BUNDLE, - CACTUS, - CAKE("CAKE_BLOCK"), - CALCITE, - CAMPFIRE, - CANDLE, - CANDLE_CAKE, - CARROT("CARROT_ITEM"), - CARROTS("CARROT"), - CARROT_ON_A_STICK("CARROT_STICK"), - CARTOGRAPHY_TABLE, - CARVED_PUMPKIN, - CAT_SPAWN_EGG, - CAULDRON("CAULDRON", "CAULDRON_ITEM"), - /** - * 1.13 tag is not added because it's the same thing as {@link #AIR} - * - * @see #VOID_AIR - */ - CAVE_AIR("AIR"), - CAVE_SPIDER_SPAWN_EGG(59, "MONSTER_EGG"), - CAVE_VINES, - CAVE_VINES_PLANT, - CHAIN, - CHAINMAIL_BOOTS, - CHAINMAIL_CHESTPLATE, - CHAINMAIL_HELMET, - CHAINMAIL_LEGGINGS, - CHAIN_COMMAND_BLOCK("COMMAND", "COMMAND_CHAIN"), - CHARCOAL(1, "COAL"), - CHEST("LOCKED_CHEST"), - CHEST_MINECART("STORAGE_MINECART"), - CHICKEN("RAW_CHICKEN"), - CHICKEN_SPAWN_EGG(93, "MONSTER_EGG"), - CHIPPED_ANVIL(1, "ANVIL"), - CHISELED_DEEPSLATE, - CHISELED_NETHER_BRICKS(1, "NETHER_BRICKS"), - CHISELED_POLISHED_BLACKSTONE("POLISHED_BLACKSTONE"), - CHISELED_QUARTZ_BLOCK(1, "QUARTZ_BLOCK"), - CHISELED_RED_SANDSTONE(1, "RED_SANDSTONE"), - CHISELED_SANDSTONE(1, "SANDSTONE"), - CHISELED_STONE_BRICKS(3, "SMOOTH_BRICK"), - CHORUS_FLOWER, - CHORUS_FRUIT, - CHORUS_PLANT, - CLAY, - CLAY_BALL, - CLOCK("WATCH"), - COAL, - COAL_BLOCK, - COAL_ORE, - COARSE_DIRT(1, "DIRT"), - COBBLED_DEEPSLATE, - COBBLED_DEEPSLATE_SLAB, - COBBLED_DEEPSLATE_STAIRS, - COBBLED_DEEPSLATE_WALL, - COBBLESTONE, - COBBLESTONE_SLAB(3, "STEP"), - COBBLESTONE_STAIRS, - COBBLESTONE_WALL("COBBLE_WALL"), - COBWEB("WEB"), - COCOA, - COCOA_BEANS(3, "INK_SACK"), - COD("RAW_FISH"), - COD_BUCKET, - COD_SPAWN_EGG, - COMMAND_BLOCK("COMMAND"), - COMMAND_BLOCK_MINECART("COMMAND_MINECART"), - /** - * Unlike redstone torch and redstone lamp... neither REDTONE_COMPARATOR_OFF nor REDSTONE_COMPARATOR_ON - * are items. REDSTONE_COMPARATOR is. - * - * @see #REDSTONE_TORCH - * @see #REDSTONE_LAMP - */ - COMPARATOR("REDSTONE_COMPARATOR_OFF", "REDSTONE_COMPARATOR_ON", "REDSTONE_COMPARATOR"), - COMPASS, - COMPOSTER, - CONDUIT, - COOKED_BEEF, - COOKED_CHICKEN, - COOKED_COD("COOKED_FISH"), - COOKED_MUTTON, - COOKED_PORKCHOP("GRILLED_PORK"), - COOKED_RABBIT, - COOKED_SALMON(1, "COOKED_FISH"), - COOKIE, - COPPER_BLOCK, - COPPER_INGOT, - COPPER_ORE, - CORNFLOWER, - COW_SPAWN_EGG(92, "MONSTER_EGG"), - CRACKED_DEEPSLATE_BRICKS, - CRACKED_DEEPSLATE_TILES, - CRACKED_NETHER_BRICKS(2, "NETHER_BRICKS"), - CRACKED_POLISHED_BLACKSTONE_BRICKS("POLISHED_BLACKSTONE_BRICKS"), - CRACKED_STONE_BRICKS(2, "SMOOTH_BRICK"), - CRAFTING_TABLE("WORKBENCH"), - CREEPER_BANNER_PATTERN, - CREEPER_HEAD(4, "SKULL", "SKULL_ITEM"), - CREEPER_SPAWN_EGG(50, "MONSTER_EGG"), - CREEPER_WALL_HEAD(4, "SKULL", "SKULL_ITEM"), - CRIMSON_BUTTON, - CRIMSON_DOOR, - CRIMSON_FENCE, - CRIMSON_FENCE_GATE, - CRIMSON_FUNGUS, - CRIMSON_HYPHAE, - CRIMSON_NYLIUM, - CRIMSON_PLANKS, - CRIMSON_PRESSURE_PLATE, - CRIMSON_ROOTS, - CRIMSON_SIGN("SIGN_POST"), - CRIMSON_SLAB, - CRIMSON_STAIRS, - CRIMSON_STEM, - CRIMSON_TRAPDOOR, - CRIMSON_WALL_SIGN("WALL_SIGN"), - CROSSBOW, - CRYING_OBSIDIAN, - CUT_COPPER, - CUT_COPPER_SLAB, - CUT_COPPER_STAIRS, - CUT_RED_SANDSTONE, - CUT_RED_SANDSTONE_SLAB("STONE_SLAB2"), - CUT_SANDSTONE, - CUT_SANDSTONE_SLAB(1, "STEP"), - CYAN_BANNER(6, "STANDING_BANNER", "BANNER"), - CYAN_BED(supports(12) ? 9 : 0, "BED_BLOCK", "BED"), - CYAN_CANDLE, - CYAN_CANDLE_CAKE, - CYAN_CARPET(9, "CARPET"), - CYAN_CONCRETE(9, "CONCRETE"), - CYAN_CONCRETE_POWDER(9, "CONCRETE_POWDER"), - CYAN_DYE(6, "INK_SACK"), - CYAN_GLAZED_TERRACOTTA, - CYAN_SHULKER_BOX, - CYAN_STAINED_GLASS(9, "STAINED_GLASS"), - CYAN_STAINED_GLASS_PANE(9, "STAINED_GLASS_PANE"), - CYAN_TERRACOTTA(9, "STAINED_CLAY"), - CYAN_WALL_BANNER(6, "WALL_BANNER"), - CYAN_WOOL(9, "WOOL"), - DAMAGED_ANVIL(2, "ANVIL"), - DANDELION("YELLOW_FLOWER"), - DARK_OAK_BOAT("BOAT_DARK_OAK"), - DARK_OAK_BUTTON("WOOD_BUTTON"), - DARK_OAK_CHEST_BOAT, - DARK_OAK_DOOR("DARK_OAK_DOOR", "DARK_OAK_DOOR_ITEM"), - DARK_OAK_FENCE, - DARK_OAK_FENCE_GATE, - DARK_OAK_LEAVES(5, "LEAVES_2"), - DARK_OAK_LOG(5, "LOG_2"), - DARK_OAK_PLANKS(5, "WOOD"), - DARK_OAK_PRESSURE_PLATE("WOOD_PLATE"), - DARK_OAK_SAPLING(5, "SAPLING"), - DARK_OAK_SIGN("SIGN_POST", "SIGN"), - DARK_OAK_SLAB(5, "WOOD_DOUBLE_STEP", "WOOD_STEP", "WOODEN_SLAB"), - DARK_OAK_STAIRS, - DARK_OAK_TRAPDOOR("TRAP_DOOR"), - DARK_OAK_WALL_SIGN("WALL_SIGN"), - DARK_OAK_WOOD(5, "LOG_2"), - DARK_PRISMARINE(2, "PRISMARINE"), - DARK_PRISMARINE_SLAB, - DARK_PRISMARINE_STAIRS, - DAYLIGHT_DETECTOR("DAYLIGHT_DETECTOR_INVERTED"), - DEAD_BRAIN_CORAL, - DEAD_BRAIN_CORAL_BLOCK, - DEAD_BRAIN_CORAL_FAN, - DEAD_BRAIN_CORAL_WALL_FAN, - DEAD_BUBBLE_CORAL, - DEAD_BUBBLE_CORAL_BLOCK, - DEAD_BUBBLE_CORAL_FAN, - DEAD_BUBBLE_CORAL_WALL_FAN, - DEAD_BUSH("LONG_GRASS"), - DEAD_FIRE_CORAL, - DEAD_FIRE_CORAL_BLOCK, - DEAD_FIRE_CORAL_FAN, - DEAD_FIRE_CORAL_WALL_FAN, - DEAD_HORN_CORAL, - DEAD_HORN_CORAL_BLOCK, - DEAD_HORN_CORAL_FAN, - DEAD_HORN_CORAL_WALL_FAN, - DEAD_TUBE_CORAL, - DEAD_TUBE_CORAL_BLOCK, - DEAD_TUBE_CORAL_FAN, - DEAD_TUBE_CORAL_WALL_FAN, - DEBUG_STICK, - DEEPSLATE, - DEEPSLATE_BRICKS, - DEEPSLATE_BRICK_SLAB, - DEEPSLATE_BRICK_STAIRS, - DEEPSLATE_BRICK_WALL, - DEEPSLATE_COAL_ORE, - DEEPSLATE_COPPER_ORE, - DEEPSLATE_DIAMOND_ORE, - DEEPSLATE_EMERALD_ORE, - DEEPSLATE_GOLD_ORE, - DEEPSLATE_IRON_ORE, - DEEPSLATE_LAPIS_ORE, - DEEPSLATE_REDSTONE_ORE, - DEEPSLATE_TILES, - DEEPSLATE_TILE_SLAB, - DEEPSLATE_TILE_STAIRS, - DEEPSLATE_TILE_WALL, - DETECTOR_RAIL, - DIAMOND, - DIAMOND_AXE, - DIAMOND_BLOCK, - DIAMOND_BOOTS, - DIAMOND_CHESTPLATE, - DIAMOND_HELMET, - DIAMOND_HOE, - DIAMOND_HORSE_ARMOR("DIAMOND_BARDING"), - DIAMOND_LEGGINGS, - DIAMOND_ORE, - DIAMOND_PICKAXE, - DIAMOND_SHOVEL("DIAMOND_SPADE"), - DIAMOND_SWORD, - DIORITE(3, "STONE"), - DIORITE_SLAB, - DIORITE_STAIRS, - DIORITE_WALL, - DIRT, - /** - * Changed in 1.17 - */ - DIRT_PATH("GRASS_PATH"), - DISC_FRAGMENT_5, - DISPENSER, - DOLPHIN_SPAWN_EGG, - DONKEY_SPAWN_EGG(32, "MONSTER_EGG"), - DRAGON_BREATH("DRAGONS_BREATH"), - DRAGON_EGG, - DRAGON_HEAD(5, "SKULL", "SKULL_ITEM"), - DRAGON_WALL_HEAD(5, "SKULL", "SKULL_ITEM"), - DRIED_KELP, - DRIED_KELP_BLOCK, - DRIPSTONE_BLOCK, - DROPPER, - DROWNED_SPAWN_EGG, - ECHO_SHARD, - EGG, - ELDER_GUARDIAN_SPAWN_EGG(4, "MONSTER_EGG"), - ELYTRA, - EMERALD, - EMERALD_BLOCK, - EMERALD_ORE, - ENCHANTED_BOOK, - ENCHANTED_GOLDEN_APPLE(1, "GOLDEN_APPLE"), - ENCHANTING_TABLE("ENCHANTMENT_TABLE"), - ENDERMAN_SPAWN_EGG(58, "MONSTER_EGG"), - ENDERMITE_SPAWN_EGG(67, "MONSTER_EGG"), - ENDER_CHEST, - ENDER_EYE("EYE_OF_ENDER"), - ENDER_PEARL, - END_CRYSTAL, - END_GATEWAY, - END_PORTAL("ENDER_PORTAL"), - END_PORTAL_FRAME("ENDER_PORTAL_FRAME"), - END_ROD, - END_STONE("ENDER_STONE"), - END_STONE_BRICKS("END_BRICKS"), - END_STONE_BRICK_SLAB, - END_STONE_BRICK_STAIRS, - END_STONE_BRICK_WALL, - EVOKER_SPAWN_EGG(34, "MONSTER_EGG"), - EXPERIENCE_BOTTLE("EXP_BOTTLE"), - EXPOSED_COPPER, - EXPOSED_CUT_COPPER, - EXPOSED_CUT_COPPER_SLAB, - EXPOSED_CUT_COPPER_STAIRS, - FARMLAND("SOIL"), - FEATHER, - FERMENTED_SPIDER_EYE, - FERN(2, "LONG_GRASS"), - /** - * For some reasons filled map items are really special. - * Their data value starts from 0 and every time a player - * creates a new map that maps data value increases. - * https://github.com/CryptoMorin/XSeries/issues/91 - */ - FILLED_MAP("MAP"), - FIRE, - FIREWORK_ROCKET("FIREWORK"), - FIREWORK_STAR("FIREWORK_CHARGE"), - FIRE_CHARGE("FIREBALL"), - FIRE_CORAL, - FIRE_CORAL_BLOCK, - FIRE_CORAL_FAN, - FIRE_CORAL_WALL_FAN, - FISHING_ROD, - FLETCHING_TABLE, - FLINT, - FLINT_AND_STEEL, - FLOWERING_AZALEA, - FLOWERING_AZALEA_LEAVES, - FLOWER_BANNER_PATTERN, - FLOWER_POT("FLOWER_POT", "FLOWER_POT_ITEM"), - FOX_SPAWN_EGG, - FROGSPAWN, - FROG_SPAWN_EGG, - /** - * This special material cannot be obtained as an item. - */ - FROSTED_ICE, - FURNACE("BURNING_FURNACE"), - FURNACE_MINECART("POWERED_MINECART"), - GHAST_SPAWN_EGG(56, "MONSTER_EGG"), - GHAST_TEAR, - GILDED_BLACKSTONE, - GLASS, - GLASS_BOTTLE, - GLASS_PANE("THIN_GLASS"), - GLISTERING_MELON_SLICE("SPECKLED_MELON"), - GLOBE_BANNER_PATTERN, - GLOWSTONE, - GLOWSTONE_DUST, - GLOW_BERRIES, - GLOW_INK_SAC, - GLOW_ITEM_FRAME, - GLOW_LICHEN, - GLOW_SQUID_SPAWN_EGG, - GOAT_HORN, - GOAT_SPAWN_EGG, - GOLDEN_APPLE, - GOLDEN_AXE("GOLD_AXE"), - GOLDEN_BOOTS("GOLD_BOOTS"), - GOLDEN_CARROT, - GOLDEN_CHESTPLATE("GOLD_CHESTPLATE"), - GOLDEN_HELMET("GOLD_HELMET"), - GOLDEN_HOE("GOLD_HOE"), - GOLDEN_HORSE_ARMOR("GOLD_BARDING"), - GOLDEN_LEGGINGS("GOLD_LEGGINGS"), - GOLDEN_PICKAXE("GOLD_PICKAXE"), - GOLDEN_SHOVEL("GOLD_SPADE"), - GOLDEN_SWORD("GOLD_SWORD"), - GOLD_BLOCK, - GOLD_INGOT, - GOLD_NUGGET, - GOLD_ORE, - GRANITE(1, "STONE"), - GRANITE_SLAB, - GRANITE_STAIRS, - GRANITE_WALL, - GRASS(1, "LONG_GRASS"), - GRASS_BLOCK("GRASS"), - GRAVEL, - GRAY_BANNER(8, "STANDING_BANNER", "BANNER"), - GRAY_BED(supports(12) ? 7 : 0, "BED_BLOCK", "BED"), - GRAY_CANDLE, - GRAY_CANDLE_CAKE, - GRAY_CARPET(7, "CARPET"), - GRAY_CONCRETE(7, "CONCRETE"), - GRAY_CONCRETE_POWDER(7, "CONCRETE_POWDER"), - GRAY_DYE(8, "INK_SACK"), - GRAY_GLAZED_TERRACOTTA, - GRAY_SHULKER_BOX, - GRAY_STAINED_GLASS(7, "STAINED_GLASS"), - GRAY_STAINED_GLASS_PANE(7, "THIN_GLASS", "STAINED_GLASS_PANE"), - GRAY_TERRACOTTA(7, "STAINED_CLAY"), - GRAY_WALL_BANNER(8, "WALL_BANNER"), - GRAY_WOOL(7, "WOOL"), - GREEN_BANNER(2, "STANDING_BANNER", "BANNER"), - GREEN_BED(supports(12) ? 13 : 0, "BED_BLOCK", "BED"), - GREEN_CANDLE, - GREEN_CANDLE_CAKE, - GREEN_CARPET(13, "CARPET"), - GREEN_CONCRETE(13, "CONCRETE"), - GREEN_CONCRETE_POWDER(13, "CONCRETE_POWDER"), - /** - * 1.13 renamed to CACTUS_GREEN - * 1.14 renamed to GREEN_DYE - */ - GREEN_DYE(2, "INK_SACK", "CACTUS_GREEN"), - GREEN_GLAZED_TERRACOTTA, - GREEN_SHULKER_BOX, - GREEN_STAINED_GLASS(13, "STAINED_GLASS"), - GREEN_STAINED_GLASS_PANE(13, "THIN_GLASS", "STAINED_GLASS_PANE"), - GREEN_TERRACOTTA(13, "STAINED_CLAY"), - GREEN_WALL_BANNER(2, "WALL_BANNER"), - GREEN_WOOL(13, "WOOL"), - GRINDSTONE, - GUARDIAN_SPAWN_EGG(68, "MONSTER_EGG"), - GUNPOWDER("SULPHUR"), - HANGING_ROOTS, - HAY_BLOCK, - HEART_OF_THE_SEA, - HEAVY_WEIGHTED_PRESSURE_PLATE("IRON_PLATE"), - HOGLIN_SPAWN_EGG("MONSTER_EGG"), - HONEYCOMB, - HONEYCOMB_BLOCK, - HONEY_BLOCK, - HONEY_BOTTLE, - HOPPER, - HOPPER_MINECART, - HORN_CORAL, - HORN_CORAL_BLOCK, - HORN_CORAL_FAN, - HORN_CORAL_WALL_FAN, - HORSE_SPAWN_EGG(100, "MONSTER_EGG"), - HUSK_SPAWN_EGG(23, "MONSTER_EGG"), - ICE, - INFESTED_CHISELED_STONE_BRICKS(5, "MONSTER_EGGS"), - INFESTED_COBBLESTONE(1, "MONSTER_EGGS"), - INFESTED_CRACKED_STONE_BRICKS(4, "MONSTER_EGGS"), - INFESTED_DEEPSLATE, - INFESTED_MOSSY_STONE_BRICKS(3, "MONSTER_EGGS"), - INFESTED_STONE("MONSTER_EGGS"), - INFESTED_STONE_BRICKS(2, "MONSTER_EGGS"), - /** - * We will only add "INK_SAC" for {@link #BLACK_DYE} since it's - * the only material (linked with this material) that is added - * after 1.13, which means it can use both INK_SACK and INK_SAC. - */ - INK_SAC("INK_SACK"), - IRON_AXE, - IRON_BARS("IRON_FENCE"), - IRON_BLOCK, - IRON_BOOTS, - IRON_CHESTPLATE, - IRON_DOOR("IRON_DOOR_BLOCK"), - IRON_HELMET, - IRON_HOE, - IRON_HORSE_ARMOR("IRON_BARDING"), - IRON_INGOT, - IRON_LEGGINGS, - IRON_NUGGET, - IRON_ORE, - IRON_PICKAXE, - IRON_SHOVEL("IRON_SPADE"), - IRON_SWORD, - IRON_TRAPDOOR, - ITEM_FRAME, - JACK_O_LANTERN, - JIGSAW, - JUKEBOX, - JUNGLE_BOAT("BOAT_JUNGLE"), - JUNGLE_BUTTON("WOOD_BUTTON"), - JUNGLE_CHEST_BOAT, - JUNGLE_DOOR("JUNGLE_DOOR", "JUNGLE_DOOR_ITEM"), - JUNGLE_FENCE, - JUNGLE_FENCE_GATE, - JUNGLE_LEAVES(3, "LEAVES"), - JUNGLE_LOG(3, "LOG"), - JUNGLE_PLANKS(3, "WOOD"), - JUNGLE_PRESSURE_PLATE("WOOD_PLATE"), - JUNGLE_SAPLING(3, "SAPLING"), - JUNGLE_SIGN("SIGN_POST", "SIGN"), - JUNGLE_SLAB(3, "WOOD_DOUBLE_STEP", "WOOD_STEP", "WOODEN_SLAB"), - JUNGLE_STAIRS("JUNGLE_WOOD_STAIRS"), - JUNGLE_TRAPDOOR("TRAP_DOOR"), - JUNGLE_WALL_SIGN("WALL_SIGN"), - JUNGLE_WOOD(3, "LOG"), - KELP, - KELP_PLANT, - KNOWLEDGE_BOOK("BOOK"), - LADDER, - LANTERN, - LAPIS_BLOCK, - LAPIS_LAZULI(4, "INK_SACK"), - LAPIS_ORE, - LARGE_AMETHYST_BUD, - LARGE_FERN(3, "DOUBLE_PLANT"), - LAVA("STATIONARY_LAVA"), - LAVA_BUCKET, - LAVA_CAULDRON, - LEAD("LEASH"), - LEATHER, - LEATHER_BOOTS, - LEATHER_CHESTPLATE, - LEATHER_HELMET, - LEATHER_HORSE_ARMOR("IRON_HORSE_ARMOR"), - LEATHER_LEGGINGS, - LECTERN, - LEVER, - LIGHT, - LIGHTNING_ROD, - LIGHT_BLUE_BANNER(12, "STANDING_BANNER", "BANNER"), - LIGHT_BLUE_BED(supports(12) ? 3 : 0, "BED_BLOCK", "BED"), - LIGHT_BLUE_CANDLE, - LIGHT_BLUE_CANDLE_CAKE, - LIGHT_BLUE_CARPET(3, "CARPET"), - LIGHT_BLUE_CONCRETE(3, "CONCRETE"), - LIGHT_BLUE_CONCRETE_POWDER(3, "CONCRETE_POWDER"), - LIGHT_BLUE_DYE(12, "INK_SACK"), - LIGHT_BLUE_GLAZED_TERRACOTTA, - LIGHT_BLUE_SHULKER_BOX, - LIGHT_BLUE_STAINED_GLASS(3, "STAINED_GLASS"), - LIGHT_BLUE_STAINED_GLASS_PANE(3, "THIN_GLASS", "STAINED_GLASS_PANE"), - LIGHT_BLUE_TERRACOTTA(3, "STAINED_CLAY"), - LIGHT_BLUE_WALL_BANNER(12, "WALL_BANNER", "STANDING_BANNER", "BANNER"), - LIGHT_BLUE_WOOL(3, "WOOL"), - LIGHT_GRAY_BANNER(7, "STANDING_BANNER", "BANNER"), - LIGHT_GRAY_BED(supports(12) ? 8 : 0, "BED_BLOCK", "BED"), - LIGHT_GRAY_CANDLE, - LIGHT_GRAY_CANDLE_CAKE, - LIGHT_GRAY_CARPET(8, "CARPET"), - LIGHT_GRAY_CONCRETE(8, "CONCRETE"), - LIGHT_GRAY_CONCRETE_POWDER(8, "CONCRETE_POWDER"), - LIGHT_GRAY_DYE(7, "INK_SACK"), - /** - * Renamed to SILVER_GLAZED_TERRACOTTA in 1.12 - * Renamed to LIGHT_GRAY_GLAZED_TERRACOTTA in 1.14 - */ - LIGHT_GRAY_GLAZED_TERRACOTTA("SILVER_GLAZED_TERRACOTTA"), - LIGHT_GRAY_SHULKER_BOX("SILVER_SHULKER_BOX"), - LIGHT_GRAY_STAINED_GLASS(8, "STAINED_GLASS"), - LIGHT_GRAY_STAINED_GLASS_PANE(8, "THIN_GLASS", "STAINED_GLASS_PANE"), - LIGHT_GRAY_TERRACOTTA(8, "STAINED_CLAY"), - LIGHT_GRAY_WALL_BANNER(7, "WALL_BANNER"), - LIGHT_GRAY_WOOL(8, "WOOL"), - LIGHT_WEIGHTED_PRESSURE_PLATE("GOLD_PLATE"), - LILAC(1, "DOUBLE_PLANT"), - LILY_OF_THE_VALLEY, - LILY_PAD("WATER_LILY"), - LIME_BANNER(10, "STANDING_BANNER", "BANNER"), - LIME_BED(supports(12) ? 5 : 0, "BED_BLOCK", "BED"), - LIME_CANDLE, - LIME_CANDLE_CAKE, - LIME_CARPET(5, "CARPET"), - LIME_CONCRETE(5, "CONCRETE"), - LIME_CONCRETE_POWDER(5, "CONCRETE_POWDER"), - LIME_DYE(10, "INK_SACK"), - LIME_GLAZED_TERRACOTTA, - LIME_SHULKER_BOX, - LIME_STAINED_GLASS(5, "STAINED_GLASS"), - LIME_STAINED_GLASS_PANE(5, "STAINED_GLASS_PANE"), - LIME_TERRACOTTA(5, "STAINED_CLAY"), - LIME_WALL_BANNER(10, "WALL_BANNER"), - LIME_WOOL(5, "WOOL"), - LINGERING_POTION, - LLAMA_SPAWN_EGG(103, "MONSTER_EGG"), - LODESTONE, - LOOM, - MAGENTA_BANNER(13, "STANDING_BANNER", "BANNER"), - MAGENTA_BED(supports(12) ? 2 : 0, "BED_BLOCK", "BED"), - MAGENTA_CANDLE, - MAGENTA_CANDLE_CAKE, - MAGENTA_CARPET(2, "CARPET"), - MAGENTA_CONCRETE(2, "CONCRETE"), - MAGENTA_CONCRETE_POWDER(2, "CONCRETE_POWDER"), - MAGENTA_DYE(13, "INK_SACK"), - MAGENTA_GLAZED_TERRACOTTA, - MAGENTA_SHULKER_BOX, - MAGENTA_STAINED_GLASS(2, "STAINED_GLASS"), - MAGENTA_STAINED_GLASS_PANE(2, "THIN_GLASS", "STAINED_GLASS_PANE"), - MAGENTA_TERRACOTTA(2, "STAINED_CLAY"), - MAGENTA_WALL_BANNER(13, "WALL_BANNER"), - MAGENTA_WOOL(2, "WOOL"), - MAGMA_BLOCK("MAGMA"), - MAGMA_CREAM, - MAGMA_CUBE_SPAWN_EGG(62, "MONSTER_EGG"), - MANGROVE_BOAT, - MANGROVE_BUTTON, - MANGROVE_CHEST_BOAT, - MANGROVE_DOOR, - MANGROVE_FENCE, - MANGROVE_FENCE_GATE, - MANGROVE_LEAVES, - MANGROVE_LOG, - MANGROVE_PLANKS, - MANGROVE_PRESSURE_PLATE, - MANGROVE_PROPAGULE, - MANGROVE_ROOTS, - MANGROVE_SIGN, - MANGROVE_SLAB, - MANGROVE_STAIRS, - MANGROVE_TRAPDOOR, - MANGROVE_WALL_SIGN, - MANGROVE_WOOD, - /** - * Adding this to the duplicated list will give you a filled map - * for 1.13+ versions and removing it from duplicated list will - * still give you a filled map in -1.12 versions. - * Since higher versions are our priority I'll keep 1.13+ support - * until I can come up with something to fix it. - */ - MAP("EMPTY_MAP"), - MEDIUM_AMETHYST_BUD, - MELON("MELON_BLOCK"), - MELON_SEEDS, - MELON_SLICE("MELON"), - MELON_STEM, - MILK_BUCKET, - MINECART, - MOJANG_BANNER_PATTERN, - MOOSHROOM_SPAWN_EGG(96, "MONSTER_EGG"), - MOSSY_COBBLESTONE, - MOSSY_COBBLESTONE_SLAB(), - MOSSY_COBBLESTONE_STAIRS, - MOSSY_COBBLESTONE_WALL(1, "COBBLE_WALL", "COBBLESTONE_WALL"), - MOSSY_STONE_BRICKS(1, "SMOOTH_BRICK"), - MOSSY_STONE_BRICK_SLAB, - MOSSY_STONE_BRICK_STAIRS, - MOSSY_STONE_BRICK_WALL, - MOSS_BLOCK, - MOSS_CARPET, - MOVING_PISTON("PISTON_MOVING_PIECE"), - MUD, - MUDDY_MANGROVE_ROOTS, - MUD_BRICKS, - MUD_BRICK_SLAB, - MUD_BRICK_STAIRS, - MUD_BRICK_WALL, - MULE_SPAWN_EGG(32, "MONSTER_EGG"), - MUSHROOM_STEM("BROWN_MUSHROOM"), - MUSHROOM_STEW("MUSHROOM_SOUP"), - MUSIC_DISC_11("RECORD_11"), - MUSIC_DISC_13("GOLD_RECORD"), - MUSIC_DISC_5, - MUSIC_DISC_BLOCKS("RECORD_3"), - MUSIC_DISC_CAT("GREEN_RECORD"), - MUSIC_DISC_CHIRP("RECORD_4"), - MUSIC_DISC_FAR("RECORD_5"), - MUSIC_DISC_MALL("RECORD_6"), - MUSIC_DISC_MELLOHI("RECORD_7"), - MUSIC_DISC_OTHERSIDE, - MUSIC_DISC_PIGSTEP, - MUSIC_DISC_STAL("RECORD_8"), - MUSIC_DISC_STRAD("RECORD_9"), - MUSIC_DISC_WAIT("RECORD_12"), - MUSIC_DISC_WARD("RECORD_10"), - MUTTON, - MYCELIUM("MYCEL"), - NAME_TAG, - NAUTILUS_SHELL, - NETHERITE_AXE, - NETHERITE_BLOCK, - NETHERITE_BOOTS, - NETHERITE_CHESTPLATE, - NETHERITE_HELMET, - NETHERITE_HOE, - NETHERITE_INGOT, - NETHERITE_LEGGINGS, - NETHERITE_PICKAXE, - NETHERITE_SCRAP, - NETHERITE_SHOVEL, - NETHERITE_SWORD, - NETHERRACK, - NETHER_BRICK("NETHER_BRICK_ITEM"), - NETHER_BRICKS("NETHER_BRICK"), - NETHER_BRICK_FENCE("NETHER_FENCE"), - NETHER_BRICK_SLAB(6, "STEP"), - NETHER_BRICK_STAIRS, - NETHER_BRICK_WALL, - NETHER_GOLD_ORE, - NETHER_PORTAL("PORTAL"), - NETHER_QUARTZ_ORE("QUARTZ_ORE"), - NETHER_SPROUTS, - NETHER_STAR, - /** - * Just like mentioned in https://minecraft.gamepedia.com/Nether_Wart - * Nether wart is also known as nether stalk in the code. - * NETHER_STALK is the planted state of nether warts. - */ - NETHER_WART("NETHER_WARTS", "NETHER_STALK"), - NETHER_WART_BLOCK, - NOTE_BLOCK, - OAK_BOAT("BOAT"), - OAK_BUTTON("WOOD_BUTTON"), - OAK_CHEST_BOAT, - OAK_DOOR("WOODEN_DOOR", "WOOD_DOOR"), - OAK_FENCE("FENCE"), - OAK_FENCE_GATE("FENCE_GATE"), - OAK_LEAVES("LEAVES"), - OAK_LOG("LOG"), - OAK_PLANKS("WOOD"), - OAK_PRESSURE_PLATE("WOOD_PLATE"), - OAK_SAPLING("SAPLING"), - OAK_SIGN("SIGN_POST", "SIGN"), - OAK_SLAB("WOOD_DOUBLE_STEP", "WOOD_STEP", "WOODEN_SLAB"), - OAK_STAIRS("WOOD_STAIRS"), - OAK_TRAPDOOR("TRAP_DOOR"), - OAK_WALL_SIGN("WALL_SIGN"), - OAK_WOOD("LOG"), - OBSERVER, - OBSIDIAN, - OCELOT_SPAWN_EGG(98, "MONSTER_EGG"), - OCHRE_FROGLIGHT, - ORANGE_BANNER(14, "STANDING_BANNER", "BANNER"), - ORANGE_BED(supports(12) ? 1 : 0, "BED_BLOCK", "BED"), - ORANGE_CANDLE, - ORANGE_CANDLE_CAKE, - ORANGE_CARPET(1, "CARPET"), - ORANGE_CONCRETE(1, "CONCRETE"), - ORANGE_CONCRETE_POWDER(1, "CONCRETE_POWDER"), - ORANGE_DYE(14, "INK_SACK"), - ORANGE_GLAZED_TERRACOTTA, - ORANGE_SHULKER_BOX, - ORANGE_STAINED_GLASS(1, "STAINED_GLASS"), - ORANGE_STAINED_GLASS_PANE(1, "STAINED_GLASS_PANE"), - ORANGE_TERRACOTTA(1, "STAINED_CLAY"), - ORANGE_TULIP(5, "RED_ROSE"), - ORANGE_WALL_BANNER(14, "WALL_BANNER"), - ORANGE_WOOL(1, "WOOL"), - OXEYE_DAISY(8, "RED_ROSE"), - OXIDIZED_COPPER, - OXIDIZED_CUT_COPPER, - OXIDIZED_CUT_COPPER_SLAB, - OXIDIZED_CUT_COPPER_STAIRS, - PACKED_ICE, - PACKED_MUD, - PAINTING, - PANDA_SPAWN_EGG, - PAPER, - PARROT_SPAWN_EGG(105, "MONSTER_EGG"), - PEARLESCENT_FROGLIGHT, - PEONY(5, "DOUBLE_PLANT"), - PETRIFIED_OAK_SLAB("WOOD_STEP"), - PHANTOM_MEMBRANE, - PHANTOM_SPAWN_EGG, - PIGLIN_BANNER_PATTERN, - PIGLIN_BRUTE_SPAWN_EGG, - PIGLIN_SPAWN_EGG(57, "MONSTER_EGG"), - PIG_SPAWN_EGG(90, "MONSTER_EGG"), - PILLAGER_SPAWN_EGG, - PINK_BANNER(9, "STANDING_BANNER", "BANNER"), - PINK_BED(supports(12) ? 6 : 0, "BED_BLOCK", "BED"), - PINK_CANDLE, - PINK_CANDLE_CAKE, - PINK_CARPET(6, "CARPET"), - PINK_CONCRETE(6, "CONCRETE"), - PINK_CONCRETE_POWDER(6, "CONCRETE_POWDER"), - PINK_DYE(9, "INK_SACK"), - PINK_GLAZED_TERRACOTTA, - PINK_SHULKER_BOX, - PINK_STAINED_GLASS(6, "STAINED_GLASS"), - PINK_STAINED_GLASS_PANE(6, "THIN_GLASS", "STAINED_GLASS_PANE"), - PINK_TERRACOTTA(6, "STAINED_CLAY"), - PINK_TULIP(7, "RED_ROSE"), - PINK_WALL_BANNER(9, "WALL_BANNER"), - PINK_WOOL(6, "WOOL"), - PISTON("PISTON_BASE"), - PISTON_HEAD("PISTON_EXTENSION"), - PLAYER_HEAD(3, "SKULL", "SKULL_ITEM"), - PLAYER_WALL_HEAD(3, "SKULL", "SKULL_ITEM"), - PODZOL(2, "DIRT"), - POINTED_DRIPSTONE, - POISONOUS_POTATO, - POLAR_BEAR_SPAWN_EGG(102, "MONSTER_EGG"), - POLISHED_ANDESITE(6, "STONE"), - POLISHED_ANDESITE_SLAB, - POLISHED_ANDESITE_STAIRS, - POLISHED_BASALT, - POLISHED_BLACKSTONE, - POLISHED_BLACKSTONE_BRICKS, - POLISHED_BLACKSTONE_BRICK_SLAB, - POLISHED_BLACKSTONE_BRICK_STAIRS, - POLISHED_BLACKSTONE_BRICK_WALL, - POLISHED_BLACKSTONE_BUTTON, - POLISHED_BLACKSTONE_PRESSURE_PLATE, - POLISHED_BLACKSTONE_SLAB, - POLISHED_BLACKSTONE_STAIRS, - POLISHED_BLACKSTONE_WALL, - POLISHED_DEEPSLATE, - POLISHED_DEEPSLATE_SLAB, - POLISHED_DEEPSLATE_STAIRS, - POLISHED_DEEPSLATE_WALL, - POLISHED_DIORITE(4, "STONE"), - POLISHED_DIORITE_SLAB, - POLISHED_DIORITE_STAIRS, - POLISHED_GRANITE(2, "STONE"), - POLISHED_GRANITE_SLAB, - POLISHED_GRANITE_STAIRS, - POPPED_CHORUS_FRUIT("CHORUS_FRUIT_POPPED"), - POPPY("RED_ROSE"), - PORKCHOP("PORK"), - POTATO("POTATO_ITEM"), - POTATOES("POTATO"), - POTION, - POTTED_ACACIA_SAPLING(4, "FLOWER_POT"), - POTTED_ALLIUM(2, "RED_ROSE", "FLOWER_POT"), - POTTED_AZALEA_BUSH, - POTTED_AZURE_BLUET(3, "RED_ROSE", "FLOWER_POT"), - POTTED_BAMBOO, - POTTED_BIRCH_SAPLING(2, "FLOWER_POT"), - POTTED_BLUE_ORCHID(1, "RED_ROSE", "FLOWER_POT"), - POTTED_BROWN_MUSHROOM("FLOWER_POT"), - POTTED_CACTUS("FLOWER_POT"), - POTTED_CORNFLOWER, - POTTED_CRIMSON_FUNGUS, - POTTED_CRIMSON_ROOTS, - POTTED_DANDELION("YELLOW_FLOWER", "FLOWER_POT"), - POTTED_DARK_OAK_SAPLING(5, "FLOWER_POT"), - POTTED_DEAD_BUSH("FLOWER_POT"), - POTTED_FERN(2, "LONG_GRASS", "FLOWER_POT"), - POTTED_FLOWERING_AZALEA_BUSH, - POTTED_JUNGLE_SAPLING(3, "FLOWER_POT"), - POTTED_LILY_OF_THE_VALLEY, - POTTED_MANGROVE_PROPAGULE, - POTTED_OAK_SAPLING("FLOWER_POT"), - POTTED_ORANGE_TULIP(5, "RED_ROSE", "FLOWER_POT"), - POTTED_OXEYE_DAISY(8, "RED_ROSE", "FLOWER_POT"), - POTTED_PINK_TULIP(7, "RED_ROSE", "FLOWER_POT"), - POTTED_POPPY("RED_ROSE", "FLOWER_POT"), - POTTED_RED_MUSHROOM("FLOWER_POT"), - POTTED_RED_TULIP(4, "RED_ROSE", "FLOWER_POT"), - POTTED_SPRUCE_SAPLING(1, "FLOWER_POT"), - POTTED_WARPED_FUNGUS, - POTTED_WARPED_ROOTS, - POTTED_WHITE_TULIP(6, "RED_ROSE", "FLOWER_POT"), - POTTED_WITHER_ROSE, - POWDER_SNOW, - POWDER_SNOW_BUCKET, - POWDER_SNOW_CAULDRON, - POWERED_RAIL, - PRISMARINE, - PRISMARINE_BRICKS(1, "PRISMARINE"), - PRISMARINE_BRICK_SLAB, - PRISMARINE_BRICK_STAIRS, - PRISMARINE_CRYSTALS, - PRISMARINE_SHARD, - PRISMARINE_SLAB, - PRISMARINE_STAIRS, - PRISMARINE_WALL, - PUFFERFISH(3, "RAW_FISH"), - PUFFERFISH_BUCKET, - PUFFERFISH_SPAWN_EGG, - PUMPKIN, - PUMPKIN_PIE, - PUMPKIN_SEEDS, - PUMPKIN_STEM, - PURPLE_BANNER(5, "STANDING_BANNER", "BANNER"), - PURPLE_BED(supports(12) ? 10 : 0, "BED_BLOCK", "BED"), - PURPLE_CANDLE, - PURPLE_CANDLE_CAKE, - PURPLE_CARPET(10, "CARPET"), - PURPLE_CONCRETE(10, "CONCRETE"), - PURPLE_CONCRETE_POWDER(10, "CONCRETE_POWDER"), - PURPLE_DYE(5, "INK_SACK"), - PURPLE_GLAZED_TERRACOTTA, - PURPLE_SHULKER_BOX, - PURPLE_STAINED_GLASS(10, "STAINED_GLASS"), - PURPLE_STAINED_GLASS_PANE(10, "THIN_GLASS", "STAINED_GLASS_PANE"), - PURPLE_TERRACOTTA(10, "STAINED_CLAY"), - PURPLE_WALL_BANNER(5, "WALL_BANNER"), - PURPLE_WOOL(10, "WOOL"), - PURPUR_BLOCK, - PURPUR_PILLAR, - PURPUR_SLAB("PURPUR_DOUBLE_SLAB"), - PURPUR_STAIRS, - QUARTZ, - QUARTZ_BLOCK, - QUARTZ_BRICKS, - QUARTZ_PILLAR(2, "QUARTZ_BLOCK"), - QUARTZ_SLAB(7, "STEP"), - QUARTZ_STAIRS, - RABBIT, - RABBIT_FOOT, - RABBIT_HIDE, - RABBIT_SPAWN_EGG(101, "MONSTER_EGG"), - RABBIT_STEW, - RAIL("RAILS"), - RAVAGER_SPAWN_EGG, - RAW_COPPER, - RAW_COPPER_BLOCK, - RAW_GOLD, - RAW_GOLD_BLOCK, - RAW_IRON, - RAW_IRON_BLOCK, - RECOVERY_COMPASS, - REDSTONE, - REDSTONE_BLOCK, - /** - * Unlike redstone torch, REDSTONE_LAMP_ON isn't an item. - * The name is just here on the list for matching. - * - * @see #REDSTONE_TORCH - */ - REDSTONE_LAMP("REDSTONE_LAMP_ON", "REDSTONE_LAMP_OFF"), - REDSTONE_ORE("GLOWING_REDSTONE_ORE"), - /** - * REDSTONE_TORCH_OFF isn't an item, but a block. - * But REDSTONE_TORCH_ON is the item. - * The name is just here on the list for matching. - */ - REDSTONE_TORCH("REDSTONE_TORCH_OFF", "REDSTONE_TORCH_ON"), - REDSTONE_WALL_TORCH, - REDSTONE_WIRE, - RED_BANNER(1, "STANDING_BANNER", "BANNER"), - /** - * Data value 14 or 0 - */ - RED_BED(supports(12) ? 14 : 0, "BED_BLOCK", "BED"), - RED_CANDLE, - RED_CANDLE_CAKE, - RED_CARPET(14, "CARPET"), - RED_CONCRETE(14, "CONCRETE"), - RED_CONCRETE_POWDER(14, "CONCRETE_POWDER"), - RED_DYE(1, "INK_SACK", "ROSE_RED"), - RED_GLAZED_TERRACOTTA, - RED_MUSHROOM, - RED_MUSHROOM_BLOCK("RED_MUSHROOM", "HUGE_MUSHROOM_2"), - RED_NETHER_BRICKS("RED_NETHER_BRICK"), - RED_NETHER_BRICK_SLAB, - RED_NETHER_BRICK_STAIRS, - RED_NETHER_BRICK_WALL, - RED_SAND(1, "SAND"), - RED_SANDSTONE, - RED_SANDSTONE_SLAB("DOUBLE_STONE_SLAB2", "STONE_SLAB2"), - RED_SANDSTONE_STAIRS, - RED_SANDSTONE_WALL, - RED_SHULKER_BOX, - RED_STAINED_GLASS(14, "STAINED_GLASS"), - RED_STAINED_GLASS_PANE(14, "THIN_GLASS", "STAINED_GLASS_PANE"), - RED_TERRACOTTA(14, "STAINED_CLAY"), - RED_TULIP(4, "RED_ROSE"), - RED_WALL_BANNER(1, "WALL_BANNER"), - RED_WOOL(14, "WOOL"), - REINFORCED_DEEPSLATE, - REPEATER("DIODE_BLOCK_ON", "DIODE_BLOCK_OFF", "DIODE"), - REPEATING_COMMAND_BLOCK("COMMAND", "COMMAND_REPEATING"), - RESPAWN_ANCHOR, - ROOTED_DIRT, - ROSE_BUSH(4, "DOUBLE_PLANT"), - ROTTEN_FLESH, - SADDLE, - SALMON(1, "RAW_FISH"), - SALMON_BUCKET, - SALMON_SPAWN_EGG, - SAND, - SANDSTONE, - SANDSTONE_SLAB(1, "DOUBLE_STEP", "STEP", "STONE_SLAB"), - SANDSTONE_STAIRS, - SANDSTONE_WALL, - SCAFFOLDING, - SCULK, - SCULK_CATALYST, - SCULK_SENSOR, - SCULK_SHRIEKER, - SCULK_VEIN, - SCUTE, - SEAGRASS, - SEA_LANTERN, - SEA_PICKLE, - SHEARS, - SHEEP_SPAWN_EGG(91, "MONSTER_EGG"), - SHIELD, - SHROOMLIGHT, - SHULKER_BOX("PURPLE_SHULKER_BOX"), - SHULKER_SHELL, - SHULKER_SPAWN_EGG(69, "MONSTER_EGG"), - SILVERFISH_SPAWN_EGG(60, "MONSTER_EGG"), - SKELETON_HORSE_SPAWN_EGG(28, "MONSTER_EGG"), - SKELETON_SKULL("SKULL", "SKULL_ITEM"), - SKELETON_SPAWN_EGG(51, "MONSTER_EGG"), - SKELETON_WALL_SKULL("SKULL", "SKULL_ITEM"), - SKULL_BANNER_PATTERN, - SLIME_BALL, - SLIME_BLOCK, - SLIME_SPAWN_EGG(55, "MONSTER_EGG"), - SMALL_AMETHYST_BUD, - SMALL_DRIPLEAF, - SMITHING_TABLE, - SMOKER, - SMOOTH_BASALT, - SMOOTH_QUARTZ, - SMOOTH_QUARTZ_SLAB, - SMOOTH_QUARTZ_STAIRS, - SMOOTH_RED_SANDSTONE(2, "RED_SANDSTONE"), - SMOOTH_RED_SANDSTONE_SLAB("STONE_SLAB2"), - SMOOTH_RED_SANDSTONE_STAIRS, - SMOOTH_SANDSTONE(2, "SANDSTONE"), - SMOOTH_SANDSTONE_SLAB, - SMOOTH_SANDSTONE_STAIRS, - SMOOTH_STONE, - SMOOTH_STONE_SLAB, - SNOW, - SNOWBALL("SNOW_BALL"), - SNOW_BLOCK, - SOUL_CAMPFIRE, - SOUL_FIRE, - SOUL_LANTERN, - SOUL_SAND, - SOUL_SOIL, - SOUL_TORCH, - SOUL_WALL_TORCH, - SPAWNER("MOB_SPAWNER"), - SPECTRAL_ARROW, - SPIDER_EYE, - SPIDER_SPAWN_EGG(52, "MONSTER_EGG"), - SPLASH_POTION, - SPONGE, - SPORE_BLOSSOM, - SPRUCE_BOAT("BOAT_SPRUCE"), - SPRUCE_BUTTON("WOOD_BUTTON"), - SPRUCE_CHEST_BOAT, - SPRUCE_DOOR("SPRUCE_DOOR", "SPRUCE_DOOR_ITEM"), - SPRUCE_FENCE, - SPRUCE_FENCE_GATE, - SPRUCE_LEAVES(1, "LEAVES"), - SPRUCE_LOG(1, "LOG"), - SPRUCE_PLANKS(1, "WOOD"), - SPRUCE_PRESSURE_PLATE("WOOD_PLATE"), - SPRUCE_SAPLING(1, "SAPLING"), - SPRUCE_SIGN("SIGN_POST", "SIGN"), - SPRUCE_SLAB(1, "WOOD_DOUBLE_STEP", "WOOD_STEP", "WOODEN_SLAB"), - SPRUCE_STAIRS("SPRUCE_WOOD_STAIRS"), - SPRUCE_TRAPDOOR("TRAP_DOOR"), - SPRUCE_WALL_SIGN("WALL_SIGN"), - SPRUCE_WOOD(1, "LOG"), - SPYGLASS, - SQUID_SPAWN_EGG(94, "MONSTER_EGG"), - STICK, - STICKY_PISTON("PISTON_BASE", "PISTON_STICKY_BASE"), - STONE, - STONECUTTER, - STONE_AXE, - STONE_BRICKS("SMOOTH_BRICK"), - STONE_BRICK_SLAB(5, "DOUBLE_STEP", "STEP", "STONE_SLAB"), - STONE_BRICK_STAIRS("SMOOTH_STAIRS"), - STONE_BRICK_WALL, - STONE_BUTTON, - STONE_HOE, - STONE_PICKAXE, - STONE_PRESSURE_PLATE("STONE_PLATE"), - STONE_SHOVEL("STONE_SPADE"), - STONE_SLAB("DOUBLE_STEP", "STEP"), - STONE_STAIRS, - STONE_SWORD, - STRAY_SPAWN_EGG(6, "MONSTER_EGG"), - STRIDER_SPAWN_EGG, - STRING, - STRIPPED_ACACIA_LOG, - STRIPPED_ACACIA_WOOD, - STRIPPED_BIRCH_LOG, - STRIPPED_BIRCH_WOOD, - STRIPPED_CRIMSON_HYPHAE, - STRIPPED_CRIMSON_STEM, - STRIPPED_DARK_OAK_LOG, - STRIPPED_DARK_OAK_WOOD, - STRIPPED_JUNGLE_LOG, - STRIPPED_JUNGLE_WOOD, - STRIPPED_MANGROVE_LOG, - STRIPPED_MANGROVE_WOOD, - STRIPPED_OAK_LOG, - STRIPPED_OAK_WOOD, - STRIPPED_SPRUCE_LOG, - STRIPPED_SPRUCE_WOOD, - STRIPPED_WARPED_HYPHAE, - STRIPPED_WARPED_STEM, - STRUCTURE_BLOCK, - /** - * Originally developers used barrier blocks for its purpose. - * So technically this isn't really considered as a suggested material. - */ - STRUCTURE_VOID(10, "BARRIER"), - SUGAR, - /** - * Sugar Cane is a known material in pre-1.13 - */ - SUGAR_CANE("SUGAR_CANE_BLOCK"), - SUNFLOWER("DOUBLE_PLANT"), - SUSPICIOUS_STEW, - SWEET_BERRIES, - SWEET_BERRY_BUSH, - TADPOLE_BUCKET, - TADPOLE_SPAWN_EGG, - TALL_GRASS(2, "DOUBLE_PLANT"), - TALL_SEAGRASS, - TARGET, - TERRACOTTA("HARD_CLAY"), - TINTED_GLASS, - TIPPED_ARROW, - TNT, - TNT_MINECART("EXPLOSIVE_MINECART"), - TORCH, - TOTEM_OF_UNDYING("TOTEM"), - TRADER_LLAMA_SPAWN_EGG, - TRAPPED_CHEST, - TRIDENT, - TRIPWIRE, - TRIPWIRE_HOOK, - TROPICAL_FISH(2, "RAW_FISH"), - TROPICAL_FISH_BUCKET("BUCKET", "WATER_BUCKET"), - TROPICAL_FISH_SPAWN_EGG("MONSTER_EGG"), - TUBE_CORAL, - TUBE_CORAL_BLOCK, - TUBE_CORAL_FAN, - TUBE_CORAL_WALL_FAN, - TUFF, - TURTLE_EGG, - TURTLE_HELMET, - TURTLE_SPAWN_EGG, - TWISTING_VINES, - TWISTING_VINES_PLANT, - VERDANT_FROGLIGHT, - VEX_SPAWN_EGG(35, "MONSTER_EGG"), - VILLAGER_SPAWN_EGG(120, "MONSTER_EGG"), - VINDICATOR_SPAWN_EGG(36, "MONSTER_EGG"), - VINE, - /** - * 1.13 tag is not added because it's the same thing as {@link #AIR} - * - * @see #CAVE_AIR - */ - VOID_AIR("AIR"), - WALL_TORCH("TORCH"), - WANDERING_TRADER_SPAWN_EGG, - WARDEN_SPAWN_EGG, - WARPED_BUTTON, - WARPED_DOOR, - WARPED_FENCE, - WARPED_FENCE_GATE, - WARPED_FUNGUS, - WARPED_FUNGUS_ON_A_STICK, - WARPED_HYPHAE, - WARPED_NYLIUM, - WARPED_PLANKS, - WARPED_PRESSURE_PLATE, - WARPED_ROOTS, - WARPED_SIGN("SIGN_POST"), - WARPED_SLAB, - WARPED_STAIRS, - WARPED_STEM, - WARPED_TRAPDOOR, - WARPED_WALL_SIGN("WALL_SIGN"), - WARPED_WART_BLOCK, - /** - * This is used for blocks only. - * In 1.13- WATER will turn into STATIONARY_WATER after it finished spreading. - * After 1.13+ this uses - * https://hub.spigotmc.org/javadocs/spigot/org/bukkit/block/data/Levelled.html water flowing system. - */ - WATER("STATIONARY_WATER"), - WATER_BUCKET, - WATER_CAULDRON, - WAXED_COPPER_BLOCK, - WAXED_CUT_COPPER, - WAXED_CUT_COPPER_SLAB, - WAXED_CUT_COPPER_STAIRS, - WAXED_EXPOSED_COPPER, - WAXED_EXPOSED_CUT_COPPER, - WAXED_EXPOSED_CUT_COPPER_SLAB, - WAXED_EXPOSED_CUT_COPPER_STAIRS, - WAXED_OXIDIZED_COPPER, - WAXED_OXIDIZED_CUT_COPPER, - WAXED_OXIDIZED_CUT_COPPER_SLAB, - WAXED_OXIDIZED_CUT_COPPER_STAIRS, - WAXED_WEATHERED_COPPER, - WAXED_WEATHERED_CUT_COPPER, - WAXED_WEATHERED_CUT_COPPER_SLAB, - WAXED_WEATHERED_CUT_COPPER_STAIRS, - WEATHERED_COPPER, - WEATHERED_CUT_COPPER, - WEATHERED_CUT_COPPER_SLAB, - WEATHERED_CUT_COPPER_STAIRS, - WEEPING_VINES, - WEEPING_VINES_PLANT, - WET_SPONGE(1, "SPONGE"), - /** - * Wheat is a known material in pre-1.13 - */ - WHEAT("CROPS"), - WHEAT_SEEDS("SEEDS"), - WHITE_BANNER(15, "STANDING_BANNER", "BANNER"), - WHITE_BED("BED_BLOCK", "BED"), - WHITE_CANDLE, - WHITE_CANDLE_CAKE, - WHITE_CARPET("CARPET"), - WHITE_CONCRETE("CONCRETE"), - WHITE_CONCRETE_POWDER("CONCRETE_POWDER"), - WHITE_DYE(15, "INK_SACK", "BONE_MEAL"), - WHITE_GLAZED_TERRACOTTA, - WHITE_SHULKER_BOX, - WHITE_STAINED_GLASS("STAINED_GLASS"), - WHITE_STAINED_GLASS_PANE("THIN_GLASS", "STAINED_GLASS_PANE"), - WHITE_TERRACOTTA("STAINED_CLAY"), - WHITE_TULIP(6, "RED_ROSE"), - WHITE_WALL_BANNER(15, "WALL_BANNER"), - WHITE_WOOL("WOOL"), - WITCH_SPAWN_EGG(66, "MONSTER_EGG"), - WITHER_ROSE, - WITHER_SKELETON_SKULL(1, "SKULL", "SKULL_ITEM"), - WITHER_SKELETON_SPAWN_EGG(5, "MONSTER_EGG"), - WITHER_SKELETON_WALL_SKULL(1, "SKULL", "SKULL_ITEM"), - WOLF_SPAWN_EGG(95, "MONSTER_EGG"), - WOODEN_AXE("WOOD_AXE"), - WOODEN_HOE("WOOD_HOE"), - WOODEN_PICKAXE("WOOD_PICKAXE"), - WOODEN_SHOVEL("WOOD_SPADE"), - WOODEN_SWORD("WOOD_SWORD"), - WRITABLE_BOOK("BOOK_AND_QUILL"), - WRITTEN_BOOK, - YELLOW_BANNER(11, "STANDING_BANNER", "BANNER"), - YELLOW_BED(supports(12) ? 4 : 0, "BED_BLOCK", "BED"), - YELLOW_CANDLE, - YELLOW_CANDLE_CAKE, - YELLOW_CARPET(4, "CARPET"), - YELLOW_CONCRETE(4, "CONCRETE"), - YELLOW_CONCRETE_POWDER(4, "CONCRETE_POWDER"), - YELLOW_DYE(11, "INK_SACK", "DANDELION_YELLOW"), - YELLOW_GLAZED_TERRACOTTA, - YELLOW_SHULKER_BOX, - YELLOW_STAINED_GLASS(4, "STAINED_GLASS"), - YELLOW_STAINED_GLASS_PANE(4, "THIN_GLASS", "STAINED_GLASS_PANE"), - YELLOW_TERRACOTTA(4, "STAINED_CLAY"), - YELLOW_WALL_BANNER(11, "WALL_BANNER"), - YELLOW_WOOL(4, "WOOL"), - ZOGLIN_SPAWN_EGG, - ZOMBIE_HEAD(2, "SKULL", "SKULL_ITEM"), - ZOMBIE_HORSE_SPAWN_EGG(29, "MONSTER_EGG"), - ZOMBIE_SPAWN_EGG(54, "MONSTER_EGG"), - ZOMBIE_VILLAGER_SPAWN_EGG(27, "MONSTER_EGG"), - ZOMBIE_WALL_HEAD(2, "SKULL", "SKULL_ITEM"), - ZOMBIFIED_PIGLIN_SPAWN_EGG(57, "MONSTER_EGG", "ZOMBIE_PIGMAN_SPAWN_EGG"); - - - /** - * Cached array of {@link XMaterial#values()} to avoid allocating memory for - * calling the method every time. - * - * @since 2.0.0 - */ - public static final XMaterial[] VALUES = values(); - - /** - * We don't want to use {@link Enums#getIfPresent(Class, String)} to avoid a few checks. - * - * @since 5.1.0 - */ - private static final Map<String, XMaterial> NAMES = new HashMap<>(); - - /** - * Guava (Google Core Libraries for Java)'s cache for performance and timed caches. - * For strings that match a certain XMaterial. Mostly cached for configs. - * - * @since 1.0.0 - */ - private static final Cache<String, XMaterial> NAME_CACHE = CacheBuilder.newBuilder() - .expireAfterAccess(1, TimeUnit.HOURS) - .build(); - /** - * This is used for {@link #isOneOf(Collection)} - * - * @since 3.4.0 - */ - private static final Cache<String, Pattern> CACHED_REGEX = CacheBuilder.newBuilder() - .expireAfterAccess(3, TimeUnit.HOURS) - .build(); - /** - * The maximum data value in the pre-flattening update which belongs to {@link #VILLAGER_SPAWN_EGG}<br> - * https://minecraftitemids.com/types/spawn-egg - * - * @see #matchXMaterialWithData(String) - * @since 8.0.0 - */ - private static final byte MAX_DATA_VALUE = 120; - /** - * Used to tell the system that the passed object's (name or material) data value - * is not provided or is invalid. - * - * @since 8.0.0 - */ - private static final byte UNKNOWN_DATA_VALUE = -1; - /** - * The maximum material ID before the pre-flattening update which belongs to {@link #MUSIC_DISC_WAIT} - * - * @since 8.1.0 - */ - private static final short MAX_ID = 2267; - /** - * <b>XMaterial Paradox (Duplication Check)</b> - * <p> - * A set of duplicated material names in 1.13 and 1.12 that will conflict with the legacy names. - * Values are the new material names. This map also contains illegal elements. Check the static initializer for more info. - * <p> - * Duplications are not useful at all in versions above the flattening update {@link Data#ISFLAT} - * This set is only used for matching materials, for parsing refer to {@link #isDuplicated()} - * - * @since 3.0.0 - */ - private static final Set<String> DUPLICATED; - - static { - for (XMaterial material : VALUES) NAMES.put(material.name(), material); - } - - static { - if (Data.ISFLAT) { - // It's not needed at all if it's the newer version. We can save some memory. - DUPLICATED = null; - } else { - // MELON_SLICE, CARROTS, POTATOES, BEETROOTS, GRASS_BLOCK, BRICKS, NETHER_BRICKS, BROWN_MUSHROOM - // Using the constructor to add elements will decide to allocate more size which we don't need. - DUPLICATED = new HashSet<>(4); - DUPLICATED.add(GRASS.name()); - DUPLICATED.add(MELON.name()); - DUPLICATED.add(BRICK.name()); - DUPLICATED.add(NETHER_BRICK.name()); - } - } - - /** - * The data value of this material https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening - * It's never a negative number. - * - * @see #getData() - */ - private final byte data; - /** - * A list of material names that was being used for older verions. - * - * @see #getLegacy() - */ - @Nonnull - private final String[] legacy; - /** - * The cached Bukkit parsed material. - * - * @see #parseMaterial() - * @since 9.0.0 - */ - @Nullable - private final Material material; - - XMaterial(int data, @Nonnull String... legacy) { - this.data = (byte) data; - this.legacy = legacy; - - Material mat = null; - if ((!Data.ISFLAT && this.isDuplicated()) || (mat = Material.getMaterial(this.name())) == null) { - for (int i = legacy.length - 1; i >= 0; i--) { - mat = Material.getMaterial(legacy[i]); - if (mat != null) break; - } - } - this.material = mat; - } - - XMaterial(String... legacy) {this(0, legacy);} - - /** - * Checks if the version is 1.13 Aquatic Update or higher. - * An invocation of this method yields the cached result from the expression: - * <p> - * <blockquote> - * {@link #supports(int) 13}} - * </blockquote> - * - * @return true if 1.13 or higher. - * @see #getVersion() - * @see #supports(int) - * @since 1.0.0 - * @deprecated Use {@code XMaterial.supports(13)} instead. This method name can be confusing. - */ - @Deprecated - public static boolean isNewVersion() { - return Data.ISFLAT; - } - - /** - * This is just an extra method that can be used for many cases. - * It can be used in {@link org.bukkit.event.player.PlayerInteractEvent} - * or when accessing {@link org.bukkit.entity.Player#getMainHand()}, - * or other compatibility related methods. - * <p> - * An invocation of this method yields exactly the same result as the expression: - * <p> - * <blockquote> - * !{@link #supports(int)} 9 - * </blockquote> - * - * @since 2.0.0 - * @deprecated Use {@code !XMaterial.supports(9)} instead. - */ - @Deprecated - public static boolean isOneEight() { - return !supports(9); - } - - /** - * Gets the XMaterial with this name similar to {@link #valueOf(String)} - * without throwing an exception. - * - * @param name the name of the material. - * - * @return an optional that can be empty. - * @since 5.1.0 - */ - @Nonnull - private static Optional<XMaterial> getIfPresent(@Nonnull String name) { - return Optional.ofNullable(NAMES.get(name)); - } - - /** - * The current version of the server. - * - * @return the current server version minor number. - * @see #supports(int) - * @since 2.0.0 - */ - public static int getVersion() { - return Data.VERSION; - } - - /** - * When using 1.13+, this helps to find the old material name - * with its data value using a cached search for optimization. - * - * @see #matchDefinedXMaterial(String, byte) - * @since 1.0.0 - */ - @Nullable - private static XMaterial requestOldXMaterial(@Nonnull String name, byte data) { - String holder = name + data; - XMaterial cache = NAME_CACHE.getIfPresent(holder); - if (cache != null) return cache; - - for (XMaterial material : VALUES) { - // Not using material.name().equals(name) check is intended. - if ((data == UNKNOWN_DATA_VALUE || data == material.data) && material.anyMatchLegacy(name)) { - NAME_CACHE.put(holder, material); - return material; - } - } - - return null; - } - - /** - * Parses the given material name as an XMaterial with a given data - * value in the string if attached. Check {@link #matchXMaterialWithData(String)} for more info. - * - * @see #matchXMaterialWithData(String) - * @see #matchDefinedXMaterial(String, byte) - * @since 2.0.0 - */ - @Nonnull - public static Optional<XMaterial> matchXMaterial(@Nonnull String name) { - if (name == null || name.isEmpty()) throw new IllegalArgumentException("Cannot match a material with null or empty material name"); - Optional<XMaterial> oldMatch = matchXMaterialWithData(name); - return oldMatch.isPresent() ? oldMatch : matchDefinedXMaterial(format(name), UNKNOWN_DATA_VALUE); - } - - /** - * Parses material name and data value from the specified string. - * The separator for the material name and its data value is {@code :} - * Spaces are allowed. Mostly used when getting materials from config for old school minecrafters. - * <p> - * <b>Examples</b> - * <p><pre> - * {@code INK_SACK:1 -> RED_DYE} - * {@code WOOL: 14 -> RED_WOOL} - * </pre> - * - * @param name the material string that consists of the material name, data and separator character. - * - * @return the parsed XMaterial. - * @see #matchXMaterial(String) - * @since 3.0.0 - */ - @Nonnull - private static Optional<XMaterial> matchXMaterialWithData(@Nonnull String name) { - int index = name.indexOf(':'); - if (index != -1) { - String mat = format(name.substring(0, index)); - try { - // We don't use Byte.parseByte because we have our own range check. - byte data = (byte) Integer.parseInt(name.substring(index + 1).replace(" ", "")); - return data >= 0 && data < MAX_DATA_VALUE ? matchDefinedXMaterial(mat, data) : matchDefinedXMaterial(mat, UNKNOWN_DATA_VALUE); - } catch (NumberFormatException ignored) { - return matchDefinedXMaterial(mat, UNKNOWN_DATA_VALUE); - } - } - - return Optional.empty(); - } - - /** - * Parses the given material as an XMaterial. - * - * @throws IllegalArgumentException may be thrown as an unexpected exception. - * @see #matchDefinedXMaterial(String, byte) - * @see #matchXMaterial(ItemStack) - * @since 2.0.0 - */ - @Nonnull - public static XMaterial matchXMaterial(@Nonnull Material material) { - Objects.requireNonNull(material, "Cannot match null material"); - return matchDefinedXMaterial(material.name(), UNKNOWN_DATA_VALUE) - .orElseThrow(() -> new IllegalArgumentException("Unsupported material with no data value: " + material.name())); - } - - /** - * Parses the given item as an XMaterial using its material and data value (durability) - * if not a damageable item {@link ItemStack#getDurability()}. - * - * @param item the ItemStack to match. - * - * @return an XMaterial if matched any. - * @throws IllegalArgumentException may be thrown as an unexpected exception. - * @see #matchXMaterial(Material) - * @since 2.0.0 - */ - @Nonnull - @SuppressWarnings("deprecation") - public static XMaterial matchXMaterial(@Nonnull ItemStack item) { - Objects.requireNonNull(item, "Cannot match null ItemStack"); - String material = item.getType().name(); - byte data = (byte) (Data.ISFLAT || item.getType().getMaxDurability() > 0 ? 0 : item.getDurability()); - - // Versions 1.9-1.12 didn't really use the items data value. - if (supports(9) && !supports(13) && item.hasItemMeta() && material.equals("MONSTER_EGG")) { - ItemMeta meta = item.getItemMeta(); - if (meta instanceof SpawnEggMeta) { - SpawnEggMeta egg = (SpawnEggMeta) meta; - material = egg.getSpawnedType().name() + "_SPAWN_EGG"; - } - } - - // Potions used the items data value to store - // information about the type of potion in 1.8 - if (!supports(9) && material.endsWith("ION")) { - // There's also 16000+ data value technique, but this is more reliable. - return Potion.fromItemStack(item).isSplash() ? SPLASH_POTION : POTION; - } - - // Refer to the enum for info. - // Currently this is the only material with a non-zero data value - // that has been renamed after the flattening update. - // If this happens to more materials in the future, - // I might have to change then system. - if (Data.ISFLAT && !supports(14) && material.equals("CACTUS_GREEN")) return GREEN_DYE; - - // Check FILLED_MAP enum for more info. - // if (!Data.ISFLAT && item.hasItemMeta() && item.getItemMeta() instanceof org.bukkit.inventory.meta.MapMeta) return FILLED_MAP; - - // No orElseThrow, I don't want to deal with Java's final variable bullshit. - Optional<XMaterial> result = matchDefinedXMaterial(material, data); - if (result.isPresent()) return result.get(); - throw new IllegalArgumentException("Unsupported material from item: " + material + " (" + data + ')'); - } - - /** - * The main method that parses the given material name and data value as an XMaterial. - * All the values passed to this method will not be null or empty and are formatted correctly. - * - * @param name the formatted name of the material. - * @param data the data value of the material. Is always 0 or {@link #UNKNOWN_DATA_VALUE} when {@link Data#ISFLAT} - * - * @return an XMaterial (with the same data value if specified) - * @see #matchXMaterial(Material) - * @see #matchXMaterial(int, byte) - * @see #matchXMaterial(ItemStack) - * @since 3.0.0 - */ - @Nonnull - protected static Optional<XMaterial> matchDefinedXMaterial(@Nonnull String name, byte data) { - // if (!Boolean.valueOf(Boolean.getBoolean(Boolean.TRUE.toString())).equals(Boolean.FALSE.booleanValue())) return null; - Boolean duplicated = null; - boolean isAMap = name.equalsIgnoreCase("MAP"); - - // Do basic number and boolean checks before accessing more complex enum stuff. - if (Data.ISFLAT || (!isAMap && data <= 0 && !(duplicated = isDuplicated(name)))) { - Optional<XMaterial> xMaterial = getIfPresent(name); - if (xMaterial.isPresent()) return xMaterial; - } - // Usually flat versions wouldn't pass this point, but some special materials do. - - XMaterial oldXMaterial = requestOldXMaterial(name, data); - if (oldXMaterial == null) { - // Special case. Refer to FILLED_MAP for more info. - return (data >= 0 && isAMap) ? Optional.of(FILLED_MAP) : Optional.empty(); - } - - if (!Data.ISFLAT && oldXMaterial.isPlural() && (duplicated == null ? isDuplicated(name) : duplicated)) return getIfPresent(name); - return Optional.of(oldXMaterial); - } - - /** - * <b>XMaterial Paradox (Duplication Check)</b> - * Checks if the material has any duplicates. - * <p> - * <b>Example:</b> - * <p>{@code MELON, CARROT, POTATO, BEETROOT -> true} - * - * @param name the name of the material to check. - * - * @return true if there's a duplicated material for this material, otherwise false. - * @since 2.0.0 - */ - private static boolean isDuplicated(@Nonnull String name) { - // Don't use matchXMaterial() since this method is being called from matchXMaterial() itself and will cause a StackOverflowError. - return DUPLICATED.contains(name); - } - - /** - * Gets the XMaterial based on the material's ID (Magic Value) and data value.<br> - * You should avoid using this for performance issues. - * - * @param id the ID (Magic value) of the material. - * @param data the data value of the material. - * - * @return a parsed XMaterial with the same ID and data value. - * @see #matchXMaterial(ItemStack) - * @since 2.0.0 - * @deprecated this method loops through all the available materials and matches their ID using {@link #getId()} - * which takes a really long time. Plugins should no longer support IDs. If you want, you can make a {@link Map} cache yourself. - * This method obviously doesn't work for 1.13+ and will not be supported. This is only here for debugging purposes. - */ - @Nonnull - @Deprecated - public static Optional<XMaterial> matchXMaterial(int id, byte data) { - if (id < 0 || id > MAX_ID || data < 0) return Optional.empty(); - for (XMaterial materials : VALUES) { - if (materials.data == data && materials.getId() == id) return Optional.of(materials); - } - return Optional.empty(); - } - - /** - * Attempts to build the string like an enum name. - * Removes all the spaces, and extra non-English characters. Also removes some config/in-game based strings. - * While this method is hard to maintain, it's extremely efficient. It's approximately more than x5 times faster than - * the normal RegEx + String Methods approach for both formatted and unformatted material names. - * - * @param name the material name to modify. - * - * @return an enum name. - * @since 2.0.0 - */ - @Nonnull - protected static String format(@Nonnull String name) { - int len = name.length(); - char[] chs = new char[len]; - int count = 0; - boolean appendUnderline = false; - - for (int i = 0; i < len; i++) { - char ch = name.charAt(i); - - if (!appendUnderline && count != 0 && (ch == '-' || ch == ' ' || ch == '_') && chs[count] != '_') - appendUnderline = true; - else { - boolean number = false; - // Old materials have numbers in them. - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (number = (ch >= '0' && ch <= '9'))) { - if (appendUnderline) { - chs[count++] = '_'; - appendUnderline = false; - } - - if (number) chs[count++] = ch; - else chs[count++] = (char) (ch & 0x5f); - } - } - } - - return new String(chs, 0, count); - } - - /** - * Checks if the specified version is the same version or higher than the current server version. - * - * @param version the major version to be checked. "1." is ignored. E.g. 1.12 = 12 | 1.9 = 9 - * - * @return true of the version is equal or higher than the current version. - * @since 2.0.0 - */ - public static boolean supports(int version) { - return Data.VERSION >= version; - } - - public String[] getLegacy() { - return this.legacy; - } - - /** - * XMaterial Paradox (Duplication Check) - * I've concluded that this is just an infinite loop that keeps - * going around the Singular Form and the Plural Form materials. A waste of brain cells and a waste of time. - * This solution works just fine anyway. - * <p> - * A solution for XMaterial Paradox. - * Manually parses the duplicated materials to find the exact material based on the server version. - * If the name ends with "S" -> Plural Form Material. - * Plural methods are only plural if they're also {@link #DUPLICATED} - * <p> - * The only special exceptions are {@link #BRICKS} and {@link #NETHER_BRICKS} - * - * @return true if this material is a plural form material, otherwise false. - * @since 8.0.0 - */ - private boolean isPlural() { - // this.name().charAt(this.name().length() - 1) == 'S' - return this == CARROTS || this == POTATOES; - } - - /** - * Checks if the list of given material names matches the given base material. - * Mostly used for configs. - * <p> - * Supports {@link String#contains} {@code CONTAINS:NAME} and Regular Expression {@code REGEX:PATTERN} formats. - * <p> - * <b>Example:</b> - * <blockquote><pre> - * XMaterial material = {@link #matchXMaterial(ItemStack)}; - * if (material.isOneOf(plugin.getConfig().getStringList("disabled-items")) return; - * </pre></blockquote> - * <br> - * <b>{@code CONTAINS} Examples:</b> - * <pre> - * {@code "CONTAINS:CHEST" -> CHEST, ENDERCHEST, TRAPPED_CHEST -> true} - * {@code "cOnTaINS:dYe" -> GREEN_DYE, YELLOW_DYE, BLUE_DYE, INK_SACK -> true} - * </pre> - * <p> - * <b>{@code REGEX} Examples</b> - * <pre> - * {@code "REGEX:^.+_.+_.+$" -> Every Material with 3 underlines or more: SHULKER_SPAWN_EGG, SILVERFISH_SPAWN_EGG, SKELETON_HORSE_SPAWN_EGG} - * {@code "REGEX:^.{1,3}$" -> Material names that have 3 letters only: BED, MAP, AIR} - * </pre> - * <p> - * The reason that there are tags for {@code CONTAINS} and {@code REGEX} is for the performance. - * Although RegEx patterns are cached in this method, - * please avoid using the {@code REGEX} tag if you can use the {@code CONTAINS} tag instead. - * It'll have a huge impact on performance. - * Please avoid using {@code (capturing groups)} there's no use for them in this case. - * If you want to use groups, use {@code (?: non-capturing groups)}. It's faster. - * <p> - * Want to learn RegEx? You can mess around in <a href="https://regexr.com/">RegExr</a> website. - * - * @param materials the material names to check base material on. - * - * @return true if one of the given material names is similar to the base material. - * @since 3.1.1 - */ - public boolean isOneOf(@Nullable Collection<String> materials) { - if (materials == null || materials.isEmpty()) return false; - String name = this.name(); - - for (String comp : materials) { - String checker = comp.toUpperCase(Locale.ENGLISH); - if (checker.startsWith("CONTAINS:")) { - comp = format(checker.substring(9)); - if (name.contains(comp)) return true; - continue; - } - if (checker.startsWith("REGEX:")) { - comp = comp.substring(6); - Pattern pattern = CACHED_REGEX.getIfPresent(comp); - if (pattern == null) { - try { - pattern = Pattern.compile(comp); - CACHED_REGEX.put(comp, pattern); - } catch (PatternSyntaxException ex) { - ex.printStackTrace(); - } - } - if (pattern != null && pattern.matcher(name).matches()) return true; - continue; - } - - // Direct Object Equals - Optional<XMaterial> xMat = matchXMaterial(comp); - if (xMat.isPresent() && xMat.get() == this) return true; - } - return false; - } - - /** - * Sets the {@link Material} (and data value on older versions) of an item. - * Damageable materials will not have their durability changed. - * <p> - * Use {@link #parseItem()} instead when creating new ItemStacks. - * - * @param item the item to change its type. - * - * @see #parseItem() - * @since 3.0.0 - */ - @Nonnull - @SuppressWarnings("deprecation") - public ItemStack setType(@Nonnull ItemStack item) { - Objects.requireNonNull(item, "Cannot set material for null ItemStack"); - Material material = this.parseMaterial(); - Objects.requireNonNull(material, () -> "Unsupported material: " + this.name()); - - item.setType(material); - if (!Data.ISFLAT && material.getMaxDurability() <= 0) item.setDurability(this.data); - return item; - } - - /** - * Checks if the given material name matches any of this xmaterial's legacy material names. - * All the values passed to this method will not be null or empty and are formatted correctly. - * - * @param name the material name to check. - * - * @return true if it's one of the legacy names, otherwise false. - * @since 2.0.0 - */ - private boolean anyMatchLegacy(@Nonnull String name) { - for (int i = this.legacy.length - 1; i >= 0; i--) { - if (name.equals(this.legacy[i])) return true; - } - return false; - } - - /** - * Parses an enum name to a user-friendly name. - * These names will have underlines removed and with each word capitalized. - * <p> - * <b>Examples:</b> - * <pre> - * {@literal EMERALD -> Emerald} - * {@literal EMERALD_BLOCK -> Emerald Block} - * {@literal ENCHANTED_GOLDEN_APPLE -> Enchanted Golden Apple} - * </pre> - * - * @return a more user-friendly enum name. - * @since 3.0.0 - */ - @Override - @Nonnull - public String toString() { - return Arrays.stream(name().split("_")) - .map(t -> t.charAt(0) + t.substring(1).toLowerCase()) - .collect(Collectors.joining(" ")); - } - - /** - * Gets the ID (Magic value) of the material. - * https://www.minecraftinfo.com/idlist.htm - * <p> - * Spigot added material ID support back in 1.16+ - * - * @return the ID of the material or <b>-1</b> if it's not a legacy material or the server doesn't support the material. - * @see #matchXMaterial(int, byte) - * @since 2.2.0 - */ - @SuppressWarnings("deprecation") - public int getId() { - // https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/diff/src/main/java/org/bukkit/Material.java?until=1cb03826ebde4ef887519ce37b0a2a341494a183 - // Should start working again in 1.16+ - Material material = this.parseMaterial(); - if (material == null) return -1; - try { - return material.getId(); - } catch (IllegalArgumentException ignored) { - return -1; - } - } - - /** - * The data value of this material <a href="https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening">pre-flattening</a>. - * <p> - * Can be accessed with {@link ItemStack#getData()} then {@code MaterialData#getData()} - * or {@link ItemStack#getDurability()} if not damageable. - * - * @return data of this material, or 0 if none. - * @since 1.0.0 - */ - @SuppressWarnings("deprecation") - public byte getData() { - return data; - } - - /** - * Parses an item from this XMaterial. - * Uses data values on older versions. - * - * @return an ItemStack with the same material (and data value if in older versions.) - * @see #setType(ItemStack) - * @since 2.0.0 - */ - @Nullable - @SuppressWarnings("deprecation") - public ItemStack parseItem() { - Material material = this.parseMaterial(); - if (material == null) return null; - return Data.ISFLAT ? new ItemStack(material) : new ItemStack(material, 1, this.data); - } - - /** - * Parses the material of this XMaterial. - * - * @return the material related to this XMaterial based on the server version. - * @since 1.0.0 - */ - @Nullable - public Material parseMaterial() { - return this.material; - } - - /** - * Checks if an item has the same material (and data value on older versions). - * - * @param item item to check. - * - * @return true if the material is the same as the item's material (and data value if on older versions), otherwise false. - * @since 1.0.0 - */ - @SuppressWarnings("deprecation") - public boolean isSimilar(@Nonnull ItemStack item) { - Objects.requireNonNull(item, "Cannot compare with null ItemStack"); - if (item.getType() != this.parseMaterial()) return false; - return Data.ISFLAT || item.getDurability() == this.data || item.getType().getMaxDurability() > 0; - } - - /** - * Checks if this material is supported in the current version. - * Suggested materials will be ignored. - * <p> - * Note that you should use {@link #parseMaterial()} or {@link #parseItem()} and check if it's null - * if you're going to parse and use the material/item later. - * - * @return true if the material exists in {@link Material} list. - * @since 2.0.0 - */ - public boolean isSupported() { - return this.material != null; - } - - /** - * Checks if this material is supported in the current version and - * returns itself if yes. - * <p> - * In the other case, the alternate material will get returned, - * no matter if it is supported or not. - * - * @param alternateMaterial the material to get if this one is not supported. - * @return this material or the {@code alternateMaterial} if not supported. - */ - public XMaterial or(XMaterial alternateMaterial) { - return isSupported() ? this : alternateMaterial; - } - - /** - * This method is needed due to Java enum initialization limitations. - * It's really inefficient yes, but it's only used for initialization. - * <p> - * Yes there are many other ways like comparing the hardcoded ordinal or using a boolean in the enum constructor, - * but it's not really a big deal. - * <p> - * This method should not be called if the version is after the flattening update {@link Data#ISFLAT} - * and is only used for parsing materials, not matching, for matching check {@link #DUPLICATED} - */ - private boolean isDuplicated() { - switch (this.name()) { - case "MELON": - case "CARROT": - case "POTATO": - case "GRASS": - case "BRICK": - case "NETHER_BRICK": - - // Illegal Elements - // Since both 1.12 and 1.13 have <type>_DOOR XMaterial will use it - // for 1.12 to parse the material, but it needs <type>_DOOR_ITEM. - // We'll trick XMaterial into thinking this needs to be parsed - // using the old methods. - // Some of these materials have their enum name added to the legacy list as well. - case "DARK_OAK_DOOR": - case "ACACIA_DOOR": - case "BIRCH_DOOR": - case "JUNGLE_DOOR": - case "SPRUCE_DOOR": - case "MAP": - case "CAULDRON": - case "BREWING_STAND": - case "FLOWER_POT": - return true; - default: - return false; - } - } - - /** - * Used for data that need to be accessed during enum initialization. - * - * @since 9.0.0 - */ - private static final class Data { - /** - * The current version of the server in the form of a major version. - * If the static initialization for this fails, you know something's wrong with the server software. - * - * @since 1.0.0 - */ - private static final int VERSION; - - static { // This needs to be right below VERSION because of initialization order. - String version = Bukkit.getVersion(); - Matcher matcher = Pattern.compile("MC: \\d\\.(\\d+)").matcher(version); - - if (matcher.find()) VERSION = Integer.parseInt(matcher.group(1)); - else throw new IllegalArgumentException("Failed to parse server version from: " + version); - } - - /** - * Cached result if the server version is after the v1.13 flattening update. - * - * @since 3.0.0 - */ - private static final boolean ISFLAT = supports(13); - } -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/utils/XPotion.java b/core/src/main/java/fr/skytasul/quests/utils/XPotion.java deleted file mode 100644 index 79e57f80..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/XPotion.java +++ /dev/null @@ -1,436 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Crypto Morin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package fr.skytasul.quests.utils; - -import java.util.EnumSet; -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.Optional; -import java.util.regex.Pattern; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.apache.commons.lang.WordUtils; -import org.bukkit.Color; -import org.bukkit.Material; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.entity.ThrownPotion; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.potion.PotionType; - -import com.google.common.base.Strings; - -/** - * Up to 1.15 potion type support for multiple aliases. - * Uses EssentialsX potion list for aliases. - * <p> - * Duration: The duration of the effect in ticks. Values 0 or lower are treated as 1. Optional, and defaults to 1 tick. - * Amplifier: The amplifier of the effect, with level I having value 0. Optional, and defaults to level I. - * <p> - * EssentialsX Potions: https://github.com/EssentialsX/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/Potions.java - * Status Effect: https://minecraft.gamepedia.com/Status_effect - * Potions: https://minecraft.gamepedia.com/Potion - * - * @author Crypto Morin - * @version 1.1.0 - * @see PotionEffect - * @see PotionEffectType - * @see PotionType - */ -public enum XPotion { - ABSORPTION(null, "ABSORB"), - BAD_OMEN(null, "OMEN_BAD", "PILLAGER"), - BLINDNESS(null, "BLIND"), - CONDUIT_POWER(null, "CONDUIT", "POWER_CONDUIT"), - CONFUSION(null, "NAUSEA", "SICKNESS", "SICK"), - DAMAGE_RESISTANCE(null, "RESISTANCE", "ARMOR", "DMG_RESIST", "DMG_RESISTANCE"), - DOLPHINS_GRACE(null, "DOLPHIN", "GRACE"), - FAST_DIGGING(null, "HASTE", "SUPER_PICK", "DIGFAST", "DIG_SPEED", "QUICK_MINE", "SHARP"), - FIRE_RESISTANCE("fire_resistance", 3600, 9600, "FIRE_RESIST", "RESIST_FIRE", "FIRE_RESISTANCE"), - GLOWING(null, "GLOW", "SHINE", "SHINY"), - HARM("harming", "INJURE", "DAMAGE", "HARMING", "INFLICT"), - HEAL("healing", "HEALTH", "INSTA_HEAL", "INSTANT_HEAL", "INSTA_HEALTH", "INSTANT_HEALTH"), - HEALTH_BOOST(null, "BOOST_HEALTH", "BOOST", "HP"), - HERO_OF_THE_VILLAGE(null, "HERO", "VILLAGE_HERO"), - HUNGER(null, "STARVE", "HUNGRY"), - INCREASE_DAMAGE("strength", 3600, 9600, 1800, "STRENGTH", "BULL", "STRONG", "ATTACK"), - INVISIBILITY("invisibility", 3600, 9600, "INVISIBLE", "VANISH", "INVIS", "DISAPPEAR", "HIDE"), - JUMP("leaping", 3600, 9600, 1800, "LEAP", "JUMP_BOOST"), - LEVITATION("levitation", "LEVITATE"), - LUCK("luck", 6000, "LUCKY"), - NIGHT_VISION("night_vision", 3600, 9600, "VISION", "VISION_NIGHT"), - POISON("poison", 900, 1800, 432, "VENOM"), - REGENERATION("regeneration", 900, 1800, 450, "REGEN"), - SATURATION(null, "FOOD"), - SLOW("slowness", 1800, 4800, 400, "SLOWNESS", "SLUGGISH"), - SLOW_DIGGING(null, "FATIGUE", "DULL", "DIGGING", "SLOW_DIG", "DIG_SLOW"), - SLOW_FALLING("slow_falling", 1800, 4800, "SLOW_FALL", "FALL_SLOW"), - TURTLE_MASTER("turtle_master", 400, 800, 400, "TURTLE"), - SPEED("swiftness", 3600, 9600, 1800, "SPRINT", "RUNFAST", "SWIFT", "FAST"), - UNLUCK(null, "UNLUCKY"), - WATER_BREATHING("water_breathing", 3600, 9600, "WATER_BREATH", "UNDERWATER_BREATHING", "UNDERWATER_BREATH", "AIR"), - WEAKNESS("weakness", 1800, 4800, "WEAK", "DONALD_TRUMP"), - WITHER(null, "DECAY"); - - /** - * An immutable cached list of {@link XPotion#values()} to avoid allocating memory for - * calling the method every time. - * - * @since 1.0.0 - */ - public static final EnumSet<XPotion> VALUES = EnumSet.allOf(XPotion.class); - private static final Pattern FORMAT_PATTERN = Pattern.compile("\\d+|\\W+"); - private final String key; - private final String[] aliases; - public String normal, splash, lingering; - public final String baseDuration, extendedDuration, strongDuration; - - XPotion(String key, String... aliases) { - this(key, 0, 0, 0, aliases); - } - - XPotion(String key, int baseDuration, String... aliases) { - this(key, baseDuration, 0, 0, aliases); - } - - XPotion(String key, int baseDuration, int extendedDuration, String... aliases) { - this(key, baseDuration, extendedDuration, 0, aliases); - } - - XPotion(String key, int baseDuration, int extendedDuration, int strongDuration, String... aliases) { - this.key = key; - this.baseDuration = baseDuration == 0 ? null : " (" + Utils.ticksToElapsedTime(baseDuration) + ")"; - this.extendedDuration = extendedDuration == 0 ? null : " (" + Utils.ticksToElapsedTime(extendedDuration) + ")"; - this.strongDuration = strongDuration == 0 ? "" : " (" + Utils.ticksToElapsedTime(strongDuration) + ")"; - this.aliases = aliases; - String name = key == null ? name() : key; - this.normal = "potion of " + name; - this.splash = "splash potion of " + name; - this.lingering = "lingering potion of " + name; - } - - /** - * Attempts to build the string like an enum name. - * Removes all the spaces, numbers and extra non-English characters. Also removes some config/in-game based strings. - * - * @param name the material name to modify. - * @return a Material enum name. - * @since 1.0.0 - */ - @Nonnull - private static String format(@Nonnull String name) { - return FORMAT_PATTERN.matcher(name.trim().replace('-', '_').replace(' ', '_')).replaceAll("").toUpperCase(Locale.ENGLISH); - } - - /** - * Parses a potion effect type from the given string. - * Supports type IDs. - * - * @param potion the type of the type's ID of the potion effect type. - * @return a potion effect type. - * @since 1.0.0 - */ - @Nonnull - public static Optional<XPotion> matchXPotion(@Nonnull String potion) { - Validate.notEmpty(potion, "Cannot match XPotion of a null or empty potion effect type"); - PotionEffectType idType = getIdFromString(potion); - if (idType != null) return Optional.of(matchXPotion(idType)); - potion = format(potion); - - for (XPotion potions : VALUES) if (potions.name().equals(potion) || potions.anyMatchAliases(potion)) return Optional.ofNullable(potions); - return Optional.empty(); - } - - /** - * Parses the XPotion for this potion effect. - * - * @param type the potion effect type. - * @return the XPotion of this potion effect. - * @throws IllegalArgumentException may be thrown as an unexpected exception. - * @since 1.0.0 - */ - @Nonnull - public static XPotion matchXPotion(@Nonnull PotionEffectType type) { - Objects.requireNonNull(type, "Cannot match XPotion of a null potion effect type"); - try { - return valueOf(type.getName()); - }catch (IllegalArgumentException ex) { - throw new IllegalArgumentException("Unsupported PotionEffectType: " + type.getName(), ex.getCause()); - } - } - - public static XPotion matchFromTranslationKey(String key) { - for (XPotion potion : values()) { - if (key.equals(potion.key)) return potion; - } - return null; - } - - /** - * Parses the type ID if available. - * - * @param type the ID of the potion effect type. - * @return a potion effect type from the ID, or null if it's not an ID or the effect is not found. - * @since 1.0.0 - */ - @Nullable - private static PotionEffectType getIdFromString(@Nonnull String type) { - try { - int id = Integer.parseInt(type); - return PotionEffectType.getById(id); - }catch (NumberFormatException ex) { - return null; - } - } - - /** - * Parse a {@link PotionEffect} from a string, usually from config. - * Supports potion type IDs. - * <pre> - * WEAKNESS, 30, 1 - * SLOWNESS 200 10 - * 1, 10000, 100 - * </pre> - * - * @param potion the potion string to parse. - * @return a potion effect, or null if the potion type is wrong. - * @see #parsePotion(int, int) - * @since 1.0.0 - */ - @Nullable - public static PotionEffect parsePotionEffectFromString(@Nullable String potion) { - if (Strings.isNullOrEmpty(potion) || potion.equalsIgnoreCase("none")) return null; - String[] split = StringUtils.contains(potion, ',') ? StringUtils.split(StringUtils.deleteWhitespace(potion), ',') : StringUtils.split(potion.replaceAll(" +", " "), ' '); - - Optional<XPotion> typeOpt = matchXPotion(split[0]); - if (!typeOpt.isPresent()) return null; - PotionEffectType type = typeOpt.get().parsePotionEffectType(); - if (type == null) return null; - - int duration = 2400; // 20 ticks * 60 seconds * 2 minutes - int amplifier = 0; - try { - if (split.length > 1) { - duration = Integer.parseInt(split[1]) * 20; - if (split.length > 2) amplifier = Integer.parseInt(split[2]) - 1; - } - }catch (NumberFormatException ignored) {} - - return new PotionEffect(type, duration, amplifier); - } - - /** - * Add a list of potion effects to a player from a string list, usually from config. - * - * @param player the player to add potion effects to. - * @param effects the list of potion effects to parse and add to the player. - * @see #parsePotionEffectFromString(String) - * @since 1.0.0 - */ - public static void addPotionEffectsFromString(@Nonnull Player player, @Nonnull List<String> effects) { - if (effects == null || effects.isEmpty()) return; - Objects.requireNonNull(player, "Cannot add potion effects to null player"); - - for (String effect : effects) { - PotionEffect potionEffect = parsePotionEffectFromString(effect); - if (potionEffect != null) player.addPotionEffect(potionEffect, true); - } - } - - /** - * Throws a splash potion from the target entity. - * This method is only compatible for 1.9+ - * - * @param entity the entity to throw the potion from. - * @param color the color of the potion's bottle. - * @param effects the effects of the potion. - * @return a thrown splash potion. - * @since 1.0.0 - */ - @Nonnull - public static ThrownPotion throwPotion(@Nonnull LivingEntity entity, @Nullable Color color, @Nullable PotionEffect... effects) { - Objects.requireNonNull(entity, "Cannot throw potion from null entity"); - ItemStack potion = XMaterial.SPLASH_POTION.parseItem(); - - PotionMeta meta = (PotionMeta) potion.getItemMeta(); - meta.setColor(color); - if (effects != null) for (PotionEffect effect : effects) meta.addCustomEffect(effect, true); - potion.setItemMeta(meta); - - ThrownPotion thrownPotion = entity.launchProjectile(ThrownPotion.class); - thrownPotion.setItem(potion); - return thrownPotion; - } - - /** - * Builds an item with the given type, color and effects. - * This method is only compatible for 1.9+ - * <p> - * The item type must be one of the following: - * <pre> - * {@link Material#POTION} - * {@link Material#SPLASH_POTION} - * {@link Material#LINGERING_POTION} - * {@link Material#TIPPED_ARROW} - * </pre> - * - * @param type the type of the potion. - * @param color the color of the potion's bottle. - * @param effects the effects of the potion. - * @return an item with the specified effects. - * @since 1.0.0 - */ - @Nonnull - public static ItemStack buildItemWithEffects(@Nonnull Material type, @Nullable Color color, @Nullable PotionEffect... effects) { - Objects.requireNonNull(type, "Cannot build an effected item with null type"); - Validate.isTrue(canHaveEffects(type), "Cannot build item with " + type.name() + " potion type"); - - ItemStack item = new ItemStack(type); - PotionMeta meta = (PotionMeta) item.getItemMeta(); - - meta.setColor(color); - meta.setDisplayName(type == Material.POTION ? "Potion" : type == Material.SPLASH_POTION ? "Splash Potion" : type == Material.TIPPED_ARROW ? "Tipped Arrow" : "Lingering Potion"); - if (effects != null) for (PotionEffect effect : effects) meta.addCustomEffect(effect, true); - item.setItemMeta(meta); - return item; - } - - /** - * Checks if a material is a potion. - * This method does not check for {@code LEGACY} materials. - * You should avoid using them or use XMaterial instead. - * - * @param material the material to check. - * @return true if the material is a potion, otherwise false. - * @since 1.0.0 - */ - public static boolean canHaveEffects(@Nullable Material material) { - if (material == null) return false; - return material.name().endsWith("POTION") || material.name().startsWith("TI"); // TIPPED_ARROW - } - - /** - * Checks if the potion effect type name matches one of the aliases. - * - * @param potionEffect the potion effect type name. - * @return true of the aliases contains the potion type. - * @since 1.0.0 - */ - private boolean anyMatchAliases(@Nullable String potionEffect) { - for (String alias : aliases) if (potionEffect.equals(alias) || potionEffect.equals(StringUtils.remove(alias, '_'))) return true; - return false; - } - - /** - * Parses the potion effect type. - * - * @return the parsed potion effect type. - * @see #getPotionType() - * @since 1.0.0 - */ - @Nullable - public PotionEffectType parsePotionEffectType() { - return PotionEffectType.getByName(this.name()); - } - - /** - * Checks if this potion is supported in the current Minecraft version. - * <p> - * An invocation of this method yields exactly the same result as the expression: - * <p> - * <blockquote> - * {@link #parsePotionEffectType()} != null - * </blockquote> - * - * @return true if the current version has this potion effect type, otherwise false. - * @since 1.0.0 - */ - public boolean isSupported() { - return this.parsePotionEffectType() != null; - } - - /** - * Gets the PotionType from this PotionEffectType. - * Usually for potion items. - * - * @return a potion type for potions. - * @see #parsePotionEffectType() - * @since 1.0.0 - * @deprecated not for removal. Use {@link PotionEffectType} instead. - */ - @Nullable - @Deprecated - public PotionType getPotionType() { - PotionEffectType type = this.parsePotionEffectType(); - return type == null ? null : PotionType.getByEffect(type); - } - - /** - * Builds a potion effect with the given duration and amplifier. - * - * @param duration the duration of the potion effect. - * @param amplifier the amplifier of the potion effect. - * @return a potion effect. - * @see #parsePotionEffectFromString(String) - * @since 1.0.0 - */ - @Nullable - public PotionEffect parsePotion(int duration, int amplifier) { - PotionEffectType type = this.parsePotionEffectType(); - return type == null ? null : new PotionEffect(type, duration, amplifier); - } - - public String getTranslated(XMaterial material) { - if (material == XMaterial.POTION) return normal; - if (material == XMaterial.SPLASH_POTION) return splash; - if (material == XMaterial.LINGERING_POTION) return lingering; - throw new IllegalArgumentException("Argument is not a potion material"); - } - - @Nonnull - public String[] getAliases() { - return aliases; - } - - public String getTranslationKey() { - return key; - } - - /** - * In most cases your should be using {@link #name()} instead. - * - * @return a friendly readable string name. - */ - @Override - public String toString() { - return WordUtils.capitalize(this.name().replace('_', ' ').toLowerCase(Locale.ENGLISH)); - } -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQCMI.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQCMI.java index 8a77a9c5..1c811395 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQCMI.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQCMI.java @@ -1,12 +1,9 @@ package fr.skytasul.quests.utils.compatibility; import java.lang.reflect.Constructor; - import org.bukkit.Location; - import com.Zrips.CMI.CMI; import com.Zrips.CMI.Modules.Holograms.CMIHologram; - import fr.skytasul.quests.api.AbstractHolograms; public class BQCMI extends AbstractHolograms<CMIHologram> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays2.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays2.java index 05719adf..2b8e00bf 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays2.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays2.java @@ -7,16 +7,13 @@ import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; - import com.gmail.filoghost.holographicdisplays.api.Hologram; import com.gmail.filoghost.holographicdisplays.api.HologramsAPI; import com.gmail.filoghost.holographicdisplays.api.VisibilityManager; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.AbstractHolograms; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays3.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays3.java index 81e054ac..98dd47f0 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays3.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays3.java @@ -7,14 +7,11 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.AbstractHolograms; - import me.filoghost.holographicdisplays.api.HolographicDisplaysAPI; import me.filoghost.holographicdisplays.api.hologram.Hologram; import me.filoghost.holographicdisplays.api.hologram.VisibilitySettings; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java index 20110ef3..8e7babdb 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java @@ -4,7 +4,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; - import com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java index dc2cbe71..d9cc0ca5 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java @@ -1,13 +1,11 @@ package fr.skytasul.quests.utils.compatibility; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.block.Block; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; - import com.songoda.ultimatetimber.events.TreeFellEvent; import com.songoda.ultimatetimber.tree.ITreeBlock; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java index 57e2be56..6b7e0e2f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java @@ -10,6 +10,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.server.PluginEnableEvent; import org.bukkit.plugin.Plugin; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.requirements.RequirementCreator; @@ -27,7 +28,6 @@ import fr.skytasul.quests.rewards.PermissionReward; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.maps.BQBlueMap; import fr.skytasul.quests.utils.compatibility.maps.BQDynmap; import fr.skytasul.quests.utils.compatibility.mobs.BQAdvancedSpawners; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java index e95dd328..218aab03 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.utils.compatibility; import java.util.Collection; - import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.FactionColl; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java index 341b2ebe..11afebdd 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java @@ -2,9 +2,7 @@ import org.bukkit.Location; import org.bukkit.entity.Player; - import com.live.bemmamin.gps.api.GPSAPI; - import fr.skytasul.quests.BeautyQuests; public class GPS { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java index 86b72ab1..234864be 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.utils.compatibility; import org.bukkit.entity.Player; - import com.gamingmesh.jobs.container.Job; import com.gamingmesh.jobs.container.JobProgression; import com.gamingmesh.jobs.container.JobsPlayer; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java index f6067da1..616150c7 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.utils.compatibility; import java.util.OptionalInt; - import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java index 272dd275..6fbb69a0 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.utils.compatibility; import org.bukkit.entity.Player; - import com.gmail.nossr50.api.ExperienceAPI; public class McMMO { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java index 6a53d5ce..20d2ce16 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java @@ -2,10 +2,8 @@ import java.util.Iterator; import java.util.function.Predicate; - import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.utils.nms.NMS; public final class Paper { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java index 2d6a4718..b9efaddf 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java @@ -9,7 +9,7 @@ import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; -import fr.skytasul.quests.utils.XMaterial; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.utils.types.BQBlock; public class Post1_13 { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java index 79d82c28..77c775cf 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java @@ -13,7 +13,6 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; import java.util.stream.Collectors; - import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; @@ -21,7 +20,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.players.PlayerAccount; @@ -31,7 +29,6 @@ import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.ChatUtils; import fr.skytasul.quests.utils.Lang; - import me.clip.placeholderapi.PlaceholderAPI; import me.clip.placeholderapi.events.ExpansionRegisterEvent; import me.clip.placeholderapi.expansion.PlaceholderExpansion; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/SkillAPI.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/SkillAPI.java index 0c83e476..e67d536b 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/SkillAPI.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/SkillAPI.java @@ -1,9 +1,7 @@ package fr.skytasul.quests.utils.compatibility; import java.util.Collection; - import org.bukkit.entity.Player; - import com.sucy.skill.api.classes.RPGClass; import com.sucy.skill.api.enums.ExpSource; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Vault.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Vault.java index 6d609100..fcdd0a39 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Vault.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Vault.java @@ -3,7 +3,6 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.RegisteredServiceProvider; - import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.permission.Permission; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java index 6f356900..50e1d6e5 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java @@ -1,19 +1,16 @@ package fr.skytasul.quests.utils.compatibility.mobs; import java.util.function.Consumer; - import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.editors.TextEditor; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; - import gcspawners.AdvancedEntityDeathEvent; public class BQAdvancedSpawners implements MobFactory<String> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java index 0df02e9f..b50d3731 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java @@ -3,7 +3,6 @@ import java.util.Arrays; import java.util.List; import java.util.function.Consumer; - import org.bukkit.DyeColor; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -15,7 +14,7 @@ import org.mineacademy.boss.api.BossAPI; import org.mineacademy.boss.api.event.BossDeathEvent; import org.mineacademy.boss.model.Boss; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.ItemUtils; @@ -23,7 +22,6 @@ import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.MinecraftNames; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; public class BQBoss implements MobFactory<Boss> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java index 2ce6fc19..25a6c861 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java @@ -8,10 +8,10 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -import fr.skytasul.quests.utils.XMaterial; import me.lokka30.levelledmobs.LevelledMobs; public class BQLevelledMobs extends BukkitEntityFactory implements LeveledMobFactory<EntityType> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java index 5a1cb5da..3ce2aab9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java @@ -3,7 +3,6 @@ import java.util.Arrays; import java.util.List; import java.util.function.Consumer; - import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; @@ -11,14 +10,13 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; - +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.MinecraftNames; -import fr.skytasul.quests.utils.XMaterial; public class BukkitEntityFactory implements MobFactory<EntityType> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java index 411ebf90..b3220a78 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java @@ -3,7 +3,6 @@ import java.util.Arrays; import java.util.List; import java.util.function.Consumer; - import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; @@ -11,13 +10,11 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.inventory.ItemStack; - import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.editors.CancellableEditor; import fr.skytasul.quests.gui.npc.SelectGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; - import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.NPCDeathEvent; import net.citizensnpcs.api.event.NPCRightClickEvent; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java index dcee1ce0..976bca45 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java @@ -10,6 +10,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.options.QuestOption; @@ -18,7 +19,6 @@ import fr.skytasul.quests.gui.templates.PagedGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.nms.NMS; import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; import io.lumine.xikage.mythicmobs.mobs.MythicMob; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java index 93ea0242..be69ece0 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java @@ -11,6 +11,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.options.QuestOption; @@ -19,7 +20,6 @@ import fr.skytasul.quests.gui.templates.PagedGUI; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.nms.NMS; import io.lumine.mythic.api.mobs.MythicMob; import io.lumine.mythic.api.skills.placeholders.PlaceholderString; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java index b33694ed..a95dc52f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java @@ -1,12 +1,10 @@ package fr.skytasul.quests.utils.compatibility.npcs; import java.util.function.BiPredicate; - import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.mcmonkey.sentinel.SentinelIntegration; import org.mcmonkey.sentinel.SentinelPlugin; - import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.players.PlayerAccount; import fr.skytasul.quests.players.PlayersManager; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java index dce77991..c0c82eb9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java @@ -6,6 +6,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; +import com.cryptomorin.xseries.XMaterial; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -18,7 +19,6 @@ import fr.skytasul.quests.stages.StageArea; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.MissingDependencyException; public class BQWorldGuard { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryEvent.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryEvent.java index e7250709..8327cc08 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryEvent.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryEvent.java @@ -1,11 +1,9 @@ package fr.skytasul.quests.utils.compatibility.worldguard; import java.util.Set; - import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; - import com.sk89q.worldguard.protection.regions.ProtectedRegion; public class WorldGuardEntryEvent extends PlayerEvent { 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 3c312c82..edee7d1c 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 @@ -4,16 +4,13 @@ import java.lang.reflect.Method; import java.util.List; import java.util.Map; - import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.meta.ItemMeta; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.ReflectUtils; - import io.netty.buffer.ByteBuf; public abstract class NMS{ diff --git a/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java b/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java index 7ff8d9c1..031d429d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java +++ b/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java @@ -4,9 +4,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.meta.ItemMeta; - import fr.skytasul.quests.utils.ReflectUtils; - import io.netty.buffer.ByteBuf; public class NullNMS extends NMS { diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java b/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java index fb0a884b..d3745392 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java @@ -8,13 +8,13 @@ import org.bukkit.block.Block; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XBlock; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.Located; import fr.skytasul.quests.api.stages.types.Locatable.Located.LocatedBlock; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.utils.MinecraftNames; -import fr.skytasul.quests.utils.XBlock; -import fr.skytasul.quests.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Post1_13; public abstract class BQBlock { diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java index 0325203b..2e4306d9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java @@ -2,11 +2,9 @@ import java.util.HashMap; import java.util.Map; - import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.compatibility.DependenciesManager; diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Dialog.java b/core/src/main/java/fr/skytasul/quests/utils/types/Dialog.java index d4b5d1ec..926801df 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Dialog.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Dialog.java @@ -4,9 +4,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import org.bukkit.configuration.ConfigurationSection; - import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.utils.Lang; diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Message.java b/core/src/main/java/fr/skytasul/quests/utils/types/Message.java index 6354d41c..03d5ae2a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Message.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Message.java @@ -2,17 +2,14 @@ import java.util.HashMap; import java.util.Map; - import org.apache.commons.lang.StringUtils; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; - import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.Utils; - import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java b/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java index f636e54c..d21d8d7c 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; - import fr.skytasul.quests.utils.Utils; public class NumberedList<T> implements Iterable<T>, Cloneable{ diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java b/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java index 96a9e2d9..ba2fe3f1 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java @@ -2,9 +2,7 @@ import java.util.HashMap; import java.util.Map; - import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.compatibility.Vault; public class Permission implements Cloneable { diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Title.java b/core/src/main/java/fr/skytasul/quests/utils/types/Title.java index d58cd28d..10382c1a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Title.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Title.java @@ -2,7 +2,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; - import fr.skytasul.quests.utils.Lang; public class Title { From 6dac66e9c7eb85a1cc0af4543bc3671c710ccc59 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 22 Apr 2023 17:41:23 +0200 Subject: [PATCH 09/95] :bug: Fixed issue with "write in chat" stage --- core/src/main/java/fr/skytasul/quests/stages/StageChat.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index b67bac16..2893595a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -36,6 +36,7 @@ public StageChat(QuestBranch branch, String text, boolean cancel, boolean ignore this.cancel = cancel; this.ignoreCase = ignoreCase; + this.placeholders = placeholders; } @Override From b36c7970f2439e746789d3a8b10279fa5635e7ca Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 22 Apr 2023 21:34:57 +0200 Subject: [PATCH 10/95] :sparkles: Added "max messages per history page" dialog config option --- .../skytasul/quests/QuestsConfiguration.java | 6 ++++ .../quests/gui/quests/DialogHistoryGUI.java | 34 +++++++++++++++---- core/src/main/resources/config.yml | 3 ++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java b/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java index 8286e264..dce4f4f1 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java @@ -514,6 +514,7 @@ public class DialogsConfig { private boolean defaultSkippable = true; private boolean disableClick = false; private boolean history = true; + private int maxMessagesPerHistoryPage = -1; private int maxDistance = 15, maxDistanceSquared = 15 * 15; private String defaultPlayerSound = null; @@ -542,6 +543,7 @@ private void init() { defaultSkippable = config.getBoolean("defaultSkippable"); disableClick = config.getBoolean("disableClick"); history = config.getBoolean("history"); + maxMessagesPerHistoryPage = config.getInt("max messages per history page"); maxDistance = config.getInt("maxDistance"); maxDistanceSquared = maxDistance <= 0 ? 0 : (maxDistance * maxDistance); @@ -569,6 +571,10 @@ public boolean isHistoryEnabled() { return history; } + public int getMaxMessagesPerHistoryPage() { + return maxMessagesPerHistoryPage; + } + public int getMaxDistance() { return maxDistance; } 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 dc095abc..a60507a4 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 @@ -15,6 +15,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.gui.quests.DialogHistoryGUI.WrappedDialogable; import fr.skytasul.quests.gui.templates.PagedGUI; @@ -110,7 +111,7 @@ class WrappedDialogable { WrappedDialogable(Dialogable dialogable) { this.dialogable = dialogable; - + List<Message> messages = dialogable.getDialog().messages; List<List<String>> lines = new ArrayList<>(messages.size()); for (int i = 0; i < messages.size(); i++) { @@ -118,34 +119,53 @@ class WrappedDialogable { String formatted = msg.formatMessage(player, dialogable.getDialog().getNPCName(dialogable.getNPC()), i, messages.size()); lines.add(ChatUtils.wordWrap(formatted, 40, 100)); } - + if (lines.isEmpty()) { pages = Arrays.asList(new Page()); return; } - + pages = new ArrayList<>(); Page page = new Page(); int messagesAdded = 0; + int messagesInPage = 0; for (int i = 0; i < lines.size(); i++) { List<String> msg = lines.get(i); boolean last = i + 1 == lines.size(); - if (last || page.lines.size() + msg.size() > MAX_LINES) { + boolean pageFull = !page.lines.isEmpty() && page.lines.size() + msg.size() > MAX_LINES; + if (QuestsConfiguration.getDialogsConfig().getMaxMessagesPerHistoryPage() > 0) + pageFull |= messagesInPage >= QuestsConfiguration.getDialogsConfig().getMaxMessagesPerHistoryPage(); + + if (last || pageFull) { + // means the page currently in writing must be flushed boolean added = false; - if (last || page.lines.isEmpty()) { + if (page.lines.isEmpty() || (last && !pageFull)) { + // means the current message must be added to the page before it is flushed page.lines.addAll(msg); messagesAdded++; + messagesInPage++; added = true; } page.header = "§7§l" + messagesAdded + "§8 / §7§l" + Lang.dialogLines.format(messages.size()); - page.lines.addLast(" " + (pages.isEmpty() ? "§8" : "§7") + "◀ " + Lang.ClickLeft + " §8/ " + (last ? "§8" : "§7") + Lang.ClickRight + " ▶"); + page.lines.addLast(" " + (pages.isEmpty() ? "§8" : "§7") + "◀ " + Lang.ClickLeft + " §8/ " + + (last && !pageFull ? "§8" : "§7") + Lang.ClickRight + " ▶"); pages.add(page); page = new Page(); - if (added) continue; + messagesInPage = 0; + if (added) // means the message has already been added to the page + continue; } messagesAdded++; + messagesInPage++; page.lines.addAll(msg); } + + if (!page.lines.isEmpty()) { + page.header = "§7§l" + messagesAdded + "§8 / §7§l" + Lang.dialogLines.format(messages.size()); + page.lines.addLast( + " " + (pages.isEmpty() ? "§8" : "§7") + "◀ " + Lang.ClickLeft + " §8/ " + Lang.ClickRight + " ▶"); + pages.add(page); + } } public Page getCurrentPage() { diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index b478f530..5dd23340 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -84,6 +84,9 @@ dialogs: disableClick: false # Enables the dialog history in the Quests menu history: true + # Limits the maximum amount of messages per history page. + # If -1 then the plugin will try to put as many messages as possible until the page is full. + max messages per history page: -1 # Maximum distance the player can be from the NPC for the dialog to continue. 0 to disable. maxDistance: 15 # Default dialog sound when players are speaking From f84efb97c2153f62bf8a954b086da5f6049e9bdb Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 22 Apr 2023 21:55:29 +0200 Subject: [PATCH 11/95] :bug: :thread: Fixed deadlock on quest pool give due to previous changes --- .../fr/skytasul/quests/QuestsListener.java | 2 +- .../quests/commands/CommandsPools.java | 3 +- .../quests/structure/pools/QuestPool.java | 44 ++++++++++--------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 215450cd..3416a440 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -116,7 +116,7 @@ public void onNPCClick(BQNPCClickEvent e) { }else if (!requirements.isEmpty()) { requirements.get(0).testRequirements(p, acc, true); }else { - Utils.sendMessage(p, npc.getPools().iterator().next().give(p)); + npc.getPools().iterator().next().give(p).thenAccept(result -> Utils.sendMessage(p, result)); } e.setCancelled(false); } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index dfd098c3..0fb551a2 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java @@ -47,8 +47,7 @@ public void start(BukkitCommandActor actor, Player player, QuestPool pool) { return; } - String result = pool.give(player); - Lang.POOL_START_SUCCESS.send(player, pool.getID(), player.getName(), result); + pool.give(player).thenAccept(result -> Lang.POOL_START_SUCCESS.send(player, pool.getID(), player.getName(), result)); } } diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java index 84befe06..88a9b171 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java @@ -169,36 +169,38 @@ public boolean canGive(Player p, PlayerAccount acc) { return notDoneQuests.stream().anyMatch(quest -> quest.isLauncheable(p, acc, false)); } - public String give(Player p) { + public CompletableFuture<String> give(Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); PlayerPoolDatas datas = acc.getPoolDatas(this); long time = (datas.getLastGive() + timeDiff) - System.currentTimeMillis(); if (time > 0) - return Lang.POOL_NO_TIME.format(Utils.millisToHumanString(time)); + return CompletableFuture.completedFuture(Lang.POOL_NO_TIME.format(Utils.millisToHumanString(time))); - List<Quest> started = new ArrayList<>(questsPerLaunch); - try { - for (int i = 0; i < questsPerLaunch; i++) { - PoolGiveResult result = giveOne(p, acc, datas, !started.isEmpty()).get(); - if (result.quest != null) { - started.add(result.quest); - datas.setLastGive(System.currentTimeMillis()); - } else if (!result.forceContinue) { - if (started.isEmpty()) - return result.reason; - else - break; + return CompletableFuture.supplyAsync(() -> { + List<Quest> started = new ArrayList<>(questsPerLaunch); + try { + for (int i = 0; i < questsPerLaunch; i++) { + PoolGiveResult result = giveOne(p, acc, datas, !started.isEmpty()).get(); + if (result.quest != null) { + started.add(result.quest); + datas.setLastGive(System.currentTimeMillis()); + } else if (!result.forceContinue) { + if (started.isEmpty()) + return result.reason; + else + break; + } } + } catch (InterruptedException ex) { + BeautyQuests.logger.severe("Interrupted!", ex); + Thread.currentThread().interrupt(); + } catch (ExecutionException ex) { + BeautyQuests.logger.severe("Failed to give quests to player " + p.getName() + " from pool " + id, ex); } - } catch (InterruptedException ex) { - BeautyQuests.logger.severe("Interrupted!", ex); - Thread.currentThread().interrupt(); - } catch (ExecutionException ex) { - BeautyQuests.logger.severe("Failed to give quests to player " + p.getName() + " from pool " + id, ex); - } - return "started quest(s) " + started.stream().map(x -> "#" + x.getID()).collect(Collectors.joining(", ")); + return "started quest(s) " + started.stream().map(x -> "#" + x.getID()).collect(Collectors.joining(", ")); + }); } private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, PlayerPoolDatas datas, boolean hadOne) { From f593ec52c4830de643d5baca9888bd51d05b82ed Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 27 Apr 2023 22:11:23 +0200 Subject: [PATCH 12/95] :construction: WIP separation api --- api/pom.xml | 110 +++++ .../quests/api/AbstractHolograms.java | 0 .../skytasul/quests/api/BossBarManager.java | 4 +- .../fr/skytasul/quests/api/QuestsAPI.java | 98 ++++ .../quests/api/QuestsAPIProvider.java | 25 ++ .../fr/skytasul/quests/api/QuestsHandler.java | 11 +- .../fr/skytasul/quests/api/QuestsPlugin.java | 38 ++ .../quests/api/commands/CommandsManager.java | 15 + .../quests/api}/commands/OutsideEditor.java | 2 +- .../quests/api/comparison/ItemComparison.java | 0 .../api/comparison/ItemComparisonMap.java | 4 +- .../quests/api/data/SQLDataSaver.java | 2 +- .../skytasul/quests/api/data/SavableData.java | 0 .../api}/editors/CancellableEditor.java | 8 +- .../quests/api/editors/DialogEditor.java | 195 ++++++++ .../skytasul/quests/api/editors/Editor.java | 88 ++++ .../quests/api/editors/EditorManager.java | 20 + .../quests/api}/editors/InventoryClear.java | 12 +- .../quests/api}/editors/SelectNPC.java | 11 +- .../quests/api}/editors/TextEditor.java | 21 +- .../quests/api}/editors/TextListEditor.java | 28 +- .../quests/api}/editors/WaitBlockClick.java | 15 +- .../quests/api}/editors/WaitClick.java | 21 +- .../api}/editors/checkers/AbstractParser.java | 2 +- .../editors/checkers/CollectionParser.java | 4 +- .../api}/editors/checkers/ColorParser.java | 4 +- .../api}/editors/checkers/DurationParser.java | 2 +- .../api}/editors/checkers/EnumParser.java | 2 +- .../api}/editors/checkers/MaterialParser.java | 10 +- .../api}/editors/checkers/NumberParser.java | 4 +- .../api}/editors/checkers/PatternParser.java | 4 +- .../checkers/ScoreboardObjectiveParser.java | 4 +- .../api}/editors/checkers/WorldParser.java | 2 +- .../quests/api/events/DialogSendEvent.java | 2 +- .../api/events/DialogSendMessageEvent.java | 4 +- .../quests/api/events/PlayerQuestEvent.java | 6 +- .../api/events/PlayerQuestResetEvent.java | 4 +- .../api/events/PlayerSetStageEvent.java | 16 +- .../quests/api/events/QuestCreateEvent.java | 2 +- .../quests/api/events/QuestEvent.java | 2 +- .../quests/api/events/QuestFinishEvent.java | 2 +- .../quests/api/events/QuestLaunchEvent.java | 2 +- .../api/events/QuestPreLaunchEvent.java | 2 +- .../quests/api/events/QuestRemoveEvent.java | 2 +- .../events/accounts/PlayerAccountEvent.java | 2 +- .../accounts/PlayerAccountJoinEvent.java | 2 +- .../accounts/PlayerAccountLeaveEvent.java | 2 +- .../accounts/PlayerAccountResetEvent.java | 2 +- .../events/internal/BQBlockBreakEvent.java | 0 .../api/events/internal/BQCraftEvent.java | 0 .../api/events/internal/BQMobDeathEvent.java | 6 +- .../api/events/internal/BQNPCClickEvent.java | 1 - .../quests/api/gui/CustomInventory.java | 110 +++++ .../skytasul/quests/api/gui/GuiManager.java | 22 + .../quests/api}/gui/ImmutableItemStack.java | 2 +- .../skytasul/quests/api}/gui/ItemUtils.java | 29 +- .../quests/api/gui/close/CloseBehavior.java | 10 + .../api/gui/close/DelayCloseBehavior.java | 22 + .../api/gui/close/OpenCloseBehavior.java | 19 + .../api/gui/close/StandardCloseBehavior.java | 7 + .../quests/api/gui/layout/Button.java | 145 ++++++ .../quests/api/gui/layout/ClickEvent.java | 54 +++ .../quests/api/gui/layout/ClickHandler.java | 11 + .../quests/api/gui/layout/LayoutedGUI.java | 159 +++++++ .../quests/api/gui/templates/ChooseGUI.java | 62 +++ .../quests/api/gui/templates/ConfirmGUI.java | 48 ++ .../quests/api}/gui/templates/ListGUI.java | 20 +- .../quests/api}/gui/templates/PagedGUI.java | 69 +-- .../api}/gui/templates/StaticPagedGUI.java | 14 +- .../quests/api/localization}/Lang.java | 3 +- .../quests/api/localization}/Locale.java | 24 +- .../quests/api/mobs/LeveledMobFactory.java | 0 .../skytasul/quests/api/mobs/MobFactory.java | 20 +- .../skytasul/quests/api/mobs/MobStacker.java | 0 .../fr/skytasul/quests/api/npcs/BQNPC.java | 20 +- .../quests/api/npcs/BQNPCsManager.java | 6 +- .../quests/api/npcs/dialogs}/Dialog.java | 43 +- .../quests/api/npcs/dialogs/DialogRunner.java | 60 +++ .../quests/api/npcs/dialogs}/Message.java | 272 +++++------ .../quests/api/objects/QuestObject.java | 40 +- .../api/objects/QuestObjectClickEvent.java | 3 +- .../api/objects/QuestObjectCreator.java | 1 - .../quests/api/objects/QuestObjectGUI.java | 87 ++++ .../api/objects/QuestObjectLocation.java | 0 .../api/objects/QuestObjectLoreBuilder.java | 2 +- .../api/objects/QuestObjectsRegistry.java | 1 - .../quests/api/options/OptionSet.java | 21 + .../quests/api/options/QuestOption.java | 11 +- .../api/options/QuestOptionBoolean.java | 2 +- .../api/options/QuestOptionCreator.java | 0 .../quests/api/options/QuestOptionItem.java | 10 +- .../quests/api/options/QuestOptionObject.java | 6 +- .../api/options/QuestOptionRewards.java | 2 +- .../quests/api/options/QuestOptionString.java | 10 +- .../api/options/UpdatableOptionSet.java | 0 .../description/DescriptionSource.java | 10 + .../options/description/QuestDescription.java | 0 .../description/QuestDescriptionContext.java | 20 +- .../description/QuestDescriptionProvider.java | 0 .../quests/api/players/PlayerAccount.java | 66 +++ .../quests/api/players/PlayerPoolDatas.java | 29 ++ .../quests/api/players/PlayerQuestDatas.java | 64 +++ .../quests/api/players/PlayersManager.java | 24 + .../skytasul/quests/api/pools/QuestPool.java | 48 ++ .../quests/api/pools/QuestPoolsManager.java | 22 + .../fr/skytasul/quests/api/quests/Quest.java | 79 ++++ .../quests/api/quests/QuestsManager.java | 42 ++ .../api/quests/branches/EndingStage.java | 13 + .../api/quests/branches/QuestBranch.java | 36 ++ .../quests/branches/QuestBranchesManager.java | 25 ++ .../api/requirements/AbstractRequirement.java | 16 +- .../quests/api/requirements/Actionnable.java | 0 .../api/requirements/RequirementCreator.java | 0 .../requirements/TargetNumberRequirement.java | 12 +- .../quests/api/rewards/AbstractReward.java | 6 +- .../rewards/InterruptingBranchException.java | 0 .../quests/api/rewards/RewardCreator.java | 0 .../api/serializable/SerializableCreator.java | 0 .../api/serializable/SerializableObject.java | 19 +- .../serializable/SerializableRegistry.java | 4 +- .../quests/api/stages/AbstractStage.java | 236 ++++++++++ .../quests/api/stages/StageController.java | 35 ++ .../quests/api/stages/StageCreation.java | 37 +- .../quests/api/stages/StageHandler.java | 20 + .../skytasul/quests/api/stages/StageType.java | 48 +- .../quests/api/stages/StageTypeRegistry.java | 4 +- .../api/stages/options/StageOption.java | 0 .../types/AbstractCountableBlockStage.java | 16 +- .../stages/types/AbstractCountableStage.java | 36 +- .../api/stages/types/AbstractEntityStage.java | 39 +- .../api/stages/types/AbstractItemStage.java | 24 +- .../quests/api/stages/types/Dialogable.java | 6 +- .../quests/api/stages/types/Locatable.java | 4 +- .../quests/api/utils/ChatColorUtils.java | 4 +- .../quests/api}/utils/ComparisonMethod.java | 5 +- .../utils/CustomizedObjectTypeAdapter.java | 2 +- .../api}/utils/LevenshteinComparator.java | 2 +- .../quests/api/utils/MessageUtils.java | 120 +++++ .../quests/api}/utils/MinecraftNames.java | 34 +- .../quests/api/utils/MinecraftVersion.java | 27 ++ .../fr/skytasul/quests/api/utils}/Pair.java | 128 +++--- .../quests/api/utils/PlayerListCategory.java | 57 +++ .../api/utils/QuestVisibilityLocation.java | 23 + .../fr/skytasul/quests/api}/utils/Utils.java | 227 +--------- .../api}/utils/logger/ILoggerHandler.java | 2 +- .../api}/utils/logger/LoggerExpanded.java | 16 +- core/pom.xml | 52 +-- .../java/fr/skytasul/quests/BeautyQuests.java | 238 ++++++---- .../skytasul/quests/DefaultQuestFeatures.java | 259 +++++++++++ .../quests/QuestsAPIImplementation.java | 223 +++++++++ .../skytasul/quests/QuestsConfiguration.java | 92 ++-- .../fr/skytasul/quests/QuestsListener.java | 107 ++--- .../fr/skytasul/quests/api/QuestsAPI.java | 194 -------- .../quests/api/options/OptionSet.java | 12 - .../api/stages/AbstractCountableStage.java | 15 - .../quests/api/stages/AbstractStage.java | 357 --------------- .../quests/api/stages/StageHandler.java | 20 - .../quests/commands/CommandsAdmin.java | 96 ++-- ...ava => CommandsManagerImplementation.java} | 49 +- .../quests/commands/CommandsPlayer.java | 25 +- .../commands/CommandsPlayerManagement.java | 100 +++-- .../quests/commands/CommandsPools.java | 26 +- .../quests/commands/CommandsRoot.java | 10 +- .../quests/commands/CommandsScoreboard.java | 2 +- .../editor/EditorManagerImplementation.java | 100 +++++ .../skytasul/quests/editors/DialogEditor.java | 186 -------- .../fr/skytasul/quests/editors/Editor.java | 142 ------ .../skytasul/quests/gui/CustomInventory.java | 60 --- .../quests/gui/GuiManagerImplementation.java | 191 ++++++++ .../fr/skytasul/quests/gui/Inventories.java | 189 -------- .../skytasul/quests/gui/blocks/BlocksGUI.java | 8 +- .../quests/gui/blocks/SelectBlockGUI.java | 304 ++++++------- .../quests/gui/creation/BucketTypeGUI.java | 10 +- .../quests/gui/creation/CommandGUI.java | 19 +- .../quests/gui/creation/FinishGUI.java | 110 ++--- .../quests/gui/creation/ItemsGUI.java | 17 +- .../gui/creation/QuestCreationSession.java | 7 +- .../quests/gui/creation/QuestObjectGUI.java | 136 ------ .../quests/gui/creation/stages/Line.java | 3 +- .../quests/gui/creation/stages/StagesGUI.java | 75 +--- .../skytasul/quests/gui/misc/BranchesGUI.java | 46 +- .../skytasul/quests/gui/misc/ConfirmGUI.java | 55 --- .../quests/gui/misc/DamageCausesGUI.java | 11 +- .../quests/gui/misc/ItemComparisonGUI.java | 58 +-- .../quests/gui/misc/ItemCreatorGUI.java | 85 ++-- .../fr/skytasul/quests/gui/misc/ItemGUI.java | 39 +- .../fr/skytasul/quests/gui/misc/ListBook.java | 15 +- .../fr/skytasul/quests/gui/misc/TitleGUI.java | 73 +-- .../quests/gui/mobs/EntityTypeGUI.java | 18 +- .../quests/gui/mobs/MobSelectionGUI.java | 17 +- .../skytasul/quests/gui/mobs/MobsListGUI.java | 34 +- .../fr/skytasul/quests/gui/npc/NPCGUI.java | 137 ------ .../skytasul/quests/gui/npc/NpcCreateGUI.java | 133 ++++++ .../skytasul/quests/gui/npc/NpcSelectGUI.java | 54 +++ .../fr/skytasul/quests/gui/npc/SelectGUI.java | 83 ---- .../gui/particles/ParticleEffectGUI.java | 60 +-- .../quests/gui/particles/ParticleListGUI.java | 6 +- .../quests/gui/permissions/PermissionGUI.java | 74 +-- .../gui/permissions/PermissionListGUI.java | 10 +- .../quests/gui/pools/PoolEditGUI.java | 82 ++-- .../quests/gui/pools/PoolsManageGUI.java | 21 +- .../quests/gui/quests/ChooseQuestGUI.java | 87 ++-- .../quests/gui/quests/DialogHistoryGUI.java | 35 +- .../quests/gui/quests/PlayerListGUI.java | 160 +++---- .../quests/gui/quests/QuestsListGUI.java | 30 +- .../quests/gui/templates/ChooseGUI.java | 56 --- .../skytasul/quests/{api => }/mobs/Mob.java | 10 +- .../quests/options/OptionAutoQuest.java | 2 +- .../quests/options/OptionBypassLimit.java | 2 +- .../quests/options/OptionCancelRewards.java | 10 +- .../quests/options/OptionCancellable.java | 2 +- .../quests/options/OptionConfirmMessage.java | 2 +- .../quests/options/OptionDescription.java | 4 +- .../quests/options/OptionEndMessage.java | 2 +- .../quests/options/OptionEndRewards.java | 8 +- .../quests/options/OptionEndSound.java | 2 +- .../quests/options/OptionFailOnDeath.java | 8 +- .../quests/options/OptionFirework.java | 8 +- .../options/OptionHideNoRequirements.java | 2 +- .../quests/options/OptionHologramLaunch.java | 4 +- .../options/OptionHologramLaunchNo.java | 4 +- .../quests/options/OptionHologramText.java | 4 +- .../skytasul/quests/options/OptionName.java | 2 +- .../quests/options/OptionQuestItem.java | 14 +- .../quests/options/OptionQuestPool.java | 32 +- .../quests/options/OptionRepeatable.java | 6 +- .../quests/options/OptionRequirements.java | 10 +- .../options/OptionScoreboardEnabled.java | 2 +- .../quests/options/OptionStartDialog.java | 14 +- .../quests/options/OptionStartMessage.java | 2 +- .../quests/options/OptionStartRewards.java | 2 +- .../quests/options/OptionStartable.java | 6 +- .../quests/options/OptionStarterNPC.java | 12 +- .../skytasul/quests/options/OptionTimer.java | 12 +- .../quests/options/OptionVisibility.java | 56 +-- ...nager.java => AbstractPlayersManager.java} | 96 ++-- .../fr/skytasul/quests/players/AdminMode.java | 12 +- ....java => PlayerAccountImplementation.java} | 77 ++-- ...ava => PlayerPoolDatasImplementation.java} | 28 +- ...va => PlayerQuestDatasImplementation.java} | 60 ++- .../quests/players/PlayersManagerDB.java | 122 ++--- .../quests/players/PlayersManagerYAML.java | 113 ++--- .../quests/requirements/ClassRequirement.java | 16 +- .../requirements/EquipmentRequirement.java | 12 +- .../requirements/FactionRequirement.java | 16 +- .../requirements/JobLevelRequirement.java | 8 +- .../quests/requirements/LevelRequirement.java | 4 +- .../McCombatLevelRequirement.java | 4 +- .../requirements/McMMOSkillRequirement.java | 8 +- .../quests/requirements/MoneyRequirement.java | 8 +- .../requirements/PermissionsRequirement.java | 22 +- .../requirements/PlaceholderRequirement.java | 28 +- .../quests/requirements/QuestRequirement.java | 27 +- .../requirements/RegionRequirement.java | 13 +- .../requirements/ScoreboardRequirement.java | 10 +- .../SkillAPILevelRequirement.java | 4 +- .../logical/LogicalOrRequirement.java | 8 +- .../quests/rewards/CheckpointReward.java | 16 +- .../quests/rewards/CommandReward.java | 17 +- .../skytasul/quests/rewards/ItemReward.java | 6 +- .../quests/rewards/MessageReward.java | 10 +- .../skytasul/quests/rewards/MoneyReward.java | 8 +- .../quests/rewards/PermissionReward.java | 4 +- .../quests/rewards/QuestStopReward.java | 6 +- .../skytasul/quests/rewards/RandomReward.java | 20 +- .../quests/rewards/RemoveItemsReward.java | 8 +- .../rewards/RequirementDependentReward.java | 95 ++-- .../quests/rewards/TeleportationReward.java | 17 +- .../skytasul/quests/rewards/TitleReward.java | 2 +- .../skytasul/quests/rewards/WaitReward.java | 8 +- .../fr/skytasul/quests/rewards/XPReward.java | 14 +- .../quests/scoreboards/Scoreboard.java | 33 +- .../quests/scoreboards/ScoreboardLine.java | 4 +- .../quests/scoreboards/ScoreboardManager.java | 33 +- .../fr/skytasul/quests/stages/StageArea.java | 33 +- .../fr/skytasul/quests/stages/StageBreed.java | 16 +- .../quests/stages/StageBringBack.java | 42 +- .../skytasul/quests/stages/StageBucket.java | 41 +- .../fr/skytasul/quests/stages/StageChat.java | 28 +- .../fr/skytasul/quests/stages/StageCraft.java | 32 +- .../quests/stages/StageDealDamage.java | 42 +- .../fr/skytasul/quests/stages/StageDeath.java | 22 +- .../skytasul/quests/stages/StageEatDrink.java | 20 +- .../skytasul/quests/stages/StageEnchant.java | 22 +- .../fr/skytasul/quests/stages/StageFish.java | 22 +- .../skytasul/quests/stages/StageInteract.java | 57 ++- .../skytasul/quests/stages/StageLocation.java | 50 +-- .../fr/skytasul/quests/stages/StageMelt.java | 22 +- .../fr/skytasul/quests/stages/StageMine.java | 20 +- .../fr/skytasul/quests/stages/StageMobs.java | 34 +- .../fr/skytasul/quests/stages/StageNPC.java | 61 +-- .../quests/stages/StagePlaceBlocks.java | 20 +- .../skytasul/quests/stages/StagePlayTime.java | 39 +- .../fr/skytasul/quests/stages/StageTame.java | 16 +- ...ava => BranchesManagerImplementation.java} | 88 ++-- .../structure/EndingStageImplementation.java | 29 ++ .../quests/structure/QuestBranch.java | 395 ---------------- .../structure/QuestBranchImplementation.java | 422 ++++++++++++++++++ .../{Quest.java => QuestImplementation.java} | 216 +++++---- ....java => QuestsManagerImplementation.java} | 87 ++-- .../StageControllerImplementation.java | 216 +++++++++ ...Pool.java => QuestPoolImplementation.java} | 93 ++-- ...a => QuestPoolsManagerImplementation.java} | 41 +- .../fr/skytasul/quests/utils/Database.java | 5 +- .../fr/skytasul/quests/utils/DebugUtils.java | 8 +- .../skytasul/quests/utils/ParticleEffect.java | 5 +- .../fr/skytasul/quests/utils/QuestUtils.java | 146 ++++++ .../BQBossBarImplementation.java | 7 +- .../utils/compatibility/BQItemsAdder.java | 6 +- .../compatibility/DependenciesManager.java | 66 +-- .../quests/utils/compatibility/Paper.java | 4 +- .../compatibility/QuestsPlaceholders.java | 51 ++- .../maps/AbstractMapIntegration.java | 18 +- .../utils/compatibility/maps/BQBlueMap.java | 17 +- .../utils/compatibility/maps/BQDynmap.java | 15 +- .../mobs/BQAdvancedSpawners.java | 8 +- .../utils/compatibility/mobs/BQBoss.java | 15 +- .../compatibility/mobs/BQLevelledMobs.java | 4 +- .../compatibility/mobs/BQWildStacker.java | 2 +- .../mobs/BukkitEntityFactory.java | 10 +- .../compatibility/mobs/CitizensFactory.java | 28 +- .../utils/compatibility/mobs/MythicMobs.java | 26 +- .../utils/compatibility/mobs/MythicMobs5.java | 28 +- .../utils/compatibility/npcs/BQCitizens.java | 6 +- .../utils/compatibility/npcs/BQSentinel.java | 14 +- .../worldguard/BQWorldGuard.java | 14 +- .../worldguard/WorldGuardEntryHandler.java | 2 +- .../quests/utils/logger/LoggerHandler.java | 3 +- .../fr/skytasul/quests/utils/nms/NMS.java | 42 +- .../skytasul/quests/utils/types/BQBlock.java | 2 +- .../skytasul/quests/utils/types/Command.java | 4 +- ...r.java => DialogRunnerImplementation.java} | 63 +-- .../quests/utils/types/NumberedList.java | 2 +- .../fr/skytasul/quests/utils/types/Title.java | 2 +- pom.xml | 1 + 335 files changed, 7411 insertions(+), 5552 deletions(-) create mode 100644 api/pom.xml rename {core => api}/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java (100%) rename core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java => api/src/main/java/fr/skytasul/quests/api/BossBarManager.java (90%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/QuestsAPIProvider.java rename {core => api}/src/main/java/fr/skytasul/quests/api/QuestsHandler.java (61%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/commands/CommandsManager.java rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/commands/OutsideEditor.java (86%) rename {core => api}/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java (97%) rename {core => api}/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java (98%) rename {core => api}/src/main/java/fr/skytasul/quests/api/data/SavableData.java (100%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/CancellableEditor.java (73%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/editors/Editor.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/InventoryClear.java (57%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/SelectNPC.java (71%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/TextEditor.java (77%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/TextListEditor.java (69%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/WaitBlockClick.java (72%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/WaitClick.java (72%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/AbstractParser.java (77%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/CollectionParser.java (90%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/ColorParser.java (94%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/DurationParser.java (98%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/EnumParser.java (91%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/MaterialParser.java (76%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/NumberParser.java (92%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/PatternParser.java (83%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/ScoreboardObjectiveParser.java (79%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/editors/checkers/WorldParser.java (84%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java (96%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java (92%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java (77%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java (81%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java (57%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java (90%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java (88%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java (88%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java (88%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java (90%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java (83%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java (89%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java (88%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java (86%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java (90%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java (100%) rename core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CompatMobDeathEvent.java => api/src/main/java/fr/skytasul/quests/api/events/internal/BQMobDeathEvent.java (76%) rename {core => api}/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java (95%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/CustomInventory.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/gui/ImmutableItemStack.java (94%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/gui/ItemUtils.java (88%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/close/CloseBehavior.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/close/DelayCloseBehavior.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/close/StandardCloseBehavior.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/layout/Button.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickEvent.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/gui/templates/ListGUI.java (81%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/gui/templates/PagedGUI.java (74%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/gui/templates/StaticPagedGUI.java (74%) rename {core/src/main/java/fr/skytasul/quests/utils => api/src/main/java/fr/skytasul/quests/api/localization}/Lang.java (97%) rename {core/src/main/java/fr/skytasul/quests/api => api/src/main/java/fr/skytasul/quests/api/localization}/Locale.java (79%) rename {core => api}/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java (81%) rename {core => api}/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java (95%) rename {core => api}/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java (92%) rename {core/src/main/java/fr/skytasul/quests/utils/types => api/src/main/java/fr/skytasul/quests/api/npcs/dialogs}/Dialog.java (69%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java rename {core/src/main/java/fr/skytasul/quests/utils/types => api/src/main/java/fr/skytasul/quests/api/npcs/dialogs}/Message.java (64%) rename {core => api}/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java (77%) rename {core => api}/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java (94%) rename {core => api}/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java (94%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java rename {core => api}/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLocation.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java (97%) rename {core => api}/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java (97%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/options/OptionSet.java rename {core => api}/src/main/java/fr/skytasul/quests/api/options/QuestOption.java (89%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java (92%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java (89%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java (92%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java (91%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java (88%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java (100%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/options/description/DescriptionSource.java rename {core => api}/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java (78%) rename {core => api}/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java (100%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/players/PlayerPoolDatas.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/players/PlayersManager.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/pools/QuestPool.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/quests/Quest.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/quests/QuestsManager.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/quests/branches/EndingStage.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranch.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranchesManager.java rename {core => api}/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java (87%) rename {core => api}/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java (88%) rename {core => api}/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java (85%) rename {core => api}/src/main/java/fr/skytasul/quests/api/rewards/InterruptingBranchException.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java (81%) rename {core => api}/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java (87%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/stages/StageController.java rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java (83%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/StageType.java (56%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java (87%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java (100%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java (89%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java (86%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java (82%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java (90%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java (73%) rename {core => api}/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java (98%) rename core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java => api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java (99%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/utils/ComparisonMethod.java (87%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/utils/CustomizedObjectTypeAdapter.java (94%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/utils/LevenshteinComparator.java (93%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/utils/MinecraftNames.java (84%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/MinecraftVersion.java rename {core/src/main/java/fr/skytasul/quests/utils/types => api/src/main/java/fr/skytasul/quests/api/utils}/Pair.java (91%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/PlayerListCategory.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/QuestVisibilityLocation.java rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/utils/Utils.java (59%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/utils/logger/ILoggerHandler.java (91%) rename {core/src/main/java/fr/skytasul/quests => api/src/main/java/fr/skytasul/quests/api}/utils/logger/LoggerExpanded.java (81%) create mode 100644 core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java create mode 100644 core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java delete mode 100644 core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java delete mode 100644 core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java delete mode 100644 core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java delete mode 100644 core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java delete mode 100644 core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java rename core/src/main/java/fr/skytasul/quests/commands/{CommandsManager.java => CommandsManagerImplementation.java} (70%) create mode 100644 core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java delete mode 100644 core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java delete mode 100644 core/src/main/java/fr/skytasul/quests/editors/Editor.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/CustomInventory.java create mode 100644 core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/Inventories.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java create mode 100644 core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java create mode 100644 core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java rename core/src/main/java/fr/skytasul/quests/{api => }/mobs/Mob.java (88%) rename core/src/main/java/fr/skytasul/quests/players/{PlayersManager.java => AbstractPlayersManager.java} (73%) rename core/src/main/java/fr/skytasul/quests/players/{PlayerAccount.java => PlayerAccountImplementation.java} (69%) rename core/src/main/java/fr/skytasul/quests/players/{PlayerPoolDatas.java => PlayerPoolDatasImplementation.java} (57%) rename core/src/main/java/fr/skytasul/quests/players/{PlayerQuestDatas.java => PlayerQuestDatasImplementation.java} (72%) rename core/src/main/java/fr/skytasul/quests/structure/{BranchesManager.java => BranchesManagerImplementation.java} (52%) create mode 100644 core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java delete mode 100644 core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java create mode 100644 core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java rename core/src/main/java/fr/skytasul/quests/structure/{Quest.java => QuestImplementation.java} (67%) rename core/src/main/java/fr/skytasul/quests/structure/{QuestsManager.java => QuestsManagerImplementation.java} (64%) create mode 100644 core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java rename core/src/main/java/fr/skytasul/quests/structure/pools/{QuestPool.java => QuestPoolImplementation.java} (71%) rename core/src/main/java/fr/skytasul/quests/structure/pools/{QuestPoolsManager.java => QuestPoolsManagerImplementation.java} (62%) create mode 100644 core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java rename core/src/main/java/fr/skytasul/quests/{api/bossbar => utils/compatibility}/BQBossBarImplementation.java (81%) rename core/src/main/java/fr/skytasul/quests/utils/types/{DialogRunner.java => DialogRunnerImplementation.java} (81%) diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 00000000..3fb761a4 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <packaging>jar</packaging> + <artifactId>beautyquests-api</artifactId> + <parent> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-parent</artifactId> + <version>0.21-SNAPSHOT</version> + </parent> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.2.1</version> + <configuration> + <relocations> + <relocation> + <pattern>revxrsal.commands</pattern> + <shadedPattern>fr.skytasul.quests.commands.revxrsal</shadedPattern> + </relocation> + <relocation> + <pattern>com.cryptomorin.xseries</pattern> + <shadedPattern>fr.skytasul.quests.utils</shadedPattern> + </relocation> + </relocations> + <filters> + <filter> + <artifact>com.github.cryptomorin:XSeries</artifact> + <includes> + <include>com/cryptomorin/xseries/XMaterial*</include> + <include>com/cryptomorin/xseries/XBlock*</include> + <include>com/cryptomorin/xseries/XPotion*</include> + </includes> + </filter> + </filters> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.4.1</version> + <configuration> + <skip>false</skip> + </configuration> + </plugin> + </plugins> + </build> + + <repositories> + <repository> + <id>papermc</id> + <url>https://repo.papermc.io/repository/maven-public/</url> + </repository> + <repository> + <id>jitpack.io</id> + <url>https://jitpack.io</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>24.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>io.papermc.paper</groupId> + <artifactId>paper-api</artifactId> + <version>1.19.4-R0.1-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>com.github.Revxrsal.Lamp</groupId> + <artifactId>bukkit</artifactId> + <version>3.1.1</version> + </dependency> + <dependency> + <groupId>com.github.Revxrsal.Lamp</groupId> + <artifactId>common</artifactId> + <version>3.1.1</version> + </dependency> + <dependency> + <groupId>com.github.cryptomorin</groupId> + <artifactId>XSeries</artifactId> + <version>9.3.1</version> + </dependency> + + </dependencies> +</project> diff --git a/core/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java b/api/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java rename to api/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java diff --git a/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java b/api/src/main/java/fr/skytasul/quests/api/BossBarManager.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java rename to api/src/main/java/fr/skytasul/quests/api/BossBarManager.java index 985911a2..0451c272 100644 --- a/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/BossBarManager.java @@ -1,11 +1,11 @@ -package fr.skytasul.quests.api.bossbar; +package fr.skytasul.quests.api; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -public interface BQBossBarManager { +public interface BossBarManager { @NotNull BQBossBar buildBossBar(@NotNull String name, @NotNull BarColor color, @NotNull BarStyle style); diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java new file mode 100644 index 00000000..df02b003 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -0,0 +1,98 @@ +package fr.skytasul.quests.api; + +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.comparison.ItemComparison; +import fr.skytasul.quests.api.mobs.MobFactory; +import fr.skytasul.quests.api.mobs.MobStacker; +import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.objects.QuestObjectsRegistry; +import fr.skytasul.quests.api.options.QuestOptionCreator; +import fr.skytasul.quests.api.pools.QuestPoolsManager; +import fr.skytasul.quests.api.quests.QuestsManager; +import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementCreator; +import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.rewards.RewardCreator; +import fr.skytasul.quests.api.stages.StageTypeRegistry; + +/** + * This class contains most of the useful accessors to fetch data from BeautyQuests and methods to + * implement custom behaviors. + */ +public interface QuestsAPI { + + @NotNull + QuestsPlugin getPlugin(); + + @NotNull + QuestsManager getQuestsManager(); + + @NotNull + QuestPoolsManager getPoolsManager(); + + /** + * Register new mob factory + * @param factory MobFactory instance + */ + void registerMobFactory(@NotNull MobFactory<?> factory); + + void registerQuestOption(@NotNull QuestOptionCreator<?, ?> creator); + + @NotNull + List<@NotNull ItemComparison> getItemComparisons(); + + void registerItemComparison(@NotNull ItemComparison comparison); + + void unregisterItemComparison(@NotNull ItemComparison comparison); + + @NotNull + List<@NotNull MobStacker> getMobStackers(); + + void registerMobStacker(@NotNull MobStacker stacker); + + @NotNull + StageTypeRegistry getStages(); + + @NotNull + QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getRequirements(); + + @NotNull + QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards(); + + @NotNull + BQNPCsManager getNPCsManager(); + + void setNPCsManager(@NotNull BQNPCsManager newNpcsManager); + + boolean hasHologramsManager(); + + @Nullable + AbstractHolograms<?> getHologramsManager(); + + void setHologramsManager(@NotNull AbstractHolograms<?> newHologramsManager); + + boolean hasBossBarManager(); + + @Nullable + BossBarManager getBossBarManager(); + + void setBossBarManager(@NotNull BossBarManager newBossBarManager); + + void registerQuestsHandler(@NotNull QuestsHandler handler); + + void unregisterQuestsHandler(@NotNull QuestsHandler handler); + + @NotNull + Collection<@NotNull QuestsHandler> getQuestsHandlers(); + + void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> consumer); + + public static @NotNull QuestsAPI getAPI() { + return QuestsAPIProvider.getAPI(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPIProvider.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPIProvider.java new file mode 100644 index 00000000..5114c214 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPIProvider.java @@ -0,0 +1,25 @@ +package fr.skytasul.quests.api; + +import java.util.Objects; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class QuestsAPIProvider { + + private static @Nullable QuestsAPI instance; + + private QuestsAPIProvider() {} + + public static @NotNull QuestsAPI getAPI() { + if (instance == null) + throw new IllegalStateException("BeautyQuests API is not yet initialized"); + return instance; + } + + static void setAPI(@NotNull QuestsAPI api) { + if (instance != null) + throw new IllegalStateException("BeautyQuests API has already been set"); + instance = Objects.requireNonNull(api); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/api/QuestsHandler.java b/api/src/main/java/fr/skytasul/quests/api/QuestsHandler.java similarity index 61% rename from core/src/main/java/fr/skytasul/quests/api/QuestsHandler.java rename to api/src/main/java/fr/skytasul/quests/api/QuestsHandler.java index 176dbc97..1c6f23d5 100644 --- a/core/src/main/java/fr/skytasul/quests/api/QuestsHandler.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsHandler.java @@ -1,9 +1,8 @@ package fr.skytasul.quests.api; -import org.bukkit.entity.Player; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.stages.StageHandler; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.Quest; public interface QuestsHandler extends StageHandler { @@ -21,12 +20,12 @@ public default void questUnload(Quest quest) {} public default void questEdit(Quest newQuest, Quest oldQuest, boolean keepDatas) {} - public default void questStart(PlayerAccount acc, Player p, Quest quest) {} + public default void questStart(PlayerAccount acc, Quest quest) {} - public default void questFinish(PlayerAccount acc, Player p, Quest quest) {} + public default void questFinish(PlayerAccount acc, Quest quest) {} public default void questReset(PlayerAccount acc, Quest quest) {} - public default void questUpdated(PlayerAccount acc, Player p, Quest quest) {} + public default void questUpdated(PlayerAccount acc, Quest quest) {} } diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java new file mode 100644 index 00000000..600fd7ce --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java @@ -0,0 +1,38 @@ +package fr.skytasul.quests.api; + +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.commands.CommandsManager; +import fr.skytasul.quests.api.editors.EditorManager; +import fr.skytasul.quests.api.gui.GuiManager; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.utils.logger.LoggerExpanded; + +public interface QuestsPlugin extends Plugin { + + public @NotNull QuestsAPI getAPI(); + + public @NotNull CommandsManager getCommand(); + + public @NotNull QuestsConfiguration getConfiguration(); + + public @NotNull PlayersManager getPlayersManager(); + + public @NotNull LoggerExpanded getLoggerExpanded(); + + public @NotNull GuiManager getGuiManager(); + + public @NotNull EditorManager getEditorManager(); + + public @NotNull String getPrefix(); // TODO maybe not necessary + + public void notifyLoadingFailure(); + + public void noticeSavingFailure(); + + public static @NotNull QuestsPlugin getPlugin() { + return QuestsAPIProvider.getAPI().getPlugin(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/commands/CommandsManager.java b/api/src/main/java/fr/skytasul/quests/api/commands/CommandsManager.java new file mode 100644 index 00000000..4b9d3a82 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/commands/CommandsManager.java @@ -0,0 +1,15 @@ +package fr.skytasul.quests.api.commands; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import revxrsal.commands.bukkit.BukkitCommandHandler; +import revxrsal.commands.orphan.OrphanCommand; + +public interface CommandsManager { + + @NotNull + BukkitCommandHandler getHandler(); + + void registerCommands(@Nullable String subpath, @NotNull OrphanCommand @NotNull... commands); + +} diff --git a/core/src/main/java/fr/skytasul/quests/commands/OutsideEditor.java b/api/src/main/java/fr/skytasul/quests/api/commands/OutsideEditor.java similarity index 86% rename from core/src/main/java/fr/skytasul/quests/commands/OutsideEditor.java rename to api/src/main/java/fr/skytasul/quests/api/commands/OutsideEditor.java index 6cc75862..8e1f8f7d 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/OutsideEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/commands/OutsideEditor.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.commands; +package fr.skytasul.quests.api.commands; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; diff --git a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java b/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java rename to api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java diff --git a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java b/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java similarity index 97% rename from core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java rename to api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java index f6d92aee..39df09d8 100644 --- a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java +++ b/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java @@ -34,7 +34,7 @@ public void setNotDefaultComparisons(@NotNull ConfigurationSection section) { this.notDefault = (Map) section.getValues(false); effective = new ArrayList<>(3); - for (ItemComparison comp : QuestsAPI.getItemComparisons()) { + for (ItemComparison comp : QuestsAPI.getAPI().getItemComparisons()) { if (section.getBoolean(comp.getID(), comp.isEnabledByDefault())) effective.add(comp); } @@ -45,7 +45,7 @@ public void setNotDefaultComparisons(@NotNull Map<String, Boolean> comparisons) this.notDefault = comparisons; effective = new ArrayList<>(3); - for (ItemComparison comp : QuestsAPI.getItemComparisons()) { + for (ItemComparison comp : QuestsAPI.getAPI().getItemComparisons()) { Boolean bool = notDefault.get(comp.getID()); if (Boolean.FALSE.equals(bool)) continue; if (!comp.isEnabledByDefault() && !Boolean.TRUE.equals(bool)) continue; diff --git a/core/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java b/api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java similarity index 98% rename from core/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java rename to api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java index 9b6b4ce4..01c2c21c 100644 --- a/core/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java +++ b/api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java @@ -10,7 +10,7 @@ import java.util.Map; import java.util.Objects; import com.google.common.collect.ImmutableMap; -import fr.skytasul.quests.utils.CustomizedObjectTypeAdapter; +import fr.skytasul.quests.api.utils.CustomizedObjectTypeAdapter; public class SQLDataSaver<T> { diff --git a/core/src/main/java/fr/skytasul/quests/api/data/SavableData.java b/api/src/main/java/fr/skytasul/quests/api/data/SavableData.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/data/SavableData.java rename to api/src/main/java/fr/skytasul/quests/api/data/SavableData.java diff --git a/core/src/main/java/fr/skytasul/quests/editors/CancellableEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/CancellableEditor.java similarity index 73% rename from core/src/main/java/fr/skytasul/quests/editors/CancellableEditor.java rename to api/src/main/java/fr/skytasul/quests/api/editors/CancellableEditor.java index edf3d2bc..a01542e3 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/CancellableEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/CancellableEditor.java @@ -1,10 +1,10 @@ -package fr.skytasul.quests.editors; +package fr.skytasul.quests.api.editors; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerInteractEvent; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.gui.ItemUtils; public abstract class CancellableEditor extends InventoryClear { @@ -14,7 +14,7 @@ public CancellableEditor(Player p, Runnable cancel) { @EventHandler (priority = EventPriority.LOW) public void onClick(PlayerInteractEvent e) { - if (e.getPlayer() != p) return; + if (e.getPlayer() != player) return; if (ItemUtils.itemCancel.equals(e.getItem())) { e.setCancelled(true); cancel(); @@ -24,7 +24,7 @@ public void onClick(PlayerInteractEvent e) { @Override public void begin() { super.begin(); - if (cancel != null) p.getInventory().setItem(8, ItemUtils.itemCancel); + if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java new file mode 100644 index 00000000..df98486a --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java @@ -0,0 +1,195 @@ +package fr.skytasul.quests.api.editors; + +import org.bukkit.entity.Player; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.Message; +import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.Utils; + +public class DialogEditor extends Editor{ + + private Runnable end; + public Dialog d; + + public DialogEditor(Player p, Runnable end, Dialog dialog) { + super(p, null); + this.end = end; + this.d = dialog; + } + + @Override + public boolean chat(String coloredMessage, String strippedMessage){ + String[] args = strippedMessage.split(" "); + String[] argsColored = coloredMessage.split(" "); + String msg = ""; + boolean hasMsg = false; + Command cmd; + try{ + cmd = Command.valueOf(args[0].toUpperCase()); + }catch (IllegalArgumentException ex){ + Lang.COMMAND_DOESNT_EXIST_NOSLASH.send(player); + return false; + } + if (args.length > 1){ + msg = Utils.buildFromArray(argsColored, 1, " "); + hasMsg = true; + } + switch (cmd) { + + case NOSENDER: + case NPC: + case PLAYER: + if (!hasMsg){ + Lang.DIALOG_SYNTAX.send(player, cmd, ""); + break; + } + d.add(msg, Sender.valueOf(cmd.name())); + MessageUtils.sendPrefixedMessage(player, Lang.valueOf("DIALOG_MSG_ADDED_" + cmd.name()).toString(), msg, + cmd.name().toLowerCase()); + break; + + case REMOVE: + if (!hasMsg){ + Lang.DIALOG_REMOVE_SYNTAX.send(player); + break; + } + try{ + Message removed = d.getMessages().remove(Integer.parseInt(args[1])); + if (removed != null){ + Lang.DIALOG_MSG_REMOVED.send(player, removed.text); + } else + Lang.OUT_OF_BOUNDS.send(player, args[1], 0, d.getMessages().size()); + }catch (IllegalArgumentException ex){ + Lang.NUMBER_INVALID.send(player); + } + break; + + case LIST: + for (int i = 0; i < d.getMessages().size(); i++) { + Message dmsg = d.getMessages().get(i); + MessageUtils.sendRawMessage(player, "§6{0}: §7\"{1}§7\"§e by §l{2}", false, i, dmsg.text, + dmsg.sender.name().toLowerCase()); + } + break; + + case NOSENDERINSERT: + case NPCINSERT: + case PLAYERINSERT: + if (args.length < 3){ + Lang.DIALOG_SYNTAX.send(player, cmd, " <id>"); + break; + } + try{ + msg = Utils.buildFromArray(argsColored, 2, " "); + Sender sender = Sender.valueOf(cmd.name().replace("INSERT", "")); + d.insert(msg, sender, Integer.parseInt(args[1])); + MessageUtils.sendPrefixedMessage(player, Lang.valueOf("DIALOG_MSG_ADDED_" + sender.name()).toString(), msg, + sender.name().toLowerCase()); + }catch (NumberFormatException ex){ + Lang.NUMBER_INVALID.send(player, args[1]); + } + break; + + case EDIT: + if (args.length < 3){ + Lang.DIALOG_SYNTAX.send(player, cmd, " <id>"); + break; + } + try{ + Message message = d.getMessages().get(Integer.parseInt(args[1])); + msg = Utils.buildFromArray(argsColored, 2, " "); + message.text = msg; + Lang.DIALOG_MSG_EDITED.send(player, msg); + }catch (IllegalArgumentException ex){ + Lang.NUMBER_INVALID.send(player); + }catch (IndexOutOfBoundsException ex) { + Lang.OBJECT_DOESNT_EXIST.send(player, args[1]); + } + break; + + case ADDSOUND: + if (args.length < 3){ + Lang.TEXTLIST_SYNTAX.send(player, "addSound <id> <sound>"); + break; + } + try{ + Message imsg = d.getMessages().get(Integer.parseInt(args[1])); + Lang.DIALOG_SOUND_ADDED.send(player, imsg.sound = args[2], args[1]); + }catch (IllegalArgumentException ex){ + Lang.NUMBER_INVALID.send(player); + }catch (IndexOutOfBoundsException ex) { + Lang.OBJECT_DOESNT_EXIST.send(player, args[1]); + } + break; + + case SETTIME: + if (args.length < 3) { + Lang.TEXTLIST_SYNTAX.send(player, "setTime <id> <time in ticks>"); + break; + } + try { + Message imsg = d.getMessages().get(Integer.parseInt(args[1])); + int time = Integer.parseInt(args[2]); + if (time < 0) { + imsg.wait = -1; + Lang.DIALOG_TIME_REMOVED.send(player, args[1]); + }else { + imsg.wait = time; + Lang.DIALOG_TIME_SET.send(player, args[1], imsg.wait = time); + } + }catch (IllegalArgumentException ex) { + Lang.NUMBER_INVALID.send(player); + }catch (IndexOutOfBoundsException ex) { + Lang.OBJECT_DOESNT_EXIST.send(player, args[1]); + } + break; + + case NPCNAME: + if (args.length < 2) { + Lang.DIALOG_NPCNAME_UNSET.send(player, d.getNpcName()); + d.setNpcName(null); + } else { + String oldName = d.getNpcName(); + d.setNpcName(msg); + Lang.DIALOG_NPCNAME_SET.send(player, oldName, msg); + } + break; + + case SKIPPABLE: + String prev = d.getSkippableStatus(); + if (args.length < 2) { + d.setSkippable(null);; + Lang.DIALOG_SKIPPABLE_UNSET.send(player, prev); + }else { + d.setSkippable(Boolean.parseBoolean(args[1])); + Lang.DIALOG_SKIPPABLE_SET.send(player, prev, d.getSkippableStatus()); + } + break; + + case CLEAR: + Lang.DIALOG_CLEARED.send(player, d.getMessages().size()); + d.getMessages().clear(); + break; + + case HELP: + for (Lang l : Lang.values()){ + if (l.getPath().startsWith("msg.editor.dialog.help.")) l.sendWP(player); + } + break; + + case CLOSE: + stop(); + end.run(); + break; + + } + return true; + } + + private enum Command{ + NPC, PLAYER, NOSENDER, REMOVE, LIST, HELP, CLOSE, NPCINSERT, PLAYERINSERT, NOSENDERINSERT, EDIT, ADDSOUND, SETTIME, NPCNAME, SKIPPABLE, CLEAR; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/Editor.java b/api/src/main/java/fr/skytasul/quests/api/editors/Editor.java new file mode 100644 index 00000000..43808316 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/editors/Editor.java @@ -0,0 +1,88 @@ +package fr.skytasul.quests.api.editors; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.ChatColorUtils; + +public abstract class Editor { + + protected final @NotNull Player player; + protected final @NotNull Runnable cancel; + private boolean started = false; + + protected Editor(@NotNull Player player, @NotNull Runnable cancel) { + this.player = player; + this.cancel = cancel; + } + + public @NotNull Player getPlayer() { + return player; + } + + public void begin() { + if (started) + throw new IllegalStateException("Editor already started"); + + started = true; + + if (this instanceof Listener) + Bukkit.getPluginManager().registerEvents((@NotNull Listener) this, QuestsPlugin.getPlugin()); + } + + public void end() { + if (!started) + throw new IllegalStateException("Editor did not started"); + + started = false; + + if (this instanceof Listener) + HandlerList.unregisterAll((Listener) this); + } + + public final void start() { + QuestsPlugin.getPlugin().getEditorManager().start(this); + } + + public final void stop() { + QuestsPlugin.getPlugin().getEditorManager().stop(this); + } + + public final void cancel() { + cancel.run(); + QuestsPlugin.getPlugin().getEditorManager().stop(this); + } + + /** + * Happens when the player in the editor type somthing in the chat + * @param coloredMessage Message typed + * @param strippedMessage Message without default colors + * @return false if the plugin needs to send an help message to the player + */ + public boolean chat(String coloredMessage, String strippedMessage) { + return false; + } + + public final void callChat(String rawText) { + rawText = rawText.trim().replaceAll("\\uFEFF", ""); // remove blank characters, remove space at the beginning + QuestsPlugin.getPlugin().getLoggerExpanded().debug(player.getName() + " entered \"" + rawText + "\" (" + + rawText.length() + " characters) in an editor. (name: " + getClass().getName() + ")"); + String coloredMessage = ChatColorUtils.translateHexColorCodes(ChatColor.translateAlternateColorCodes('&', rawText)); + String strippedMessage = ChatColor.stripColor(rawText); + if (strippedMessage.equalsIgnoreCase(cancelWord())) { + cancel(); + }else if (!chat(coloredMessage, strippedMessage)) { + Lang.CHAT_EDITOR.send(player); + } + } + + protected String cancelWord(){ + return null; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java b/api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java new file mode 100644 index 00000000..8f540224 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java @@ -0,0 +1,20 @@ +package fr.skytasul.quests.api.editors; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public interface EditorManager { + + public <T extends Editor> T start(@NotNull T editor); + + public default void stop(@NotNull Editor editor) { + leave(editor.getPlayer()); + } + + public void leave(@NotNull Player player); + + public void leaveAll(); + + public boolean isInEditor(@NotNull Player player); + +} diff --git a/core/src/main/java/fr/skytasul/quests/editors/InventoryClear.java b/api/src/main/java/fr/skytasul/quests/api/editors/InventoryClear.java similarity index 57% rename from core/src/main/java/fr/skytasul/quests/editors/InventoryClear.java rename to api/src/main/java/fr/skytasul/quests/api/editors/InventoryClear.java index 93eec9a5..14a6b863 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/InventoryClear.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/InventoryClear.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors; +package fr.skytasul.quests.api.editors; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -15,16 +15,16 @@ public InventoryClear(Player p, Runnable cancel) { @Override public void begin(){ super.begin(); - contents = p.getInventory().getContents(); - heldItemSlot = p.getInventory().getHeldItemSlot(); - p.getInventory().setContents(new ItemStack[0]); + contents = player.getInventory().getContents(); + heldItemSlot = player.getInventory().getHeldItemSlot(); + player.getInventory().setContents(new ItemStack[0]); } @Override public void end(){ super.end(); - p.getInventory().setContents(contents); - p.getInventory().setHeldItemSlot(heldItemSlot); + player.getInventory().setContents(contents); + player.getInventory().setHeldItemSlot(heldItemSlot); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java b/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java similarity index 71% rename from core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java rename to api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java index 4e59f6a3..693baa93 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/SelectNPC.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java @@ -1,13 +1,12 @@ -package fr.skytasul.quests.editors; +package fr.skytasul.quests.api.editors; import java.util.function.Consumer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class SelectNPC extends InventoryClear{ @@ -20,16 +19,16 @@ public SelectNPC(Player p, Runnable cancel, Consumer<BQNPC> end) { @EventHandler (priority = EventPriority.LOW) private void onNPCClick(BQNPCClickEvent e) { - if (e.getPlayer() != p) return; + if (e.getPlayer() != player) return; e.setCancelled(true); - leave(e.getPlayer()); + stop(); run.accept(e.getNPC()); } @Override public void begin(){ super.begin(); - Utils.sendMessage(p, Lang.NPC_EDITOR_ENTER.toString()); + Lang.NPC_EDITOR_ENTER.send(player); } } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/editors/TextEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java similarity index 77% rename from core/src/main/java/fr/skytasul/quests/editors/TextEditor.java rename to api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java index 49a1bdc4..8256d197 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/TextEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java @@ -1,11 +1,10 @@ -package fr.skytasul.quests.editors; +package fr.skytasul.quests.api.editors; import java.util.function.Consumer; import org.apache.commons.lang.Validate; import org.bukkit.entity.Player; -import fr.skytasul.quests.editors.checkers.AbstractParser; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.editors.checkers.AbstractParser; +import fr.skytasul.quests.api.localization.Lang; public class TextEditor<T> extends Editor { @@ -49,10 +48,10 @@ public TextEditor<T> useStrippedMessage() { public boolean chat(String msg, String strippedMessage){ if (strippedMessage.equals("null")) { if (nul == null && !nullIntoConsumer) { - Utils.sendMessage(p, Lang.ARG_NOT_SUPPORTED.toString(), "null"); + Lang.ARG_NOT_SUPPORTED.send(player, "null"); return false; } - leave(p); + stop(); if (nullIntoConsumer) { run.accept(null); }else nul.run(); @@ -66,21 +65,21 @@ public boolean chat(String msg, String strippedMessage){ boolean invalid = false; if (parser != null){ try{ - T tmp = parser.parse(p, strippedMessage); + T tmp = parser.parse(player, strippedMessage); if (tmp == null){ invalid = true; }else { returnment = tmp; } }catch (Throwable ex){ - Lang.ERROR_OCCURED.send(p, strippedMessage + " parsingText"); + Lang.ERROR_OCCURED.send(player, strippedMessage + " parsingText"); invalid = true; ex.printStackTrace(); } }else returnment = (T) (useStripped ? strippedMessage : msg); if (!invalid){ - leave(p); + stop(); run.accept(returnment); return true; } @@ -88,9 +87,9 @@ public boolean chat(String msg, String strippedMessage){ } @Override - protected void begin() { + public void begin() { super.begin(); - if (parser != null) parser.sendIndication(p); + if (parser != null) parser.sendIndication(player); } } diff --git a/core/src/main/java/fr/skytasul/quests/editors/TextListEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java similarity index 69% rename from core/src/main/java/fr/skytasul/quests/editors/TextListEditor.java rename to api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java index 86157ebb..b84a03b5 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/TextListEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors; +package fr.skytasul.quests.api.editors; import java.util.List; import java.util.StringJoiner; @@ -6,8 +6,8 @@ import java.util.function.Predicate; import org.apache.commons.lang.Validate; import org.bukkit.entity.Player; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; public class TextListEditor extends Editor{ @@ -24,9 +24,9 @@ public TextListEditor(Player p, Consumer<List<String>> end, List<String> texts){ } @Override - protected void begin() { + public void begin() { super.begin(); - Lang.ENTER_EDITOR_LIST.send(p); + Lang.ENTER_EDITOR_LIST.send(player); } @Override @@ -38,7 +38,7 @@ public boolean chat(String coloredMessage, String strippedMessage){ try{ cmd = Command.valueOf(args[0].toUpperCase()); }catch (IllegalArgumentException ex){ - Utils.sendMessage(p, Lang.COMMAND_DOESNT_EXIST_NOSLASH.toString()); + Lang.COMMAND_DOESNT_EXIST_NOSLASH.send(player); return false; } if (args.length > 1){ @@ -49,25 +49,25 @@ public boolean chat(String coloredMessage, String strippedMessage){ case ADD: if (!hasMsg){ - Utils.sendMessage(p, Lang.TEXTLIST_SYNTAX.toString() + " add <message>"); + Lang.TEXTLIST_SYNTAX.send(player, " add <message>"); break; } if (valid != null){ if (!valid.test(msg)) break; } texts.add(msg); - Lang.TEXTLIST_TEXT_ADDED.send(p, msg); + Lang.TEXTLIST_TEXT_ADDED.send(player, msg); break; case REMOVE: if (!hasMsg){ - Utils.sendMessage(p, Lang.TEXTLIST_SYNTAX.toString() + " remove <id>"); + Lang.TEXTLIST_SYNTAX.send(player, " remove <id>"); break; } try{ - Utils.sendMessage(p, Lang.TEXTLIST_TEXT_REMOVED.toString(), texts.remove(Integer.parseInt(args[1]))); + Lang.TEXTLIST_TEXT_REMOVED.send(player, texts.remove(Integer.parseInt(args[1]))); }catch (IllegalArgumentException ex){ - Utils.sendMessage(p, Lang.NUMBER_INVALID.toString()); + Lang.NUMBER_INVALID.send(player); } break; @@ -76,17 +76,17 @@ public boolean chat(String coloredMessage, String strippedMessage){ for (int i = 0; i < texts.size(); i++) { joiner.add("§6" + i + ": §r" + texts.get(i)); } - p.sendMessage(joiner.toString()); + player.sendMessage(joiner.toString()); break; case HELP: for (Lang l : Lang.values()){ - if (l.getPath().startsWith("msg.editor.textList.help.")) l.sendWP(p); + if (l.getPath().startsWith("msg.editor.textList.help.")) l.sendWP(player); } break; case CLOSE: - leave(p); + stop(); run.accept(texts); break; diff --git a/core/src/main/java/fr/skytasul/quests/editors/WaitBlockClick.java b/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java similarity index 72% rename from core/src/main/java/fr/skytasul/quests/editors/WaitBlockClick.java rename to api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java index ad27e7f6..a1ef6256 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/WaitBlockClick.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors; +package fr.skytasul.quests.api.editors; import java.util.function.Consumer; import org.bukkit.Location; @@ -7,7 +7,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.gui.ItemUtils; public class WaitBlockClick extends InventoryClear{ @@ -22,7 +22,7 @@ public WaitBlockClick(Player p, Runnable cancel, Consumer<Location> end, ItemSta @EventHandler public void onClick(PlayerInteractEvent e){ - if (e.getPlayer() != p) return; + if (e.getPlayer() != player) return; if (ItemUtils.itemCancel.equals(e.getItem())) { cancel(); return; @@ -31,15 +31,16 @@ public void onClick(PlayerInteractEvent e){ if (e.getClickedBlock() == null) return; if (!item.equals(e.getItem())) return; e.setCancelled(true); - leave(e.getPlayer()); + stop(); run.accept(e.getClickedBlock().getLocation()); } + @Override public void begin(){ super.begin(); - p.getInventory().setItem(4, item); - p.getInventory().setHeldItemSlot(4); - if (cancel != null) p.getInventory().setItem(8, ItemUtils.itemCancel); + player.getInventory().setItem(4, item); + player.getInventory().setHeldItemSlot(4); + if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); } } diff --git a/core/src/main/java/fr/skytasul/quests/editors/WaitClick.java b/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java similarity index 72% rename from core/src/main/java/fr/skytasul/quests/editors/WaitClick.java rename to api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java index 39cdea38..9e6506ab 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/WaitClick.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors; +package fr.skytasul.quests.api.editors; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -6,7 +6,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.gui.ItemUtils; public class WaitClick extends InventoryClear{ @@ -29,7 +29,7 @@ public WaitClick(Player p, Runnable cancel, ItemStack validateItem, Runnable val @EventHandler (priority = EventPriority.LOW) public void onInteract(PlayerInteractEvent e) { - if (e.getPlayer() != p) return; + if (e.getPlayer() != player) return; if (e.getAction() != Action.RIGHT_CLICK_AIR && e.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (e.getItem() == null) return; Runnable run; @@ -41,21 +41,22 @@ public void onInteract(PlayerInteractEvent e) { run = cancel; }else return; e.setCancelled(true); - leave(e.getPlayer()); + stop(); run.run(); } + @Override public void begin(){ super.begin(); if (none == null){ - p.getInventory().setItem(4, validateItem); - p.getInventory().setHeldItemSlot(4); + player.getInventory().setItem(4, validateItem); + player.getInventory().setHeldItemSlot(4); }else { - p.getInventory().setItem(3, validateItem); - p.getInventory().setHeldItemSlot(3); - p.getInventory().setItem(5, noneItem); + player.getInventory().setItem(3, validateItem); + player.getInventory().setHeldItemSlot(3); + player.getInventory().setItem(5, noneItem); } - if (cancel != null) p.getInventory().setItem(8, ItemUtils.itemCancel); + if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); } } diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/AbstractParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/AbstractParser.java similarity index 77% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/AbstractParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/AbstractParser.java index 68e4b172..5a747e8a 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/AbstractParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/AbstractParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/CollectionParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/CollectionParser.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/CollectionParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/CollectionParser.java index 430bd832..72aaee7b 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/CollectionParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/CollectionParser.java @@ -1,11 +1,11 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import java.util.Collection; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; import org.bukkit.entity.Player; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; public class CollectionParser<T> implements AbstractParser<T> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/ColorParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ColorParser.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/ColorParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/ColorParser.java index e7d9e264..a6850ca0 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/ColorParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ColorParser.java @@ -1,11 +1,11 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bukkit.ChatColor; import org.bukkit.Color; import org.bukkit.entity.Player; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; public class ColorParser implements AbstractParser<Color> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/DurationParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/DurationParser.java similarity index 98% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/DurationParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/DurationParser.java index 46eba6a1..93f19519 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/DurationParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/DurationParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import java.util.HashMap; import java.util.Map; diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/EnumParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/EnumParser.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/EnumParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/EnumParser.java index 7fd8014c..0a6bc2e6 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/EnumParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/EnumParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import java.util.Arrays; import java.util.function.Predicate; diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/MaterialParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/MaterialParser.java similarity index 76% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/MaterialParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/MaterialParser.java index 96c26277..42adc7c8 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/MaterialParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/MaterialParser.java @@ -1,11 +1,11 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import org.bukkit.Material; import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.compatibility.Post1_13; -import fr.skytasul.quests.utils.nms.NMS; public class MaterialParser implements AbstractParser<XMaterial> { @@ -35,12 +35,12 @@ public XMaterial parse(Player p, String msg) throws Throwable { } } if (item) { - if (NMS.getMCVersion() >= 13 && !Post1_13.isItem(tmp.parseMaterial())) { + if (MinecraftVersion.MAJOR >= 13 && !Post1_13.isItem(tmp.parseMaterial())) { Lang.INVALID_ITEM_TYPE.send(p); return null; } }else if (block) { - if (NMS.getMCVersion() >= 13 && !Post1_13.isBlock(tmp.parseMaterial())) { + if (MinecraftVersion.MAJOR >= 13 && !Post1_13.isBlock(tmp.parseMaterial())) { Lang.INVALID_BLOCK_TYPE.send(p); return null; } diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/NumberParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/NumberParser.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/NumberParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/NumberParser.java index 46c87322..54d781b6 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/NumberParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/NumberParser.java @@ -1,8 +1,8 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import java.math.BigDecimal; import org.bukkit.entity.Player; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; public class NumberParser<T extends Number> implements AbstractParser<T> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/PatternParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/PatternParser.java similarity index 83% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/PatternParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/PatternParser.java index d11db8d5..c47671ae 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/PatternParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/PatternParser.java @@ -1,9 +1,9 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.bukkit.entity.Player; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; public class PatternParser implements AbstractParser<Pattern> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/ScoreboardObjectiveParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ScoreboardObjectiveParser.java similarity index 79% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/ScoreboardObjectiveParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/ScoreboardObjectiveParser.java index 4f21b4f0..342a7558 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/ScoreboardObjectiveParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ScoreboardObjectiveParser.java @@ -1,9 +1,9 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scoreboard.Objective; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; public class ScoreboardObjectiveParser implements AbstractParser<Objective> { diff --git a/core/src/main/java/fr/skytasul/quests/editors/checkers/WorldParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/WorldParser.java similarity index 84% rename from core/src/main/java/fr/skytasul/quests/editors/checkers/WorldParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/checkers/WorldParser.java index 8075fd4d..a1d1e76c 100644 --- a/core/src/main/java/fr/skytasul/quests/editors/checkers/WorldParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/checkers/WorldParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.editors.checkers; +package fr.skytasul.quests.api.editors.checkers; import org.bukkit.Bukkit; import org.bukkit.World; diff --git a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java similarity index 96% rename from core/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java index 5ad1c6ca..bcd4e182 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java @@ -6,7 +6,7 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.utils.types.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.Dialog; public class DialogSendEvent extends Event implements Cancellable { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java index 25c93849..f9cc1c79 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java @@ -6,8 +6,8 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.utils.types.Dialog; -import fr.skytasul.quests.utils.types.Message; +import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.Message; public class DialogSendMessageEvent extends Event implements Cancellable { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java similarity index 77% rename from core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java index 8bd567ba..4b01b00d 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/PlayerQuestEvent.java @@ -3,9 +3,9 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.events.accounts.PlayerAccountEvent; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.Quest; public abstract class PlayerQuestEvent extends PlayerAccountEvent { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java index bcd2d8a0..9cfced52 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/PlayerQuestResetEvent.java @@ -2,8 +2,8 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; /** * Called when the stage of a player is cancelled diff --git a/core/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java similarity index 57% rename from core/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java index 59c0d77f..644009da 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/PlayerSetStageEvent.java @@ -2,28 +2,28 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.BranchesManager; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.branches.QuestBranchesManager; +import fr.skytasul.quests.api.stages.StageController; /** * Called when a player finish a stage */ public class PlayerSetStageEvent extends PlayerQuestEvent { - private final @NotNull AbstractStage stage; + private final @NotNull StageController stage; - public PlayerSetStageEvent(@NotNull PlayerAccount account, @NotNull Quest quest, @NotNull AbstractStage stage) { + public PlayerSetStageEvent(@NotNull PlayerAccount account, @NotNull Quest quest, @NotNull StageController stage) { super(account, quest); this.stage = stage; } - public @NotNull AbstractStage getStage() { + public @NotNull StageController getStage() { return stage; } - public BranchesManager getStageManager(){ + public QuestBranchesManager getStageManager() { return quest.getBranchesManager(); } diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java index 7da6e507..7b56fdf8 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/QuestCreateEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.quests.Quest; /** * Called when a quest is created diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java index 26bd2a8a..143e4540 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/QuestEvent.java @@ -3,7 +3,7 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.quests.Quest; public abstract class QuestEvent extends Event { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java index 679d92fd..182573cf 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/QuestFinishEvent.java @@ -3,7 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.quests.Quest; /** * Called when a player finish a quest diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java index b9944578..63dab676 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/QuestLaunchEvent.java @@ -3,7 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.quests.Quest; /** * Called when a player starts a quest diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java index a2a72004..3f8e5953 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/QuestPreLaunchEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.quests.Quest; /** * Called before a player starts a quest diff --git a/core/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java similarity index 83% rename from core/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java index ea9888b7..42e3fe49 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/QuestRemoveEvent.java @@ -1,7 +1,7 @@ package fr.skytasul.quests.api.events; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.quests.Quest; /** * Called when a quest is removed<br> diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java similarity index 89% rename from core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java index f985c609..a0b613d9 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Event; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerAccount; public abstract class PlayerAccountEvent extends Event { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java index e977be80..6a0e5708 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountJoinEvent.java @@ -2,7 +2,7 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerAccount; public class PlayerAccountJoinEvent extends PlayerAccountEvent { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java similarity index 86% rename from core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java index 853dc0a7..e5e8f2bd 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountLeaveEvent.java @@ -2,7 +2,7 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerAccount; public class PlayerAccountLeaveEvent extends PlayerAccountEvent { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java index 61c5813f..a4663bbb 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/accounts/PlayerAccountResetEvent.java @@ -2,7 +2,7 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerAccount; public class PlayerAccountResetEvent extends PlayerAccountEvent { diff --git a/core/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/internal/BQBlockBreakEvent.java diff --git a/core/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/internal/BQCraftEvent.java diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CompatMobDeathEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQMobDeathEvent.java similarity index 76% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CompatMobDeathEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/internal/BQMobDeathEvent.java index fa5cf22d..d90e167d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CompatMobDeathEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQMobDeathEvent.java @@ -1,11 +1,11 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.api.events.internal; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -public class CompatMobDeathEvent extends Event { +public class BQMobDeathEvent extends Event { private static final HandlerList handlers = new HandlerList(); private final Object pluginEntity; @@ -13,7 +13,7 @@ public class CompatMobDeathEvent extends Event { private final Entity bukkitEntity; private final int amount; - public CompatMobDeathEvent(Object pluginEntity, Player killer, Entity bukkitEntity, int amount) { + public BQMobDeathEvent(Object pluginEntity, Player killer, Entity bukkitEntity, int amount) { this.pluginEntity = pluginEntity; this.killer = killer; this.bukkitEntity = bukkitEntity; diff --git a/core/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java similarity index 95% rename from core/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java rename to api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java index c5d9ef41..be030a6d 100644 --- a/core/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java @@ -5,7 +5,6 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.QuestsConfiguration.ClickType; import fr.skytasul.quests.api.npcs.BQNPC; public class BQNPCClickEvent extends PlayerEvent implements Cancellable { diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/CustomInventory.java b/api/src/main/java/fr/skytasul/quests/api/gui/CustomInventory.java new file mode 100644 index 00000000..3764b20f --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/CustomInventory.java @@ -0,0 +1,110 @@ +package fr.skytasul.quests.api.gui; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; + +public abstract class CustomInventory { + + private @Nullable Inventory inventory; + + public @Nullable Inventory getInventory() { + return inventory; + } + + /** + * Called internally when opening inventory + * + * @param p Player to open + * @return inventory opened + */ + public final void show(Player player) { + if (inventory == null) { + inventory = instanciate(player); + populate(player, inventory); + } else { + refresh(player, inventory); + } + inventory = player.openInventory(inventory).getTopInventory(); + } + + /** + * Opens the inventory to the player. Direct reference to + * {@link GuiManager#open(Player, CustomInventory)} + * + * @param player Player + * @see Inventories#create(Player, CustomInventory) + */ + public final void open(@NotNull Player player) { + QuestsPlugin.getPlugin().getGuiManager().open(player, this); + } + + public final void reopen(@NotNull Player player) { + reopen(player, false); + } + + public final void reopen(@NotNull Player player, boolean refresh) { + if (refresh) + inventory = null; + open(player); + } + + public final void repopulate(@NotNull Player player) { + if (inventory == null) + return; + + inventory.clear(); + populate(player, inventory); + } + + public final void close(@NotNull Player player) { + QuestsPlugin.getPlugin().getGuiManager().closeAndExit(player); + } + + protected abstract Inventory instanciate(@NotNull Player player); + + protected abstract void populate(@NotNull Player player, @NotNull Inventory inventory); + + protected void refresh(@NotNull Player player, @NotNull Inventory inventory) {} + + /** + * Called when clicking on an item + * + * @param player Player who clicked + * @param current Item clicked + * @param slot Slot of item clicked + * @param click Type of click + * @return Cancel click + */ + public abstract boolean onClick(@NotNull Player player, @NotNull ItemStack current, int slot, @NotNull ClickType click); + + /** + * Called when clicking on an item <b>with something on the cursor</b> + * + * @param player Player who clicked + * @param current Item clicked + * @param cursor Item on the cursor when click + * @param slot Slot of item clicked + * @return Cancel click + */ + public boolean onClickCursor(@NotNull Player player, @NotNull ItemStack current, @NotNull ItemStack cursor, int slot) { + return true; + } + + /** + * Called when closing the inventory + * + * @param player Player who has the inventory opened + * @return Remove player from inventories system + */ + public @NotNull CloseBehavior onClose(@NotNull Player player) { + return StandardCloseBehavior.CONFIRM; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java new file mode 100644 index 00000000..f6e1204f --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java @@ -0,0 +1,22 @@ +package fr.skytasul.quests.api.gui; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface GuiManager { + + void open(@NotNull Player player, @NotNull CustomInventory inventory); + + void closeAndExit(@NotNull Player player); + + void closeWithoutExit(@NotNull Player player); + + void closeAll(); + + boolean hasGuiOpened(@NotNull Player player); + + @Nullable + CustomInventory getOpenedGui(@NotNull Player player); + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/ImmutableItemStack.java b/api/src/main/java/fr/skytasul/quests/api/gui/ImmutableItemStack.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/gui/ImmutableItemStack.java rename to api/src/main/java/fr/skytasul/quests/api/gui/ImmutableItemStack.java index df579f28..74c391a4 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/ImmutableItemStack.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/ImmutableItemStack.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui; +package fr.skytasul.quests.api.gui; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; diff --git a/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java b/api/src/main/java/fr/skytasul/quests/api/gui/ItemUtils.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java rename to api/src/main/java/fr/skytasul/quests/api/gui/ItemUtils.java index 77b948d9..fdfcb552 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/ItemUtils.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui; +package fr.skytasul.quests.api.gui; import java.util.ArrayList; import java.util.Arrays; @@ -18,10 +18,10 @@ import org.bukkit.inventory.meta.SkullMeta; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.utils.ChatUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.MinecraftNames; -import fr.skytasul.quests.utils.nms.NMS; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.ChatColorUtils; +import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.MinecraftVersion; import net.md_5.bungee.api.ChatColor; public class ItemUtils { @@ -77,7 +77,7 @@ public static ItemStack skull(String name, String skull, String... lore) { private static ItemMeta applyMeta(ItemMeta im, String name, Object lore) { List<String> editLore = null; if (name != null) { - editLore = ChatUtils.wordWrap(name, LORE_LINE_LENGTH, LORE_LINE_LENGTH_CRITICAL); + editLore = ChatColorUtils.wordWrap(name, LORE_LINE_LENGTH, LORE_LINE_LENGTH_CRITICAL); if (editLore.isEmpty()) { name = ""; editLore = null; @@ -134,9 +134,9 @@ public static ItemStack clearVisibleAttributes(ItemStack is) { // add flags to hide various descriptions, // depending on the item type/attributes/other things if (im.hasEnchants()) im.addItemFlags(ItemFlag.HIDE_ENCHANTS); - if (NMS.getMCVersion() >= 11 && im.isUnbreakable()) im.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); - if (is.getType().getMaxDurability() != 0 || (NMS.getMCVersion() > 12 && im.hasAttributeModifiers())) im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); - if (im instanceof BookMeta || im instanceof PotionMeta || im instanceof EnchantmentStorageMeta || (NMS.getMCVersion() >= 12 && im instanceof KnowledgeBookMeta)) im.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); + if (MinecraftVersion.MAJOR >= 11 && im.isUnbreakable()) im.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); + if (is.getType().getMaxDurability() != 0 || (MinecraftVersion.MAJOR > 12 && im.hasAttributeModifiers())) im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); + if (im instanceof BookMeta || im instanceof PotionMeta || im instanceof EnchantmentStorageMeta || (MinecraftVersion.MAJOR >= 12 && im instanceof KnowledgeBookMeta)) im.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); if (im instanceof LeatherArmorMeta) im.addItemFlags(ItemFlag.HIDE_DYE); is.setItemMeta(im); @@ -180,7 +180,7 @@ private static List<String> getLoreLines(String... lore) { if (line == null) { if (i + 1 == lore.length) break; // if last line and null : not shown finalLines.add("§a"); - }else finalLines.addAll(ChatUtils.wordWrap(line, LORE_LINE_LENGTH, LORE_LINE_LENGTH_CRITICAL)); + }else finalLines.addAll(ChatColorUtils.wordWrap(line, LORE_LINE_LENGTH, LORE_LINE_LENGTH_CRITICAL)); } } return finalLines; @@ -196,7 +196,7 @@ private static List<String> getLoreLines(List<String> lore) { if (line == null) { if (i + 1 == lore.size()) break; // if last line and null : not shown finalLines.add("§a"); - }else finalLines.addAll(ChatUtils.wordWrap(line, LORE_LINE_LENGTH, LORE_LINE_LENGTH_CRITICAL)); + }else finalLines.addAll(ChatColorUtils.wordWrap(line, LORE_LINE_LENGTH, LORE_LINE_LENGTH_CRITICAL)); } } return finalLines; @@ -322,6 +322,11 @@ public static ItemStack removeEnchant(ItemStack is, Enchantment en){ */ public static final ImmutableItemStack itemCancel = new ImmutableItemStack(item(XMaterial.BARRIER, Lang.cancel.toString())); + /** + * Immutable ItemStack instance with name : <i>"§cNone"</i> and material : barrier + */ + public static final ImmutableItemStack itemNone = new ImmutableItemStack(item(XMaterial.BARRIER, "§cNone")); + /** * Immutable ItemStack instance with name : <i>inv.done</i> and material : diamond * @see #itemNotDone @@ -377,7 +382,7 @@ public static ItemStack set(ItemStack itemSwitch, boolean enable) { if (itemSwitch == null) return null; String name = getName(itemSwitch); name(itemSwitch, (enable ? "§a" : "§7") + name.substring(2)); - if (NMS.getMCVersion() >= 13) { + if (MinecraftVersion.MAJOR >= 13) { itemSwitch.setType(enable ? XMaterial.LIME_DYE.parseMaterial() : XMaterial.GRAY_DYE.parseMaterial()); }else itemSwitch.setDurability((short) (enable ? 10 : 8)); return itemSwitch; diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/close/CloseBehavior.java b/api/src/main/java/fr/skytasul/quests/api/gui/close/CloseBehavior.java new file mode 100644 index 00000000..1aa64413 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/close/CloseBehavior.java @@ -0,0 +1,10 @@ +package fr.skytasul.quests.api.gui.close; + +/** + * Represents the behavior that a closing GUI must take. + * <p> + * This class is effectively sealed: its only subclasses are {@link StandardCloseBehavior}, + * {@link OpenCloseBehavior} and {@link DelayCloseBehavior}. + */ +public interface CloseBehavior { +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/close/DelayCloseBehavior.java b/api/src/main/java/fr/skytasul/quests/api/gui/close/DelayCloseBehavior.java new file mode 100644 index 00000000..e5a9f152 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/close/DelayCloseBehavior.java @@ -0,0 +1,22 @@ +package fr.skytasul.quests.api.gui.close; + +import java.util.Objects; +import org.jetbrains.annotations.NotNull; + +/** + * This close behavior will remove the player from the GUI system and execute the runnable on the + * next tick. + */ +public class DelayCloseBehavior implements CloseBehavior { + + private final @NotNull Runnable delayed; + + public DelayCloseBehavior(@NotNull Runnable delayed) { + this.delayed = Objects.requireNonNull(delayed); + } + + public @NotNull Runnable getDelayed() { + return delayed; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java b/api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java new file mode 100644 index 00000000..0c0655d4 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java @@ -0,0 +1,19 @@ +package fr.skytasul.quests.api.gui.close; + +import java.util.Objects; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.CustomInventory; + +public class OpenCloseBehavior implements CloseBehavior { + + private final @NotNull CustomInventory other; + + public OpenCloseBehavior(@NotNull CustomInventory other) { + this.other = Objects.requireNonNull(other); + } + + public @NotNull CustomInventory getOther() { + return other; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/close/StandardCloseBehavior.java b/api/src/main/java/fr/skytasul/quests/api/gui/close/StandardCloseBehavior.java new file mode 100644 index 00000000..94cd537b --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/close/StandardCloseBehavior.java @@ -0,0 +1,7 @@ +package fr.skytasul.quests.api.gui.close; + +public enum StandardCloseBehavior implements CloseBehavior { + + REOPEN, CONFIRM, REMOVE, NOTHING; + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/Button.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/Button.java new file mode 100644 index 00000000..5e1dc77a --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/Button.java @@ -0,0 +1,145 @@ +package fr.skytasul.quests.api.gui.layout; + +import java.util.List; +import java.util.function.Supplier; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; + +public interface Button extends ClickHandler { + + public void place(@NotNull Inventory inventory, int slot); + + interface ItemButton extends Button { + + public @Nullable ItemStack getItem(); + + @Override + default void place(@NotNull Inventory inventory, int slot) { + inventory.setItem(slot, getItem()); + } + + } + + public static @NotNull Button create(@NotNull XMaterial material, @Nullable String name, @Nullable List<String> lore, + @NotNull ClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull ClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemUtils.item(material, name, lore); + } + + }; + } + + public static @NotNull Button create(@NotNull XMaterial material, @Nullable String name, + @NotNull Supplier<@Nullable List<String>> lore, @NotNull ClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull ClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemUtils.item(material, name, lore.get()); + } + + }; + } + + public static @NotNull Button create(@NotNull XMaterial material, @NotNull Supplier<@Nullable String> name, + @NotNull Supplier<@Nullable List<String>> lore, @NotNull ClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull ClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemUtils.item(material, name.get(), lore.get()); + } + + }; + } + + public static @NotNull Button create(@NotNull XMaterial material, @NotNull Supplier<@Nullable String> name, + @Nullable List<String> lore, @NotNull ClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull ClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemUtils.item(material, name.get(), lore); + } + + }; + } + + public static @NotNull Button create(@NotNull Supplier<@NotNull XMaterial> material, + @NotNull Supplier<@Nullable String> name, @NotNull Supplier<@Nullable List<String>> lore, + @NotNull ClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull ClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemUtils.item(material.get(), name.get(), lore.get()); + } + + }; + } + + public static @NotNull Button create(@NotNull Supplier<@Nullable ItemStack> item, @NotNull ClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull ClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + return item.get(); + } + + }; + } + + public static @NotNull Button create(@Nullable ItemStack item, @NotNull ClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull ClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + return item; + } + + }; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickEvent.java new file mode 100644 index 00000000..d40d1e7e --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickEvent.java @@ -0,0 +1,54 @@ +package fr.skytasul.quests.api.gui.layout; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.jetbrains.annotations.NotNull; + +public class ClickEvent { + + private final @NotNull Player player; + private final @NotNull LayoutedGUI gui; + private final int slot; + private final @NotNull ClickType click; + + public ClickEvent(@NotNull Player player, @NotNull LayoutedGUI gui, int slot, @NotNull ClickType click) { + this.player = player; + this.gui = gui; + this.slot = slot; + this.click = click; + } + + public @NotNull Player getPlayer() { + return player; + } + + public @NotNull LayoutedGUI getGui() { + return gui; + } + + public int getSlot() { + return slot; + } + + public @NotNull ClickType getClick() { + return click; + } + + public void reopen() { + gui.reopen(player); + } + + public void refreshItemReopen() { + gui.refresh(slot); + gui.reopen(player); + } + + public void refreshGuiReopen() { + gui.reopen(player, true); + } + + public void close() { + gui.close(player); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java new file mode 100644 index 00000000..1f106d48 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java @@ -0,0 +1,11 @@ +package fr.skytasul.quests.api.gui.layout; + +import org.jetbrains.annotations.NotNull; + +public interface ClickHandler { + + public static final ClickHandler EMPTY = event -> {}; + + void click(@NotNull ClickEvent event); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java new file mode 100644 index 00000000..3fef7080 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java @@ -0,0 +1,159 @@ +package fr.skytasul.quests.api.gui.layout; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; + +public abstract class LayoutedGUI extends CustomInventory { + + protected final @Nullable String name; + protected final @NotNull Map<Integer, Button> buttons; + protected final @NotNull CloseBehavior closeBehavior; + + protected LayoutedGUI(@Nullable String name, @NotNull Map<Integer, Button> buttons, + @NotNull CloseBehavior closeBehavior) { + this.name = name; + this.buttons = buttons; + this.closeBehavior = closeBehavior; + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + buttons.forEach((slot, button) -> button.place(inventory, slot)); + } + + @Override + public boolean onClick(@NotNull Player player, @NotNull ItemStack current, int slot, @NotNull ClickType click) { + Button button = buttons.get(slot); + if (button == null) + return true; + + ClickEvent event = new ClickEvent(player, this, slot, click); + button.click(event); + return true; + } + + public void refresh(int slot) { + if (getInventory() == null) + return; + + Button button = buttons.get(slot); + if (button == null) + return; + + button.place(getInventory(), slot); + } + + @Override + public @NotNull CloseBehavior onClose(@NotNull Player player) { + return closeBehavior; + } + + public static @NotNull Builder newBuilder() { + return new Builder(); + } + + public static class LayoutedRowsGUI extends LayoutedGUI { + + private final int rows; + + protected LayoutedRowsGUI(@Nullable String name, @NotNull Map<Integer, Button> buttons, + @NotNull CloseBehavior closeBehavior, int rows) { + super(name, buttons, closeBehavior); + Validate.isTrue(rows >= 1); + this.rows = rows; + } + + @Override + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, rows, name); + } + + } + + public static class LayoutedTypeGUI extends LayoutedGUI { + + private @NotNull InventoryType type; + + protected LayoutedTypeGUI(@Nullable String name, @NotNull Map<Integer, Button> buttons, + @NotNull CloseBehavior closeBehavior, @NotNull InventoryType type) { + super(name, buttons, closeBehavior); + this.type = Objects.requireNonNull(type); + } + + @Override + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, type, name); + } + + } + + public static class Builder { + + private final Map<Integer, Button> buttons = new HashMap<>(); + private @Nullable Integer rows = null; + private @Nullable InventoryType type = null; + private @Nullable String name = null; + private @NotNull CloseBehavior closeBehavior = StandardCloseBehavior.CONFIRM; + + private Builder() {} + + public @NotNull Builder addButton(int slot, @NotNull Button button) { + Validate.isTrue(!buttons.containsKey(slot)); + buttons.put(slot, button); + return this; + } + + public @NotNull Builder setRowNumber(int rows) { + Validate.isTrue(rows >= 1); + this.rows = rows; + this.type = null; + return this; + } + + public @NotNull Builder setInventoryType(@Nullable InventoryType type) { + this.type = type; + this.rows = null; + return this; + } + + public @NotNull Builder setName(@Nullable String name) { + this.name = name; + return this; + } + + public @NotNull Builder setCloseBehavior(@NotNull CloseBehavior closeBehavior) { + this.closeBehavior = closeBehavior; + return this; + } + + public @NotNull LayoutedGUI build() { + if (buttons.isEmpty()) + throw new IllegalArgumentException("Cannot build a layouted GUI with no buttons"); + + if (type != null) + return new LayoutedTypeGUI(name, buttons, closeBehavior, type); + + if (rows == null) { + int maxSlot = buttons.keySet().stream().mapToInt(Integer::intValue).max().getAsInt(); + rows = (int) Math.floor(maxSlot / 9D) + 1; + } + + return new LayoutedRowsGUI(name, buttons, closeBehavior, rows); + } + + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java new file mode 100644 index 00000000..491985e2 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java @@ -0,0 +1,62 @@ +package fr.skytasul.quests.api.gui.templates; + +import java.util.List; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; + +public abstract class ChooseGUI<T> extends CustomInventory { + + private List<T> available; + + protected ChooseGUI(List<T> available) { + this.available = available; + } + + @Override + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, (int) Math.ceil(available.size() * 1.0 / 9.0) * 9, name()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + for (int i = 0; i < available.size(); i++) { + inventory.setItem(i, getItemStack(available.get(i))); + } + } + + @Override + public boolean onClick(Player player, ItemStack current, int slot, ClickType click) { + finish(available.get(slot)); + return true; + } + + @Override + public CloseBehavior onClose(Player player) { + return StandardCloseBehavior.REOPEN; + } + + /** + * @return Inventory's name + */ + public abstract String name(); + + /** + * @param object existing object to represent + * @return ItemStack who represents the object + */ + + public abstract ItemStack getItemStack(T object); + + /** + * Called when the player click on an item + */ + public abstract void finish(T object); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java new file mode 100644 index 00000000..695d3a21 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java @@ -0,0 +1,48 @@ +package fr.skytasul.quests.api.gui.templates; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.layout.Button; +import fr.skytasul.quests.api.gui.layout.ClickHandler; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; +import fr.skytasul.quests.api.localization.Lang; + +public final class ConfirmGUI { + + private ConfirmGUI() {} + + public static CustomInventory confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + @Nullable String @Nullable... lore) { + return confirm(yes, no, indication, lore == null ? null : Arrays.asList(lore)); + } + + public static CustomInventory confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + @Nullable List<@Nullable String> lore) { + return LayoutedGUI.newBuilder() + .addButton(1, + Button.create(XMaterial.LIME_DYE, Lang.confirmYes.toString(), Collections.emptyList(), event -> { + event.close(); + if (yes != null) + yes.run(); + })) + .addButton(3, + Button.create(XMaterial.RED_DYE, Lang.confirmNo.toString(), Collections.emptyList(), event -> { + event.close(); + if (no != null) + no.run(); + })) + .addButton(2, Button.create(XMaterial.PAPER, indication, lore, ClickHandler.EMPTY)) + .setInventoryType(InventoryType.HOPPER) + .setName(Lang.INVENTORY_CONFIRM.toString()) + .setCloseBehavior(StandardCloseBehavior.REOPEN) + .build(); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ListGUI.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java rename to api/src/main/java/fr/skytasul/quests/api/gui/templates/ListGUI.java index b5ecd412..75d74778 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ListGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.templates; +package fr.skytasul.quests.api.gui.templates; import java.util.Collection; import java.util.List; @@ -7,12 +7,13 @@ import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; /** * An inventory which has up to 54 slots to store items. Each item is linked in a list to an instance of type T. @@ -79,12 +80,13 @@ public void updateObject(T object, T newObject) { if (index == -1) return; objects.set(index, newObject); int slot = getObjectSlot(newObject); - if (slot != -1) inv.setItem(slot, getItemStack(newObject)); + if (slot != -1) + getInventory().setItem(slot, getItemStack(newObject)); } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - return CloseBehavior.REOPEN; + public CloseBehavior onClose(Player player) { + return StandardCloseBehavior.REOPEN; } /** @@ -98,8 +100,8 @@ private ItemStack finishItem(T object) { calcMaxPages(); page = maxPage - 1; setItems(); - reopen(); - return inv.getItem(getObjectSlot(object)); + reopen(player); + return getInventory().getItem(getObjectSlot(object)); } /** diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/PagedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java similarity index 74% rename from core/src/main/java/fr/skytasul/quests/gui/templates/PagedGUI.java rename to api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java index e8d128f4..30c8a310 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/PagedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.templates; +package fr.skytasul.quests.api.gui.templates; import java.util.ArrayList; import java.util.Collection; @@ -13,13 +13,13 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.LevenshteinComparator; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.LevenshteinComparator; /** * An inventory with an infinite amount of pages of 35 items (integer limit). @@ -27,12 +27,11 @@ * * @param <T> type of objects stocked in the inventory */ -public abstract class PagedGUI<T> implements CustomInventory { +public abstract class PagedGUI<T> extends CustomInventory { private static ItemStack itemSearch = ItemUtils.item(XMaterial.COMPASS, Lang.search.toString()); - protected Player p; - protected Inventory inv; + protected Player player; protected int page = 0; protected int maxPage; @@ -56,28 +55,30 @@ protected PagedGUI(String name, DyeColor color, Collection<T> objects, Consumer< } @Override - public Inventory open(Player p) { - this.p = p; + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 45, name); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + this.player = player; calcMaxPages(); - inv = Bukkit.createInventory(null, 45, name); - setBarItem(0, ItemUtils.itemLaterPage); setBarItem(4, ItemUtils.itemNextPage); if (validate != null) setBarItem(2, validationItem); if (comparator != null) setBarItem(3, itemSearch); - for (int i = 0; i < 5; i++) inv.setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); + for (int i = 0; i < 5; i++) + inventory.setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); setItems(); - - inv = p.openInventory(inv).getTopInventory(); - return inv; } public PagedGUI<T> setValidate(Consumer<List<T>> validate, ItemStack validationItem) { if (this.validate != null) throw new IllegalStateException("A validation has already be added."); - if (this.inv != null) throw new IllegalStateException("Cannot add a validation after inventory opening."); + if (this.getInventory() != null) + throw new IllegalStateException("Cannot add a validation after inventory opening."); if (validationItem == null) throw new IllegalArgumentException("Cannot set a null validation item."); this.validate = validate; this.validationItem = validationItem; @@ -128,16 +129,16 @@ private int setBarItem(int barSlot, ItemStack is){ } private void setItem(ItemStack is, int rawSlot) { - inv.setItem(rawSlot, is); + getInventory().setItem(rawSlot, is); if (is != null && is.getType() != Material.AIR) { - ItemStack invItem = inv.getItem(rawSlot); + ItemStack invItem = getInventory().getItem(rawSlot); if (invItem == null || invItem.getType() == Material.AIR) { // means the item was a material that cannot be put in an inventory: // fire, water block, crops... is = is.clone(); is.setType(Material.STONE); - inv.setItem(rawSlot, is); + getInventory().setItem(rawSlot, is); } } } @@ -156,7 +157,7 @@ public int getObjectSlot(T object){ @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player player, ItemStack current, int slot, ClickType click) { switch (slot % 9){ case 8: int barSlot = (slot - 8) / 9; @@ -177,13 +178,13 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli break; case 3: - new TextEditor<String>(p, () -> p.openInventory(inv), (obj) -> { + new TextEditor<String>(player, this::reopen, obj -> { //objects.stream().filter(x -> getName(x).contains((String) obj)); objects.sort(comparator.setReference(obj)); page = 0; setItems(); - p.openInventory(inv); - }).enter(); + reopen(); + }).start(); break; } break; @@ -200,17 +201,19 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli return true; } - public void reopen() { - Inventories.closeWithoutExit(p); - Inventories.put(p, this, inv); - inv = p.openInventory(inv).getTopInventory(); + public final void reopen() { + reopen(player); } - + + public final void close() { + close(player); + } + /** * @param object existing object to represent * @return ItemStack who represents the object */ - public abstract ItemStack getItemStack(T object); + public abstract @NotNull ItemStack getItemStack(@NotNull T object); /** * Called when an object is clicked @@ -218,6 +221,6 @@ public void reopen() { * @param item item clicked * @param clickType click type */ - public abstract void click(T existing, ItemStack item, ClickType clickType); + public abstract void click(@NotNull T existing, @NotNull ItemStack item, @NotNull ClickType clickType); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/StaticPagedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/StaticPagedGUI.java similarity index 74% rename from core/src/main/java/fr/skytasul/quests/gui/templates/StaticPagedGUI.java rename to api/src/main/java/fr/skytasul/quests/api/gui/templates/StaticPagedGUI.java index 67d1a0f4..e02e5cd3 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/StaticPagedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/StaticPagedGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.templates; +package fr.skytasul.quests.api.gui.templates; import java.util.Map; import java.util.Map.Entry; @@ -7,9 +7,10 @@ import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; public class StaticPagedGUI<T> extends PagedGUI<Entry<T, ItemStack>> { @@ -37,12 +38,11 @@ public void click(Entry<T, ItemStack> existing, ItemStack item, ClickType clickT } @Override - public CloseBehavior onClose(Player p, Inventory inv) { + public CloseBehavior onClose(Player player) { if (cancelAllowed) { - Utils.runSync(() -> clicked.accept(null)); - return CloseBehavior.NOTHING; + return new DelayCloseBehavior(() -> clicked.accept(null)); }else { - return CloseBehavior.REOPEN; + return StandardCloseBehavior.REOPEN; } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/Lang.java b/api/src/main/java/fr/skytasul/quests/api/localization/Lang.java similarity index 97% rename from core/src/main/java/fr/skytasul/quests/utils/Lang.java rename to api/src/main/java/fr/skytasul/quests/api/localization/Lang.java index d7efcaa5..6c4d8bdb 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Lang.java +++ b/api/src/main/java/fr/skytasul/quests/api/localization/Lang.java @@ -1,9 +1,8 @@ -package fr.skytasul.quests.utils; +package fr.skytasul.quests.api.localization; import java.util.Objects; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.Locale; /** * Stores all string paths and methods to format and send them to players. diff --git a/core/src/main/java/fr/skytasul/quests/api/Locale.java b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java similarity index 79% rename from core/src/main/java/fr/skytasul/quests/api/Locale.java rename to api/src/main/java/fr/skytasul/quests/api/localization/Locale.java index 3c71dd28..c66dbb0c 100644 --- a/core/src/main/java/fr/skytasul/quests/api/Locale.java +++ b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api; +package fr.skytasul.quests.api.localization; import java.io.File; import java.io.IOException; @@ -14,9 +14,10 @@ import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.utils.ChatUtils; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.utils.ChatColorUtils; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.Utils; public interface Locale { @@ -29,19 +30,19 @@ public interface Locale { void setValue(@NotNull String value); default @NotNull String format(@Nullable Object @Nullable... replace) { - return Utils.format(getValue(), replace); + return MessageUtils.format(getValue(), replace); } default @NotNull String format(@NotNull Supplier<Object> @Nullable... replace) { - return Utils.format(getValue(), replace); + return MessageUtils.format(getValue(), replace); } default void send(@NotNull CommandSender sender, @Nullable Object @Nullable... args) { - Utils.sendMessage(sender, getValue(), args); + MessageUtils.sendPrefixedMessage(sender, getValue(), args); } default void sendWP(@NotNull CommandSender p, @Nullable Object @Nullable... args) { - Utils.sendMessageWP(p, getValue(), args); + MessageUtils.sendUnprefixedMessage(p, getValue(), args); } public static void loadStrings(@NotNull Locale @NotNull [] locales, @NotNull YamlConfiguration defaultConfig, @@ -49,8 +50,9 @@ public static void loadStrings(@NotNull Locale @NotNull [] locales, @NotNull Yam for (Locale l : locales) { String value = config.getString(l.getPath(), null); if (value == null) value = defaultConfig.getString(l.getPath(), null); - if (value == null) DebugUtils.logMessage("Unavailable string in config for key " + l.getPath()); - l.setValue(ChatUtils.translateHexColorCodes(ChatColor.translateAlternateColorCodes('&', value == null ? "§cunknown string" : value))); + if (value == null) + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Unavailable string in config for key " + l.getPath()); + l.setValue(ChatColorUtils.translateHexColorCodes(ChatColor.translateAlternateColorCodes('&', value == null ? "§cunknown string" : value))); } } @@ -85,7 +87,7 @@ public static YamlConfiguration loadLang(@NotNull Plugin plugin, @NotNull Locale if (!def.isConfigurationSection(key)) { // if not a block if (!conf.contains(key)) { // if string does not exist in the file conf.set(key, def.get(key)); // copy string - if (!created) DebugUtils.logMessage("String copied from source file to " + language + ". Key: " + key); + if (!created) QuestsPlugin.getPlugin().getLoggerExpanded().debug("String copied from source file to " + language + ". Key: " + key); changes = true; } } diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java b/api/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java rename to api/src/main/java/fr/skytasul/quests/api/mobs/LeveledMobFactory.java diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java b/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java rename to api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java index 099ee2f1..eea4f35b 100644 --- a/core/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java @@ -20,9 +20,9 @@ import org.jetbrains.annotations.Nullable; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.utils.compatibility.mobs.CompatMobDeathEvent; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.events.internal.BQMobDeathEvent; /** * This class implements {@link Listener} to permit the implementation to have at least one {@link EventHandler}. @@ -85,10 +85,7 @@ public default boolean mobApplies(@Nullable T first, @Nullable Object other) { return Objects.equals(first, other); } - public default boolean bukkitMobApplies(@NotNull T first, @NotNull Entity entity) { // TODO abstract (introduced in 0.20) - BeautyQuests.logger.warning("The mob factory " + getID() + " has not been updated. Nag its author about it!"); - return false; - } + public boolean bukkitMobApplies(@NotNull T first, @NotNull Entity entity); /** * Has to be called when a mob corresponding to this factory has been killed @@ -103,22 +100,23 @@ public default void callEvent(@Nullable Event originalEvent, @NotNull T pluginMo Validate.notNull(pluginMob, "Plugin mob object cannot be null"); Validate.notNull(player, "Player cannot be null"); if (originalEvent != null) { - CompatMobDeathEvent existingCompat = eventsCache.getIfPresent(originalEvent); + BQMobDeathEvent existingCompat = eventsCache.getIfPresent(originalEvent); if (existingCompat != null && mobApplies(pluginMob, existingCompat.getPluginMob())) { - BeautyQuests.logger.warning("MobFactory.callEvent() called twice!"); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("MobFactory.callEvent() called twice!"); return; } } - OptionalInt optionalStackSize = QuestsAPI.getMobStackers().stream() + OptionalInt optionalStackSize = QuestsAPI.getAPI().getMobStackers().stream() .mapToInt(stacker -> stacker.getEntityStackSize(entity)).filter(size -> size > 1).max(); - CompatMobDeathEvent compatEvent = new CompatMobDeathEvent(pluginMob, player, entity, optionalStackSize.orElse(1)); + BQMobDeathEvent compatEvent = new BQMobDeathEvent(pluginMob, player, entity, optionalStackSize.orElse(1)); if (originalEvent != null) eventsCache.put(originalEvent, compatEvent); Bukkit.getPluginManager().callEvent(compatEvent); } - static final Cache<Event, CompatMobDeathEvent> eventsCache = CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build(); + static final Cache<Event, BQMobDeathEvent> eventsCache = + CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build(); public static final List<MobFactory<?>> factories = new ArrayList<>(); public static @Nullable MobFactory<?> getMobFactory(@NotNull String id) { diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java b/api/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java rename to api/src/main/java/fr/skytasul/quests/api/mobs/MobStacker.java diff --git a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java similarity index 95% rename from core/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java rename to api/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java index 30d1f4b9..44f8d67b 100644 --- a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java @@ -17,18 +17,18 @@ import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.AbstractHolograms; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.stages.types.Locatable.Located; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.options.OptionHologramLaunch; import fr.skytasul.quests.options.OptionHologramLaunchNo; import fr.skytasul.quests.options.OptionHologramText; import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public abstract class BQNPC implements Located.LocatedEntity { @@ -313,14 +313,14 @@ public void unload() { } public void delete(String cause) { - DebugUtils.logMessage("Removing NPC Starter " + getId()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + getId()); for (Quest qu : quests.keySet()) { - BeautyQuests.logger.warning("Starter NPC #" + getId() + " has been removed from quest " + qu.getID() + ". Reason: " + cause); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Starter NPC #" + getId() + " has been removed from quest " + qu.getId() + ". Reason: " + cause); qu.removeOption(OptionStarterNPC.class); } quests = null; for (QuestPool pool : pools) { - BeautyQuests.logger.warning("NPC #" + getId() + " has been removed from pool " + pool.getID() + ". Reason: " + cause); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("NPC #" + getId() + " has been removed from pool " + pool.getID() + ". Reason: " + cause); pool.unloadStarter(); } unload(); diff --git a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java rename to api/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java index e3c9a809..1378c692 100644 --- a/core/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java @@ -10,10 +10,10 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration.ClickType; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; public abstract class BQNPCsManager implements Listener { @@ -32,7 +32,7 @@ public abstract class BQNPCsManager implements Listener { try { if (type == EntityType.PLAYER) npc.setSkin(skin); }catch (Exception ex) { - BeautyQuests.logger.severe("Failed to set NPC skin", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Failed to set NPC skin", ex); } npcs.put(npc.getId(), npc); return npc; diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Dialog.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java similarity index 69% rename from core/src/main/java/fr/skytasul/quests/utils/types/Dialog.java rename to api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java index 926801df..39911182 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Dialog.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java @@ -1,30 +1,41 @@ -package fr.skytasul.quests.utils.types; +package fr.skytasul.quests.api.npcs.dialogs; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.types.Message.Sender; +import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; +import fr.skytasul.quests.utils.types.NumberedList; public class Dialog implements Cloneable { - public List<Message> messages; - public String npcName = null; - public Boolean skippable = null; + private @NotNull List<Message> messages; + private @Nullable String npcName = null; + private @Nullable Boolean skippable = null; public Dialog() { this(new ArrayList<>()); } - public Dialog(List<Message> messages) { + public Dialog(@NotNull List<Message> messages) { this.messages = messages; } - public String getNPCName(BQNPC defaultNPC) { + public @NotNull List<Message> getMessages() { + return messages; + } + + public void setMessages(@NotNull List<Message> messages) { + this.messages = messages; + } + + public @NotNull String getNPCName(@Nullable BQNPC defaultNPC) { if (npcName != null) return npcName; if (defaultNPC == null) @@ -32,6 +43,14 @@ public String getNPCName(BQNPC defaultNPC) { return defaultNPC.getName(); } + public @Nullable String getNpcName() { + return npcName; + } + + public void setNpcName(@Nullable String npcName) { + this.npcName = npcName; + } + public void add(String msg, Sender sender){ messages.add(new Message(msg, sender)); } @@ -40,14 +59,14 @@ public void insert(String msg, Sender sender, int id){ messages.add(id, new Message(msg, sender)); } - public void setNPCName(String npcName) { - this.npcName = npcName; - } - public boolean isSkippable() { return skippable == null ? QuestsConfiguration.getDialogsConfig().isSkippableByDefault() : skippable.booleanValue(); } + public void setSkippable(@Nullable Boolean skippable) { + this.skippable = skippable; + } + public String getSkippableStatus() { String msg = isSkippable() ? Lang.Enabled.toString() : Lang.Disabled.toString(); if (skippable == null) msg += " " + Lang.defaultValue.toString(); diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java new file mode 100644 index 00000000..60d798d3 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java @@ -0,0 +1,60 @@ +package fr.skytasul.quests.api.npcs.dialogs; + +import java.util.function.Consumer; +import java.util.function.Predicate; +import org.bukkit.entity.Player; + +public interface DialogRunner { + + void addTest(Predicate<Player> test); + + void addTestCancelling(Predicate<Player> test); + + void addEndAction(Consumer<Player> action); + + /** + * Tests if the player is close enough to the NPC for the dialog to continue. + * <p> + * This is <i>not</i> tested on player click, only for automatic messages with durations. + * @param p Player to check the distance from the NPC + * @return <code>true</code> if the player is close enough to the NPC or if the distance feature is disabled, <code>false</code> otherwise. + */ + boolean canContinue(Player p); + + /** + * Must be called when the player clicks on the NPC. + * This will send the dialog to the player if conditions are met. + * @param p player which + * @return the result of tests to run this dialog + */ + TestResult onClick(Player p); + + TestResult handleNext(Player p, DialogNextReason reason); + + boolean isPlayerInDialog(Player p); + + int getPlayerMessage(Player p); + + boolean removePlayer(Player player); + + public enum DialogNextReason { + NPC_CLICK, AUTO_TIME, COMMAND, PLUGIN; + } + + public enum TestResult { + ALLOW, DENY, DENY_CANCEL; + + public TestResult accumulate(TestResult other) { + if (this == DENY_CANCEL || other == DENY_CANCEL) + return DENY_CANCEL; + if (this == DENY || other == DENY) + return DENY; + return ALLOW; + } + + public boolean shouldCancel() { + return this == DENY_CANCEL || this == ALLOW; + } + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Message.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java similarity index 64% rename from core/src/main/java/fr/skytasul/quests/utils/types/Message.java rename to api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java index 03d5ae2a..b441daef 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Message.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java @@ -1,132 +1,142 @@ -package fr.skytasul.quests.utils.types; - -import java.util.HashMap; -import java.util.Map; -import org.apache.commons.lang.StringUtils; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; - -public class Message implements Cloneable { - public String text; - public Sender sender; - public String sound; - public int wait = -1; - - public Message(String msg, Sender sender){ - this.text = msg; - this.sender = sender; - } - - public int getWaitTime() { - return wait == -1 ? QuestsConfiguration.getDialogsConfig().getDefaultTime() : wait; - } - - public BukkitTask sendMessage(Player p, String npc, int id, int size) { - BukkitTask task = null; - - String sent = formatMessage(p, npc, id, size); - if (QuestsConfiguration.getDialogsConfig().sendInActionBar()) { - BaseComponent[] components = TextComponent.fromLegacyText(sent.replace("{nl}", " ")); - p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); - if (getWaitTime() > 60) { - task = new BukkitRunnable() { - int time = 40; - - @Override - public void run() { - if (!p.isOnline()) { - cancel(); - return; - } - - time += 40; - if (time > getWaitTime()) cancel(); - p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); - } - }.runTaskTimerAsynchronously(BeautyQuests.getInstance(), 40, 40); - } - }else p.sendMessage(StringUtils.splitByWholeSeparator(sent, "{nl}")); - - if (!"none".equals(sound)) { - String sentSound = getSound(); - if (sentSound != null) p.playSound(p.getLocation(), sentSound, 1, 1); - } - - return task; - } - - private String getSound() { - String sentSound = sound; - if (sentSound == null) { - if (sender == Sender.PLAYER) { - sentSound = QuestsConfiguration.getDialogsConfig().getDefaultPlayerSound(); - }else if (sender == Sender.NPC) { - sentSound = QuestsConfiguration.getDialogsConfig().getDefaultNPCSound(); - } - } - return sentSound; - } - - public String formatMessage(Player p, String npc, int id, int size) { - String sent = null; - switch (sender) { - case PLAYER: - sent = Utils.finalFormat(p, Lang.SelfText.format(p.getName(), text, id + 1, size), true); - break; - case NPC: - sent = Utils.finalFormat(p, Lang.NpcText.format(npc, text, id + 1, size), true); - break; - case NOSENDER: - sent = Utils.finalFormat(p, Utils.format(text, id + 1, size), true); - break; - } - return sent; - } - - public void finished(Player p, boolean endOfDialog, boolean forced) { - if (endOfDialog || !forced) return; - String sentSound = getSound(); - if (sentSound != null) p.stopSound(sentSound); - } - - @Override - public Message clone() { - Message clone = new Message(text, sender); - clone.sound = sound; - clone.wait = wait; - return clone; - } - - public Map<String, Object> serialize(){ - Map<String, Object> map = new HashMap<>(); - map.put("text", text); - map.put("sender", sender.name()); - if (sound != null) map.put("sound", sound); - if (wait != -1) map.put("wait", wait); - return map; - } - - public static Message deserialize(Map<String, Object> map){ - Message msg = new Message((String) map.get("text"), Sender.fromString((String) map.get("sender"))); - if (map.containsKey("sound")) msg.sound = (String) map.get("sound"); - if (map.containsKey("wait")) msg.wait = (int) map.get("wait"); - return msg; - } - - public enum Sender { - PLAYER, NPC, NOSENDER; - - public static Sender fromString(String string){ - if (string.equalsIgnoreCase("NOTHING")) return NOSENDER; - return valueOf(string.toUpperCase()); - } - } +package fr.skytasul.quests.api.npcs.dialogs; + +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.lang.StringUtils; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; +import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; + +public class Message implements Cloneable { + public String text; + public Sender sender; + public String sound; + public int wait = -1; + + public Message(String msg, Sender sender) { + this.text = msg; + this.sender = sender; + } + + public int getWaitTime() { + return wait == -1 ? QuestsConfiguration.getDialogsConfig().getDefaultTime() : wait; + } + + public BukkitTask sendMessage(Player p, String npc, int id, int size) { + BukkitTask task = null; + + String sent = formatMessage(p, npc, id, size); + if (QuestsConfiguration.getDialogsConfig().sendInActionBar()) { + BaseComponent[] components = TextComponent.fromLegacyText(sent.replace("{nl}", " ")); + p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); + if (getWaitTime() > 60) { + task = new BukkitRunnable() { + int time = 40; + + @Override + public void run() { + if (!p.isOnline()) { + cancel(); + return; + } + + time += 40; + if (time > getWaitTime()) + cancel(); + p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); + } + }.runTaskTimerAsynchronously(BeautyQuests.getInstance(), 40, 40); + } + } else + p.sendMessage(StringUtils.splitByWholeSeparator(sent, "{nl}")); + + if (!"none".equals(sound)) { + String sentSound = getSound(); + if (sentSound != null) + p.playSound(p.getLocation(), sentSound, 1, 1); + } + + return task; + } + + private String getSound() { + String sentSound = sound; + if (sentSound == null) { + if (sender == Sender.PLAYER) { + sentSound = QuestsConfiguration.getDialogsConfig().getDefaultPlayerSound(); + } else if (sender == Sender.NPC) { + sentSound = QuestsConfiguration.getDialogsConfig().getDefaultNPCSound(); + } + } + return sentSound; + } + + public String formatMessage(Player p, String npc, int id, int size) { + String sent = null; + switch (sender) { + case PLAYER: + sent = Utils.finalFormat(p, Lang.SelfText.format(p.getName(), text, id + 1, size), true); + break; + case NPC: + sent = Utils.finalFormat(p, Lang.NpcText.format(npc, text, id + 1, size), true); + break; + case NOSENDER: + sent = Utils.finalFormat(p, Utils.format(text, id + 1, size), true); + break; + } + return sent; + } + + public void finished(Player p, boolean endOfDialog, boolean forced) { + if (endOfDialog || !forced) + return; + String sentSound = getSound(); + if (sentSound != null) + p.stopSound(sentSound); + } + + @Override + public Message clone() { + Message clone = new Message(text, sender); + clone.sound = sound; + clone.wait = wait; + return clone; + } + + public Map<String, Object> serialize() { + Map<String, Object> map = new HashMap<>(); + map.put("text", text); + map.put("sender", sender.name()); + if (sound != null) + map.put("sound", sound); + if (wait != -1) + map.put("wait", wait); + return map; + } + + public static Message deserialize(Map<String, Object> map) { + Message msg = new Message((String) map.get("text"), Sender.fromString((String) map.get("sender"))); + if (map.containsKey("sound")) + msg.sound = (String) map.get("sound"); + if (map.containsKey("wait")) + msg.wait = (int) map.get("wait"); + return msg; + } + + public enum Sender { + PLAYER, NPC, NOSENDER; + + public static Sender fromString(String string) { + if (string.equalsIgnoreCase("NOTHING")) + return NOSENDER; + return valueOf(string.toUpperCase()); + } + } } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java similarity index 77% rename from core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java rename to api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index 888190e9..1d46e2c2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -1,20 +1,17 @@ package fr.skytasul.quests.api.objects; -import java.util.HashMap; -import java.util.Map; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; 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.editors.TextEditor; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public abstract class QuestObject extends SerializableObject implements Cloneable { @@ -54,7 +51,7 @@ public void setCustomDescription(@Nullable String customDescription) { } public @NotNull String debugName() { - return getClass().getSimpleName() + (quest == null ? ", unknown quest" : (", quest " + quest.getID())); + return getClass().getSimpleName() + (quest == null ? ", unknown quest" : (", quest " + quest.getId())); } public boolean isValid() { @@ -64,26 +61,14 @@ public boolean isValid() { @Override public abstract @NotNull QuestObject clone(); - @Deprecated - protected void save(Map<String, Object> datas) {} - - @Deprecated - protected void load(Map<String, Object> savedDatas) {} - @Override public void save(@NotNull ConfigurationSection section) { - Map<String, Object> datas = new HashMap<>(); - save(datas); - Utils.setConfigurationSectionContent(section, datas); - if (customDescription != null) section.set(CUSTOM_DESCRIPTION_KEY, customDescription); } @Override public void load(@NotNull ConfigurationSection section) { - load(section.getValues(false)); - if (section.contains(CUSTOM_DESCRIPTION_KEY)) customDescription = section.getString(CUSTOM_DESCRIPTION_KEY); } @@ -102,16 +87,7 @@ public void load(@NotNull ConfigurationSection section) { return null; } - @Deprecated - public String[] getLore() { // backward compatibility from 0.20.1 - TODO REMOVE - return null; - } - public @NotNull String @Nullable [] getItemLore() { - String[] legacyLore = getLore(); - if (legacyLore != null) - return legacyLore; - QuestObjectLoreBuilder lore = new QuestObjectLoreBuilder(); addLore(lore); return lore.toLoreArray(); @@ -126,7 +102,7 @@ protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { description = getDescription(null); } catch (Exception ex) { description = "§cerror"; - BeautyQuests.logger.warning("Could not get quest object description during edition", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Could not get quest object description during edition", ex); } loreBuilder.addDescription( Lang.object_description.format(description + (customDescription == null ? " " + Lang.defaultValue : ""))); @@ -155,7 +131,7 @@ public final void click(@NotNull QuestObjectClickEvent event) { new TextEditor<String>(event.getPlayer(), event::reopenGUI, msg -> { setCustomDescription(msg); event.reopenGUI(); - }).passNullIntoEndConsumer().enter(); + }).passNullIntoEndConsumer().start(); } else { clickInternal(event); } diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java rename to api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java index 542b46f0..6fce3ee7 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectClickEvent.java @@ -4,8 +4,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.creation.QuestObjectGUI; +import fr.skytasul.quests.api.gui.ItemUtils; public class QuestObjectClickEvent { diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java rename to api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java index 453e39fa..2243c829 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java @@ -4,7 +4,6 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.serializable.SerializableCreator; -import fr.skytasul.quests.gui.creation.QuestObjectGUI; public class QuestObjectCreator<T extends QuestObject> extends SerializableCreator<T> { diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java new file mode 100644 index 00000000..b382b549 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java @@ -0,0 +1,87 @@ +package fr.skytasul.quests.api.objects; + +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.bukkit.DyeColor; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.gui.templates.PagedGUI; + +public class QuestObjectGUI<T extends QuestObject> extends ListGUI<T> { + + private String name; + private Collection<QuestObjectCreator<T>> creators; + private Consumer<List<T>> end; + + public QuestObjectGUI(@NotNull String name, @NotNull QuestObjectLocation objectLocation, + @NotNull Collection<@NotNull QuestObjectCreator<T>> creators, @NotNull Consumer<@NotNull List<T>> end, + @NotNull List<T> objects) { + super(name, DyeColor.CYAN, (List<T>) objects.stream().map(QuestObject::clone).collect(Collectors.toList())); + this.name = name; + this.creators = creators.stream() + .filter(creator -> creator.isAllowed(objectLocation)) + .filter(creator -> creator.canBeMultiple() + || objects.stream().noneMatch(object -> object.getCreator() == creator)) + .collect(Collectors.toList()); + this.end = end; + } + + @Override + public ItemStack getObjectItemStack(QuestObject object) { + return object.getItemStack(); + } + + @Override + protected ClickType getRemoveClick(T object) { + return object.getRemoveClick(); + } + + @Override + protected void removed(T object) { + if (!object.getCreator().canBeMultiple()) creators.add(object.getCreator()); + } + + @Override + public void createObject(Function<T, ItemStack> callback) { + new PagedGUI<QuestObjectCreator<T>>(name, DyeColor.CYAN, creators) { + + @Override + public ItemStack getItemStack(QuestObjectCreator<T> object) { + return object.getItem(); + } + + @Override + public void click(QuestObjectCreator<T> existing, ItemStack item, ClickType clickType) { + T object = existing.newObject(); + if (!existing.canBeMultiple()) creators.remove(existing); + object.click( + new QuestObjectClickEvent(player, QuestObjectGUI.this, callback.apply(object), clickType, true, object)); + } + + @Override + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(QuestObjectGUI.super::reopen); + } + + }.open(player); + } + + @Override + public void clickObject(QuestObject existing, ItemStack item, ClickType clickType) { + existing.click(new QuestObjectClickEvent(player, this, item, clickType, false, existing)); + } + + @Override + public void finish(List<T> objects) { + end.accept(objects); + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLocation.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLocation.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLocation.java rename to api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLocation.java diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java similarity index 97% rename from core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java rename to api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java index 97a8f973..6d397e06 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java @@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; public class QuestObjectLoreBuilder { diff --git a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java similarity index 97% rename from core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java rename to api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java index 01d93e6f..4fd5bb5c 100644 --- a/core/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectsRegistry.java @@ -8,7 +8,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.serializable.SerializableRegistry; -import fr.skytasul.quests.gui.creation.QuestObjectGUI; public class QuestObjectsRegistry<T extends QuestObject, C extends QuestObjectCreator<T>> extends SerializableRegistry<T, C> { diff --git a/api/src/main/java/fr/skytasul/quests/api/options/OptionSet.java b/api/src/main/java/fr/skytasul/quests/api/options/OptionSet.java new file mode 100644 index 00000000..033bdf6c --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/options/OptionSet.java @@ -0,0 +1,21 @@ +package fr.skytasul.quests.api.options; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@SuppressWarnings ("rawtypes") +public interface OptionSet extends Iterable<QuestOption> { + + <T extends QuestOption<?>> @NotNull T getOption(@NotNull Class<T> optionClass); + + boolean hasOption(@NotNull Class<? extends QuestOption<?>> clazz); + + default @Nullable <D> D getOptionValueOrDef(@NotNull Class<? extends QuestOption<D>> clazz) { + for (QuestOption<?> option : this) { + if (clazz.isInstance(option)) + return (D) option.getValue(); + } + return (D) QuestOptionCreator.creators.get(clazz).defaultValue; + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java similarity index 89% rename from core/src/main/java/fr/skytasul/quests/api/options/QuestOption.java rename to api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index b60faa3e..aada029e 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -11,11 +11,11 @@ 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.localization.Lang; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; public abstract class QuestOption<T> implements Cloneable { @@ -75,11 +75,12 @@ public void setValueUpdaterListener(@Nullable Runnable listener) { public void attach(@NotNull Quest quest) { Validate.notNull(quest, "Attached quest cannot be null"); - if (this.attachedQuest != null) throw new IllegalStateException("This option is already attached to " + attachedQuest.getID()); + if (this.attachedQuest != null) + throw new IllegalStateException("This option is already attached to " + attachedQuest.getId()); this.attachedQuest = quest; if (this instanceof Listener) { - Bukkit.getPluginManager().registerEvents((Listener) this, BeautyQuests.getInstance()); + Bukkit.getPluginManager().registerEvents((Listener) this, QuestsPlugin.getPlugin()); } if (this instanceof QuestDescriptionProvider) { diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java rename to api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java index dc4aa876..55aaecfb 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java @@ -4,7 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; public abstract class QuestOptionBoolean extends QuestOption<Boolean> { diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java rename to api/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java similarity index 89% rename from core/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java rename to api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java index b2cf98e7..d302b230 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java @@ -8,11 +8,11 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.gui.misc.ItemGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public abstract class QuestOptionItem extends QuestOption<ItemStack> { @@ -80,8 +80,8 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c new ItemGUI(is -> { setValue(is); gui.inv.setItem(slot, getItemStack(null)); - gui.reopen(p); - }, () -> gui.reopen(p)).create(p); + gui.reopen(player); + }, () -> gui.reopen(player)).open(p); } } diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java rename to api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java index b3a44824..674b74c4 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java @@ -8,14 +8,14 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectCreator; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.structure.Quest; public abstract class QuestOptionObject<T extends QuestObject, C extends QuestObjectCreator<T>> extends QuestOption<List<T>> { @@ -88,7 +88,7 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c setValue(objects); ItemUtils.lore(item, getLore()); gui.reopen(p); - }, getValue()).create(p); + }, getValue()).open(p); } public abstract XMaterial getItemMaterial(); diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java rename to api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java index 340e141a..dc21ca69 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java @@ -2,10 +2,10 @@ import java.util.Map; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.RewardCreator; -import fr.skytasul.quests.utils.Lang; public abstract class QuestOptionRewards extends QuestOptionObject<AbstractReward, RewardCreator> { diff --git a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java rename to api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java index 821c1834..341280b6 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java @@ -9,9 +9,9 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.TextListEditor; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.TextListEditor; +import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; public abstract class QuestOptionString extends QuestOption<String> { @@ -56,7 +56,7 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c setValue(list.stream().collect(Collectors.joining("{nl}"))); ItemUtils.lore(item, getLore()); gui.reopen(p); - }, splitText).enter(); + }, splitText).start(); }else { new TextEditor<String>(p, () -> gui.reopen(p), obj -> { setValue(obj); @@ -66,7 +66,7 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c resetValue(); ItemUtils.lore(item, getLore()); gui.reopen(p); - }).enter(); + }).start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java b/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java rename to api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java diff --git a/api/src/main/java/fr/skytasul/quests/api/options/description/DescriptionSource.java b/api/src/main/java/fr/skytasul/quests/api/options/description/DescriptionSource.java new file mode 100644 index 00000000..52963dc7 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/options/description/DescriptionSource.java @@ -0,0 +1,10 @@ +package fr.skytasul.quests.api.options.description; + +/** + * Where do the description request come from + */ +public enum DescriptionSource { + + SCOREBOARD, MENU, PLACEHOLDER, FORCESPLIT, FORCELINE; + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java rename to api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java diff --git a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java similarity index 78% rename from core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java rename to api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java index 3181e534..5c6543db 100644 --- a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionContext.java @@ -5,25 +5,23 @@ import java.util.Objects; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.gui.quests.PlayerListGUI; -import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch.Source; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.PlayerListCategory; public class QuestDescriptionContext { private final QuestDescription descriptionOptions; private final Quest quest; private final PlayerAccount acc; - private final Category category; - private final Source source; + private final PlayerListCategory category; + private final DescriptionSource source; private PlayerQuestDatas cachedDatas; public QuestDescriptionContext(@NotNull QuestDescription descriptionOptions, @NotNull Quest quest, - @NotNull PlayerAccount acc, @NotNull PlayerListGUI.Category category, @NotNull Source source) { + @NotNull PlayerAccount acc, @NotNull PlayerListCategory category, @NotNull DescriptionSource source) { this.descriptionOptions = descriptionOptions; this.quest = quest; this.acc = acc; @@ -43,11 +41,11 @@ public QuestDescriptionContext(@NotNull QuestDescription descriptionOptions, @No return acc; } - public @NotNull Category getCategory() { + public @NotNull PlayerListCategory getCategory() { return category; } - public @NotNull Source getSource() { + public @NotNull DescriptionSource getSource() { return source; } diff --git a/core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java rename to api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java diff --git a/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java b/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java new file mode 100644 index 00000000..1c7ac53c --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java @@ -0,0 +1,66 @@ +package fr.skytasul.quests.api.players; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import fr.skytasul.quests.api.data.SavableData; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; + +public interface PlayerAccount { + /** + * @return if this account is currently used by the player (if true, {@link #getPlayer()} cannot + * return a null player) + */ + public boolean isCurrent(); + + /** + * @return the OfflinePlayer instance attached to this account (no matter if the player is online or + * not, or if the account is the currently used) + */ + public @NotNull OfflinePlayer getOfflinePlayer(); + + /** + * @return the Player instance who own this account. If the account is not which in use by the + * player ({@link #isCurrent()}), this will return null. + */ + public @Nullable Player getPlayer(); + + public boolean hasQuestDatas(@NotNull Quest quest); + + public @Nullable PlayerQuestDatas getQuestDatasIfPresent(@NotNull Quest quest); + + public @NotNull PlayerQuestDatas getQuestDatas(@NotNull Quest quest); + + public @NotNull CompletableFuture<PlayerQuestDatas> removeQuestDatas(@NotNull Quest quest); + + public @NotNull CompletableFuture<PlayerQuestDatas> removeQuestDatas(int id); + + public @UnmodifiableView @NotNull Collection<@NotNull PlayerQuestDatas> getQuestsDatas(); + + public boolean hasPoolDatas(@NotNull QuestPool pool); + + public @NotNull PlayerPoolDatas getPoolDatas(@NotNull QuestPool pool); + + public @NotNull CompletableFuture<PlayerPoolDatas> removePoolDatas(@NotNull QuestPool pool); + + public @NotNull CompletableFuture<PlayerPoolDatas> removePoolDatas(int id); + + public @UnmodifiableView @NotNull Collection<@NotNull PlayerPoolDatas> getPoolDatas(); + + public <T> @Nullable T getData(@NotNull SavableData<T> data); + + public <T> void setData(@NotNull SavableData<T> data, @Nullable T value); + + public void resetDatas(); + + public @NotNull String getName(); + + public @NotNull String getNameAndID(); + + public @NotNull String debugName(); +} diff --git a/api/src/main/java/fr/skytasul/quests/api/players/PlayerPoolDatas.java b/api/src/main/java/fr/skytasul/quests/api/players/PlayerPoolDatas.java new file mode 100644 index 00000000..77065ede --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/players/PlayerPoolDatas.java @@ -0,0 +1,29 @@ +package fr.skytasul.quests.api.players; + +import java.util.Set; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import fr.skytasul.quests.api.pools.QuestPool; + +public interface PlayerPoolDatas { + + @NotNull + PlayerAccount getAccount(); + + int getPoolID(); + + @Nullable + QuestPool getPool(); + + long getLastGive(); + + void setLastGive(long lastGive); + + @NotNull + @UnmodifiableView + Set<@NotNull Integer> getCompletedQuests(); + + void setCompletedQuests(@NotNull Set<Integer> completedQuests); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java b/api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java new file mode 100644 index 00000000..b4cd056e --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java @@ -0,0 +1,64 @@ +package fr.skytasul.quests.api.players; + +import java.util.Map; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.StageController; + +public interface PlayerQuestDatas { + + int getQuestID(); + + @Nullable + Quest getQuest(); + + boolean isFinished(); + + void incrementFinished(); + + int getTimesFinished(); + + long getTimer(); + + void setTimer(long timer); + + int getBranch(); + + void setBranch(int branch); + + int getStage(); + + void setStage(int stage); + + boolean hasStarted(); + + boolean isInQuestEnd(); + + void setInQuestEnd(); + + boolean isInEndingStages(); + + void setInEndingStages(); + + <T> @Nullable T getAdditionalData(@NotNull String key); + + <T> @Nullable T setAdditionalData(@NotNull String key, @Nullable T value); + + @Nullable + Map<@NotNull String, @Nullable Object> getStageDatas(int stage); + + void setStageDatas(int stage, @Nullable Map<@NotNull String, @Nullable Object> datas); + + long getStartingTime(); + + void setStartingTime(long time); + + @NotNull + String getQuestFlow(); + + void addQuestFlow(@NotNull StageController finished); + + void resetQuestFlow(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/players/PlayersManager.java b/api/src/main/java/fr/skytasul/quests/api/players/PlayersManager.java new file mode 100644 index 00000000..d9584d6d --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/players/PlayersManager.java @@ -0,0 +1,24 @@ +package fr.skytasul.quests.api.players; + +import java.util.Collection; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.UnknownNullability; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.data.SavableData; + +public interface PlayersManager { + + public abstract void save(); + + public void addAccountData(@NotNull SavableData<?> data); + + public @NotNull Collection<@NotNull SavableData<?>> getAccountDatas(); + + public @UnknownNullability PlayerAccount getAccount(@NotNull Player p); + + public static @UnknownNullability PlayerAccount getPlayerAccount(@NotNull Player p) { + return QuestsPlugin.getPlugin().getPlayersManager().getAccount(p); + } + +} 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 new file mode 100644 index 00000000..0f6b52b0 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPool.java @@ -0,0 +1,48 @@ +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 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.AbstractRequirement; + +public interface QuestPool { + + int getId(); + + int getNpcId(); + + String getHologram(); + + int getMaxQuests(); + + int getQuestsPerLaunch(); + + boolean isRedoAllowed(); + + long getTimeDiff(); + + boolean doAvoidDuplicates(); + + List<AbstractRequirement> getRequirements(); + + List<Quest> getQuests(); + + void addQuest(Quest quest); + + void removeQuest(Quest quest); + + ItemStack getItemStack(String action); + + CompletableFuture<PlayerPoolDatas> resetPlayer(PlayerAccount acc); + + void resetPlayerTimer(PlayerAccount acc); + + boolean canGive(Player p, PlayerAccount acc); + + CompletableFuture<String> give(Player p); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java new file mode 100644 index 00000000..c313d4a4 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java @@ -0,0 +1,22 @@ +package fr.skytasul.quests.api.pools; + +import java.util.Collection; +import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import fr.skytasul.quests.api.requirements.AbstractRequirement; + +public interface QuestPoolsManager { + + public @NotNull QuestPool createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, int maxQuests, + int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, + @NotNull List<AbstractRequirement> requirements); + + public void removePool(int id); + + public @Nullable QuestPool getPool(int id); + + public @NotNull @UnmodifiableView Collection<QuestPool> getPools(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java new file mode 100644 index 00000000..f26dae4a --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java @@ -0,0 +1,79 @@ +package fr.skytasul.quests.api.quests; + +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.options.OptionSet; +import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.branches.QuestBranchesManager; +import fr.skytasul.quests.api.utils.QuestVisibilityLocation; + +public interface Quest extends OptionSet, Comparable<Quest> { + + int getId(); + + boolean isValid(); + + void delete(boolean silently, boolean keepDatas); + + @NotNull + QuestBranchesManager getBranchesManager(); + + public void addOption(@NotNull QuestOption<?> option); + + public void removeOption(@NotNull Class<? extends QuestOption<?>> clazz); + + public @NotNull List<QuestDescriptionProvider> getDescriptions(); + + public @Nullable String getName(); + + public @Nullable String getDescription(); + + public @NotNull ItemStack getQuestItem(); + + public boolean isScoreboardEnabled(); + + public boolean isCancellable(); + + public boolean isRepeatable(); + + public boolean isHidden(QuestVisibilityLocation location); + + public boolean isHiddenWhenRequirementsNotMet(); + + public boolean canBypassLimit(); + + public boolean hasStarted(@NotNull PlayerAccount acc); + + public boolean hasFinished(@NotNull PlayerAccount acc); + + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); + + public boolean canStart(@NotNull Player player, boolean sendMessage); + + public boolean cancelPlayer(@NotNull PlayerAccount acc); + + public @NotNull CompletableFuture<Boolean> resetPlayer(@NotNull PlayerAccount acc); + + public @NotNull CompletableFuture<Boolean> attemptStart(@NotNull Player player); + + public default void start(@NotNull Player player) { + start(player, false); + } + + public void start(@NotNull Player player, boolean silently); + + public void finish(@NotNull Player player); + + @Override + default int compareTo(Quest o) { + return Integer.compare(getId(), o.getId()); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/QuestsManager.java b/api/src/main/java/fr/skytasul/quests/api/quests/QuestsManager.java new file mode 100644 index 00000000..f049ebaa --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/quests/QuestsManager.java @@ -0,0 +1,42 @@ +package fr.skytasul.quests.api.quests; + +import java.io.File; +import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import fr.skytasul.quests.api.players.PlayerAccount; + +public interface QuestsManager { + + @NotNull + File getSaveFolder(); + + @NotNull + @UnmodifiableView + List<@NotNull Quest> getQuests(); + + @Nullable + Quest getQuest(int id); + + void addQuest(@NotNull Quest quest); + + @NotNull + List<@NotNull Quest> getQuestsStarted(PlayerAccount acc); + + @NotNull + List<@NotNull Quest> getQuestsStarted(@NotNull PlayerAccount acc, boolean hide, + boolean withoutScoreboard); + + @NotNull + List<@NotNull Quest> getQuestsFinished(@NotNull PlayerAccount acc, boolean hide); + + @NotNull + List<@NotNull Quest> getQuestsNotStarted(@NotNull PlayerAccount acc, boolean hide, + boolean clickableAndRedoable); + + void updateQuestsStarted(@NotNull PlayerAccount acc, boolean withoutScoreboard, @NotNull List<@NotNull Quest> list); + + int getStartedSize(@NotNull PlayerAccount acc); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/branches/EndingStage.java b/api/src/main/java/fr/skytasul/quests/api/quests/branches/EndingStage.java new file mode 100644 index 00000000..2b32500e --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/quests/branches/EndingStage.java @@ -0,0 +1,13 @@ +package fr.skytasul.quests.api.quests.branches; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.stages.StageController; + +public interface EndingStage { + + public @NotNull StageController getStage(); + + public @Nullable QuestBranch getBranch(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranch.java b/api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranch.java new file mode 100644 index 00000000..7d2f53c1 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranch.java @@ -0,0 +1,36 @@ +package fr.skytasul.quests.api.quests.branches; + +import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.StageController; + +public interface QuestBranch { + + int getId(); + + @NotNull + QuestBranchesManager getManager(); + + @NotNull + default Quest getQuest() { + return getManager().getQuest(); + } + + public @NotNull @UnmodifiableView List<@NotNull StageController> getRegularStages(); + + public @NotNull StageController getRegularStage(int id); + + public @NotNull @UnmodifiableView List<EndingStage> getEndingStages(); + + public @NotNull StageController getEndingStage(int id); + + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); + + public boolean hasStageLaunched(@Nullable PlayerAccount acc, @NotNull StageController stage); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranchesManager.java b/api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranchesManager.java new file mode 100644 index 00000000..b98a8c0d --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/quests/branches/QuestBranchesManager.java @@ -0,0 +1,25 @@ +package fr.skytasul.quests.api.quests.branches; + +import java.util.Collection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; + +public interface QuestBranchesManager { + + @NotNull + Quest getQuest(); + + public int getId(@NotNull QuestBranch branch); + + public @UnmodifiableView @NotNull Collection<@NotNull QuestBranch> getBranches(); + + public @Nullable QuestBranch getBranch(int id); + + public @Nullable QuestBranch getPlayerBranch(@NotNull PlayerAccount acc); + + public boolean hasBranchStarted(@NotNull PlayerAccount acc, @NotNull QuestBranch branch); + +} diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java similarity index 87% rename from core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java rename to api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index d3ae3ab8..a5f61aa9 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -7,13 +7,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.MessageUtils; public abstract class AbstractRequirement extends QuestObject { @@ -26,7 +26,7 @@ protected AbstractRequirement() { } protected AbstractRequirement(@Nullable String customDescription, @Nullable String customReason) { - super(QuestsAPI.getRequirements(), customDescription); + super(QuestsAPI.getAPI().getRequirements(), customDescription); this.customReason = customReason; } @@ -47,7 +47,7 @@ public void setCustomReason(@Nullable String customReason) { /** * Called if the condition if not filled and if the plugin allows to send a message to the player - * @param p Player to send the reason + * @param player Player to send the reason */ public final boolean sendReason(@NotNull Player player) { String reason; @@ -60,7 +60,7 @@ else if (customReason != null) reason = getDefaultReason(player); if (reason != null && !reason.isEmpty() && !"none".equals(reason)) { - Utils.sendMessage(player, reason); + MessageUtils.sendPrefixedMessage(player, reason); return true; } @@ -102,7 +102,7 @@ protected final void clickInternal(@NotNull QuestObjectClickEvent event) { new TextEditor<String>(event.getPlayer(), event::reopenGUI, msg -> { setCustomReason(msg); event.reopenGUI(); - }).passNullIntoEndConsumer().enter(); + }).passNullIntoEndConsumer().start(); } else { itemClick(event); } @@ -136,7 +136,7 @@ public void load(@NotNull ConfigurationSection section) { } public static @NotNull AbstractRequirement deserialize(Map<String, Object> map) { - return SerializableObject.deserialize(map, QuestsAPI.getRequirements()); + return SerializableObject.deserialize(map, QuestsAPI.getAPI().getRequirements()); } } diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java b/api/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java rename to api/src/main/java/fr/skytasul/quests/api/requirements/Actionnable.java diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java b/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java rename to api/src/main/java/fr/skytasul/quests/api/requirements/RequirementCreator.java diff --git a/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java rename to api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java index e543de27..ee65c1ad 100644 --- a/core/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java @@ -6,13 +6,13 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.utils.ComparisonMethod; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.ComparisonMethod; public abstract class TargetNumberRequirement extends AbstractRequirement { @@ -90,8 +90,8 @@ public void itemClick(@NotNull QuestObjectClickEvent event) { new TextEditor<>(event.getPlayer(), null, comp -> { this.comparison = comp == null ? ComparisonMethod.GREATER_OR_EQUAL : comp; event.reopenGUI(); - }, ComparisonMethod.getComparisonParser()).passNullIntoEndConsumer().enter(); - }, event::remove, new NumberParser<>(numberClass(), true)).enter(); + }, ComparisonMethod.getComparisonParser()).passNullIntoEndConsumer().start(); + }, event::remove, new NumberParser<>(numberClass(), true)).start(); } } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java b/api/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java similarity index 85% rename from core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java rename to api/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java index 49090b04..c8aa56d1 100644 --- a/core/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java +++ b/api/src/main/java/fr/skytasul/quests/api/rewards/AbstractReward.java @@ -6,10 +6,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.utils.Lang; public abstract class AbstractReward extends QuestObject { @@ -18,7 +18,7 @@ protected AbstractReward() { } protected AbstractReward(@Nullable String customDescription) { - super(QuestsAPI.getRewards(), customDescription); + super(QuestsAPI.getAPI().getRewards(), customDescription); } @Override @@ -49,7 +49,7 @@ protected final void clickInternal(@NotNull QuestObjectClickEvent event) { public abstract @NotNull AbstractReward clone(); public static @NotNull AbstractReward deserialize(Map<String, Object> map) { - return SerializableObject.deserialize(map, QuestsAPI.getRewards()); + return SerializableObject.deserialize(map, QuestsAPI.getAPI().getRewards()); } public boolean isAsync() { diff --git a/core/src/main/java/fr/skytasul/quests/api/rewards/InterruptingBranchException.java b/api/src/main/java/fr/skytasul/quests/api/rewards/InterruptingBranchException.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/rewards/InterruptingBranchException.java rename to api/src/main/java/fr/skytasul/quests/api/rewards/InterruptingBranchException.java diff --git a/core/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java b/api/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java rename to api/src/main/java/fr/skytasul/quests/api/rewards/RewardCreator.java diff --git a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java b/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java rename to api/src/main/java/fr/skytasul/quests/api/serializable/SerializableCreator.java diff --git a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java b/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java rename to api/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java index 4ca78d42..40de71f5 100644 --- a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java @@ -8,8 +8,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemoryConfiguration; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.utils.Utils; public abstract class SerializableObject { @@ -64,12 +64,12 @@ public static <T extends SerializableObject, C extends SerializableCreator<T>> T }catch (ClassNotFoundException e) {} if (creator == null) { - BeautyQuests.logger.severe("Cannot find object class " + className); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot find object class " + className); return null; } } if (creator == null) { - BeautyQuests.logger.severe("Cannot find object creator with id: " + id); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot find object creator with id: " + id); return null; } T reward = creator.newObject(); @@ -84,12 +84,15 @@ public static <T extends SerializableObject, C extends SerializableCreator<T>> T try { T object = deserializeFunction.apply((Map<String, Object>) objectMap); if (object == null) { - BeautyQuests.loadingFailure = true; - BeautyQuests.getInstance().getLogger().severe("The quest object for class " + String.valueOf(objectMap.get("class")) + " has not been deserialized."); + QuestsPlugin.getPlugin().notifyLoadingFailure(); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("The quest object for class " + + String.valueOf(objectMap.get("class")) + " has not been deserialized."); }else objects.add(object); }catch (Exception e) { - BeautyQuests.logger.severe("An exception occured while deserializing a quest object (class " + objectMap.get("class") + ").", e); - BeautyQuests.loadingFailure = true; + QuestsPlugin.getPlugin().notifyLoadingFailure(); + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "An exception occured while deserializing a quest object (class " + objectMap.get("class") + ").", + e); } } return objects; diff --git a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java b/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java similarity index 87% rename from core/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java rename to api/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java index 82f73f17..08eca9ac 100644 --- a/core/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableRegistry.java @@ -5,7 +5,7 @@ import java.util.List; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.utils.DebugUtils; +import fr.skytasul.quests.api.QuestsPlugin; /** * This class is a registry for types of objects that can be serialized @@ -35,7 +35,7 @@ public void register(@NotNull C creator) { if (creators.stream().anyMatch(x -> x.getID().equals(creator.getID()))) throw new IllegalStateException("A creator with the same id " + creator.getID() + " has been registered."); creators.add(creator); - DebugUtils.logMessage("Quest object registered in registry " + id + " (id: " + creator.getID() + ", class: " + creator.getSerializableClass().getName() + ")"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Quest object registered in registry " + id + " (id: " + creator.getID() + ", class: " + creator.getSerializableClass().getName() + ")"); } public @Nullable C getByClass(@NotNull Class<?> clazz) { diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java new file mode 100644 index 00000000..a2d9d452 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -0,0 +1,236 @@ +package fr.skytasul.quests.api.stages; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.branches.QuestBranch; +import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.serializable.SerializableCreator; +import fr.skytasul.quests.api.serializable.SerializableObject; +import fr.skytasul.quests.api.stages.options.StageOption; +import fr.skytasul.quests.api.utils.Utils; + +public abstract class AbstractStage { + + protected final @NotNull StageController controller; + + private @Nullable String startMessage = null; + private @Nullable String customText = null; + private @NotNull List<@NotNull AbstractReward> rewards = new ArrayList<>(); + private @NotNull List<@NotNull AbstractRequirement> validationRequirements = new ArrayList<>(); + + private @NotNull List<@NotNull StageOption> options; + protected boolean asyncEnd = false; + + protected AbstractStage(@NotNull StageController controller) { + this.controller = controller; + + options = controller.getStageType().getOptionsRegistry().getCreators().stream().map(SerializableCreator::newObject) + .collect(Collectors.toList()); + } + + public @NotNull StageController getController() { + return controller; + } + + public @NotNull Quest getQuest() { + return controller.getBranch().getQuest(); + } + + public void setStartMessage(@Nullable String text) { + this.startMessage = text; + } + + public @Nullable String getStartMessage() { + return startMessage; + } + + public @NotNull List<@NotNull AbstractReward> getRewards() { + return rewards; + } + + public void setRewards(@NotNull List<@NotNull AbstractReward> rewards) { + this.rewards = rewards; + rewards.forEach(reward -> reward.attach(getQuest())); + checkAsync(); + } + + public @NotNull List<@NotNull AbstractRequirement> getValidationRequirements() { + return validationRequirements; + } + + public void setValidationRequirements(@NotNull List<@NotNull AbstractRequirement> validationRequirements) { + this.validationRequirements = validationRequirements; + validationRequirements.forEach(requirement -> requirement.attach(getQuest())); + } + + public @NotNull List<@NotNull StageOption> getOptions() { + return options; + } + + public void setOptions(@NotNull List<@NotNull StageOption> options) { + this.options = options; + } + + public @Nullable String getCustomText() { + return customText; + } + + public void setCustomText(@Nullable String message) { + this.customText = message; + } + + public boolean sendStartMessage(){ + return startMessage == null && QuestsConfiguration.sendStageStartMessage(); + } + + public boolean hasAsyncEnd() { + return asyncEnd; + } + + private void checkAsync() { + for (AbstractReward rew : rewards) { + if (rew.isAsync()) { + asyncEnd = true; + break; + } + } + } + + protected boolean canUpdate(@NotNull Player player) { + return canUpdate(player, false); + } + + protected boolean canUpdate(@NotNull Player player, boolean msg) { + return Utils.testRequirements(player, validationRequirements, msg); + } + + /** + * Called internally when a player finish stage's objectives + * + * @param player Player who finish the stage + */ + protected final void finishStage(@NotNull Player player) { + controller.finishStage(player); + } + + /** + * Called internally to test if a player has the stage started + * + * @param player Player to test + * @see QuestBranch#hasStageLaunched(PlayerAccount, AbstractStage) + */ + protected final boolean hasStarted(@NotNull Player player) { + return controller.hasStarted(player); + } + + /** + * Called when the stage starts (player can be offline) + * @param acc PlayerAccount for which the stage starts + */ + public void started(@NotNull PlayerAccount acc) {} + + /** + * Called when the stage ends (player can be offline) + * @param acc PlayerAccount for which the stage ends + */ + public void ended(@NotNull PlayerAccount acc) {} + + /** + * Called when an account with this stage launched joins + */ + public void joined(@NotNull Player player) {} + + /** + * Called when an account with this stage launched leaves + */ + public void left(@NotNull Player player) {} + + public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) {} + + /** + * @param acc PlayerAccount who has the stage in progress + * @param source source of the description request + * @return the progress of the stage for the player + */ + public abstract @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); + + /** + * Will be called only if there is a {@link #customText} + * @param acc PlayerAccount who has the stage in progress + * @param source source of the description request + * @return all strings that can be used to format the custom description text + */ + public @Nullable Object @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { + return null; + } + + public void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullable Object dataValue) { + controller.updateObjective(p, dataKey, dataValue); + } + + protected <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { + return controller.getData(acc, dataKey); + } + + /** + * Called when the stage has to be unloaded + */ + public void unload(){ + rewards.forEach(AbstractReward::detach); + validationRequirements.forEach(AbstractRequirement::detach); + } + + /** + * Called when the stage loads + */ + public void load() {} + + protected void serialize(@NotNull ConfigurationSection section) {} + + public final void save(@NotNull ConfigurationSection section) { + serialize(section); + + section.set("stageType", controller.getStageType().getID()); + section.set("customText", customText); + if (startMessage != null) section.set("text", startMessage); + + if (!rewards.isEmpty()) section.set("rewards", SerializableObject.serializeList(rewards)); + if (!validationRequirements.isEmpty()) section.set("requirements", SerializableObject.serializeList(validationRequirements)); + + options.stream().filter(StageOption::shouldSave).forEach(option -> option.save(section.createSection("options." + option.getCreator().getID()))); + } + + public final void load(@NotNull ConfigurationSection section) { + if (section.contains("text")) + startMessage = section.getString("text"); + if (section.contains("customText")) + customText = section.getString("customText"); + if (section.contains("rewards")) + setRewards(SerializableObject.deserializeList(section.getMapList("rewards"), AbstractReward::deserialize)); + if (section.contains("requirements")) + setValidationRequirements(SerializableObject.deserializeList(section.getMapList("requirements"), + AbstractRequirement::deserialize)); + + if (section.contains("options")) { + ConfigurationSection optionsSection = section.getConfigurationSection("options"); + optionsSection.getKeys(false).forEach(optionID -> { + options + .stream() + .filter(option -> option.getCreator().getID().equals(optionID)) + .findAny() + .ifPresent(option -> option.load(optionsSection.getConfigurationSection(optionID))); + }); + } + } +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java new file mode 100644 index 00000000..86d4230d --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java @@ -0,0 +1,35 @@ +package fr.skytasul.quests.api.stages; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.branches.QuestBranch; + +public interface StageController { + + public @NotNull QuestBranch getBranch(); + + public @NotNull AbstractStage getStage(); + + public @NotNull StageType<?> getStageType(); + + public void finishStage(@NotNull Player player); + + public boolean hasStarted(@NotNull PlayerAccount acc); + + public default boolean hasStarted(@NotNull Player player) { + return hasStarted(PlayersManager.getPlayerAccount(player)); + } + + public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nullable Object dataValue); + + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); + + public <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey); + + public @NotNull String getFlowId(); + +} diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java similarity index 83% rename from core/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java rename to api/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java index dd5823d5..87b40f19 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java @@ -3,21 +3,20 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import javax.sound.sampled.Line; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.stages.options.StageOption; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.creation.stages.StagesGUI; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.Lang; public abstract class StageCreation<T extends AbstractStage> { @@ -40,30 +39,30 @@ protected StageCreation(Line line, boolean ending) { line.setItem(1, StagesGUI.ending.clone(), (p, item) -> QuestsAPI.getRewards().createGUI(QuestObjectLocation.STAGE, rewards -> { setRewards(rewards); - reopenGUI(p, true); - }, rewards).create(p)); + reopenGUI(player, true); + }, rewards).open(player)); line.setItem(2, StagesGUI.descMessage.clone(), (p, item) -> { - Lang.DESC_MESSAGE.send(p); - new TextEditor<String>(p, () -> reopenGUI(p, false), obj -> { + Lang.DESC_MESSAGE.send(player); + new TextEditor<String>(player, () -> reopenGUI(player, false), obj -> { setCustomDescription(obj); - reopenGUI(p, false); - }).passNullIntoEndConsumer().enter(); + reopenGUI(player, false); + }).passNullIntoEndConsumer().start(); }); line.setItem(3, StagesGUI.startMessage.clone(), (p, item) -> { - Lang.START_TEXT.send(p); - new TextEditor<String>(p, () -> reopenGUI(p, false), obj -> { + Lang.START_TEXT.send(player); + new TextEditor<String>(player, () -> reopenGUI(player, false), obj -> { setStartMessage(obj); - reopenGUI(p, false); - }).passNullIntoEndConsumer().enter(); + reopenGUI(player, false); + }).passNullIntoEndConsumer().start(); }); line.setItem(4, StagesGUI.validationRequirements.clone(), (p, item) -> { QuestsAPI.getRequirements().createGUI(QuestObjectLocation.STAGE, requirements -> { setRequirements(requirements); - reopenGUI(p, true); - }, requirements).create(p); + reopenGUI(player, true); + }, requirements).open(player); }); } @@ -170,7 +169,7 @@ public void edit(@NotNull T stage) { options.forEach(option -> option.startEdition(this)); } - public final @NotNull T finish(@NotNull QuestBranch branch) { + public final @NotNull T finish(@NotNull StageController branch) { T stage = finishStage(branch); stage.setRewards(rewards); stage.setValidationRequirements(requirements); @@ -185,6 +184,6 @@ public void edit(@NotNull T stage) { * @param branch quest created * @return AsbtractStage created */ - protected abstract @NotNull T finishStage(@NotNull QuestBranch branch); + protected abstract @NotNull T finishStage(@NotNull StageController branch); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java new file mode 100644 index 00000000..9eb3ff81 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java @@ -0,0 +1,20 @@ +package fr.skytasul.quests.api.stages; + +import org.bukkit.entity.Player; +import fr.skytasul.quests.api.players.PlayerAccount; + +public interface StageHandler { + + default void stageStart(PlayerAccount acc, StageController stage) {} + + default void stageEnd(PlayerAccount acc, StageController stage) {} + + default void stageJoin(Player p, StageController stage) {} + + default void stageLeave(Player p, StageController stage) {} + + default void stageLoad(StageController stage) {} + + default void stageUnload(StageController stage) {} + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageType.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java similarity index 56% rename from core/src/main/java/fr/skytasul/quests/api/stages/StageType.java rename to api/src/main/java/fr/skytasul/quests/api/stages/StageType.java index 3c854a91..3a504f6e 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageType.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java @@ -1,16 +1,12 @@ package fr.skytasul.quests.api.stages; -import java.util.Map; -import org.bukkit.Bukkit; +import javax.sound.sampled.Line; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.serializable.SerializableRegistry; import fr.skytasul.quests.api.stages.options.StageOption; -import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.structure.QuestBranch; public class StageType<T extends AbstractStage> { @@ -20,8 +16,6 @@ public class StageType<T extends AbstractStage> { private final @NotNull StageLoader<T> loader; private final @NotNull ItemStack item; private final @NotNull StageCreationSupplier<T> creationSupplier; - @Deprecated - public final String[] dependencies; // TODO remove private final @NotNull SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> optionsRegistry; @@ -37,16 +31,6 @@ public class StageType<T extends AbstractStage> { */ public StageType(@NotNull String id, @NotNull Class<T> clazz, @NotNull String name, @NotNull StageLoader<T> loader, @NotNull ItemStack item, @NotNull StageCreationSupplier<T> creationSupplier) { - this(id, clazz, name, loader, item, creationSupplier, new String[0]); - } - - @Deprecated - public StageType(String id, Class<T> clazz, String name, StageDeserializationSupplier<T> deserializationSupplier, ItemStack item, StageCreationSupplier<T> creationSupplier, String... dependencies) { - this(id, clazz, name, (StageLoader<T>) deserializationSupplier, item, creationSupplier, dependencies); - } - - @Deprecated - public StageType(String id, Class<T> clazz, String name, StageLoader<T> loader, ItemStack item, StageCreationSupplier<T> creationSupplier, String... dependencies) { this.id = id; this.clazz = clazz; this.name = name; @@ -55,9 +39,6 @@ public StageType(String id, Class<T> clazz, String name, StageLoader<T> loader, this.creationSupplier = creationSupplier; this.optionsRegistry = new SerializableRegistry<>("stage-options-" + id); - - this.dependencies = dependencies; - if (dependencies.length != 0) BeautyQuests.logger.warning("Nag author of the " + id + " stage type about its use of the deprecated \"dependencies\" feature."); } public @NotNull String getID() { @@ -88,14 +69,6 @@ public StageType(String id, Class<T> clazz, String name, StageLoader<T> loader, return optionsRegistry; } - @Deprecated - public boolean isValid() { - for (String depend : dependencies) { - if (!Bukkit.getPluginManager().isPluginEnabled(depend)) return false; - } - return true; - } - @FunctionalInterface public static interface StageCreationSupplier<T extends AbstractStage> { @@ -104,28 +77,11 @@ public static interface StageCreationSupplier<T extends AbstractStage> { } - @FunctionalInterface - @Deprecated - public static interface StageDeserializationSupplier<T extends AbstractStage> extends StageLoader<T> { - - /** - * @deprecated for removal, {@link StageLoader#supply(ConfigurationSection, QuestBranch)} should be used instead. - */ - @Deprecated - T supply(Map<String, Object> serializedDatas, QuestBranch branch); - - @Override - default T supply(ConfigurationSection section, QuestBranch branch) { - return supply(section.getValues(false), branch); - } - - } - @FunctionalInterface public static interface StageLoader<T extends AbstractStage> { @NotNull - T supply(@NotNull ConfigurationSection section, @NotNull QuestBranch branch); + T supply(@NotNull ConfigurationSection section, @NotNull StageController controller); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java similarity index 87% rename from core/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java rename to api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java index 349d2d38..4b15b130 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java @@ -6,7 +6,7 @@ import java.util.Optional; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.utils.DebugUtils; +import fr.skytasul.quests.api.QuestsPlugin; public class StageTypeRegistry implements Iterable<StageType<?>> { @@ -19,7 +19,7 @@ public class StageTypeRegistry implements Iterable<StageType<?>> { public void register(@NotNull StageType<? extends AbstractStage> type) { Validate.notNull(type); types.add(type); - DebugUtils.logMessage("Stage registered (" + type.getName() + ", " + (types.size() - 1) + ")"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Stage registered (" + type.getName() + ", " + (types.size() - 1) + ")"); } public @NotNull List<@NotNull StageType<?>> getTypes() { diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java similarity index 100% rename from core/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java rename to api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java similarity index 89% rename from core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java rename to api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java index 541b1f9b..e55250b3 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java @@ -3,16 +3,16 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import javax.sound.sampled.Line; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.blocks.BlocksGUI; -import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.CountableObject; import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; @@ -55,8 +55,8 @@ protected AbstractCreator(Line line, boolean ending) { line.setItem(getBlocksSlot(), getBlocksItem(), (p, item) -> { new BlocksGUI(blocks, obj -> { setBlocks(obj); - reopenGUI(p, true); - }).create(p); + reopenGUI(player, true); + }).open(player); }); } @@ -80,8 +80,8 @@ public void start(Player p) { super.start(p); new BlocksGUI(Collections.emptyList(), obj -> { setBlocks(obj); - reopenGUI(p, true); - }).create(p); + reopenGUI(player, true); + }).open(p); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java similarity index 86% rename from core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java rename to api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index 695f0918..2a990e0d 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -20,14 +20,14 @@ import org.jetbrains.annotations.UnknownNullability; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.BossBarManager.BQBossBar; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.bossbar.BQBossBarManager.BQBossBar; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.utils.types.CountableObject; import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; @@ -49,10 +49,10 @@ protected AbstractCountableStage(@NotNull QuestBranch branch, @NotNull List<@Not protected AbstractCountableStage(QuestBranch branch, Map<Integer, Entry<T, Integer>> objects) { this(branch, objects.keySet().stream().sorted().map(index -> { Entry<T, Integer> entry = objects.get(index); - return CountableObject.create(uuidFromLegacyIndex(index), entry.getKey(), entry.getValue()); + return CountableObject.open(uuidFromLegacyIndex(index), entry.getKey(), entry.getValue()); }).collect(Collectors.toList())); - BeautyQuests.logger.warning("The stage " + getType().getName() + QuestsPlugin.getPlugin().getLoggerExpanded().warning("The stage " + getType().getName() + " uses an outdated way to store player datas. Please notice its author."); } @@ -83,7 +83,7 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { public @NotNull Map<@NotNull UUID, @NotNull Integer> getPlayerRemainings(@NotNull PlayerAccount acc, boolean warnNull) { Map<?, Integer> remaining = getData(acc, "remaining"); if (warnNull && remaining == null) - BeautyQuests.logger.severe("Cannot retrieve stage datas for " + acc.getNameAndID() + " on " + super.toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot retrieve stage datas for " + acc.getNameAndID() + " on " + super.toString()); if (remaining == null || remaining.isEmpty()) return (Map) remaining; @@ -96,7 +96,7 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { remaining.forEach((key, amount) -> { UUID uuid = uuidFromLegacyIndex((Integer) key); if (!getObject(uuid).isPresent()) { - BeautyQuests.logger.warning("Cannot migrate " + acc.getNameAndID() + " data for stage " + toString() + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot migrate " + acc.getNameAndID() + " data for stage " + toString() + " as there is no migrated data for object " + key); } newRemaining.put(uuid, amount); @@ -191,7 +191,7 @@ public boolean event(@NotNull PlayerAccount acc, @NotNull Player p, @UnknownNull if (barsEnabled) { BossBar bar = bars.get(p); if (bar == null) { - BeautyQuests.logger.warning(p.getName() + " does not have boss bar for stage " + toString() + ". This is a bug!"); + QuestsPlugin.getPlugin().getLoggerExpanded().warning(p.getName() + " does not have boss bar for stage " + toString() + ". This is a bug!"); }else bar.update(playerAmounts.values().stream().mapToInt(Integer::intValue).sum()); } @@ -210,8 +210,8 @@ public void start(@NotNull PlayerAccount acc) { } @Override - public void end(@NotNull PlayerAccount acc) { - super.end(acc); + public void ended(@NotNull PlayerAccount acc) { + super.ended(acc); if (acc.isCurrent()) removeBar(acc.getPlayer()); } @@ -238,7 +238,7 @@ public void leaves(@NotNull PlayerAccount acc, @NotNull Player p) { protected void createBar(@NotNull Player p, int amount) { if (barsEnabled) { if (bars.containsKey(p)) { // NOSONAR Map#computeIfAbsent cannot be used here as we should log the issue - BeautyQuests.logger.warning("Trying to create an already existing bossbar for player " + p.getName()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to create an already existing bossbar for player " + p.getName()); return; } bars.put(p, new BossBar(p, amount)); @@ -306,11 +306,11 @@ protected void deserialize(@NotNull ConfigurationSection section) { ConfigurationSection objectSection = objectsSection.getConfigurationSection(key); Object serialized = objectSection.get("object"); if (serialized instanceof ConfigurationSection) serialized = ((ConfigurationSection) serialized).getValues(false); - objects.add(CountableObject.create(uuid, deserialize(serialized), objectSection.getInt("amount"))); + objects.add(CountableObject.open(uuid, deserialize(serialized), objectSection.getInt("amount"))); } } - if (objects.isEmpty()) BeautyQuests.logger.warning("Stage with no content: " + toString()); + if (objects.isEmpty()) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Stage with no content: " + toString()); calculateSize(); } @@ -350,7 +350,7 @@ public void remove() { public void update(int amount) { if (amount >= 0 && amount <= cachedSize) { bar.setProgress((double) (cachedSize - amount) / (double) cachedSize); - }else BeautyQuests.logger.warning("Amount of objects superior to max objects in " + AbstractCountableStage.this.toString() + " for player " + p.getName() + ": " + amount + " > " + cachedSize); + }else QuestsPlugin.getPlugin().getLoggerExpanded().warning("Amount of objects superior to max objects in " + AbstractCountableStage.this.toString() + " for player " + p.getName() + ": " + amount + " > " + cachedSize); bar.setTitle(Lang.MobsProgression.format(branch.getQuest().getName(), cachedSize - amount, cachedSize)); bar.addPlayer(p); timer(); @@ -360,7 +360,7 @@ private void timer() { if (QuestsConfiguration.getProgressBarTimeout() <= 0) return; if (timer != null) timer.cancel(); timer = Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), () -> { - bar.removePlayer(p); + bar.removePlayer(player); timer = null; }, QuestsConfiguration.getProgressBarTimeout() * 20L); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java similarity index 82% rename from core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java rename to api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index ecddeb35..7667116a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -8,30 +8,29 @@ import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Supplier; +import javax.sound.sampled.Line; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.creation.stages.Line; +import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.MinecraftNames; -import fr.skytasul.quests.utils.Utils; @LocatableType (types = LocatedType.ENTITY) public abstract class AbstractEntityStage extends AbstractStage implements Locatable.MultipleLocatable { @@ -51,7 +50,7 @@ protected void event(@NotNull Player p, @NotNull EntityType type) { if (entity == null || type.equals(entity)) { Integer playerAmount = getPlayerAmount(acc); if (playerAmount == null) { - BeautyQuests.logger.warning(p.getName() + " does not have object datas for stage " + toString() + ". This is a bug!"); + QuestsPlugin.getPlugin().getLoggerExpanded().warning(p.getName() + " does not have object datas for stage " + toString() + ". This is a bug!"); }else if (playerAmount.intValue() <= 1) { finishStage(p); }else { @@ -107,7 +106,7 @@ public boolean canBeFetchedAsynchronously() { }) .filter(Objects::nonNull) .sorted(Comparator.comparing(Entry::getValue)) - .<Located>map(entry -> Located.LocatedEntity.create(entry.getKey())) + .<Located>map(entry -> Located.LocatedEntity.open(entry.getKey())) .spliterator(); } @@ -122,17 +121,17 @@ protected AbstractCreator(Line line, boolean ending) { line.setItem(6, ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, Lang.changeEntityType.toString()), (p, item) -> { new EntityTypeGUI(x -> { setEntity(x); - reopenGUI(p, true); - }, x -> x == null ? canBeAnyEntity() : canUseEntity(x)).create(p); + reopenGUI(player, true); + }, x -> x == null ? canBeAnyEntity() : canUseEntity(x)).open(player); }); line.setItem(7, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1)), (p, item) -> { - new TextEditor<>(p, () -> { - reopenGUI(p, false); + new TextEditor<>(player, () -> { + reopenGUI(player, false); }, x -> { setAmount(x); - reopenGUI(p, false); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + reopenGUI(player, false); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); }); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java rename to api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java index 78e88f2a..5aa6afad 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java @@ -6,20 +6,20 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; +import javax.sound.sampled.Line; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.ItemsGUI; -import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.types.CountableObject; public abstract class AbstractItemStage extends AbstractCountableStage<ItemStack> { @@ -86,14 +86,14 @@ protected Creator(Line line, boolean ending) { line.setItem(6, getEditItem().clone(), (p, item) -> { new ItemsGUI(items -> { setItems(items); - reopenGUI(p, true); - }, items).create(p); + reopenGUI(player, true); + }, items).open(player); }); line.setItem(7, stageComparison.clone(), (p, item) -> { new ItemComparisonGUI(comparisons, () -> { setComparisons(comparisons); - reopenGUI(p, true); - }).create(p); + reopenGUI(player, true); + }).open(player); }); } @@ -114,8 +114,8 @@ public void start(Player p) { super.start(p); new ItemsGUI(items -> { setItems(items); - reopenGUI(p, true); - }, Collections.emptyList()).create(p); + reopenGUI(player, true); + }, Collections.emptyList()).open(p); } @Override @@ -136,7 +136,7 @@ public final T finishStage(QuestBranch branch) { ItemStack item = items.get(i); int amount = item.getAmount(); item.setAmount(1); - itemsMap.add(CountableObject.create(new UUID(item.hashCode(), 2478), item, amount)); + itemsMap.add(CountableObject.open(new UUID(item.hashCode(), 2478), item, amount)); } return finishStage(branch, itemsMap, comparisons); } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java similarity index 73% rename from core/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java rename to api/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java index f115ad2c..d9efb592 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/Dialogable.java @@ -2,8 +2,8 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.utils.types.Dialog; -import fr.skytasul.quests.utils.types.DialogRunner; +import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; public interface Dialogable { @@ -17,7 +17,7 @@ public interface Dialogable { BQNPC getNPC(); default boolean hasDialog() { - return getNPC() != null && getDialog() != null && !getDialog().messages.isEmpty(); + return getNPC() != null && getDialog() != null && !getDialog().getMessages().isEmpty(); } } diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java similarity index 98% rename from core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java rename to api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java index 255f724e..33ddf0dd 100644 --- a/core/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java @@ -14,8 +14,8 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.stages.types.Locatable.MultipleLocatable; -import fr.skytasul.quests.utils.DebugUtils; /** * This interface indicates that an object can provide some locations on demand. @@ -368,7 +368,7 @@ static boolean hasLocatedTypes(@NotNull Class<? extends Locatable> clazz, @NotNu }while ((superclass = superclass.getSuperclass()) != null); if (!foundAnnotation) { - DebugUtils.logMessage("Class " + clazz.getName() + " does not have the @LocatableType annotation."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Class " + clazz.getName() + " does not have the @LocatableType annotation."); return true; } diff --git a/core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java similarity index 99% rename from core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java rename to api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java index cc4973ea..f8a9160d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/ChatUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils; +package fr.skytasul.quests.api.utils; import java.io.PrintStream; import java.util.ArrayList; @@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class ChatUtils { +public class ChatColorUtils { // For testing purposes public static void main(String[] args) { diff --git a/core/src/main/java/fr/skytasul/quests/utils/ComparisonMethod.java b/api/src/main/java/fr/skytasul/quests/api/utils/ComparisonMethod.java similarity index 87% rename from core/src/main/java/fr/skytasul/quests/utils/ComparisonMethod.java rename to api/src/main/java/fr/skytasul/quests/api/utils/ComparisonMethod.java index 7239a586..5882fbc2 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/ComparisonMethod.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/ComparisonMethod.java @@ -1,6 +1,7 @@ -package fr.skytasul.quests.utils; +package fr.skytasul.quests.api.utils; -import fr.skytasul.quests.editors.checkers.EnumParser; +import fr.skytasul.quests.api.editors.checkers.EnumParser; +import fr.skytasul.quests.api.localization.Lang; public enum ComparisonMethod { EQUALS('=', Lang.ComparisonEquals), diff --git a/core/src/main/java/fr/skytasul/quests/utils/CustomizedObjectTypeAdapter.java b/api/src/main/java/fr/skytasul/quests/api/utils/CustomizedObjectTypeAdapter.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/utils/CustomizedObjectTypeAdapter.java rename to api/src/main/java/fr/skytasul/quests/api/utils/CustomizedObjectTypeAdapter.java index 1001cd14..f9463a4d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/CustomizedObjectTypeAdapter.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/CustomizedObjectTypeAdapter.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils; +package fr.skytasul.quests.api.utils; import java.io.IOException; import java.util.ArrayList; diff --git a/core/src/main/java/fr/skytasul/quests/utils/LevenshteinComparator.java b/api/src/main/java/fr/skytasul/quests/api/utils/LevenshteinComparator.java similarity index 93% rename from core/src/main/java/fr/skytasul/quests/utils/LevenshteinComparator.java rename to api/src/main/java/fr/skytasul/quests/api/utils/LevenshteinComparator.java index 4ba91530..16ad207e 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/LevenshteinComparator.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/LevenshteinComparator.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils; +package fr.skytasul.quests.api.utils; import java.util.Comparator; import java.util.function.Function; diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java new file mode 100644 index 00000000..e75ce389 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java @@ -0,0 +1,120 @@ +package fr.skytasul.quests.api.utils; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.lang.StringUtils; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import net.md_5.bungee.api.ChatColor; + +public class MessageUtils { + + private MessageUtils() {} + + private static final Map<Integer, Pattern> REPLACEMENT_PATTERNS = new ConcurrentHashMap<>(); + private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); + + public static void sendPrefixedMessage(CommandSender sender, String msg, Object... replace) { + if (StringUtils.isEmpty(msg)) + return; + sendRawMessage(sender, QuestsPlugin.getPlugin().getPrefix() + msg, false, replace); + } + + public static void sendUnprefixedMessage(CommandSender sender, String msg, Object... replace) { + if (StringUtils.isEmpty(msg)) + return; + sendRawMessage(sender, "§6" + msg, false, replace); + } + + public static void sendRawMessage(CommandSender sender, String text, boolean playerName, Object... replace) { + sender.sendMessage(StringUtils.splitByWholeSeparator(finalFormat(sender, text, playerName, replace), "{nl}")); + } + + public static String finalFormat(CommandSender sender, String text, boolean playerName, Object... replace) { + if (DependenciesManager.papi.isEnabled() && sender instanceof Player) + text = QuestsPlaceholders.setPlaceholders((Player) sender, text); + if (playerName && sender != null) + text = text.replace("{PLAYER}", sender.getName()).replace("{PREFIX}", QuestsConfiguration.getPrefix()); + text = ChatColor.translateAlternateColorCodes('&', text); + return format(text, replace); + } + + public static void sendOffMessage(Player p, String msg, Object... replace) { + if (msg != null && !msg.isEmpty()) + sendRawMessage(p, Lang.OffText.format(msg, replace), true); + } + + public static String itemsToFormattedString(String[] items) { + return itemsToFormattedString(items, ""); + } + + public static String itemsToFormattedString(String[] items, String separator) { + if (items.length == 0) + return ""; + if (items.length == 1) + return items[0]; + if (items.length == 2) + return items[0] + " " + separator + Lang.And.toString() + " " + ChatColorUtils.getLastColors(null, items[0]) + + items[1]; + StringBuilder stb = new StringBuilder("§e" + items[0] + ", "); + for (int i = 1; i < items.length - 1; i++) { + stb.append(items[i] + ((i == items.length - 2) ? "" : ", ")); + } + stb.append(" " + Lang.And.toString() + " " + items[items.length - 1]); + return stb.toString(); + } + + public static @NotNull String format(@NotNull String msg, @NotNull Supplier<Object> @Nullable... replace) { + if (replace != null && replace.length != 0) { + for (int i = 0; i < replace.length; i++) { + Supplier<Object> supplier = replace[i]; + msg = format(msg, i, supplier); + } + } + return msg; + } + + public static @NotNull String format(@NotNull String msg, @Nullable Object @Nullable... replace) { + if (replace != null && replace.length != 0) { + for (int i = 0; i < replace.length; i++) { + Object replacement = replace[i]; + if (replacement instanceof Supplier) { + msg = format(msg, i, (Supplier<Object>) replacement); + } else { + msg = format(msg, i, () -> replacement); + } + } + } + return msg; + } + + public static String format(@NotNull String msg, int i, @NotNull Supplier<Object> replace) { + Pattern pattern = REPLACEMENT_PATTERNS.computeIfAbsent(i, __ -> Pattern.compile("\\{" + i + "\\}")); + Matcher matcher = pattern.matcher(msg); + StringBuilder output = new StringBuilder(msg.length()); + int lastAppend = 0; + String colors = ""; + String replacement = null; + while (matcher.find()) { + String substring = msg.substring(lastAppend, matcher.start()); + colors = ChatColorUtils.getLastColors(colors, substring); + output.append(substring); + if (replacement == null) + replacement = Objects.toString(replace.get()); + Matcher replMatcher = RESET_PATTERN.matcher(replacement); + output.append(replMatcher.replaceAll("§r" + colors)); + lastAppend = matcher.end(); + } + output.append(msg, lastAppend, msg.length()); + return output.toString(); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/utils/MinecraftNames.java b/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftNames.java similarity index 84% rename from core/src/main/java/fr/skytasul/quests/utils/MinecraftNames.java rename to api/src/main/java/fr/skytasul/quests/api/utils/MinecraftNames.java index 83d1f5d1..632de31a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/MinecraftNames.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftNames.java @@ -1,7 +1,8 @@ -package fr.skytasul.quests.utils; +package fr.skytasul.quests.api.utils; -import java.io.File; -import java.io.FileReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -17,8 +18,7 @@ import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XPotion; import com.google.gson.GsonBuilder; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.utils.nms.NMS; +import fr.skytasul.quests.api.QuestsPlugin; public class MinecraftNames { @@ -29,24 +29,16 @@ public class MinecraftNames { private static Map<EntityType, String> cachedEntities = new HashMap<>(); private static Map<XMaterial, String> cachedMaterials = new HashMap<>(); - public static boolean intialize(@NotNull String fileName) { + public static boolean intialize(@NotNull Path path) { try { - if (!fileName.contains(".")) fileName = fileName + ".json"; - File file = new File(BeautyQuests.getInstance().getDataFolder(), fileName); - if (!file.exists()) { - BeautyQuests.logger.warning("File " + fileName + " not found for loading translations."); + if (!Files.exists(path)) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("File " + path.getFileName() + " not found for translations."); return false; } - int lastPoint = file.getName().lastIndexOf('.'); - String extension = lastPoint == -1 ? "" : file.getName().substring(lastPoint + 1); - - if (!extension.equalsIgnoreCase("json")) { - BeautyQuests.logger.warning("File " + fileName + " is not a JSON file."); - return false; - } - map = new GsonBuilder().create().fromJson(new FileReader(file), new HashMap<String, Object>().getClass()); - BeautyQuests.logger.info("Loaded vanilla translation file for language: " + map.get("language.name") + ". Sorting values."); + map = new GsonBuilder().create().fromJson(Files.newBufferedReader(path, StandardCharsets.UTF_8), HashMap.class); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Loaded vanilla translation file for language: " + map.get("language.name") + ". Sorting values."); for (Entry<String, Object> en : map.entrySet()) { String key = en.getKey(); if (key.startsWith("entity.minecraft.")) { @@ -68,7 +60,7 @@ public static boolean intialize(@NotNull String fileName) { } } }catch (Exception e) { - BeautyQuests.logger.severe("Problem when loading Minecraft Translations.", e); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Problem when loading Minecraft Translations.", e); } return true; } @@ -88,7 +80,7 @@ public static boolean intialize(@NotNull String fileName) { public static @NotNull String getMaterialName(ItemStack item) { XMaterial type = XMaterial.matchXMaterial(item); - if (NMS.getMCVersion() > 8 + if (MinecraftVersion.MAJOR > 8 && (type == XMaterial.POTION || type == XMaterial.LINGERING_POTION || type == XMaterial.SPLASH_POTION)) { PotionMeta meta = (PotionMeta) item.getItemMeta(); try { diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftVersion.java b/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftVersion.java new file mode 100644 index 00000000..6c2b279c --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/MinecraftVersion.java @@ -0,0 +1,27 @@ +package fr.skytasul.quests.api.utils; + +import org.bukkit.Bukkit; + +public final class MinecraftVersion { + + public static final String VERSION_STRING; + public static final String VERSION_NMS; + public static final int MAJOR; + public static final int MINOR; + + static { + VERSION_STRING = Bukkit.getBukkitVersion().split("-R")[0]; + VERSION_NMS = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3].substring(1); + String[] versions = VERSION_NMS.split("_"); + MAJOR = Integer.parseInt(versions[1]); // 1.X + if (MAJOR >= 17) { + // e.g. Bukkit.getBukkitVersion() -> 1.17.1-R0.1-SNAPSHOT + versions = VERSION_STRING.split("\\."); + MINOR = versions.length <= 2 ? 0 : Integer.parseInt(versions[2]); + } else + MINOR = Integer.parseInt(versions[2].substring(1)); // 1.X.Y + } + + private MinecraftVersion() {} + +} diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Pair.java b/api/src/main/java/fr/skytasul/quests/api/utils/Pair.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/types/Pair.java rename to api/src/main/java/fr/skytasul/quests/api/utils/Pair.java index dc82702d..f6d15b00 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Pair.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/Pair.java @@ -1,65 +1,65 @@ -package fr.skytasul.quests.utils.types; - -import java.io.Serializable; - -public class Pair<K, V> implements Serializable { - private static final long serialVersionUID = -5836480055910467672L; - private K key; - private V value; - - public Pair(K key, V value) { - this.key = key; - this.value = value; - } - - public K getKey() { - return this.key; - } - - public V getValue() { - return this.value; - } - - public void setKey(K key) { - this.key = key; - } - - public void setValue(V value) { - this.value = value; - } - - public String toString() { - return this.key + "=" + this.value; - } - - public int hashCode() { - return this.key.hashCode() * 13 + (this.value == null ? 0 : this.value.hashCode()); - } - - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (!(obj instanceof Pair)) { - return false; - } else { - Pair<?, ?> pair = (Pair<?, ?>) obj; - if (this.key != null) { - if (!this.key.equals(pair.key)) { - return false; - } - } else if (pair.key != null) { - return false; - } - - if (this.value != null) { - if (!this.value.equals(pair.value)) { - return false; - } - } else if (pair.value != null) { - return false; - } - - return true; - } - } +package fr.skytasul.quests.api.utils; + +import java.io.Serializable; + +public class Pair<K, V> implements Serializable { + private static final long serialVersionUID = -5836480055910467672L; + private K key; + private V value; + + public Pair(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return this.key; + } + + public V getValue() { + return this.value; + } + + public void setKey(K key) { + this.key = key; + } + + public void setValue(V value) { + this.value = value; + } + + public String toString() { + return this.key + "=" + this.value; + } + + public int hashCode() { + return this.key.hashCode() * 13 + (this.value == null ? 0 : this.value.hashCode()); + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (!(obj instanceof Pair)) { + return false; + } else { + Pair<?, ?> pair = (Pair<?, ?>) obj; + if (this.key != null) { + if (!this.key.equals(pair.key)) { + return false; + } + } else if (pair.key != null) { + return false; + } + + if (this.value != null) { + if (!this.value.equals(pair.value)) { + return false; + } + } else if (pair.value != null) { + return false; + } + + return true; + } + } } \ No newline at end of file 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 new file mode 100644 index 00000000..e6d19514 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/PlayerListCategory.java @@ -0,0 +1,57 @@ +package fr.skytasul.quests.api.utils; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.localization.Lang; + +public enum PlayerListCategory { + + FINISHED( + 1, + XMaterial.WRITTEN_BOOK, + Lang.finisheds.toString()), + IN_PROGRESS( + 2, + XMaterial.BOOK, + Lang.inProgress.toString()), + NOT_STARTED( + 3, + XMaterial.WRITABLE_BOOK, + Lang.notStarteds.toString()); + + private final int slot; + private final @NotNull XMaterial material; + private final @NotNull String name; + + private PlayerListCategory(int slot, @NotNull XMaterial material, @NotNull String name) { + this.slot = slot; + this.material = material; + this.name = name; + } + + public int getSlot() { + return slot; + } + + public @NotNull XMaterial getMaterial() { + return material; + } + + public @NotNull String getName() { + return name; + } + + public boolean isEnabled() { + return QuestsConfiguration.getMenuConfig().getEnabledTabs().contains(this); + } + + public static @Nullable PlayerListCategory fromString(@NotNull String name) { + try { + return PlayerListCategory.valueOf(name.toUpperCase()); + }catch (IllegalArgumentException ex) {} + return null; + } + +} \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/QuestVisibilityLocation.java b/api/src/main/java/fr/skytasul/quests/api/utils/QuestVisibilityLocation.java new file mode 100644 index 00000000..5ebfb274 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/QuestVisibilityLocation.java @@ -0,0 +1,23 @@ +package fr.skytasul.quests.api.utils; + +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.localization.Lang; + +public enum QuestVisibilityLocation { + + TAB_NOT_STARTED(Lang.visibility_notStarted.toString()), + TAB_IN_PROGRESS(Lang.visibility_inProgress.toString()), + TAB_FINISHED(Lang.visibility_finished.toString()), + MAPS(Lang.visibility_maps.toString()); + + private final @NotNull String name; + + private QuestVisibilityLocation(@NotNull String name) { + this.name = name; + } + + public @NotNull String getName() { + return name; + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/utils/Utils.java b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java similarity index 59% rename from core/src/main/java/fr/skytasul/quests/utils/Utils.java rename to api/src/main/java/fr/skytasul/quests/api/utils/Utils.java index 0b79209b..4e73b1f7 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Utils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils; +package fr.skytasul.quests.api.utils; import java.io.IOException; import java.net.URI; @@ -17,47 +17,29 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Optional; -import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Stream; -import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Sound; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemoryConfiguration; import org.bukkit.entity.EntityType; -import org.bukkit.entity.Firework; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.scoreboard.DisplaySlot; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.rewards.InterruptingBranchException; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.compatibility.DependenciesManager; -import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.utils.nms.NMS; -import net.md_5.bungee.api.ChatColor; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -83,66 +65,6 @@ public static void openBook(Player p, ItemStack book){ NMS.getNMS().sendPacket(p, NMS.getNMS().bookPacket(buf)); p.getInventory().setItem(slot, old); } - - - public static void spawnFirework(Location lc, FireworkMeta meta) { - if (!QuestsConfiguration.doFireworks() || meta == null) return; - runOrSync(() -> { - Consumer<Firework> fwConsumer = fw -> { - fw.setMetadata("questFinish", new FixedMetadataValue(BeautyQuests.getInstance(), true)); - fw.setFireworkMeta(meta); - }; - if (NMS.getMCVersion() >= 12) { - 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 - // before it is sent to the players, as it will not create flickering - }else { - fwConsumer.accept(lc.getWorld().spawn(lc, Firework.class)); - } - }); - } - - public static List<String> giveRewards(Player p, List<AbstractReward> rewards) throws InterruptingBranchException { - InterruptingBranchException interrupting = null; - - List<String> msg = new ArrayList<>(); - for (AbstractReward rew : rewards) { - try { - List<String> messages = rew.give(p); - if (messages != null) msg.addAll(messages); - } catch (InterruptingBranchException ex) { - if (interrupting != null) { - BeautyQuests.logger.warning("Interrupting the same branch via rewards twice!"); - } else { - interrupting = ex; - } - } catch (Throwable e) { - BeautyQuests.logger.severe("Error when giving reward " + rew.getName() + " to " + p.getName(), e); - } - } - - if (interrupting != null) - throw interrupting; - return msg; - } - - public static boolean testRequirements(Player p, List<AbstractRequirement> requirements, boolean message) { - for (AbstractRequirement requirement : requirements) { - try { - if (!requirement.test(p)) { - if (message && !requirement.sendReason(p)) - continue; // means a reason has not yet been sent - return false; - } - } catch (Exception ex) { - BeautyQuests.logger.severe( - "Cannot test requirement " + requirement.getClass().getSimpleName() + " for player " + p.getName(), - ex); - return false; - } - } - return true; - } public static String ticksToElapsedTime(int ticks) { int i = ticks / 20; @@ -194,49 +116,6 @@ public static String getStringFromNameAndAmount(String name, String amountColor, } return string; } - - public static void sendMessage(CommandSender sender, String msg, Object... replace){ - if (StringUtils.isEmpty(msg)) return; - IsendMessage(sender, QuestsConfiguration.getPrefix() + msg, false, replace); - } - - public static void sendMessageWP(CommandSender sender, String msg, Object... replace){ - if (StringUtils.isEmpty(msg)) return; - IsendMessage(sender, "§6" + msg, false, replace); - } - - public static String finalFormat(CommandSender sender, String text, boolean playerName, Object... replace) { - if (DependenciesManager.papi.isEnabled() && sender instanceof Player) - text = QuestsPlaceholders.setPlaceholders((Player) sender, text); - if (playerName && sender != null) - text = text.replace("{PLAYER}", sender.getName()).replace("{PREFIX}", QuestsConfiguration.getPrefix()); - text = ChatColor.translateAlternateColorCodes('&', text); - return format(text, replace); - } - - public static void IsendMessage(CommandSender sender, String text, boolean playerName, Object... replace) { - sender.sendMessage(StringUtils.splitByWholeSeparator(finalFormat(sender, text, playerName, replace), "{nl}")); - } - - public static void sendOffMessage(Player p, String msg, Object... replace) { - if (msg != null && !msg.isEmpty()) IsendMessage(p, Lang.OffText.format(msg, replace), true); - } - - public static String itemsToFormattedString(String[] items){ - return itemsToFormattedString(items, ""); - } - - public static String itemsToFormattedString(String[] items, String separator){ - if (items.length == 0) return ""; - if (items.length == 1) return items[0]; - if (items.length == 2) return items[0] + " " + separator + Lang.And.toString() + " " + ChatUtils.getLastColors(null, items[0]) + items[1]; - StringBuilder stb = new StringBuilder("§e" + items[0] + ", "); - for (int i = 1; i < items.length - 1; i++){ - stb.append(items[i] + ((i == items.length - 2) ? "" : ", ")); - } - stb.append(" " + Lang.And.toString() + " " + items[items.length - 1]); - return stb.toString(); - } public static String locationToString(Location lc){ if (lc == null) return null; @@ -268,7 +147,7 @@ public static boolean isSimilar(ItemStack item1, ItemStack item2) { try { return NMS.getNMS().equalsWithoutNBT(item1.getItemMeta(), item2.getItemMeta()); }catch (ReflectiveOperationException ex) { - BeautyQuests.logger.severe("An error occurred while attempting to compare items using NMS", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while attempting to compare items using NMS", ex); } } return false; @@ -303,53 +182,6 @@ public static <T, E> List<T> getKeysByValue(Map<T, E> map, E value) { return list; } - public static @NotNull String format(@NotNull String msg, @NotNull Supplier<Object> @Nullable... replace) { - if (replace != null && replace.length != 0) { - for (int i = 0; i < replace.length; i++) { - Supplier<Object> supplier = replace[i]; - msg = format(msg, i, supplier); - } - } - return msg; - } - - public static @NotNull String format(@NotNull String msg, @Nullable Object @Nullable... replace) { - if (replace != null && replace.length != 0){ - for (int i = 0; i < replace.length; i++){ - Object replacement = replace[i]; - if (replacement instanceof Supplier) { - msg = format(msg, i, (Supplier<Object>) replacement); - }else { - msg = format(msg, i, () -> replacement); - } - } - } - return msg; - } - - private static final Map<Integer, Pattern> REPLACEMENT_PATTERNS = new HashMap<>(); - private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); - - public static String format(@NotNull String msg, int i, @NotNull Supplier<Object> replace) { - Pattern pattern = REPLACEMENT_PATTERNS.computeIfAbsent(i, __ -> Pattern.compile("\\{" + i + "\\}")); - Matcher matcher = pattern.matcher(msg); - StringBuilder output = new StringBuilder(msg.length()); - int lastAppend = 0; - String colors = ""; - String replacement = null; - while (matcher.find()) { - String substring = msg.substring(lastAppend, matcher.start()); - colors = ChatUtils.getLastColors(colors, substring); - output.append(substring); - if (replacement == null) replacement = Objects.toString(replace.get()); - Matcher replMatcher = RESET_PATTERN.matcher(replacement); - output.append(replMatcher.replaceAll("§r" + colors)); - lastAppend = matcher.end(); - } - output.append(msg, lastAppend, msg.length()); - return output.toString(); - } - public static String buildFromArray(Object[] array, int start, String insert){ if (array == null || array.length == 0) return ""; StringBuilder stb = new StringBuilder(); @@ -406,24 +238,6 @@ public static void walkResources(Class<?> clazz, String path, int depth, Consume } } - public static void runOrSync(Runnable run) { - if (Bukkit.isPrimaryThread()) { - run.run(); - }else Bukkit.getScheduler().runTask(BeautyQuests.getInstance(), run); - } - - public static <T> BiConsumer<T, Throwable> runSyncConsumer(Runnable run) { - return (__, ___) -> runSync(run); - } - - public static void runSync(Runnable run){ - Bukkit.getScheduler().runTask(BeautyQuests.getInstance(), run); - } - - public static void runAsync(Runnable run){ - Bukkit.getScheduler().runTaskAsynchronously(BeautyQuests.getInstance(), run); - } - public static <T> List<Map<String, Object>> serializeList(Collection<T> objects, Function<T, Map<String, Object>> serialize) { List<Map<String, Object>> ls = new ArrayList<>(); for (T obj : objects){ @@ -508,29 +322,6 @@ public static DateFormat getDateFormat(){ return cachedFormat; } - public static void playPluginSound(Player p, String sound, float volume){ - playPluginSound(p, sound, volume, 1); - } - - public static void playPluginSound(Player p, String sound, float volume, float pitch) { - if (!QuestsConfiguration.playSounds()) return; - if ("none".equals(sound)) return; - try { - p.playSound(p.getLocation(), Sound.valueOf(sound), volume, pitch); - }catch (Exception ex) { - if (NMS.getMCVersion() > 8) p.playSound(p.getLocation(), sound, volume, pitch); - } - } - - public static void playPluginSound(Location lc, String sound, float volume){ - if (!QuestsConfiguration.playSounds()) return; - try { - lc.getWorld().playSound(lc, Sound.valueOf(sound), volume, 1); - }catch (Exception ex) { - if (NMS.getMCVersion() > 8) lc.getWorld().playSound(lc, sound, volume, 1); - } - } - public static String convertLocationToString(Location loc) { String world = loc.getWorld().getName(); double x = loc.getX(); @@ -561,14 +352,6 @@ public static Location convertStringToLocation(String loc) { return null; } - public static String descriptionLines(Source source, String... elements){ - if (elements.length == 0) return Lang.Unknown.toString(); - if (QuestsConfiguration.splitDescription(source) && (!QuestsConfiguration.inlineAlone() || elements.length > 1)) { - return QuestsConfiguration.getDescriptionItemPrefix() + buildFromArray(elements, 0, QuestsConfiguration.getDescriptionItemPrefix()); - } - return itemsToFormattedString(elements, QuestsConfiguration.getItemAmountColor()); - } - public static boolean isQuestItem(ItemStack item) { if (item == null) return false; String lore = Lang.QuestItemLore.toString(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/logger/ILoggerHandler.java b/api/src/main/java/fr/skytasul/quests/api/utils/logger/ILoggerHandler.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/logger/ILoggerHandler.java rename to api/src/main/java/fr/skytasul/quests/api/utils/logger/ILoggerHandler.java index 25889652..44ef7c50 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/logger/ILoggerHandler.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/logger/ILoggerHandler.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.logger; +package fr.skytasul.quests.api.utils.logger; import java.util.logging.Handler; diff --git a/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerExpanded.java b/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/utils/logger/LoggerExpanded.java rename to api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java index 51c39d46..c30c14f9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerExpanded.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.logger; +package fr.skytasul.quests.api.utils.logger; import java.util.concurrent.CompletionException; import java.util.function.BiConsumer; @@ -8,14 +8,20 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; public class LoggerExpanded { private final @NotNull Logger logger; + private final @NotNull ILoggerHandler handler; - public LoggerExpanded(@NotNull Logger logger) { + public LoggerExpanded(@NotNull Logger logger, @Nullable ILoggerHandler handler) { this.logger = logger; + this.handler = handler == null ? ILoggerHandler.EMPTY_LOGGER : handler; + } + + public @NotNull ILoggerHandler getHandler() { + return handler; } public void info(@Nullable String msg) { @@ -38,6 +44,10 @@ public void severe(@Nullable String msg, @Nullable Throwable throwable) { logger.log(Level.SEVERE, msg, throwable); } + public void debug(@Nullable String msg) { + handler.write(msg, "DEBUG"); + } + public <T> BiConsumer<T, Throwable> logError(@Nullable Consumer<T> consumer, @Nullable String friendlyErrorMessage, @Nullable CommandSender sender) { return (object, ex) -> { diff --git a/core/pom.xml b/core/pom.xml index a99e8825..129cb8e1 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -47,29 +47,11 @@ <pattern>com.jeff_media.updatechecker</pattern> <shadedPattern>fr.skytasul.quests.utils.updatechecker</shadedPattern> </relocation> - <relocation> - <pattern>revxrsal.commands</pattern> - <shadedPattern>fr.skytasul.quests.commands.revxrsal</shadedPattern> - </relocation> <relocation> <pattern>com.zaxxer.hikari</pattern> <shadedPattern>fr.skytasul.quests.utils.hikari</shadedPattern> </relocation> - <relocation> - <pattern>com.cryptomorin.xseries</pattern> - <shadedPattern>fr.skytasul.quests.utils</shadedPattern> - </relocation> </relocations> - <filters> - <filter> - <artifact>com.github.cryptomorin:XSeries</artifact> - <includes> - <include>com/cryptomorin/xseries/XMaterial*</include> - <include>com/cryptomorin/xseries/XBlock*</include> - <include>com/cryptomorin/xseries/XPotion*</include> - </includes> - </filter> - </filters> </configuration> <executions> <execution> @@ -165,12 +147,25 @@ </repositories> <dependencies> + <dependency> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.jetbrains</groupId> <artifactId>annotations</artifactId> <version>24.0.0</version> <scope>provided</scope> </dependency> + + <dependency> + <groupId>com.zaxxer</groupId> + <artifactId>HikariCP</artifactId> + <version>4.0.3</version> <!-- For Java 8 compatibility --> + </dependency> <dependency> <groupId>io.papermc.paper</groupId> @@ -178,6 +173,7 @@ <version>1.19.4-R0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> + <dependency> <groupId>net.citizensnpcs</groupId> <artifactId>citizens-main</artifactId> @@ -322,26 +318,6 @@ <version>3.2.5</version> <scope>provided</scope> </dependency> - <dependency> - <groupId>com.github.Revxrsal.Lamp</groupId> - <artifactId>bukkit</artifactId> - <version>3.1.1</version> - </dependency> - <dependency> - <groupId>com.github.Revxrsal.Lamp</groupId> - <artifactId>common</artifactId> - <version>3.1.1</version> - </dependency> - <dependency> - <groupId>com.zaxxer</groupId> - <artifactId>HikariCP</artifactId> - <version>4.0.3</version> <!-- For Java 8 compatibility --> - </dependency> - <dependency> - <groupId>com.github.cryptomorin</groupId> - <artifactId>XSeries</artifactId> - <version>9.3.1</version> - </dependency> <!-- Local JARs --> <dependency> diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 37bec606..7e518306 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -2,6 +2,7 @@ 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; @@ -33,38 +34,36 @@ import com.jeff_media.updatechecker.UpdateCheckSource; import com.jeff_media.updatechecker.UpdateChecker; import com.tchristofferson.configupdater.ConfigUpdater; -import fr.skytasul.quests.api.Locale; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.bossbar.BQBossBarImplementation; -import fr.skytasul.quests.commands.CommandsManager; -import fr.skytasul.quests.editors.Editor; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.gui.creation.QuestObjectGUI; -import fr.skytasul.quests.gui.creation.stages.StagesGUI; -import fr.skytasul.quests.gui.misc.ItemComparisonGUI; +import fr.skytasul.quests.api.QuestsAPIProvider; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.EditorManager; +import fr.skytasul.quests.api.gui.GuiManager; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.localization.Locale; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.logger.LoggerExpanded; +import fr.skytasul.quests.commands.CommandsManagerImplementation; +import fr.skytasul.quests.editor.EditorManagerImplementation; +import fr.skytasul.quests.gui.GuiManagerImplementation; import fr.skytasul.quests.options.OptionAutoQuest; -import fr.skytasul.quests.players.PlayersManager; +import fr.skytasul.quests.players.AbstractPlayersManager; import fr.skytasul.quests.players.PlayersManagerDB; import fr.skytasul.quests.players.PlayersManagerYAML; import fr.skytasul.quests.scoreboards.ScoreboardManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestsManager; -import fr.skytasul.quests.structure.pools.QuestPoolsManager; +import fr.skytasul.quests.structure.QuestImplementation; +import fr.skytasul.quests.structure.QuestsManagerImplementation; +import fr.skytasul.quests.structure.pools.QuestPoolsManagerImplementation; import fr.skytasul.quests.utils.Database; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.utils.compatibility.BQBossBarImplementation; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.compatibility.Post1_16; import fr.skytasul.quests.utils.compatibility.mobs.BukkitEntityFactory; -import fr.skytasul.quests.utils.logger.ILoggerHandler; -import fr.skytasul.quests.utils.logger.LoggerExpanded; import fr.skytasul.quests.utils.logger.LoggerHandler; import fr.skytasul.quests.utils.nms.NMS; -public class BeautyQuests extends JavaPlugin { +public class BeautyQuests extends JavaPlugin implements QuestsPlugin { - public static LoggerExpanded logger; private static BeautyQuests instance; private BukkitRunnable saveTask; private boolean isPaper; @@ -86,29 +85,32 @@ public class BeautyQuests extends JavaPlugin { /* --------- Datas --------- */ - private ScoreboardManager scoreboards; - private QuestsManager quests; - private QuestPoolsManager pools; - private PlayersManager players; + private @Nullable ScoreboardManager scoreboards; + private @Nullable QuestsManagerImplementation quests; + private @Nullable QuestPoolsManagerImplementation pools; + private @Nullable AbstractPlayersManager players; /* ---------- Operations -------- */ - private static boolean disable = false; - public static boolean loadingFailure = false; - public static boolean savingFailure = false; - public static boolean loaded = false; - - public DependenciesManager dependencies = new DependenciesManager(); - private CommandsManager command; - - private LoggerHandler loggerHandler; + private boolean disable = false; + protected boolean loadingFailure = false; + protected boolean savingFailure = false; + protected boolean loaded = false; + + private @NotNull DependenciesManager dependencies = new DependenciesManager(); + private @Nullable CommandsManagerImplementation command; + private @Nullable LoggerExpanded logger; + private @Nullable LoggerHandler loggerHandler; + private @Nullable GuiManagerImplementation guiManager; + private @Nullable EditorManagerImplementation editorManager; /* ---------------------------------------------- */ @Override public void onLoad(){ instance = this; - logger = new LoggerExpanded(getLogger()); + + loggerHandler = null; try{ if (!getDataFolder().exists()) getDataFolder().mkdir(); loggerHandler = new LoggerHandler(this); @@ -116,10 +118,24 @@ public void onLoad(){ }catch (Throwable ex){ getLogger().log(Level.SEVERE, "Failed to insert logging handler.", ex); } + + logger = new LoggerExpanded(getLogger(), loggerHandler); + + try { + initApi(); + } catch (Exception ex) { + logger.severe("An unexpected exception occurred while initializing the API.", ex); + logger.severe("This is a fatal error. Now disabling."); + disable = true; + setEnabled(false); + } } @Override public void onEnable(){ + if (disable) + return; + try { logger.info("------------ BeautyQuests ------------"); @@ -129,7 +145,7 @@ public void onEnable(){ Bukkit.getPluginManager().registerEvents(dependencies, this); saveDefaultConfig(); - NMS.getMCVersion(); + NMS.isValid(); // to force initialization saveFolder = new File(getDataFolder(), "quests"); if (!saveFolder.exists()) saveFolder.mkdirs(); @@ -144,7 +160,7 @@ public void onEnable(){ logger.severe("An error occurred while initializing compatibilities. Consider restarting.", ex); } - if (QuestsAPI.getNPCsManager() == null) { + if (getAPI().getNPCsManager() == null) { throw new LoadingException("No NPC plugin installed - please install Citizens or znpcs"); } @@ -160,17 +176,14 @@ public void run() { + (((double) System.currentTimeMillis() - lastMillis) / 1000D) + "s)!"); getServer().getPluginManager().registerEvents(new QuestsListener(), BeautyQuests.this); - if (NMS.getMCVersion() >= 16) + if (MinecraftVersion.MAJOR >= 16) getServer().getPluginManager().registerEvents(new Post1_16(), BeautyQuests.this); launchSaveCycle(); if (!lastVersion.equals(pluginVersion)) { // maybe change in data structure : update of all quest files - DebugUtils.logMessage("Migrating from " + lastVersion + " to " + pluginVersion); - int updated = 0; - for (Quest qu : quests) { - if (qu.saveToFile()) updated++; - } + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Migrating from " + lastVersion + " to " + pluginVersion); + int updated = quests.updateAll(); if (updated > 0) logger.info("Updated " + updated + " quests during migration."); saveAllConfig(false); } @@ -178,7 +191,7 @@ public void run() { logger.severe("An error occurred while loading plugin datas.", e); } } - }.runTaskLater(this, QuestsAPI.getNPCsManager().getTimeToWaitForNPCs()); + }.runTaskLater(this, getAPI().getNPCsManager().getTimeToWaitForNPCs()); // Start of non-essential systems if (loggerHandler != null) loggerHandler.launchFlushTimer(); @@ -212,8 +225,8 @@ public void onDisable(){ } try { - Editor.leaveAll(); - Inventories.closeAll(); + editorManager.leaveAll(); + guiManager.closeAll(); stopSaveCycle(); }catch (Throwable ex) { logger.severe("An error occurred while disabling editing systems.", ex); @@ -238,10 +251,16 @@ public void onDisable(){ /* ---------- Various init ---------- */ + private void initApi() throws ReflectiveOperationException { + Method setMethod = QuestsAPIProvider.class.getDeclaredMethod("setAPI", QuestsAPI.class); + setMethod.setAccessible(true); // NOSONAR + setMethod.invoke(null, QuestsAPIImplementation.INSTANCE); + } + private void checkPaper() { try { isPaper = Class.forName("com.destroystokyo.paper.ParticleBuilder") != null; - DebugUtils.logMessage("Paper detected."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Paper detected."); }catch (ClassNotFoundException ex) { isPaper = false; logger.warning("You are not running the Paper software.\n" @@ -250,7 +269,7 @@ private void checkPaper() { } private void registerCommands(){ - command = new CommandsManager(); + command = new CommandsManagerImplementation(); command.initializeCommands(); command.lockCommands(); // we are obligated to register Brigadier during plugin initialization... } @@ -316,11 +335,11 @@ private void launchMetrics(String pluginVersion) { .distinct() .collect(Collectors.toMap(Function.identity(), __ -> 1)); })); - DebugUtils.logMessage("Started bStats metrics"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Started bStats metrics"); } private void launchUpdateChecker(String pluginVersion) { - DebugUtils.logMessage("Starting Spigot updater"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Starting Spigot updater"); UpdateChecker checker; if (pluginVersion.contains("_")) { Matcher matcher = Pattern.compile("_BUILD(\\d+)").matcher(pluginVersion); @@ -374,16 +393,24 @@ private void loadConfigParameters(boolean init) throws LoadingException { } players = db == null ? new PlayersManagerYAML() : new PlayersManagerDB(db); - PlayersManager.manager = players; /* static initialization */ if (init) { - StagesGUI.initialize(); // initializing default stage types - QuestObjectGUI.initialize(); // initializing default rewards and requirements - FinishGUI.initialize(); // initializing default quest options - ItemComparisonGUI.initialize(); - QuestsAPI.registerMobFactory(new BukkitEntityFactory()); - if (NMS.getMCVersion() >= 9) QuestsAPI.setBossBarManager(new BQBossBarImplementation()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default stage types."); + DefaultQuestFeatures.registerStages(); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default quest options."); + DefaultQuestFeatures.registerQuestOptions(); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default item comparisons."); + DefaultQuestFeatures.registerItemComparisons(); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default rewards."); + DefaultQuestFeatures.registerRewards(); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default requirements."); + DefaultQuestFeatures.registerRequirements(); + getServer().getPluginManager().registerEvents(guiManager = new GuiManagerImplementation(), this); + getServer().getPluginManager().registerEvents(editorManager = new EditorManagerImplementation(), this); + getAPI().registerMobFactory(new BukkitEntityFactory()); + if (MinecraftVersion.MAJOR >= 9) + getAPI().setBossBarManager(new BQBossBarImplementation()); } }catch (LoadingException ex) { throw ex; @@ -411,7 +438,7 @@ private void loadDataFile() throws LoadingException { throw new LoadingException("Couldn't create data file.", e); } } - DebugUtils.logMessage("Loading data file, last time edited : " + new Date(dataFile.lastModified()).toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Loading data file, last time edited : " + new Date(dataFile.lastModified()).toString()); data = YamlConfiguration.loadConfiguration(dataFile); if (data.contains("version")){ @@ -436,7 +463,7 @@ private void loadAllDatas() throws Throwable { File scFile = new File(getDataFolder(), "scoreboard.yml"); if (!scFile.exists()) saveResource("scoreboard.yml", true); scoreboards = new ScoreboardManager(scFile); - QuestsAPI.registerQuestsHandler(scoreboards); + getAPI().registerQuestsHandler(scoreboards); } try{ @@ -449,20 +476,20 @@ private void loadAllDatas() throws Throwable { logger.severe("Error while loading player datas.", ex); } - QuestsAPI.getQuestsHandlers().forEach(handler -> { + getAPI().getQuestsHandlers().forEach(handler -> { try { handler.load(); }catch (Exception ex) { - ex.printStackTrace(); + logger.severe("Cannot load quest handler " + handler.getClass().getName(), ex); } }); - pools = new QuestPoolsManager(new File(getDataFolder(), "questPools.yml")); - quests = new QuestsManager(this, data.getInt("lastID"), saveFolder); + pools = new QuestPoolsManagerImplementation(new File(getDataFolder(), "questPools.yml")); + quests = new QuestsManagerImplementation(this, data.getInt("lastID"), saveFolder); if (QuestsConfiguration.firstQuestID != -1) { logger.warning("The config option \"firstQuest\" is present in your config.yml but is now unsupported. Please remove it."); - Quest quest = quests.getQuest(QuestsConfiguration.firstQuestID); + QuestImplementation quest = quests.getQuest(QuestsConfiguration.firstQuestID); if (quest != null) { if (quest.hasOption(OptionAutoQuest.class)) { OptionAutoQuest option = quest.getOption(OptionAutoQuest.class); @@ -491,11 +518,11 @@ public void saveAllConfig(boolean unload) throws Exception { if (unload) { if (quests != null) quests.unloadQuests(); - QuestsAPI.getQuestsHandlers().forEach(handler -> { + getAPI().getQuestsHandlers().forEach(handler -> { try { handler.unload(); }catch (Exception ex) { - ex.printStackTrace(); + logger.severe("Cannot unload quest handler " + handler.getClass().getName(), ex); } }); } @@ -511,11 +538,11 @@ public void saveAllConfig(boolean unload) throws Exception { logger.severe("Error when saving player datas.", ex); } data.save(dataFile); - DebugUtils.logMessage("Saved datas (" + (((double) System.currentTimeMillis() - time) / 1000D) + "s)!"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Saved datas (" + (((double) System.currentTimeMillis() - time) / 1000D) + "s)!"); } if (unload){ - QuestsAPI.getNPCsManager().unload(); + getAPI().getNPCsManager().unload(); resetDatas(); } } @@ -529,7 +556,6 @@ private void resetDatas(){ logger.severe("An error occurred while closing database connection.", ex); } players = null; - PlayersManager.manager = null; //HandlerList.unregisterAll(this); loaded = false; } @@ -652,7 +678,7 @@ public void run() { try { data = YamlConfiguration.loadConfiguration(dataFile); loadAllDatas(); - sender.sendMessage("§a " + quests.getQuestsAmount() + " quests loaded"); + sender.sendMessage("§a " + quests.getQuests().size() + " quests loaded"); sender.sendMessage("§a§lPlugin entierely reloaded from files !"); } catch (Throwable e) { sender.sendMessage("§cError when loading the data file. §lOperation failed!"); @@ -662,10 +688,54 @@ public void run() { }.runTaskLater(BeautyQuests.getInstance(), 20L); } - public @NotNull CommandsManager getCommand() { - return command; + @Override + public void notifyLoadingFailure() { + loadingFailure = true; + } + + public void resetLoadingFailure() { + loadingFailure = false; + } + + public boolean hasLoadingFailed() { + return loadingFailure; + } + + @Override + public void noticeSavingFailure() { + savingFailure = true; + } + + public void resetSavingFailure() { + savingFailure = false; + } + + public boolean hasSavingFailed() { + return savingFailure; + } + + private <T> @NotNull T ensureLoaded(@Nullable T object) { + if (object == null) + throw new IllegalStateException("BeautyQuests is not yet initialized"); + return object; + } + + @Override + public @NotNull LoggerExpanded getLoggerExpanded() { + return ensureLoaded(logger); + } + + @Override + public @NotNull String getPrefix() { + return QuestsConfiguration.getPrefix(); + } + + @Override + public @NotNull CommandsManagerImplementation getCommand() { + return ensureLoaded(command); } + @Override public @NotNull QuestsConfiguration getConfiguration() { return config; } @@ -682,20 +752,32 @@ public void run() { return scoreboards; } - public @NotNull QuestsManager getQuestsManager() { - return quests; + public @NotNull QuestsManagerImplementation getQuestsManager() { + return ensureLoaded(quests); } - public @NotNull QuestPoolsManager getPoolsManager() { - return pools; + public @NotNull QuestPoolsManagerImplementation getPoolsManager() { + return ensureLoaded(pools); } - public @NotNull PlayersManager getPlayersManager() { - return players; + @Override + public @NotNull GuiManager getGuiManager() { + return ensureLoaded(guiManager); } - public @NotNull ILoggerHandler getLoggerHandler() { - return loggerHandler == null ? ILoggerHandler.EMPTY_LOGGER : loggerHandler; + @Override + public @NotNull EditorManager getEditorManager() { + return ensureLoaded(editorManager); + } + + @Override + public @NotNull QuestsAPI getAPI() { + return QuestsAPIImplementation.INSTANCE; + } + + @Override + public @NotNull AbstractPlayersManager getPlayersManager() { + return ensureLoaded(players); } public boolean isRunningPaper() { diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java new file mode 100644 index 00000000..5b9e1dc5 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -0,0 +1,259 @@ +package fr.skytasul.quests; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Objects; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.Repairable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.comparison.ItemComparison; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.objects.QuestObjectLocation; +import fr.skytasul.quests.api.options.QuestOptionCreator; +import fr.skytasul.quests.api.requirements.RequirementCreator; +import fr.skytasul.quests.api.rewards.RewardCreator; +import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.options.*; +import fr.skytasul.quests.requirements.EquipmentRequirement; +import fr.skytasul.quests.requirements.LevelRequirement; +import fr.skytasul.quests.requirements.PermissionsRequirement; +import fr.skytasul.quests.requirements.QuestRequirement; +import fr.skytasul.quests.requirements.ScoreboardRequirement; +import fr.skytasul.quests.requirements.logical.LogicalOrRequirement; +import fr.skytasul.quests.rewards.*; +import fr.skytasul.quests.stages.*; + +public final class DefaultQuestFeatures { + + private DefaultQuestFeatures() {} + + private static final ItemStack stageNPC = ItemUtils.item(XMaterial.OAK_SIGN, Lang.stageNPC.toString()); + private static final ItemStack stageItems = ItemUtils.item(XMaterial.CHEST, Lang.stageBring.toString()); + private static final ItemStack stageMobs = ItemUtils.item(XMaterial.WOODEN_SWORD, Lang.stageMobs.toString()); + private static final ItemStack stageMine = ItemUtils.item(XMaterial.WOODEN_PICKAXE, Lang.stageMine.toString()); + private static final ItemStack stagePlace = ItemUtils.item(XMaterial.OAK_STAIRS, Lang.stagePlace.toString()); + private static final ItemStack stageChat = ItemUtils.item(XMaterial.PLAYER_HEAD, Lang.stageChat.toString()); + private static final ItemStack stageInteract = ItemUtils.item(XMaterial.STICK, Lang.stageInteract.toString()); + private static final ItemStack stageFish = ItemUtils.item(XMaterial.COD, Lang.stageFish.toString()); + private static final ItemStack stageMelt = ItemUtils.item(XMaterial.FURNACE, Lang.stageMelt.toString()); + private static final ItemStack stageEnchant = ItemUtils.item(XMaterial.ENCHANTING_TABLE, Lang.stageEnchant.toString()); + private static final ItemStack stageCraft = ItemUtils.item(XMaterial.CRAFTING_TABLE, Lang.stageCraft.toString()); + private static final ItemStack stageBucket = ItemUtils.item(XMaterial.BUCKET, Lang.stageBucket.toString()); + private static final ItemStack stageLocation = ItemUtils.item(XMaterial.MINECART, Lang.stageLocation.toString()); + private static final ItemStack stagePlayTime = ItemUtils.item(XMaterial.CLOCK, Lang.stagePlayTime.toString()); + private static final ItemStack stageBreed = ItemUtils.item(XMaterial.WHEAT, Lang.stageBreedAnimals.toString()); + private static final ItemStack stageTame = ItemUtils.item(XMaterial.CARROT, Lang.stageTameAnimals.toString()); + private static final ItemStack stageDeath = ItemUtils.item(XMaterial.SKELETON_SKULL, Lang.stageDeath.toString()); + private static final ItemStack stageDealDamage = ItemUtils.item(XMaterial.REDSTONE, Lang.stageDealDamage.toString()); + private static final ItemStack stageEatDrink = ItemUtils.item(XMaterial.COOKED_PORKCHOP, Lang.stageEatDrink.toString()); + + public static void registerStages() { + QuestsAPI.getAPI().getStages().register(new StageType<>("NPC", StageNPC.class, Lang.Talk.name(), + StageNPC::deserialize, stageNPC, StageNPC.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("ITEMS", StageBringBack.class, Lang.Items.name(), + StageBringBack::deserialize, stageItems, StageBringBack.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("MOBS", StageMobs.class, Lang.Mobs.name(), + StageMobs::deserialize, stageMobs, StageMobs.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("MINE", StageMine.class, Lang.Mine.name(), + StageMine::deserialize, stageMine, StageMine.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("PLACE_BLOCKS", StagePlaceBlocks.class, Lang.Place.name(), + StagePlaceBlocks::deserialize, stagePlace, StagePlaceBlocks.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("CHAT", StageChat.class, Lang.Chat.name(), + StageChat::deserialize, stageChat, StageChat.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("INTERACT", StageInteract.class, Lang.Interact.name(), + StageInteract::deserialize, stageInteract, StageInteract.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("FISH", StageFish.class, Lang.Fish.name(), + StageFish::deserialize, stageFish, StageFish.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("MELT", StageMelt.class, Lang.Melt.name(), + StageMelt::deserialize, stageMelt, StageMelt.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("ENCHANT", StageEnchant.class, Lang.Enchant.name(), + StageEnchant::deserialize, stageEnchant, StageEnchant.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("CRAFT", StageCraft.class, Lang.Craft.name(), + StageCraft::deserialize, stageCraft, StageCraft.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("BUCKET", StageBucket.class, Lang.Bucket.name(), + StageBucket::deserialize, stageBucket, StageBucket.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("LOCATION", StageLocation.class, Lang.Location.name(), + StageLocation::deserialize, stageLocation, StageLocation.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("PLAY_TIME", StagePlayTime.class, Lang.PlayTime.name(), + StagePlayTime::deserialize, stagePlayTime, StagePlayTime.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("BREED", StageBreed.class, Lang.Breed.name(), + StageBreed::deserialize, stageBreed, StageBreed.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("TAME", StageTame.class, Lang.Tame.name(), + StageTame::deserialize, stageTame, StageTame.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("DEATH", StageDeath.class, Lang.Death.name(), + StageDeath::deserialize, stageDeath, StageDeath.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("DEAL_DAMAGE", StageDealDamage.class, Lang.DealDamage.name(), + StageDealDamage::deserialize, stageDealDamage, StageDealDamage.Creator::new)); + QuestsAPI.getAPI().getStages().register(new StageType<>("EAT_DRINK", StageEatDrink.class, Lang.EatDrink.name(), + StageEatDrink::new, stageEatDrink, StageEatDrink.Creator::new)); + } + + public static void registerQuestOptions() { + QuestsAPI.getAPI() + .registerQuestOption(new QuestOptionCreator<>("pool", 9, OptionQuestPool.class, OptionQuestPool::new, null)); + QuestsAPI.getAPI() + .registerQuestOption(new QuestOptionCreator<>("name", 10, OptionName.class, OptionName::new, null)); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("description", 12, OptionDescription.class, OptionDescription::new, null)); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("customItem", 13, OptionQuestItem.class, + OptionQuestItem::new, QuestsConfiguration.getItemMaterial(), "customMaterial")); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("confirmMessage", 15, OptionConfirmMessage.class, OptionConfirmMessage::new, null)); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramText", 17, OptionHologramText.class, + OptionHologramText::new, Lang.HologramText.toString())); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("bypassLimit", 18, OptionBypassLimit.class, OptionBypassLimit::new, false)); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("startableFromGUI", 19, OptionStartable.class, OptionStartable::new, false)); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("failOnDeath", 20, OptionFailOnDeath.class, OptionFailOnDeath::new, false)); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("cancellable", 21, OptionCancellable.class, OptionCancellable::new, true)); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("cancelActions", 22, OptionCancelRewards.class, + OptionCancelRewards::new, new ArrayList<>())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunch", 25, OptionHologramLaunch.class, + OptionHologramLaunch::new, QuestsConfiguration.getHoloLaunchItem())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunchNo", 26, OptionHologramLaunchNo.class, + OptionHologramLaunchNo::new, QuestsConfiguration.getHoloLaunchNoItem())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("scoreboard", 27, OptionScoreboardEnabled.class, + OptionScoreboardEnabled::new, true)); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hideNoRequirements", 28, + OptionHideNoRequirements.class, OptionHideNoRequirements::new, false)); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("auto", 29, OptionAutoQuest.class, OptionAutoQuest::new, false)); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("repeatable", 30, OptionRepeatable.class, + OptionRepeatable::new, false, "multiple")); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("timer", 31, OptionTimer.class, OptionTimer::new, + QuestsConfiguration.getTimeBetween())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("visibility", 32, OptionVisibility.class, + OptionVisibility::new, Arrays.asList(QuestVisibilityLocation.values()), "hid", "hide")); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endSound", 34, OptionEndSound.class, + OptionEndSound::new, QuestsConfiguration.getFinishSound())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("firework", 35, OptionFirework.class, + OptionFirework::new, QuestsConfiguration.getDefaultFirework())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("requirements", 36, OptionRequirements.class, + OptionRequirements::new, new ArrayList<>())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("startRewards", 38, OptionStartRewards.class, + OptionStartRewards::new, new ArrayList<>(), "startRewardsList")); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("startMessage", 39, OptionStartMessage.class, + OptionStartMessage::new, QuestsConfiguration.getPrefix() + Lang.STARTED_QUEST.toString())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("starterNPC", 40, OptionStarterNPC.class, + OptionStarterNPC::new, null, "starterID")); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("startDialog", 41, OptionStartDialog.class, OptionStartDialog::new, null)); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endRewards", 43, OptionEndRewards.class, + OptionEndRewards::new, new ArrayList<>(), "rewardsList")); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endMsg", 44, OptionEndMessage.class, + OptionEndMessage::new, QuestsConfiguration.getPrefix() + Lang.FINISHED_BASE.toString())); + } + + public static void registerRewards() { + QuestsAPI.getAPI().getRewards().register(new RewardCreator("commandReward", CommandReward.class, + ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.command.toString()), CommandReward::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("itemReward", ItemReward.class, + ItemUtils.item(XMaterial.STONE_SWORD, Lang.rewardItems.toString()), ItemReward::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("removeItemsReward", RemoveItemsReward.class, + ItemUtils.item(XMaterial.CHEST, Lang.rewardRemoveItems.toString()), RemoveItemsReward::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("textReward", MessageReward.class, + ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.endMessage.toString()), MessageReward::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("tpReward", TeleportationReward.class, + ItemUtils.item(XMaterial.ENDER_PEARL, Lang.location.toString()), TeleportationReward::new, false)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("expReward", XPReward.class, + ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.rewardXP.toString()), XPReward::new)); + QuestsAPI.getAPI().getRewards() + .register(new RewardCreator("checkpointReward", CheckpointReward.class, + ItemUtils.item(XMaterial.NETHER_STAR, Lang.rewardCheckpoint.toString()), CheckpointReward::new, + false, QuestObjectLocation.STAGE)); + QuestsAPI.getAPI().getRewards() + .register(new RewardCreator("questStopReward", QuestStopReward.class, + ItemUtils.item(XMaterial.BARRIER, Lang.rewardStopQuest.toString()), QuestStopReward::new, false, + QuestObjectLocation.STAGE)); + QuestsAPI.getAPI().getRewards() + .register(new RewardCreator("requirementDependentReward", RequirementDependentReward.class, + ItemUtils.item(XMaterial.REDSTONE, Lang.rewardWithRequirements.toString()), + RequirementDependentReward::new, true).setCanBeAsync(true)); + QuestsAPI.getAPI().getRewards() + .register(new RewardCreator("randomReward", RandomReward.class, + ItemUtils.item(XMaterial.EMERALD, Lang.rewardRandom.toString()), RandomReward::new, true) + .setCanBeAsync(true)); + QuestsAPI.getAPI().getRewards() + .register(new RewardCreator("wait", WaitReward.class, + ItemUtils.item(XMaterial.CLOCK, Lang.rewardWait.toString()), WaitReward::new, true) + .setCanBeAsync(true)); + if (MinecraftVersion.MAJOR >= 9) + QuestsAPI.getAPI().getRewards().register(new RewardCreator("titleReward", TitleReward.class, + ItemUtils.item(XMaterial.NAME_TAG, Lang.rewardTitle.toString()), TitleReward::new, false)); + } + + public static void registerRequirements() { + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("logicalOr", LogicalOrRequirement.class, + ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.RLOR.toString()), LogicalOrRequirement::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("questRequired", QuestRequirement.class, + ItemUtils.item(XMaterial.ARMOR_STAND, Lang.RQuest.toString()), QuestRequirement::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("levelRequired", LevelRequirement.class, + ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RLevel.toString()), LevelRequirement::new)); + QuestsAPI.getAPI().getRequirements() + .register(new RequirementCreator("permissionRequired", PermissionsRequirement.class, + ItemUtils.item(XMaterial.PAPER, Lang.RPermissions.toString()), PermissionsRequirement::new)); + QuestsAPI.getAPI().getRequirements() + .register(new RequirementCreator("scoreboardRequired", ScoreboardRequirement.class, + ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.RScoreboard.toString()), ScoreboardRequirement::new)); + if (MinecraftVersion.MAJOR >= 9) + QuestsAPI.getAPI().getRequirements() + .register(new RequirementCreator("equipmentRequired", EquipmentRequirement.class, + ItemUtils.item(XMaterial.CHAINMAIL_HELMET, Lang.REquipment.toString()), + EquipmentRequirement::new)); + } + + public static void registerItemComparisons() { + QuestsAPI.getAPI().registerItemComparison(new ItemComparison("bukkit", Lang.comparisonBukkit.toString(), + Lang.comparisonBukkitLore.toString(), ItemStack::isSimilar).setEnabledByDefault()); + QuestsAPI.getAPI().registerItemComparison(new ItemComparison("customBukkit", Lang.comparisonCustomBukkit.toString(), + Lang.comparisonCustomBukkitLore.toString(), Utils::isSimilar)); + QuestsAPI.getAPI().registerItemComparison(new ItemComparison("material", Lang.comparisonMaterial.toString(), + Lang.comparisonMaterialLore.toString(), (item1, item2) -> { + if (item2.getType() != item1.getType()) + return false; + if (item1.getType().getMaxDurability() > 0 || MinecraftVersion.MAJOR >= 13) + return true; + return item2.getDurability() == item1.getDurability(); + })); + QuestsAPI.getAPI().registerItemComparison(new ItemComparison("name", Lang.comparisonName.toString(), + Lang.comparisonNameLore.toString(), (item1, item2) -> { + ItemMeta meta1 = item1.getItemMeta(); + ItemMeta meta2 = item2.getItemMeta(); + return (meta1.hasDisplayName() == meta2.hasDisplayName()) + && Objects.equals(meta1.getDisplayName(), meta2.getDisplayName()); + }).setMetaNeeded()); + QuestsAPI.getAPI().registerItemComparison(new ItemComparison("lore", Lang.comparisonLore.toString(), + Lang.comparisonLoreLore.toString(), (item1, item2) -> { + ItemMeta meta1 = item1.getItemMeta(); + ItemMeta meta2 = item2.getItemMeta(); + return (meta1.hasLore() == meta2.hasLore()) && Objects.equals(meta1.getLore(), meta2.getLore()); + }).setMetaNeeded()); + QuestsAPI.getAPI().registerItemComparison(new ItemComparison("enchants", Lang.comparisonEnchants.toString(), + Lang.comparisonEnchantsLore.toString(), (item1, item2) -> { + ItemMeta meta1 = item1.getItemMeta(); + ItemMeta meta2 = item2.getItemMeta(); + return (meta1.hasEnchants() == meta2.hasEnchants()) + && Objects.equals(meta1.getEnchants(), meta2.getEnchants()); + }).setMetaNeeded()); + QuestsAPI.getAPI().registerItemComparison(new ItemComparison("repair", Lang.comparisonRepairCost.toString(), + Lang.comparisonRepairCostLore.toString(), (item1, item2) -> { + ItemMeta meta1 = item1.getItemMeta(); + if (!(meta1 instanceof Repairable)) + return true; + ItemMeta meta2 = item2.getItemMeta(); + if (!(meta2 instanceof Repairable)) + return true; + return ((Repairable) meta1).getRepairCost() == ((Repairable) meta2).getRepairCost(); + }).setMetaNeeded()); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java new file mode 100644 index 00000000..2412dbb3 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -0,0 +1,223 @@ +package fr.skytasul.quests; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.AbstractHolograms; +import fr.skytasul.quests.api.BossBarManager; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsHandler; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.comparison.ItemComparison; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.mobs.MobFactory; +import fr.skytasul.quests.api.mobs.MobStacker; +import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.objects.QuestObjectsRegistry; +import fr.skytasul.quests.api.options.QuestOptionCreator; +import fr.skytasul.quests.api.pools.QuestPoolsManager; +import fr.skytasul.quests.api.quests.QuestsManager; +import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementCreator; +import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.rewards.RewardCreator; +import fr.skytasul.quests.api.stages.StageTypeRegistry; + +public class QuestsAPIImplementation implements QuestsAPI { + + static final QuestsAPIImplementation INSTANCE = new QuestsAPIImplementation(); + + private final QuestObjectsRegistry<AbstractRequirement, RequirementCreator> requirements = + new QuestObjectsRegistry<>("requirements", Lang.INVENTORY_REQUIREMENTS.toString()); + private final QuestObjectsRegistry<AbstractReward, RewardCreator> rewards = + new QuestObjectsRegistry<>("rewards", Lang.INVENTORY_REWARDS.toString()); + private final StageTypeRegistry stages = new StageTypeRegistry(); + private final List<ItemComparison> itemComparisons = new LinkedList<>(); + private final List<MobStacker> mobStackers = new ArrayList<>(); + + private BQNPCsManager npcsManager = null; + private AbstractHolograms<?> hologramsManager = null; + private BossBarManager bossBarManager = null; + + private final Set<QuestsHandler> handlers = new HashSet<>(); + + private QuestsAPIImplementation() {} + + @Override + public @NotNull StageTypeRegistry getStages() { + return stages; + } + + /** + * Register new mob factory + * + * @param factory MobFactory instance + */ + @Override + public void registerMobFactory(@NotNull MobFactory<?> factory) { + MobFactory.factories.add(factory); + Bukkit.getPluginManager().registerEvents(factory, BeautyQuests.getInstance()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Mob factory registered (id: " + factory.getID() + ")"); + } + + @Override + public void registerQuestOption(@NotNull QuestOptionCreator<?, ?> creator) { + Validate.notNull(creator); + Validate.isTrue(!QuestOptionCreator.creators.containsKey(creator.optionClass), + "This quest option was already registered"); + QuestOptionCreator.creators.put(creator.optionClass, creator); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Quest option registered (id: " + creator.id + ")"); + } + + @Override + public @NotNull List<@NotNull ItemComparison> getItemComparisons() { + return itemComparisons; + } + + @Override + public void registerItemComparison(@NotNull ItemComparison comparison) { + Validate.isTrue(itemComparisons.stream().noneMatch(x -> x.getID().equals(comparison.getID())), + "This item comparison was already registered"); + itemComparisons.add(comparison); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Item comparison registered (id: " + comparison.getID() + ")"); + } + + @Override + public void unregisterItemComparison(@NotNull ItemComparison comparison) { + Validate.isTrue(itemComparisons.remove(comparison), "This item comparison was not registered"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Item comparison unregistered (id: " + comparison.getID() + ")"); + } + + @Override + public @NotNull List<@NotNull MobStacker> getMobStackers() { + return mobStackers; + } + + @Override + public void registerMobStacker(@NotNull MobStacker stacker) { + mobStackers.add(stacker); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Added " + stacker.toString() + " mob stacker"); + } + + @Override + public @NotNull QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getRequirements() { + return requirements; + } + + @Override + public @NotNull QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards() { + return rewards; + } + + @Override + public @NotNull BQNPCsManager getNPCsManager() { + return npcsManager; + } + + @Override + public void setNPCsManager(@NotNull BQNPCsManager newNpcsManager) { + if (npcsManager != null) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning(newNpcsManager.getClass().getSimpleName() + " will replace " + + npcsManager.getClass().getSimpleName() + " as the new NPCs manager."); + HandlerList.unregisterAll(npcsManager); + } + npcsManager = newNpcsManager; + Bukkit.getPluginManager().registerEvents(npcsManager, BeautyQuests.getInstance()); + } + + @Override + public boolean hasHologramsManager() { + return hologramsManager != null; + } + + @Override + public @Nullable AbstractHolograms<?> getHologramsManager() { + return hologramsManager; + } + + @Override + public void setHologramsManager(@NotNull AbstractHolograms<?> newHologramsManager) { + Validate.notNull(newHologramsManager); + if (hologramsManager != null) + QuestsPlugin.getPlugin().getLoggerExpanded().warning(newHologramsManager.getClass().getSimpleName() + + " will replace " + hologramsManager.getClass().getSimpleName() + " as the new holograms manager."); + hologramsManager = newHologramsManager; + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug("Holograms manager has been registered: " + newHologramsManager.getClass().getName()); + } + + @Override + public boolean hasBossBarManager() { + return bossBarManager != null; + } + + @Override + public @Nullable BossBarManager getBossBarManager() { + return bossBarManager; + } + + @Override + public void setBossBarManager(@NotNull BossBarManager newBossBarManager) { + Validate.notNull(newBossBarManager); + if (bossBarManager != null) + QuestsPlugin.getPlugin().getLoggerExpanded().warning(newBossBarManager.getClass().getSimpleName() + + " will replace " + hologramsManager.getClass().getSimpleName() + " as the new boss bar manager."); + bossBarManager = newBossBarManager; + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug("Bossbars manager has been registered: " + newBossBarManager.getClass().getName()); + } + + @Override + public void registerQuestsHandler(@NotNull QuestsHandler handler) { + Validate.notNull(handler); + if (handlers.add(handler) && BeautyQuests.getInstance().loaded) + handler.load(); // if BeautyQuests not loaded so far, it will automatically call the load method + } + + @Override + public void unregisterQuestsHandler(@NotNull QuestsHandler handler) { + if (handlers.remove(handler)) + handler.unload(); + } + + @Override + public @NotNull Collection<@NotNull QuestsHandler> getQuestsHandlers() { + return handlers; + } + + @Override + public void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> consumer) { + handlers.forEach(handler -> { + try { + consumer.accept(handler); + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while updating quests handler.", ex); + } + }); + } + + @Override + public @NotNull QuestsManager getQuestsManager() { + return BeautyQuests.getInstance().getQuestsManager(); + } + + @Override + public @NotNull QuestPoolsManager getPoolsManager() { + return BeautyQuests.getInstance().getPoolsManager(); + } + + @Override + public @NotNull QuestsPlugin getPlugin() { + return BeautyQuests.getInstance(); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java b/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java index dce4f4f1..0030435d 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java @@ -4,6 +4,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.bukkit.Bukkit; @@ -18,17 +19,19 @@ import com.cryptomorin.xseries.XMaterial; import com.google.common.collect.Sets; import fr.skytasul.quests.api.QuestsAPI; +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.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescription; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; import fr.skytasul.quests.utils.compatibility.Accounts; import fr.skytasul.quests.utils.compatibility.DependenciesManager; -import fr.skytasul.quests.utils.nms.NMS; public class QuestsConfiguration { @@ -73,7 +76,7 @@ public class QuestsConfiguration { private static String descAmountFormat = "x{0}"; private static boolean descXOne = true; private static boolean inlineAlone = true; - private static List<Source> descSources = new ArrayList<>(); + private static List<DescriptionSource> descSources = new ArrayList<>(); private static boolean requirementReasonOnMultipleQuests = true; private static boolean stageEndRewardsMessage = true; private static QuestDescription questDescription; @@ -121,20 +124,12 @@ boolean update() { void init() { backups = config.getBoolean("backups", true); - if (!backups) BeautyQuests.logger.warning("Backups are disabled due to the presence of \"backups: false\" in config.yml."); + if (!backups) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Backups are disabled due to the presence of \"backups: false\" in config.yml."); timer = config.getInt("redoMinuts"); minecraftTranslationsFile = config.getString("minecraftTranslationsFile"); if (isMinecraftTranslationsEnabled()) { - if (NMS.getMCVersion() >= 13) { - if (!MinecraftNames.intialize(minecraftTranslationsFile)) { - BeautyQuests.logger.warning("Cannot enable the \"minecraftTranslationsFile\" option : problem when initializing"); - minecraftTranslationsFile = null; - } - }else{ - BeautyQuests.logger.warning("Cannot enable the \"minecraftTranslationsFile\" option : only supported on Spigot 1.13 and higher"); - minecraftTranslationsFile = null; - } + initializeTranslations(); } dialogs.init(); menu.init(); @@ -178,7 +173,7 @@ void init() { .collect(Collectors.toList()); } }catch (IllegalArgumentException ex) { - BeautyQuests.logger.warning("Unknown click type " + config.get("npcClick") + " for config entry \"npcClick\""); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unknown click type " + config.get("npcClick") + " for config entry \"npcClick\""); } skipNpcGuiIfOnlyOneQuest = config.getBoolean("skip npc gui if only one quest"); enablePrefix = config.getBoolean("enablePrefix"); @@ -188,7 +183,7 @@ void init() { hookAcounts = DependenciesManager.acc.isEnabled() && config.getBoolean("accountsHook"); if (hookAcounts) { Bukkit.getPluginManager().registerEvents(new Accounts(), BeautyQuests.getInstance()); - BeautyQuests.logger.info("AccountsHook is now managing player datas for quests !"); + QuestsPlugin.getPlugin().getLoggerExpanded().info("AccountsHook is now managing player datas for quests !"); } usePlayerBlockTracker = DependenciesManager.PlayerBlockTracker.isEnabled() && config.getBoolean("usePlayerBlockTracker"); dSetName = config.getString("dynmap.markerSetName"); @@ -208,15 +203,15 @@ void init() { inlineAlone = config.getBoolean("stageDescriptionItemsSplit.inlineAlone"); for (String s : config.getStringList("stageDescriptionItemsSplit.sources")){ try{ - descSources.add(Source.valueOf(s)); + descSources.add(DescriptionSource.valueOf(s)); }catch (IllegalArgumentException ex){ - BeautyQuests.logger.warning("Loading of description splitted sources failed : source " + s + " does not exist"); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Loading of description splitted sources failed : source " + s + " does not exist"); } } questDescription = new QuestDescription(config.getConfigurationSection("questDescription")); - if (NMS.getMCVersion() >= 9) { + if (MinecraftVersion.MAJOR >= 9) { particleStart = loadParticles(config, "start", new ParticleEffect(Particle.REDSTONE, ParticleShape.POINT, Color.YELLOW)); particleTalk = loadParticles(config, "talk", new ParticleEffect(Particle.VILLAGER_HAPPY, ParticleShape.BAR, null)); particleNext = loadParticles(config, "next", new ParticleEffect(Particle.SMOKE_NORMAL, ParticleShape.SPOT, null)); @@ -236,16 +231,41 @@ void init() { } } + private void initializeTranslations() { + if (MinecraftVersion.MAJOR >= 13) { + String fileName = minecraftTranslationsFile; + Optional<String> extension = Utils.getFilenameExtension(minecraftTranslationsFile); + if (extension.isPresent()) { + if (extension.get().equalsIgnoreCase("json")) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("File " + fileName + " is not a JSON file."); + return; + } + } else { + fileName += ".json"; + } + + if (!MinecraftNames.intialize(QuestsPlugin.getPlugin().getDataFolder().toPath().resolve(fileName))) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Cannot enable the \"minecraftTranslationsFile\" option : problem when initializing"); + minecraftTranslationsFile = null; + } + } else { + QuestsPlugin.getPlugin().getLoggerExpanded().warning( + "Cannot enable the \"minecraftTranslationsFile\" option : only supported on Spigot 1.13 and higher"); + minecraftTranslationsFile = null; + } + } + private ParticleEffect loadParticles(FileConfiguration config, String name, ParticleEffect defaultParticle) { ParticleEffect particle = null; if (config.getBoolean(name + ".enabled")) { try{ particle = ParticleEffect.deserialize(config.getConfigurationSection(name)); }catch (Exception ex){ - BeautyQuests.logger.warning("Loading of " + name + " particles failed: Invalid particle, color or shape.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Loading of " + name + " particles failed: Invalid particle, color or shape.", ex); } if (particle == null) particle = defaultParticle; - BeautyQuests.logger.info("Loaded " + name + " particles: " + particle.toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Loaded " + name + " particles: " + particle.toString()); } return particle; } @@ -263,7 +283,7 @@ private String loadSound(String key) { Sound.valueOf(sound.toUpperCase()); sound = sound.toUpperCase(); }catch (IllegalArgumentException ex) { - BeautyQuests.logger.warning("Sound " + sound + " is not a valid Bukkit sound."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Sound " + sound + " is not a valid Bukkit sound."); } return sound; } @@ -310,7 +330,7 @@ public static boolean doFireworks(){ } public static boolean showMobsProgressBar() { - return mobsProgressBar && QuestsAPI.hasBossBarManager(); + return mobsProgressBar && QuestsAPI.getAPI().hasBossBarManager(); } public static int getProgressBarTimeout(){ @@ -461,7 +481,7 @@ public static String getDescriptionAmountFormat() { return descAmountFormat; } - public static boolean showDescriptionItemsXOne(Source source){ + public static boolean showDescriptionItemsXOne(DescriptionSource source){ return splitDescription(source) && descXOne; } @@ -469,9 +489,9 @@ public static boolean inlineAlone() { return inlineAlone; } - public static boolean splitDescription(Source source){ - if (source == Source.FORCESPLIT) return true; - if (source == Source.FORCELINE) return false; + public static boolean splitDescription(DescriptionSource source){ + if (source == DescriptionSource.FORCESPLIT) return true; + if (source == DescriptionSource.FORCELINE) return false; return descSources.contains(source); } @@ -538,7 +558,7 @@ private boolean update() { } private void init() { - inActionBar = NMS.getMCVersion() > 8 && config.getBoolean("inActionBar"); + inActionBar = MinecraftVersion.MAJOR > 8 && config.getBoolean("inActionBar"); defaultTime = config.getInt("defaultTime"); defaultSkippable = config.getBoolean("defaultSkippable"); disableClick = config.getBoolean("disableClick"); @@ -595,7 +615,7 @@ public String getDefaultNPCSound() { public class QuestsMenuConfig { - private Set<Category> tabs; + private Set<PlayerListCategory> tabs; private boolean openNotStartedTabWhenEmpty = true; private boolean allowPlayerCancelQuest = true; @@ -615,10 +635,10 @@ private boolean update() { } private void init() { - tabs = config.getStringList("enabledTabs").stream().map(Category::fromString).collect(Collectors.toSet()); + tabs = config.getStringList("enabledTabs").stream().map(PlayerListCategory::fromString).collect(Collectors.toSet()); if (tabs.isEmpty()) { - BeautyQuests.logger.warning("Quests Menu must have at least one enabled tab."); - tabs = Sets.newHashSet(Category.values()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Quests Menu must have at least one enabled tab."); + tabs = Sets.newHashSet(PlayerListCategory.values()); } openNotStartedTabWhenEmpty = config.getBoolean("openNotStartedTabWhenEmpty"); allowPlayerCancelQuest = config.getBoolean("allowPlayerCancelQuest"); @@ -632,7 +652,7 @@ public boolean allowPlayerCancelQuest() { return allowPlayerCancelQuest; } - public Set<Category> getEnabledTabs() { + public Set<PlayerListCategory> getEnabledTabs() { return tabs; } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 3416a440..60e9cab0 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -15,10 +15,6 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.CraftItemEvent; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.player.PlayerJoinEvent; @@ -27,25 +23,25 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; import fr.skytasul.quests.api.events.internal.BQCraftEvent; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.options.OptionAutoQuest; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.players.PlayerAccountImplementation; +import fr.skytasul.quests.structure.QuestImplementation; import fr.skytasul.quests.utils.compatibility.Paper; public class QuestsListener implements Listener{ @@ -58,27 +54,34 @@ public void onNPCClick(BQNPCClickEvent e) { Player p = e.getPlayer(); BQNPC npc = e.getNPC(); - if (Inventories.isInSystem(p)) return; + if (QuestsPlugin.getPlugin().getGuiManager().hasGuiOpened(p) + || QuestsPlugin.getPlugin().getEditorManager().isInEditor(p)) + return; - PlayerAccount acc = PlayersManager.getPlayerAccount(p); + PlayerAccountImplementation acc = BeautyQuests.getInstance().getPlayersManager().getAccount(p); if (acc == null) return; Set<Quest> quests = npc.getQuests(); - quests = quests.stream().filter(qu -> !qu.hasStarted(acc) && (qu.isRepeatable() ? true : !qu.hasFinished(acc))).collect(Collectors.toSet()); + quests = quests.stream().filter(qu -> !qu.hasStarted(acc) && (qu.isRepeatable() || !qu.hasFinished(acc))) + .collect(Collectors.toSet()); if (quests.isEmpty() && npc.getPools().isEmpty()) return; - List<Quest> launcheable = new ArrayList<>(); - List<Quest> requirements = new ArrayList<>(); - List<Quest> timer = new ArrayList<>(); + List<QuestImplementation> launcheable = new ArrayList<>(); + List<QuestImplementation> requirements = new ArrayList<>(); + List<QuestImplementation> timer = new ArrayList<>(); for (Quest qu : quests) { + QuestImplementation quest = (QuestImplementation) qu; try { - if (!qu.testRequirements(p, acc, false)) { - requirements.add(qu); - }else if (!qu.testTimer(acc, false)) { - timer.add(qu); - }else launcheable.add(qu); + if (!quest.testRequirements(p, acc, false)) { + requirements.add(quest); + } else if (!quest.testTimer(acc, false)) { + timer.add(quest); + } else + launcheable.add(quest); }catch (Exception ex) { - BeautyQuests.logger.severe("An exception occured when checking requirements on the quest " + qu.getID() + " for player " + p.getName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("An exception occured when checking requirements on the quest " + quest.getId() + + " for player " + p.getName(), ex); } } @@ -86,70 +89,50 @@ public void onNPCClick(BQNPCClickEvent e) { try { return pool.canGive(p, acc); }catch (Exception ex) { - BeautyQuests.logger.severe("An exception occured when checking requirements on the pool " + pool.getID() + " for player " + p.getName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An exception occured when checking requirements on the pool " + pool.getId() + " for player " + p.getName(), ex); return false; } }).collect(Collectors.toSet()); e.setCancelled(true); if (!launcheable.isEmpty()) { - for (Quest quest : launcheable) { + for (QuestImplementation quest : launcheable) { if (quest.isInDialog(p)) { quest.clickNPC(p); return; } } - ChooseQuestGUI gui = new ChooseQuestGUI(launcheable, quest -> { - if (quest == null) return; - quest.clickNPC(p); - }, true); - gui.setValidate(__ -> { - new PlayerListGUI(acc).create(p); - }, ItemUtils.item(XMaterial.BOOKSHELF, Lang.questMenu.toString(), QuestOption.formatDescription(Lang.questMenuLore.toString()))); - gui.create(p); + ChooseQuestGUI.choose(p, quests, quest -> { + ((QuestImplementation) quest).clickNPC(p); + }, null, true, gui -> { + gui.setValidate(__ -> { + new PlayerListGUI(acc).open(p); + }, ItemUtils.item(XMaterial.BOOKSHELF, Lang.questMenu.toString(), + QuestOption.formatDescription(Lang.questMenuLore.toString()))); + }); }else if (!startablePools.isEmpty()) { QuestPool pool = startablePools.iterator().next(); - DebugUtils.logMessage("NPC " + npc.getId() + ": " + startablePools.size() + " pools, result: " + pool.give(p)); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("NPC " + npc.getId() + ": " + startablePools.size() + " pools, result: " + pool.give(p)); }else { if (!timer.isEmpty()) { timer.get(0).testTimer(acc, true); }else if (!requirements.isEmpty()) { requirements.get(0).testRequirements(p, acc, true); }else { - npc.getPools().iterator().next().give(p).thenAccept(result -> Utils.sendMessage(p, result)); + npc.getPools().iterator().next().give(p).thenAccept(result -> MessageUtils.sendPrefixedMessage(p, result)); } e.setCancelled(false); } } - @EventHandler - public void onClose(InventoryCloseEvent e) { - Inventories.onClose(e); - } - - @EventHandler - public void onClick(InventoryClickEvent e) { - Inventories.onClick(e); - } - - @EventHandler - public void onDrag(InventoryDragEvent e) { - Inventories.onDrag(e); - } - - @EventHandler (priority = EventPriority.MONITOR) - public void onOpen(InventoryOpenEvent e) { - Inventories.onOpen(e); - } - @EventHandler (priority = EventPriority.LOWEST) public void onJoin(PlayerJoinEvent e){ Player player = e.getPlayer(); - DebugUtils.logMessage(player.getName() + " (" + player.getUniqueId().toString() + ") joined the server"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug(player.getName() + " (" + player.getUniqueId().toString() + ") joined the server"); // for timing purpose - if (BeautyQuests.loaded && !QuestsConfiguration.hookAccounts()) { + if (BeautyQuests.getInstance().loaded && !QuestsConfiguration.hookAccounts()) { BeautyQuests.getInstance().getPlayersManager().loadPlayer(player); } } @@ -157,7 +140,7 @@ public void onJoin(PlayerJoinEvent e){ @EventHandler public void onQuit(PlayerQuitEvent e) { Player player = e.getPlayer(); - DebugUtils.logMessage(player.getName() + " left the server"); // for timing purpose + QuestsPlugin.getPlugin().getLoggerExpanded().debug(player.getName() + " left the server"); // for timing purpose if (!QuestsConfiguration.hookAccounts()) { BeautyQuests.getInstance().getPlayersManager().unloadPlayer(player); } @@ -166,13 +149,13 @@ public void onQuit(PlayerQuitEvent e) { @EventHandler (priority = EventPriority.LOW) public void onAccountJoin(PlayerAccountJoinEvent e) { if (e.isFirstJoin()) { - QuestsAPI.getQuests().getQuests().stream().filter(qu -> qu.getOptionValueOrDef(OptionAutoQuest.class)).forEach(qu -> qu.start(e.getPlayer())); + QuestsAPI.getAPI().getQuestsManager().getQuests().stream().filter(qu -> qu.getOptionValueOrDef(OptionAutoQuest.class)).forEach(qu -> qu.start(e.getPlayer())); } } @EventHandler public void onAccountLeave(PlayerAccountLeaveEvent e) { - QuestsAPI.getQuests().forEach(x -> x.leave(e.getPlayer())); + BeautyQuests.getInstance().getQuestsManager().getQuestsRaw().forEach(x -> x.leave(e.getPlayer())); } @EventHandler (priority = EventPriority.HIGH) diff --git a/core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java deleted file mode 100644 index aba5df4a..00000000 --- a/core/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ /dev/null @@ -1,194 +0,0 @@ -package fr.skytasul.quests.api; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.function.Consumer; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.event.HandlerList; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.api.bossbar.BQBossBarManager; -import fr.skytasul.quests.api.comparison.ItemComparison; -import fr.skytasul.quests.api.mobs.MobFactory; -import fr.skytasul.quests.api.mobs.MobStacker; -import fr.skytasul.quests.api.npcs.BQNPCsManager; -import fr.skytasul.quests.api.objects.QuestObjectsRegistry; -import fr.skytasul.quests.api.options.QuestOptionCreator; -import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.api.requirements.RequirementCreator; -import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.rewards.RewardCreator; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageType; -import fr.skytasul.quests.api.stages.StageTypeRegistry; -import fr.skytasul.quests.structure.QuestsManager; -import fr.skytasul.quests.structure.pools.QuestPoolsManager; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; - -/** - * This class contains most of the useful accessors to fetch data from BeautyQuests - * and methods to implement custom behaviors. - */ -public final class QuestsAPI { - - private static final QuestObjectsRegistry<AbstractRequirement, RequirementCreator> requirements = new QuestObjectsRegistry<>("requirements", Lang.INVENTORY_REQUIREMENTS.toString()); - private static final QuestObjectsRegistry<AbstractReward, RewardCreator> rewards = new QuestObjectsRegistry<>("rewards", Lang.INVENTORY_REWARDS.toString()); - private static final StageTypeRegistry stages = new StageTypeRegistry(); - private static final List<ItemComparison> itemComparisons = new LinkedList<>(); - private static final List<MobStacker> mobStackers = new ArrayList<>(); - - private static BQNPCsManager npcsManager = null; - private static AbstractHolograms<?> hologramsManager = null; - private static BQBossBarManager bossBarManager = null; - - private static final Set<QuestsHandler> handlers = new HashSet<>(); - - private QuestsAPI() {} - - /** - * Register new stage type into the plugin - * @param type StageType instance - * @deprecated use {@link StageTypeRegistry#register(StageType)} - */ - @Deprecated - public static <T extends AbstractStage> void registerStage(StageType<T> type) { // TODO remove, edited on 0.20 - stages.register(type); - } - - public static @NotNull StageTypeRegistry getStages() { - return stages; - } - - /** - * Register new mob factory - * @param factory MobFactory instance - */ - public static void registerMobFactory(@NotNull MobFactory<?> factory) { - MobFactory.factories.add(factory); - Bukkit.getPluginManager().registerEvents(factory, BeautyQuests.getInstance()); - DebugUtils.logMessage("Mob factory registered (id: " + factory.getID() + ")"); - } - - public static void registerQuestOption(@NotNull QuestOptionCreator<?, ?> creator) { - Validate.notNull(creator); - Validate.isTrue(!QuestOptionCreator.creators.containsKey(creator.optionClass), "This quest option was already registered"); - QuestOptionCreator.creators.put(creator.optionClass, creator); - DebugUtils.logMessage("Quest option registered (id: " + creator.id + ")"); - } - - public static @NotNull List<@NotNull ItemComparison> getItemComparisons() { - return itemComparisons; - } - - public static void registerItemComparison(@NotNull ItemComparison comparison) { - Validate.isTrue(itemComparisons.stream().noneMatch(x -> x.getID().equals(comparison.getID())), - "This item comparison was already registered"); - itemComparisons.add(comparison); - DebugUtils.logMessage("Item comparison registered (id: " + comparison.getID() + ")"); - } - - public static void unregisterItemComparison(@NotNull ItemComparison comparison) { - Validate.isTrue(itemComparisons.remove(comparison), "This item comparison was not registered"); - DebugUtils.logMessage("Item comparison unregistered (id: " + comparison.getID() + ")"); - } - - public static @NotNull List<@NotNull MobStacker> getMobStackers() { - return mobStackers; - } - - public static void registerMobStacker(@NotNull MobStacker stacker) { - mobStackers.add(stacker); - DebugUtils.logMessage("Added " + stacker.toString() + " mob stacker"); - } - - public static @NotNull QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getRequirements() { - return requirements; - } - - public static @NotNull QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards() { - return rewards; - } - - public static @NotNull BQNPCsManager getNPCsManager() { - return npcsManager; - } - - public static void setNPCsManager(@NotNull BQNPCsManager newNpcsManager) { - if (npcsManager != null) { - BeautyQuests.logger.warning(newNpcsManager.getClass().getSimpleName() + " will replace " + npcsManager.getClass().getSimpleName() + " as the new NPCs manager."); - HandlerList.unregisterAll(npcsManager); - } - npcsManager = newNpcsManager; - Bukkit.getPluginManager().registerEvents(npcsManager, BeautyQuests.getInstance()); - } - - public static boolean hasHologramsManager() { - return hologramsManager != null; - } - - public static @Nullable AbstractHolograms<?> getHologramsManager() { - return hologramsManager; - } - - public static void setHologramsManager(@NotNull AbstractHolograms<?> newHologramsManager) { - Validate.notNull(newHologramsManager); - if (hologramsManager != null) BeautyQuests.logger.warning(newHologramsManager.getClass().getSimpleName() + " will replace " + hologramsManager.getClass().getSimpleName() + " as the new holograms manager."); - hologramsManager = newHologramsManager; - DebugUtils.logMessage("Holograms manager has been registered: " + newHologramsManager.getClass().getName()); - } - - public static boolean hasBossBarManager() { - return bossBarManager != null; - } - - public static @Nullable BQBossBarManager getBossBarManager() { - return bossBarManager; - } - - public static void setBossBarManager(@NotNull BQBossBarManager newBossBarManager) { - Validate.notNull(newBossBarManager); - if (bossBarManager != null) BeautyQuests.logger.warning(newBossBarManager.getClass().getSimpleName() + " will replace " + hologramsManager.getClass().getSimpleName() + " as the new boss bar manager."); - bossBarManager = newBossBarManager; - DebugUtils.logMessage("Bossbars manager has been registered: " + newBossBarManager.getClass().getName()); - } - - public static void registerQuestsHandler(@NotNull QuestsHandler handler) { - Validate.notNull(handler); - if (handlers.add(handler) && BeautyQuests.loaded) - handler.load(); // if BeautyQuests not loaded so far, it will automatically call the load method - } - - public static void unregisterQuestsHandler(@NotNull QuestsHandler handler) { - if (handlers.remove(handler)) handler.unload(); - } - - public static @NotNull Collection<@NotNull QuestsHandler> getQuestsHandlers() { - return handlers; - } - - public static void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> consumer) { - handlers.forEach(handler -> { - try { - consumer.accept(handler); - }catch (Exception ex) { - BeautyQuests.logger.severe("An error occurred while updating quests handler.", ex); - } - }); - } - - public static @NotNull QuestsManager getQuests() { - return BeautyQuests.getInstance().getQuestsManager(); - } - - public static @NotNull QuestPoolsManager getQuestPools() { - return BeautyQuests.getInstance().getPoolsManager(); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java b/core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java deleted file mode 100644 index 4fa5a6c9..00000000 --- a/core/src/main/java/fr/skytasul/quests/api/options/OptionSet.java +++ /dev/null @@ -1,12 +0,0 @@ -package fr.skytasul.quests.api.options; - -import org.jetbrains.annotations.NotNull; - -@SuppressWarnings ("rawtypes") -public interface OptionSet extends Iterable<QuestOption> { - - <T extends QuestOption<?>> @NotNull T getOption(@NotNull Class<T> optionClass); - - boolean hasOption(@NotNull Class<? extends QuestOption<?>> clazz); - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java deleted file mode 100644 index 231bd442..00000000 --- a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractCountableStage.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.skytasul.quests.api.stages; - -import java.util.Map; -import java.util.Map.Entry; -import fr.skytasul.quests.structure.QuestBranch; - -@Deprecated -public abstract class AbstractCountableStage<T> extends fr.skytasul.quests.api.stages.types.AbstractCountableStage<T> { - - @Deprecated - protected AbstractCountableStage(QuestBranch branch, Map<Integer, Entry<T, Integer>> objects) { - super(branch, objects); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java deleted file mode 100644 index 8abe45d2..00000000 --- a/core/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ /dev/null @@ -1,357 +0,0 @@ -package fr.skytasul.quests.api.stages; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; -import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; -import fr.skytasul.quests.api.objects.QuestObject; -import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.serializable.SerializableCreator; -import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.api.stages.options.StageOption; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Utils; - -public abstract class AbstractStage implements Listener { - - private final @NotNull StageType<?> type; - - protected final @NotNull QuestBranch branch; - - private @Nullable String startMessage = null; - private @Nullable String customText = null; - private @NotNull List<@NotNull AbstractReward> rewards = new ArrayList<>(); - private @NotNull List<@NotNull AbstractRequirement> validationRequirements = new ArrayList<>(); - - private @NotNull List<@NotNull StageOption> options; - protected boolean asyncEnd = false; - - protected AbstractStage(@NotNull QuestBranch branch) { - this.branch = branch; - this.type = QuestsAPI.getStages().getType(getClass()).orElseThrow(() -> new IllegalArgumentException(getClass().getName() + "has not been registered as a stage type via the API.")); - - Bukkit.getPluginManager().registerEvents(this, BeautyQuests.getInstance()); - } - - public @NotNull QuestBranch getQuestBranch() { - return branch; - } - - public void setStartMessage(@Nullable String text) { - this.startMessage = text; - } - - public @Nullable String getStartMessage() { - return startMessage; - } - - public @NotNull List<@NotNull AbstractReward> getRewards() { - return rewards; - } - - public void setRewards(@NotNull List<@NotNull AbstractReward> rewards) { - this.rewards = rewards; - rewards.forEach(reward -> reward.attach(branch.getQuest())); - checkAsync(); - } - - public @NotNull List<@NotNull AbstractRequirement> getValidationRequirements() { - return validationRequirements; - } - - public void setValidationRequirements(@NotNull List<@NotNull AbstractRequirement> validationRequirements) { - this.validationRequirements = validationRequirements; - validationRequirements.forEach(requirement -> requirement.attach(branch.getQuest())); - } - - public @NotNull List<@NotNull StageOption> getOptions() { - return options; - } - - public void setOptions(@NotNull List<@NotNull StageOption> options) { - this.options = options; - } - - public @Nullable String getCustomText() { - return customText; - } - - public void setCustomText(@Nullable String message) { - this.customText = message; - } - - public boolean sendStartMessage(){ - return startMessage == null && QuestsConfiguration.sendStageStartMessage(); - } - - public @NotNull StageType<?> getType() { - return type; - } - - public boolean hasAsyncEnd(){ - return asyncEnd; - } - - private void checkAsync(){ - for(AbstractReward rew : rewards){ - if (rew.isAsync()) { - asyncEnd = true; - break; - } - } - } - - public int getID(){ - return branch.getID(this); - } - - public int getStoredID(){ - if (branch.isRegularStage(this)) { - return 0; - } - int index = 0; - for (AbstractStage stage : branch.getEndingStages().keySet()) { - if (stage == this) break; - index++; - } - return index; - } - - protected boolean canUpdate(@NotNull Player p) { - return canUpdate(p, false); - } - - protected boolean canUpdate(@NotNull Player p, boolean msg) { - return Utils.testRequirements(p, validationRequirements, msg); - } - - @Override - public String toString() { - return "stage " + getID() + "(" + type.getID() + ") of quest " + branch.getQuest().getID() + ", branch " + branch.getID(); - } - - private void propagateStageHandlers(@NotNull Consumer<@NotNull StageHandler> consumer) { - Consumer<StageHandler> newConsumer = handler -> { - try { - consumer.accept(handler); - }catch (Exception ex) { - BeautyQuests.logger.severe("An error occurred while updating stage handler.", ex); - } - }; - QuestsAPI.getQuestsHandlers().forEach(newConsumer); - options.forEach(newConsumer); - } - - /** - * Called internally when a player finish stage's objectives - * @param p Player who finish the stage - */ - protected final void finishStage(@NotNull Player p) { - Utils.runSync(() -> branch.finishStage(p, this)); - } - - /** - * Called internally to test if a player has the stage started - * @param p Player to test - * @see QuestBranch#hasStageLaunched(PlayerAccount, AbstractStage) - */ - protected final boolean hasStarted(@NotNull Player p) { - return branch.hasStageLaunched(PlayersManager.getPlayerAccount(p), this); - } - - /** - * Called when the stage starts (player can be offline) - * @param acc PlayerAccount for which the stage starts - */ - public void start(@NotNull PlayerAccount acc) { - if (acc.isCurrent()) Utils.sendOffMessage(acc.getPlayer(), startMessage); - Map<String, Object> datas = new HashMap<>(); - initPlayerDatas(acc, datas); - acc.getQuestDatas(branch.getQuest()).setStageDatas(getStoredID(), datas); - propagateStageHandlers(handler -> handler.stageStart(acc, this)); - } - - protected void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) {} - - /** - * Called when the stage ends (player can be offline) - * @param acc PlayerAccount for which the stage ends - */ - public void end(@NotNull PlayerAccount acc) { - acc.getQuestDatas(branch.getQuest()).setStageDatas(getStoredID(), null); - propagateStageHandlers(handler -> handler.stageEnd(acc, this)); - } - - /** - * Called when an account with this stage launched joins - * @param acc PlayerAccount which just joined - */ - public void joins(@NotNull PlayerAccount acc, @NotNull Player p) { - propagateStageHandlers(handler -> handler.stageJoin(acc, p, this)); - } - - /** - * Called when an account with this stage launched leaves - * @param acc PlayerAccount which just left - */ - public void leaves(@NotNull PlayerAccount acc, @NotNull Player p) { - propagateStageHandlers(handler -> handler.stageLeave(acc, p, this)); - } - - public final @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { - if (customText != null) return "§e" + Utils.format(customText, descriptionFormat(acc, source)); - try{ - return descriptionLine(acc, source); - }catch (Exception ex){ - BeautyQuests.logger.severe("An error occurred while getting the description line for player " + acc.getName() + " in " + toString(), ex); - return "§a" + type.getName(); - } - } - - /** - * @param acc PlayerAccount who has the stage in progress - * @param source source of the description request - * @return the progress of the stage for the player - */ - protected abstract @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull Source source); - - /** - * Will be called only if there is a {@link #customText} - * @param acc PlayerAccount who has the stage in progress - * @param source source of the description request - * @return all strings that can be used to format the custom description text - */ - protected @Nullable Object @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull Source source) { - return null; - } - - public void updateObjective(@NotNull PlayerAccount acc, @NotNull Player p, @NotNull String dataKey, - @Nullable Object dataValue) { - Map<String, Object> datas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStoredID()); - Validate.notNull(datas, "Account " + acc.debugName() + " does not have datas for " + toString()); - datas.put(dataKey, dataValue); - acc.getQuestDatas(branch.getQuest()).setStageDatas(getStoredID(), datas); - branch.getBranchesManager().objectiveUpdated(p, acc); - } - - protected <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { - Map<String, Object> stageDatas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStoredID()); - return stageDatas == null ? null : (T) stageDatas.get(dataKey); - } - - /** - * Called when the stage has to be unloaded - */ - public void unload(){ - propagateStageHandlers(handler -> handler.stageUnload(this)); - HandlerList.unregisterAll(this); - rewards.forEach(AbstractReward::detach); - validationRequirements.forEach(AbstractRequirement::detach); - } - - /** - * Called when the stage loads - */ - public void load() { - propagateStageHandlers(handler -> handler.stageLoad(this)); - } - - @EventHandler - public void onJoin(PlayerAccountJoinEvent e) { - if (e.isFirstJoin()) return; - if (branch.hasStageLaunched(e.getPlayerAccount(), this)) { - joins(e.getPlayerAccount(), e.getPlayer()); - } - } - - @EventHandler - public void onLeave(PlayerAccountLeaveEvent e) { - if (branch.hasStageLaunched(e.getPlayerAccount(), this)) { - leaves(e.getPlayerAccount(), e.getPlayer()); - } - } - - /** - * @deprecated for removal, {@link #serialize(ConfigurationSection)} should be used instead. - */ - @Deprecated - protected void serialize(Map<String, Object> map) {} - - protected void serialize(@NotNull ConfigurationSection section) { - Map<String, Object> map = new HashMap<>(); - serialize(map); - Utils.setConfigurationSectionContent(section, map); - } - - public final void save(@NotNull ConfigurationSection section) { - serialize(section); - - section.set("stageType", type.getID()); - section.set("customText", customText); - if (startMessage != null) section.set("text", startMessage); - - if (!rewards.isEmpty()) section.set("rewards", SerializableObject.serializeList(rewards)); - if (!validationRequirements.isEmpty()) section.set("requirements", SerializableObject.serializeList(validationRequirements)); - - options.stream().filter(StageOption::shouldSave).forEach(option -> option.save(section.createSection("options." + option.getCreator().getID()))); - } - - public static @NotNull AbstractStage deserialize(@NotNull ConfigurationSection section, @NotNull QuestBranch branch) { - String typeID = section.getString("stageType"); - - Optional<StageType<?>> stageTypeOptional = QuestsAPI.getStages().getType(typeID); - if (!stageTypeOptional.isPresent()) { - BeautyQuests.getInstance().getLogger().severe("Unknown stage type : " + typeID); - return null; - } - - StageType<?> stageType = stageTypeOptional.get(); - if (!stageType.isValid()) { - BeautyQuests.getInstance().getLogger().severe("The stage " + typeID + " requires not enabled dependencies: " + Arrays.toString(stageType.dependencies)); - return null; - } - - AbstractStage st = stageType.getLoader().supply(section, branch); - if (section.contains("text")) st.startMessage = section.getString("text"); - if (section.contains("customText")) st.customText = section.getString("customText"); - if (section.contains("rewards")) st.setRewards(QuestObject.deserializeList(section.getMapList("rewards"), AbstractReward::deserialize)); - if (section.contains("requirements")) st.setValidationRequirements(QuestObject.deserializeList(section.getMapList("requirements"), AbstractRequirement::deserialize)); - - st.options = stageType.getOptionsRegistry().getCreators().stream().map(SerializableCreator::newObject).collect(Collectors.toList()); - if (section.contains("options")) { - ConfigurationSection optionsSection = section.getConfigurationSection("options"); - optionsSection.getKeys(false).forEach(optionID -> { - st.options - .stream() - .filter(option -> option.getCreator().getID().equals(optionID)) - .findAny() - .ifPresent(option -> option.load(optionsSection.getConfigurationSection(optionID))); - }); - - } - - return st; - } -} diff --git a/core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java b/core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java deleted file mode 100644 index 66154747..00000000 --- a/core/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.skytasul.quests.api.stages; - -import org.bukkit.entity.Player; -import fr.skytasul.quests.players.PlayerAccount; - -public interface StageHandler { - - default void stageStart(PlayerAccount acc, AbstractStage stage) {} - - default void stageEnd(PlayerAccount acc, AbstractStage stage) {} - - default void stageJoin(PlayerAccount acc, Player p, AbstractStage stage) {} - - default void stageLeave(PlayerAccount acc, Player p, AbstractStage stage) {} - - default void stageLoad(AbstractStage stage) {} - - default void stageUnload(AbstractStage stage) {} - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 6f12fa6f..b4d838db 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -10,30 +10,30 @@ import java.nio.file.Path; import java.sql.SQLException; import org.bukkit.Material; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.commands.OutsideEditor; +import fr.skytasul.quests.api.editors.SelectNPC; +import fr.skytasul.quests.api.gui.templates.ConfirmGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.editors.Editor; -import fr.skytasul.quests.editors.SelectNPC; -import fr.skytasul.quests.gui.Inventories; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.gui.creation.QuestCreationSession; -import fr.skytasul.quests.gui.misc.ConfirmGUI; import fr.skytasul.quests.gui.misc.ListBook; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; import fr.skytasul.quests.players.AdminMode; -import fr.skytasul.quests.players.PlayersManager; import fr.skytasul.quests.players.PlayersManagerDB; import fr.skytasul.quests.players.PlayersManagerYAML; -import fr.skytasul.quests.structure.Quest; import fr.skytasul.quests.utils.Database; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.MinecraftNames; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.nms.NMS; import revxrsal.commands.annotation.Flag; import revxrsal.commands.annotation.Optional; @@ -54,7 +54,7 @@ public void create(Player player, @Optional @Flag Integer id) { QuestCreationSession session = new QuestCreationSession(); if (id != null) { if (id.intValue() < 0) throw new CommandErrorException(Lang.NUMBER_NEGATIVE.toString()); - if (QuestsAPI.getQuests().getQuest(id) != null) + if (QuestsAPI.getAPI().getQuestsManager().getQuest(id) != null) throw new CommandErrorException("Invalid quest ID: another quest exists with ID {0}", id); session.setCustomID(id); @@ -73,14 +73,13 @@ public void edit(Player player, @Optional Quest quest) { new SelectNPC(player, () -> {}, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { - new ChooseQuestGUI(npc.getQuests(), questClicked -> { - if (questClicked == null) return; - new QuestCreationSession(questClicked).openMainGUI(player); - }).create(player); + ChooseQuestGUI.choose(player, npc.getQuests(), clickedQuest -> { + new QuestCreationSession(clickedQuest).openMainGUI(player); + }, null, false); }else { Lang.NPC_NOT_QUEST.send(player); } - }).enter(); + }).start(); } } @@ -89,32 +88,31 @@ public void edit(Player player, @Optional Quest quest) { @OutsideEditor public void remove(BukkitCommandActor actor, @Optional Quest quest) { if (quest != null) { - remove(actor.getSender(), quest); + doRemove(actor, quest); }else { Lang.CHOOSE_NPC_STARTER.send(actor.requirePlayer()); new SelectNPC(actor.getAsPlayer(), () -> {}, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { - new ChooseQuestGUI(npc.getQuests(), questClicked -> { - if (questClicked == null) return; - remove(actor.getSender(), questClicked); - }).create(actor.getAsPlayer()); + ChooseQuestGUI.choose(actor.getAsPlayer(), npc.getQuests(), clickedQuest -> { + doRemove(actor, clickedQuest); + }, null, false); }else { Lang.NPC_NOT_QUEST.send(actor.getAsPlayer()); } - }).enter(); + }).start(); } } - private void remove(CommandSender sender, Quest quest) { - if (sender instanceof Player) { - Inventories.create((Player) sender, new ConfirmGUI(() -> { - quest.remove(true, true); - Lang.SUCCESFULLY_REMOVED.send(sender, quest.getName()); - }, ((Player) sender)::closeInventory, Lang.INDICATION_REMOVE.format(quest.getName()))); + private void doRemove(BukkitCommandActor sender, Quest quest) { + if (sender.isPlayer()) { + ConfirmGUI.confirm(() -> { + quest.delete(false, false); + Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getName()); + }, null, Lang.INDICATION_REMOVE.format(quest.getName())).open(sender.getAsPlayer()); }else { - quest.remove(true, true); - Lang.SUCCESFULLY_REMOVED.send(sender, quest.getName()); + quest.delete(false, false); + Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getName()); } } @@ -131,7 +129,7 @@ public void save(BukkitCommandActor actor) { try { BeautyQuests.getInstance().saveAllConfig(false); actor.reply("§aDatas saved!"); - BeautyQuests.logger.info("Datas saved ~ manual save from " + actor.getName()); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Datas saved ~ manual save from " + actor.getName()); }catch (Throwable e) { e.printStackTrace(); actor.error("Error while saving the data file."); @@ -144,7 +142,7 @@ public void backup(BukkitCommandActor actor, @Switch boolean force) { if (!force) save(actor); boolean success = true; - BeautyQuests.logger.info("Creating backup due to " + actor.getName() + "'s manual command."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Creating backup due to " + actor.getName() + "'s manual command."); Path backup = BeautyQuests.getInstance().backupDir(); if (!BeautyQuests.getInstance().createFolderBackup(backup)) { Lang.BACKUP_QUESTS_FAILED.send(actor.getSender()); @@ -166,15 +164,15 @@ public void adminMode(BukkitCommandActor actor) { @Subcommand ("exitEditor") @SecretCommand public void exitEditor(Player player) { - Editor.leave(player); - Inventories.closeAndExit(player); + QuestsPlugin.getPlugin().getGuiManager().closeAndExit(player); + QuestsPlugin.getPlugin().getEditorManager().leave(player); } @Subcommand ("reopenInventory") @SecretCommand public void reopenInventory(Player player) { - if (Inventories.isInSystem(player)) { - Inventories.openInventory(player); + if (QuestsPlugin.getPlugin().getGuiManager().hasGuiOpened(player)) { + QuestsPlugin.getPlugin().getGuiManager().getOpenedGui(player).open(player); } } @@ -183,19 +181,20 @@ public void reopenInventory(Player player) { public void list(Player player) { if (NMS.isValid()) { ListBook.openQuestBook(player); - }else Utils.sendMessage(player, "Version not supported"); + } else + MessageUtils.sendPrefixedMessage(player, "Version not supported"); } @Subcommand ("downloadTranslations") @CommandPermission ("beautyquests.command.manage") public void downloadTranslations(BukkitCommandActor actor, @Optional String lang, @Switch boolean overwrite) { - if (NMS.getMCVersion() < 13) + if (MinecraftVersion.MAJOR < 13) throw new CommandErrorException(Lang.VERSION_REQUIRED.format("≥ 1.13")); if (lang == null) throw new CommandErrorException(Lang.COMMAND_TRANSLATION_SYNTAX.toString()); - String version = NMS.getVersionString(); + String version = MinecraftVersion.VERSION_STRING; String url = MinecraftNames.LANG_DOWNLOAD_URL.replace("%version%", version).replace("%language%", lang); try { @@ -215,7 +214,7 @@ public void downloadTranslations(BukkitCommandActor actor, @Optional String lang throw new CommandErrorException(Lang.COMMAND_TRANSLATION_NOT_FOUND.format(lang, version)); } }catch (IOException e) { - BeautyQuests.logger.severe("An error occurred while downloading translation.", e); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while downloading translation.", e); throw new CommandErrorException(Lang.ERROR_OCCURED.format("IO Exception when downloading translation.")); } } @@ -223,27 +222,28 @@ public void downloadTranslations(BukkitCommandActor actor, @Optional String lang @Subcommand ("migrateDatas") @CommandPermission ("beautyquests.command.manage") public void migrateDatas(BukkitCommandActor actor) { - if (!(PlayersManager.manager instanceof PlayersManagerYAML)) + if (!(QuestsPlugin.getPlugin().getPlayersManager() instanceof PlayersManagerYAML)) throw new CommandErrorException("§cYou can't migrate YAML datas to a DB system if you are already using the DB system."); - Utils.runAsync(() -> { + QuestUtils.runAsync(() -> { actor.reply("§aConnecting to the database."); try (Database db = new Database(BeautyQuests.getInstance().getConfig().getConfigurationSection("database"))) { db.testConnection(); actor.reply("§aConnection to database etablished."); final Database fdb = db; - Utils.runSync(() -> { + QuestUtils.runSync(() -> { actor.reply("§aStarting migration..."); try { - actor.reply(PlayersManagerDB.migrate(fdb, (PlayersManagerYAML) PlayersManager.manager)); + actor.reply(PlayersManagerDB.migrate(fdb, + (PlayersManagerYAML) QuestsPlugin.getPlugin().getPlayersManager())); }catch (Exception ex) { actor.error("An exception occured during migration. Process aborted. " + ex.getMessage()); - BeautyQuests.logger.severe("Error during data migration", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error during data migration", ex); } }); }catch (SQLException ex) { actor.error("§cConnection to database has failed. Aborting. " + ex.getMessage()); - BeautyQuests.logger.severe("An error occurred while connecting to the database for datas migration.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while connecting to the database for datas migration.", ex); } }); } @@ -283,9 +283,9 @@ public void setFirework(Player player, @Switch boolean remove) { @Subcommand ("testNPC") @CommandPermission (value = "beautyquests.command.create") @SecretCommand - public void testNPC(BukkitCommandActor actor, BQNPC npc) { - Utils.sendMessage(actor.getSender(), npc.toString()); + public String testNPC(BukkitCommandActor actor, BQNPC npc) { npc.toggleDebug(); + return npc.toString(); } public enum ItemHologram { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsManager.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java similarity index 70% rename from core/src/main/java/fr/skytasul/quests/commands/CommandsManager.java rename to core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java index e3c25e64..2faeb350 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManager.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -9,14 +9,15 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.commands.CommandsManager; +import fr.skytasul.quests.api.commands.OutsideEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.editors.Editor; -import fr.skytasul.quests.gui.Inventories; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.scoreboards.Scoreboard; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; import revxrsal.commands.autocomplete.SuggestionProvider; import revxrsal.commands.bukkit.BukkitCommandActor; import revxrsal.commands.bukkit.BukkitCommandHandler; @@ -26,53 +27,53 @@ import revxrsal.commands.orphan.OrphanCommand; import revxrsal.commands.orphan.Orphans; -public class CommandsManager { +public class CommandsManagerImplementation implements CommandsManager { private static String[] COMMAND_ALIASES = { "quests", "quest", "bq", "beautyquests", "bquests" }; private BukkitCommandHandler handler; private boolean locked = false; - public CommandsManager() { + public CommandsManagerImplementation() { handler = BukkitCommandHandler.create(BeautyQuests.getInstance()); handler.setMessagePrefix(QuestsConfiguration.getPrefix()); handler.failOnTooManyArguments(); handler.registerValueResolver(Quest.class, context -> { int id = context.popInt(); - Quest quest = QuestsAPI.getQuests().getQuest(id); + Quest quest = QuestsAPI.getAPI().getQuestsManager().getQuest(id); if (quest == null) throw new CommandErrorException(Lang.QUEST_INVALID.format(id)); return quest; }); handler.getAutoCompleter().registerParameterSuggestions(Quest.class, - SuggestionProvider.of(() -> QuestsAPI.getQuests().getQuests() + SuggestionProvider.of(() -> QuestsAPI.getAPI().getQuestsManager().getQuests() .stream() - .map(quest -> Integer.toString(quest.getID())) + .map(quest -> Integer.toString(quest.getId())) .collect(Collectors.toList()))); handler.registerValueResolver(QuestPool.class, context -> { int id = context.popInt(); - QuestPool pool = QuestsAPI.getQuestPools().getPool(id); + QuestPool pool = QuestsAPI.getAPI().getPoolsManager().getPool(id); if (pool == null) throw new CommandErrorException(Lang.POOL_INVALID.format(id)); return pool; }); handler.getAutoCompleter().registerParameterSuggestions(QuestPool.class, - SuggestionProvider.of(() -> QuestsAPI.getQuestPools().getPools() + SuggestionProvider.of(() -> QuestsAPI.getAPI().getPoolsManager().getPools() .stream() - .map(pool -> Integer.toString(pool.getID())) + .map(pool -> Integer.toString(pool.getId())) .collect(Collectors.toList()))); handler.registerValueResolver(BQNPC.class, context -> { int id = context.popInt(); - BQNPC npc = QuestsAPI.getNPCsManager().getById(id); + BQNPC npc = QuestsAPI.getAPI().getNPCsManager().getById(id); if (npc == null) throw new CommandErrorException(Lang.NPC_DOESNT_EXIST.format(id)); return npc; }); handler.getAutoCompleter().registerParameterSuggestions(BQNPC.class, - SuggestionProvider.of(() -> QuestsAPI.getNPCsManager().getIDs() + SuggestionProvider.of(() -> QuestsAPI.getAPI().getNPCsManager().getIDs() .stream() .map(String::valueOf) .collect(Collectors.toList()))); @@ -80,7 +81,9 @@ public CommandsManager() { handler.registerCondition((@NotNull CommandActor actor, @NotNull ExecutableCommand command, @NotNull @Unmodifiable List<String> arguments) -> { if (command.hasAnnotation(OutsideEditor.class)) { BukkitCommandActor bukkitActor = (BukkitCommandActor) actor; - if (bukkitActor.isPlayer() && (Inventories.isInSystem(bukkitActor.getAsPlayer()) || Editor.hasEditor(bukkitActor.getAsPlayer()))) + if (bukkitActor.isPlayer() + && (QuestsPlugin.getPlugin().getGuiManager().hasGuiOpened(bukkitActor.getAsPlayer()) + || QuestsPlugin.getPlugin().getEditorManager().isInEditor(bukkitActor.getAsPlayer()))) throw new CommandErrorException(Lang.ALREADY_EDITOR.toString()); } }); @@ -96,15 +99,20 @@ public CommandsManager() { return null; }); + handler.registerResponseHandler(String.class, (msg, actor, command) -> { + MessageUtils.sendPrefixedMessage(((BukkitCommandActor) actor).getSender(), msg); + }); + handler.registerContextResolver(Scoreboard.class, context -> { return BeautyQuests.getInstance().getScoreboardManager().getPlayerScoreboard(context.getResolvedArgument(Player.class)); }); handler.registerCondition((actor, command, arguments) -> { - DebugUtils.logMessage(actor.getName() + " executed command: " + command.getPath().toRealString() + " " + String.join(" ", arguments)); + QuestsPlugin.getPlugin().getLoggerExpanded().debug(actor.getName() + " executed command: " + command.getPath().toRealString() + " " + String.join(" ", arguments)); }); } + @Override public BukkitCommandHandler getHandler() { return handler; } @@ -117,6 +125,7 @@ public void initializeCommands() { registerCommands("pools", new CommandsPools()); } + @Override public void registerCommands(String subpath, OrphanCommand... commands) { Orphans path; if (subpath == null || subpath.isEmpty()) { @@ -125,7 +134,7 @@ public void registerCommands(String subpath, OrphanCommand... commands) { path = Orphans.path(Arrays.stream(COMMAND_ALIASES).map(x -> x + " " + subpath).toArray(String[]::new)); } handler.register(Arrays.stream(commands).map(path::handler).toArray()); - // if (locked) BeautyQuests.logger.warning("Registered commands after final locking."); + // if (locked) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Registered commands after final locking."); } public void lockCommands() { @@ -133,7 +142,7 @@ public void lockCommands() { locked = true; handler.getBrigadier().ifPresent(brigadier -> { brigadier.register(); - DebugUtils.logMessage("Brigadier registered!"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Brigadier registered!"); }); } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java index 456e2239..a06c783e 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java @@ -2,16 +2,16 @@ import java.util.Optional; import org.bukkit.entity.Player; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.gui.quests.PlayerListGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.players.PlayersManager; import fr.skytasul.quests.rewards.CheckpointReward; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.Lang; import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Subcommand; import revxrsal.commands.bukkit.BukkitCommandActor; @@ -28,9 +28,9 @@ public void menu(BukkitCommandActor actor, ExecutableCommand command, @revxrsal. if (subcommand != null) throw new revxrsal.commands.exception.InvalidSubcommandException(command.getPath(), subcommand); PlayerAccount acc = PlayersManager.getPlayerAccount(actor.requirePlayer()); if (acc == null) { - BeautyQuests.logger.severe("Player " + actor.getName() + " has got no account. This is a CRITICAL issue."); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Player " + actor.getName() + " has got no account. This is a CRITICAL issue."); throw new CommandErrorException("no player datas"); - }else new PlayerListGUI(acc).create(actor.getAsPlayer()); + }else new PlayerListGUI(acc).open(actor.getAsPlayer()); } @Subcommand ("checkpoint") @@ -40,9 +40,12 @@ public void checkpoint(Player player, Quest quest) { if (account.hasQuestDatas(quest)) { PlayerQuestDatas datas = account.getQuestDatas(quest); QuestBranch branch = quest.getBranchesManager().getBranch(datas.getBranch()); - int max = datas.isInEndingStages() ? branch.getStageSize() : datas.getStage(); + int max = datas.isInEndingStages() ? branch.getRegularStages().size() : datas.getStage(); + + // TODO: should use quest flow + for (int id = max - 1; id >= 0; id--) { - AbstractStage stage = branch.getRegularStage(id); + AbstractStage stage = branch.getRegularStage(id).getStage(); Optional<CheckpointReward> optionalCheckpoint = stage.getRewards().stream().filter(CheckpointReward.class::isInstance).findAny().map(CheckpointReward.class::cast); if (optionalCheckpoint.isPresent()) { optionalCheckpoint.get().applies(player); 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 0c5a6c7c..3558acdc 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java @@ -8,26 +8,31 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.Permission; +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; import fr.skytasul.quests.api.events.accounts.PlayerAccountResetEvent; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner.DialogNextReason; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerPoolDatas; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.branches.EndingStage; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.gui.quests.QuestsListGUI; import fr.skytasul.quests.options.OptionStartDialog; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerPoolDatas; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.BranchesManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.types.DialogRunner; -import fr.skytasul.quests.utils.types.DialogRunner.DialogNextReason; +import fr.skytasul.quests.structure.BranchesManagerImplementation; +import fr.skytasul.quests.structure.EndingStageImplementation; +import fr.skytasul.quests.structure.QuestBranchImplementation; +import fr.skytasul.quests.utils.QuestUtils; import revxrsal.commands.annotation.Optional; import revxrsal.commands.annotation.Range; import revxrsal.commands.annotation.Subcommand; @@ -53,12 +58,13 @@ public void finishAll(BukkitCommandActor actor, EntitySelector<Player> players) PlayerAccount acc = PlayersManager.getPlayerAccount(player); int success = 0; int errors = 0; - for (Quest q : QuestsAPI.getQuests().getQuestsStarted(acc)) { + for (Quest q : QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc)) { try { q.finish(player); success++; }catch (Exception ex) { - BeautyQuests.logger.severe("An error occurred while finishing quest " + q.getID(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("An error occurred while finishing quest " + q.getId(), ex); errors++; } } @@ -76,7 +82,8 @@ public void finish(BukkitCommandActor actor, EntitySelector<Player> players, Que Lang.LEAVE_ALL_RESULT.send(actor.getSender(), 1, 0); } }catch (Exception ex) { - BeautyQuests.logger.severe("An error occurred while finishing quest " + quest.getID(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("An error occurred while finishing quest " + quest.getId(), ex); Lang.LEAVE_ALL_RESULT.send(actor.getSender(), 1, 1); } } @@ -90,8 +97,9 @@ public void setStage( Quest quest, @Range (min = 0, max = 14) @Optional Integer branchID, @Range (min = 0, max = 14) @Optional Integer stageID) { + // syntax: no arg: next or start | 1 arg: start branch | 2 args: set branch stage PlayerAccount acc = PlayersManager.getPlayerAccount(player); - BranchesManager manager = quest.getBranchesManager(); // syntax: no arg: next or start | 1 arg: start branch | 2 args: set branch stage + BranchesManagerImplementation manager = (BranchesManagerImplementation) quest.getBranchesManager(); PlayerQuestDatas datas = acc.getQuestDatasIfPresent(quest); if (branchID == null && (datas == null || !datas.hasStarted())) { // start quest @@ -101,7 +109,7 @@ public void setStage( } if (datas == null) datas = acc.getQuestDatas(quest); // creates quest datas - QuestBranch currentBranch = manager.getBranch(datas.getBranch()); + QuestBranchImplementation currentBranch = manager.getBranch(datas.getBranch()); if (branchID == null) { // next if (!datas.isInEndingStages()) { @@ -109,7 +117,7 @@ public void setStage( Lang.COMMAND_SETSTAGE_NEXT.send(actor.getSender()); }else Lang.COMMAND_SETSTAGE_NEXT_UNAVAILABLE.send(actor.getSender()); }else { - QuestBranch branch = manager.getBranch(branchID); + QuestBranchImplementation branch = manager.getBranch(branchID); if (branch == null) throw new CommandErrorException(Lang.COMMAND_SETSTAGE_BRANCH_DOESNTEXIST.format(branchID)); @@ -122,7 +130,8 @@ public void setStage( Lang.COMMAND_SETSTAGE_SET.send(actor.getSender(), stageID); if (currentBranch != null) { if (datas.isInEndingStages()) { - for (AbstractStage stage : currentBranch.getEndingStages().keySet()) stage.end(acc); + for (EndingStage stage : currentBranch.getEndingStages()) + ((EndingStageImplementation) stage).getStage().end(acc); }else { currentBranch.getRegularStage(datas.getStage()).end(acc); } @@ -133,7 +142,7 @@ public void setStage( datas.setBranch(branchID); branch.setStage(acc, stageID); } - QuestsAPI.propagateQuestsHandlers(handler -> handler.questUpdated(acc, player, quest)); + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questUpdated(acc, quest)); } } @@ -153,7 +162,8 @@ public void startDialog(BukkitCommandActor actor, Player player, Quest quest) { Lang.COMMAND_STARTDIALOG_IMPOSSIBLE.send(actor.getSender()); return; }else { - AbstractStage stage = quest.getBranchesManager().getBranch(datas.getBranch()).getRegularStage(datas.getStage()); + AbstractStage stage = + quest.getBranchesManager().getBranch(datas.getBranch()).getRegularStage(datas.getStage()).getStage(); if (stage instanceof Dialogable) { runner = ((Dialogable) stage).getDialogRunner(); } @@ -167,7 +177,7 @@ public void startDialog(BukkitCommandActor actor, Player player, Quest quest) { Lang.COMMAND_STARTDIALOG_ALREADY.send(actor.getSender()); }else { runner.handleNext(player, DialogNextReason.COMMAND); - Lang.COMMAND_STARTDIALOG_SUCCESS.send(actor.getSender(), player.getName(), quest.getID()); + Lang.COMMAND_STARTDIALOG_SUCCESS.send(actor.getSender(), player.getName(), quest.getId()); } } } @@ -181,20 +191,23 @@ public void resetPlayer(BukkitCommandActor actor, EntitySelector<Player> players List<CompletableFuture<?>> futures = new ArrayList<>(acc.getQuestsDatas().size() + acc.getPoolDatas().size()); int quests = 0, pools = 0; - for (PlayerQuestDatas questDatas : new ArrayList<>(acc.getQuestsDatas())) { + for (@NotNull + PlayerQuestDatas questDatas : new ArrayList<>(acc.getQuestsDatas())) { Quest quest = questDatas.getQuest(); CompletableFuture<?> future = quest == null ? acc.removeQuestDatas(questDatas.getQuestID()) : quest.resetPlayer(acc); - future = future.whenComplete(BeautyQuests.logger.logError("An error occurred while resetting quest " + future = future.whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError("An error occurred while resetting quest " + questDatas.getQuestID() + " to player " + player.getName(), actor.getSender())); futures.add(future); quests++; } - for (PlayerPoolDatas poolDatas : new ArrayList<>(acc.getPoolDatas())) { + for (@NotNull + PlayerPoolDatas poolDatas : new ArrayList<>(acc.getPoolDatas())) { + @Nullable QuestPool pool = poolDatas.getPool(); CompletableFuture<?> future = pool == null ? acc.removePoolDatas(poolDatas.getPoolID()) : pool.resetPlayer(acc); - future = future.whenComplete(BeautyQuests.logger.logError( + future = future.whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError( "An error occurred while resetting pool " + poolDatas.getPoolID() + " to player " + player.getName(), actor.getSender())); futures.add(future); @@ -204,7 +217,8 @@ public void resetPlayer(BukkitCommandActor actor, EntitySelector<Player> players final int questsFinal = quests; final int poolsFinal = pools; - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).whenComplete(Utils.runSyncConsumer(() -> { + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .whenComplete(QuestUtils.runSyncConsumer(() -> { Bukkit.getPluginManager().callEvent(new PlayerAccountResetEvent(acc)); if (acc.isCurrent()) Lang.DATA_REMOVED.send(player, questsFinal, actor.getName(), poolsFinal); @@ -223,12 +237,12 @@ public void resetPlayerQuest(BukkitCommandActor actor, Player player, @Optional }else { new QuestsListGUI(obj -> { reset(actor.getSender(), player, acc, obj); - }, acc, true, false, true).create(actor.requirePlayer()); + }, acc, true, false, true).open(actor.requirePlayer()); } } private void reset(CommandSender sender, Player target, PlayerAccount acc, Quest qu) { - qu.resetPlayer(acc).whenComplete(BeautyQuests.logger.logError(__ -> { + qu.resetPlayer(acc).whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError(__ -> { if (acc.isCurrent()) Lang.DATA_QUEST_REMOVED.send(target, qu.getName(), sender.getName()); Lang.DATA_QUEST_REMOVED_INFO.send(sender, target.getName(), qu.getName()); @@ -242,8 +256,8 @@ public void resetQuest(BukkitCommandActor actor, Quest quest) { for (Player p : Bukkit.getOnlinePlayers()) { futures.add(quest.resetPlayer(PlayersManager.getPlayerAccount(p)) - .whenComplete(BeautyQuests.logger.logError( - "An error occurred while resetting quest " + quest.getID() + " to player " + p.getName(), + .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError( + "An error occurred while resetting quest " + quest.getId() + " to player " + p.getName(), actor.getSender()))); } @@ -263,22 +277,24 @@ public void resetQuest(BukkitCommandActor actor, Quest quest) { }).count(); BeautyQuests.getInstance().getPlayersManager().removeQuestDatas(quest) - .whenComplete(BeautyQuests.logger.logError(removedAmount -> { + .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError(removedAmount -> { Lang.QUEST_PLAYERS_REMOVED.send(actor.getSender(), removedAmount + resetAmount); }, "An error occurred while removing quest datas", actor.getSender())); - }).whenComplete(BeautyQuests.logger.logError()); + }).whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError()); } @Subcommand ("seePlayer") @CommandPermission ("beautyquests.command.seePlayer") public void seePlayer(Player actor, Player player) { - new PlayerListGUI(PlayersManager.getPlayerAccount(player), false).create(actor); + new PlayerListGUI(PlayersManager.getPlayerAccount(player), false).open(actor); } @Subcommand ("start") @CommandPermission ("beautyquests.command.start") - public void start(BukkitCommandActor actor, ExecutableCommand command, EntitySelector<Player> players, @Optional Quest quest, @CommandPermission ("beautyquests.command.start.other") @Switch boolean overrideRequirements) { + public void start(BukkitCommandActor actor, ExecutableCommand command, EntitySelector<Player> players, + @Optional Quest quest, + @CommandPermission("beautyquests.command.start.other") @Switch boolean overrideRequirements) { if (actor.isPlayer() && !startOtherPermission.canExecute(actor)) { if (players.isEmpty() || players.size() > 1 || (players.get(0) != actor.getAsPlayer())) throw new NoPermissionException(command, startOtherPermission); @@ -290,15 +306,16 @@ public void start(BukkitCommandActor actor, ExecutableCommand command, EntitySel if (quest == null) { new QuestsListGUI(obj -> { start(actor.getSender(), player, acc, obj, overrideRequirements); - }, acc, false, true, false).create(actor.requirePlayer()); + }, acc, false, true, false).open(actor.requirePlayer()); }else { start(actor.getSender(), player, acc, quest, overrideRequirements); } } } - private void start(CommandSender sender, Player player, PlayerAccount acc, Quest quest, boolean overrideRequirements) { - if (!overrideRequirements && !(quest.isLauncheable(player, acc, true) && quest.testTimer(acc, true))) { + private void start(CommandSender sender, Player player, PlayerAccount acc, Quest quest, + boolean overrideRequirements) { + if (!overrideRequirements && !quest.canStart(player, true)) { Lang.START_QUEST_NO_REQUIREMENT.send(sender, quest.getName()); return; } @@ -308,7 +325,8 @@ private void start(CommandSender sender, Player player, PlayerAccount acc, Quest @Subcommand ("cancel") @CommandPermission ("beautyquests.command.cancel") - public void cancel(BukkitCommandActor actor, ExecutableCommand command, EntitySelector<Player> players, @Optional Quest quest) { + public void cancel(BukkitCommandActor actor, ExecutableCommand command, EntitySelector<Player> players, + @Optional Quest quest) { if (actor.isPlayer() && !cancelOtherPermission.canExecute(actor)) { if (players.isEmpty() || players.size() > 1 || (players.get(0) != actor.getAsPlayer())) throw new NoPermissionException(command, cancelOtherPermission); @@ -320,7 +338,7 @@ public void cancel(BukkitCommandActor actor, ExecutableCommand command, EntitySe if (quest == null) { new QuestsListGUI(obj -> { cancel(actor.getSender(), acc, obj); - }, acc, true, false, false).create(actor.requirePlayer()); + }, acc, true, false, false).open(actor.requirePlayer()); }else { cancel(actor.getSender(), acc, quest); } @@ -340,7 +358,7 @@ private void cancel(CommandSender sender, PlayerAccount acc, Quest quest) { Lang.QUEST_NOT_STARTED.send(sender); } else { Lang.ERROR_OCCURED.send(sender, - "Player " + acc.getName() + " does not have the quest " + quest.getID() + " started."); + "Player " + acc.getName() + " does not have the quest " + quest.getId() + " started."); } } } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index 0fb551a2..4eb6580c 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.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.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.gui.pools.PoolsManageGUI; import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.structure.pools.QuestPoolImplementation; import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Subcommand; import revxrsal.commands.annotation.Switch; @@ -19,35 +19,35 @@ public class CommandsPools implements OrphanCommand { @Default @CommandPermission("beautyquests.command.pools") public void pools(Player player) { - PoolsManageGUI.get().create(player); + PoolsManageGUI.get().open(player); } @Subcommand("resetPlayer") @CommandPermission("beautyquests.command.resetPlayer") - public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPool pool, @Switch boolean timer) { + public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPoolImplementation pool, @Switch boolean timer) { PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (timer) { pool.resetPlayerTimer(acc); - Lang.POOL_RESET_TIMER.send(actor.getSender(), pool.getID(), player.getName()); + Lang.POOL_RESET_TIMER.send(actor.getSender(), pool.getId(), player.getName()); } else { - pool.resetPlayer(acc).whenComplete(BeautyQuests.logger.logError(__ -> { - Lang.POOL_RESET_FULL.send(actor.getSender(), pool.getID(), player.getName()); - }, "An error occurred while resetting pool " + pool.getID() + " to player " + player.getName(), + pool.resetPlayer(acc).whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError(__ -> { + Lang.POOL_RESET_FULL.send(actor.getSender(), pool.getId(), player.getName()); + }, "An error occurred while resetting pool " + pool.getId() + " to player " + player.getName(), actor.getSender())); } } @Subcommand("start") @CommandPermission("beautyquests.command.pools.start") - public void start(BukkitCommandActor actor, Player player, QuestPool pool) { + public void start(BukkitCommandActor actor, Player player, QuestPoolImplementation pool) { PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (!pool.canGive(player, acc)) { - Lang.POOL_START_ERROR.send(player, pool.getID(), player.getName()); + Lang.POOL_START_ERROR.send(player, pool.getId(), player.getName()); return; } - pool.give(player).thenAccept(result -> Lang.POOL_START_SUCCESS.send(player, pool.getID(), player.getName(), result)); + pool.give(player).thenAccept(result -> Lang.POOL_START_SUCCESS.send(player, pool.getId(), player.getName(), result)); } } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java index fc90f428..f9eaa7d9 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java @@ -1,8 +1,8 @@ package fr.skytasul.quests.commands; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.MessageUtils; import revxrsal.commands.annotation.Command; import revxrsal.commands.annotation.Description; import revxrsal.commands.annotation.Subcommand; @@ -18,13 +18,13 @@ public class CommandsRoot { @Subcommand ("help") public void help(BukkitCommandActor actor, CommandHelp<String> helpEntries) { Lang.COMMAND_HELP.sendWP(actor.getSender()); - helpEntries.forEach(help -> Utils.sendMessageWP(actor.getSender(), help)); + helpEntries.forEach(help -> MessageUtils.sendUnprefixedMessage(actor.getSender(), help)); } @Subcommand ("version") @CommandPermission ("beautyquests.command.version") - public void version(BukkitCommandActor actor) { - actor.reply("§eBeautyQuests version : §6§l" + BeautyQuests.getInstance().getDescription().getVersion()); + public String version() { + return "§eBeautyQuests version : §6§l" + BeautyQuests.getInstance().getDescription().getVersion(); } } 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 4ca70c7d..77c89268 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java @@ -2,8 +2,8 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.scoreboards.Scoreboard; -import fr.skytasul.quests.utils.Lang; import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Optional; import revxrsal.commands.annotation.Range; diff --git a/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java new file mode 100644 index 00000000..a357de84 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java @@ -0,0 +1,100 @@ +package fr.skytasul.quests.editor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.BossBarManager.BQBossBar; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.Editor; +import fr.skytasul.quests.api.editors.EditorManager; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.utils.QuestUtils; + +public class EditorManagerImplementation implements EditorManager, Listener { + + private final @NotNull Map<Player, Editor> players = new HashMap<>(); + private final @Nullable BQBossBar bar; + + public EditorManagerImplementation() { + if (QuestsAPI.getAPI().hasBossBarManager()) { + bar = QuestsAPI.getAPI().getBossBarManager().buildBossBar("§6Quests Editor", "YELLOW", "SOLID"); + bar.setProgress(0); + } else { + bar = null; + } + } + + @Override + public <T extends Editor> T start(@NotNull T editor) { + Player player = editor.getPlayer(); + if (isInEditor(player)) { + Lang.ALREADY_EDITOR.send(player); + throw new IllegalStateException(player.getName() + " is already in an editor"); + } + + players.put(player, editor); + QuestsPlugin.getPlugin().getGuiManager().closeAndExit(player); + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug(player.getName() + " is entering editor " + editor.getClass().getName() + "."); + editor.begin(); + + if (MinecraftVersion.MAJOR > 11) { + player.sendTitle(Lang.ENTER_EDITOR_TITLE.toString(), Lang.ENTER_EDITOR_SUB.toString(), 5, 50, 5); + } else { + Lang.ENTER_EDITOR_TITLE.send(player); + Lang.ENTER_EDITOR_SUB.send(player); + } + if (bar != null) + bar.addPlayer(player); + + return editor; + } + + @Override + public void leave(@NotNull Player player) { + Editor editor = players.remove(player); + if (editor == null) + return; + + QuestsPlugin.getPlugin().getLoggerExpanded().debug(player.getName() + " has left the editor."); + if (bar != null) + bar.removePlayer(player); + editor.end(); + } + + @Override + public void leaveAll() { + new ArrayList<>(players.keySet()).forEach(this::leave); + } + + @Override + public boolean isInEditor(@NotNull Player player) { + return players.containsKey(player); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false) + public void onChat(AsyncPlayerChatEvent e) { + Editor editor = players.get(e.getPlayer()); + if (editor == null) + return; + + e.setCancelled(true); + QuestUtils.runOrSync(() -> editor.callChat(e.getMessage())); + } + + @EventHandler + public void onQuit(PlayerQuitEvent e) { + leave(e.getPlayer()); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java b/core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java deleted file mode 100644 index 2af87d79..00000000 --- a/core/src/main/java/fr/skytasul/quests/editors/DialogEditor.java +++ /dev/null @@ -1,186 +0,0 @@ -package fr.skytasul.quests.editors; - -import org.bukkit.entity.Player; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.types.Dialog; -import fr.skytasul.quests.utils.types.Message; -import fr.skytasul.quests.utils.types.Message.Sender; - -public class DialogEditor extends Editor{ - - private Runnable end; - public Dialog d; - - public DialogEditor(Player p, Runnable end, Dialog dialog) { - super(p, null); - this.end = end; - this.d = dialog; - } - - @Override - public boolean chat(String coloredMessage, String strippedMessage){ - String[] args = strippedMessage.split(" "); - String[] argsColored = coloredMessage.split(" "); - String msg = ""; - boolean hasMsg = false; - Command cmd; - try{ - cmd = Command.valueOf(args[0].toUpperCase()); - }catch (IllegalArgumentException ex){ - Utils.sendMessage(p, Lang.COMMAND_DOESNT_EXIST_NOSLASH.toString()); - return false; - } - if (args.length > 1){ - msg = Utils.buildFromArray(argsColored, 1, " "); - hasMsg = true; - } - switch (cmd) { - - case NOSENDER: - case NPC: - case PLAYER: - if (!hasMsg){ - Lang.DIALOG_SYNTAX.send(p, cmd, ""); - break; - } - d.add(msg, Sender.valueOf(cmd.name())); - Utils.sendMessage(p, Lang.valueOf("DIALOG_MSG_ADDED_" + cmd.name()).toString(), msg, cmd.name().toLowerCase()); - break; - - case REMOVE: - if (!hasMsg){ - Lang.DIALOG_REMOVE_SYNTAX.send(p); - break; - } - try{ - Message removed = d.messages.remove(Integer.parseInt(args[1])); - if (removed != null){ - Utils.sendMessage(p, Lang.DIALOG_MSG_REMOVED.toString(), removed.text); - }else Lang.OUT_OF_BOUNDS.send(p, args[1], 0, d.messages.size()); - }catch (IllegalArgumentException ex){ - Utils.sendMessage(p, Lang.NUMBER_INVALID.toString()); - } - break; - - case LIST: - for (int i = 0; i < d.messages.size(); i++) { - Message dmsg = d.messages.get(i); - Utils.IsendMessage(p, "§6{0}: §7\"{1}§7\"§e by §l{2}", false, i, dmsg.text, dmsg.sender.name().toLowerCase()); - } - break; - - case NOSENDERINSERT: - case NPCINSERT: - case PLAYERINSERT: - if (args.length < 3){ - Lang.DIALOG_SYNTAX.send(p, cmd, " <id>"); - break; - } - try{ - msg = Utils.buildFromArray(argsColored, 2, " "); - Sender sender = Sender.valueOf(cmd.name().replace("INSERT", "")); - d.insert(msg, sender, Integer.parseInt(args[1])); - Utils.sendMessage(p, Lang.valueOf("DIALOG_MSG_ADDED_" + sender.name()).toString(), msg, sender.name().toLowerCase()); - }catch (NumberFormatException ex){ - Lang.NUMBER_INVALID.send(p, args[1]); - } - break; - - case EDIT: - if (args.length < 3){ - Lang.DIALOG_SYNTAX.send(p, cmd, " <id>"); - break; - } - try{ - Message message = d.messages.get(Integer.parseInt(args[1])); - msg = Utils.buildFromArray(argsColored, 2, " "); - message.text = msg; - Lang.DIALOG_MSG_EDITED.send(p, msg); - }catch (IllegalArgumentException ex){ - Utils.sendMessage(p, Lang.NUMBER_INVALID.toString()); - }catch (IndexOutOfBoundsException ex) { - Lang.OBJECT_DOESNT_EXIST.send(p, args[1]); - } - break; - - case ADDSOUND: - if (args.length < 3){ - Utils.sendMessage(p, Lang.TEXTLIST_SYNTAX.toString() + "addSound <id> <sound>"); - break; - } - try{ - Message imsg = d.messages.get(Integer.parseInt(args[1])); - Lang.DIALOG_SOUND_ADDED.send(p, imsg.sound = args[2], args[1]); - }catch (IllegalArgumentException ex){ - Utils.sendMessage(p, Lang.NUMBER_INVALID.toString()); - }catch (IndexOutOfBoundsException ex) { - Lang.OBJECT_DOESNT_EXIST.send(p, args[1]); - } - break; - - case SETTIME: - if (args.length < 3) { - Utils.sendMessage(p, Lang.TEXTLIST_SYNTAX.toString() + "setTime <id> <time in ticks>"); - break; - } - try { - Message imsg = d.messages.get(Integer.parseInt(args[1])); - int time = Integer.parseInt(args[2]); - if (time < 0) { - imsg.wait = -1; - Lang.DIALOG_TIME_REMOVED.send(p, args[1]); - }else { - imsg.wait = time; - Lang.DIALOG_TIME_SET.send(p, args[1], imsg.wait = time); - } - }catch (IllegalArgumentException ex) { - Utils.sendMessage(p, Lang.NUMBER_INVALID.toString()); - }catch (IndexOutOfBoundsException ex) { - Lang.OBJECT_DOESNT_EXIST.send(p, args[1]); - } - break; - - case NPCNAME: - if (args.length < 2) { - Lang.DIALOG_NPCNAME_UNSET.send(p, d.npcName); - d.npcName = null; - }else Lang.DIALOG_NPCNAME_SET.send(p, d.npcName, d.npcName = msg); - break; - - case SKIPPABLE: - String prev = d.getSkippableStatus(); - if (args.length < 2) { - d.skippable = null; - Lang.DIALOG_SKIPPABLE_UNSET.send(p, prev); - }else { - d.skippable = Boolean.parseBoolean(args[1]); - Lang.DIALOG_SKIPPABLE_SET.send(p, prev, d.getSkippableStatus()); - } - break; - - case CLEAR: - Lang.DIALOG_CLEARED.send(p, d.messages.size()); - d.messages.clear(); - break; - - case HELP: - for (Lang l : Lang.values()){ - if (l.getPath().startsWith("msg.editor.dialog.help.")) l.sendWP(p); - } - break; - - case CLOSE: - leave(p); - end.run(); - break; - - } - return true; - } - - private enum Command{ - NPC, PLAYER, NOSENDER, REMOVE, LIST, HELP, CLOSE, NPCINSERT, PLAYERINSERT, NOSENDERINSERT, EDIT, ADDSOUND, SETTIME, NPCNAME, SKIPPABLE, CLEAR; - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/editors/Editor.java b/core/src/main/java/fr/skytasul/quests/editors/Editor.java deleted file mode 100644 index 691c2930..00000000 --- a/core/src/main/java/fr/skytasul/quests/editors/Editor.java +++ /dev/null @@ -1,142 +0,0 @@ -package fr.skytasul.quests.editors; - -import java.util.HashMap; -import java.util.Map; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.bossbar.BQBossBarManager.BQBossBar; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.utils.ChatUtils; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; - -public abstract class Editor implements Listener{ - - private static Map<Player, Editor> players = new HashMap<>(); - private static BQBossBar bar = null; - - static { - if (QuestsAPI.hasBossBarManager()) { - bar = QuestsAPI.getBossBarManager().buildBossBar("§6Quests Editor", "YELLOW", "SOLID"); - bar.setProgress(0); - } - } - - protected final Player p; - protected final Runnable cancel; - - public Editor(Player p, Runnable cancel) { - this.p = p; - this.cancel = cancel; - } - - protected void begin() { - DebugUtils.logMessage(p.getName() + " has entered editor " + getClass().getName() + "."); - Inventories.closeWithoutExit(p); - if (NMS.getMCVersion() > 11){ - p.sendTitle(Lang.ENTER_EDITOR_TITLE.toString(), Lang.ENTER_EDITOR_SUB.toString(), 5, 50, 5); - }else { - Lang.ENTER_EDITOR_TITLE.send(p); - Lang.ENTER_EDITOR_SUB.send(p); - } - if (bar != null) bar.addPlayer(p); - } - - protected void end() { - DebugUtils.logMessage(p.getName() + " has left the editor."); - if (bar != null) bar.removePlayer(p); - } - - protected final void cancel() { - leave(p); - cancel.run(); - } - - @Deprecated - public <T extends Editor> T enterOrLeave(Player p) { - Validate.isTrue(p == this.p); - return enter(); - } - - public <T extends Editor> T enter() { - Editor edit = players.get(p); - if (edit == null) { - begin(); - Bukkit.getPluginManager().registerEvents(this, BeautyQuests.getInstance()); - players.put(p, this); - return (T) this; - } - Utils.sendMessage(p, Lang.ALREADY_EDITOR.toString()); - return null; - } - - /** - * Happens when the player in the editor type somthing in the chat - * @param coloredMessage Message typed - * @param strippedMessage Message without default colors - * @return false if the plugin needs to send an help message to the player - */ - public boolean chat(String coloredMessage, String strippedMessage) { - return false; - } - - private final void callChat(String rawText){ - rawText = rawText.trim().replaceAll("\\uFEFF", ""); // remove blank characters, remove space at the beginning - DebugUtils.logMessage(p.getName() + " entered \"" + rawText + "\" (" + rawText.length() + " characters) in an editor. (name: " + getClass().getName() + ")"); - String coloredMessage = ChatUtils.translateHexColorCodes(ChatColor.translateAlternateColorCodes('&', rawText)); - String strippedMessage = ChatColor.stripColor(rawText); - if (cancel != null && strippedMessage.equalsIgnoreCase(cancelWord())) { - cancel(); - }else if (!chat(coloredMessage, strippedMessage)) { - Lang.CHAT_EDITOR.send(p); - } - } - - protected String cancelWord(){ - return null; - } - - @EventHandler (priority = EventPriority.LOWEST, ignoreCancelled = false) - public void onChat(AsyncPlayerChatEvent e){ - if (e.getPlayer() != p) return; - e.setCancelled(true); - if (e.isAsynchronous()){ - Utils.runSync(() -> callChat(e.getMessage())); - }else callChat(e.getMessage()); - } - - @EventHandler - public void onQuit(PlayerQuitEvent e) { - if (e.getPlayer() == p) leave(p); - } - - public static boolean hasEditor(Player player){ - return players.containsKey(player); - } - - public static void leave(Player player){ - if (!hasEditor(player)) - return; - Editor editor = players.remove(player); - HandlerList.unregisterAll(editor); - editor.end(); - } - - public static void leaveAll(){ - players.keySet().iterator().forEachRemaining(Editor::leave); - players.clear(); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/gui/CustomInventory.java b/core/src/main/java/fr/skytasul/quests/gui/CustomInventory.java deleted file mode 100644 index d5ed8596..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/CustomInventory.java +++ /dev/null @@ -1,60 +0,0 @@ -package fr.skytasul.quests.gui; - -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -public abstract interface CustomInventory { - - /** - * Called when opening inventory - * @param p Player to open - * @return inventory opened - */ - public abstract Inventory open(Player p); - - /** - * Called when clicking on an item - * @param p Player who clicked - * @param inv Inventory clicked - * @param current Item clicked - * @param slot Slot of item clicked - * @param click Type of click - * @return Cancel click - */ - public abstract boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click); - - /** - * Called when clicking on an item <b>with something on the cursor</b> - * @param p Player who clicked - * @param inv Inventory clicked - * @param current Item clicked - * @param cursor Item on the cursor when click - * @param slot Slot of item clicked - * @return Cancel click - */ - public default boolean onClickCursor(Player p, Inventory inv, ItemStack current, ItemStack cursor, int slot){return true;} - - /** - * Called when closing the inventory - * @param p Player who has the inventory opened - * @param inv Inventory closed - * @return Remove player from inventories system - */ - public default CloseBehavior onClose(Player p, Inventory inv){return CloseBehavior.CONFIRM;} - - /** - * Opens the inventory to the player. Direct reference to {@link Inventories#create(Player, CustomInventory)} - * @param p Player - * @see Inventories#create(Player, CustomInventory) - */ - public default void create(Player p) { - Inventories.create(p, this); - } - - public static enum CloseBehavior{ - REOPEN, CONFIRM, REMOVE, NOTHING; - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java new file mode 100644 index 00000000..83d48d7e --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -0,0 +1,191 @@ +package fr.skytasul.quests.gui; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.GuiManager; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.close.OpenCloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.ConfirmGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.utils.QuestUtils; + +public class GuiManagerImplementation implements GuiManager, Listener { + + private Map<Player, CustomInventory> players = new HashMap<>(); + private boolean dismissClose = false; + + @Override + public void open(@NotNull Player player, @NotNull CustomInventory inventory) { + try { + closeWithoutExit(player); + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug(player.getName() + " has opened inventory " + inventory.getClass().getName() + "."); + inventory.open(player); + players.put(player, inventory); + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "Cannot open inventory " + inventory.getClass().getSimpleName() + " to player " + player.getName(), ex); + closeAndExit(player); + } + } + + @Override + public void closeAndExit(@NotNull Player player) { + players.remove(player); + player.closeInventory(); + } + + @Override + public void closeWithoutExit(@NotNull Player player) { + dismissClose = true; + player.closeInventory(); + dismissClose = false; // in case the player did not have an inventory opened + } + + @Override + public void closeAll() { + for (Iterator<Player> iterator = players.keySet().iterator(); iterator.hasNext();) { + Player player = iterator.next(); + iterator.remove(); + player.closeInventory(); + } + } + + @Override + public boolean hasGuiOpened(@NotNull Player player) { + return players.containsKey(player); + } + + @Override + public @Nullable CustomInventory getOpenedGui(@NotNull Player player) { + return players.get(player); + } + + @EventHandler + public void onClose(InventoryCloseEvent event) { + if (dismissClose) { + dismissClose = false; + return; + } + + if (!(event.getPlayer() instanceof Player)) + return; + Player player = (Player) event.getPlayer(); + + CustomInventory gui = players.get(player); + if (gui == null) + return; + + ensureSameInventory(gui, event.getInventory()); + + CloseBehavior behavior = gui.onClose(player); + if (behavior instanceof StandardCloseBehavior) { + switch ((StandardCloseBehavior) behavior) { + case CONFIRM: + QuestUtils.runSync(() -> ConfirmGUI.confirm(() -> closeAndExit(player), () -> open(player, gui), + Lang.INDICATION_CLOSE.toString()).open(player)); + break; + case NOTHING: + break; + case REMOVE: + players.remove(player); + break; + case REOPEN: + QuestUtils.runSync(() -> open(player, gui)); + break; + } + } else if (behavior instanceof DelayCloseBehavior) { + players.remove(player); + QuestUtils.runSync(((DelayCloseBehavior) behavior).getDelayed()); + } else if (behavior instanceof OpenCloseBehavior) { + open(player, ((OpenCloseBehavior) behavior).getOther()); + } + } + + @EventHandler + public void onClick(InventoryClickEvent event) { + if (!(event.getWhoClicked() instanceof Player)) + return; + Player player = (Player) event.getWhoClicked(); + + CustomInventory gui = players.get(player); + if (gui == null) + return; + + event.setCancelled(false); + + try { + if (event.getClickedInventory() == player.getInventory()) { + if (event.isShiftClick()) + event.setCancelled(true); + return; + } + + ClickType click = event.getClick(); + if (click == ClickType.NUMBER_KEY || click == ClickType.DOUBLE_CLICK || click == ClickType.DROP + || click == ClickType.CONTROL_DROP || click.name().equals("SWAP_OFFHAND")) { // SWAP_OFFHAND introduced + // in 1.16 + event.setCancelled(true); + return; + } + + ensureSameInventory(gui, event.getClickedInventory()); + + if (event.getCursor().getType() == Material.AIR) { + if (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR) + return; + if (gui.onClick(player, event.getCurrentItem(), event.getSlot(), click)) + event.setCancelled(true); + } else { + if (gui.onClickCursor(player, event.getCurrentItem(), event.getCursor(), + event.getSlot())) + event.setCancelled(true); + } + } catch (Exception ex) { + event.setCancelled(true); + Lang.ERROR_OCCURED.send(player, ex.getMessage() + " in " + gui.getClass().getSimpleName()); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred when " + player.getName() + + " clicked in inventory " + gui.getClass().getName() + " at slot " + event.getSlot(), ex); + } + } + + @EventHandler + public void onDrag(InventoryDragEvent event) { + if (players.containsKey(event.getWhoClicked())) + event.setCancelled(true); + } + + @EventHandler + public void onOpen(InventoryOpenEvent event) { + if (!event.isCancelled()) + return; + if (players.containsKey(event.getPlayer())) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("The opening of a BeautyQuests menu for player " + + event.getPlayer().getName() + " has been cancelled by another plugin."); + } + } + + private void ensureSameInventory(CustomInventory gui, Inventory inventory) { + if (gui.getInventory() != inventory) + throw new IllegalStateException( + "The inventory opened by the player is not the same as the one registered by the plugin"); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/Inventories.java b/core/src/main/java/fr/skytasul/quests/gui/Inventories.java deleted file mode 100644 index af6665dd..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/Inventories.java +++ /dev/null @@ -1,189 +0,0 @@ -package fr.skytasul.quests.gui; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.event.inventory.InventoryOpenEvent; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.gui.misc.ConfirmGUI; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.types.Pair; - -public class Inventories{ - - private static Map<Player, Pair<CustomInventory, Inventory>> g = new HashMap<>(); - - private static boolean close = false; - - public static Inventory createGetInv(Player p, CustomInventory inv){ - put(p, inv, inv.open(p)); - return g.get(p).getValue(); - } - - /** - * Open a CustomInventory to player, and insert it to the Inventories system. - * @param p Player to open - * @param inv CustomInventory instance to open - * @param <T> Class who implements the CustomInventory interface - * @return Same CustomInventory - */ - public static <T extends CustomInventory> T create(Player p, T inv) { - closeWithoutExit(p); - try { - DebugUtils.logMessage(p.getName() + " has opened inventory " + inv.getClass().getName() + "."); - Inventory tinv = inv.open(p); - if (tinv == null) return inv; - put(p, inv, tinv); - return inv; - } catch (Exception ex) { - BeautyQuests.logger.severe("Cannot open inventory " + inv.getClass().getSimpleName() + " to player " + p.getName(), ex); - closeAndExit(p); - return null; - } - } - - public static void onClick(InventoryClickEvent e) { - Player p = (Player) e.getWhoClicked(); - Inventory inv = e.getClickedInventory(); - ItemStack current = e.getCurrentItem(); - - Pair<CustomInventory, Inventory> pair = g.get(p); - if (pair == null) return; - if (inv == null) return; - - e.setCancelled(false); - - try { - if (inv == p.getInventory()) { - if (e.isShiftClick()) e.setCancelled(true); - return; - } - - ClickType click = e.getClick(); - if (click == ClickType.NUMBER_KEY || click == ClickType.DOUBLE_CLICK || click == ClickType.DROP || click == ClickType.CONTROL_DROP || click.name().equals("SWAP_OFFHAND")) { // SWAP_OFFHAND introduced in 1.16 - e.setCancelled(true); - return; - } - - if (!inv.equals(pair.getValue())) return; - - if (e.getCursor().getType() == Material.AIR) { - if (current == null || current.getType() == Material.AIR) return; - if (pair.getKey().onClick(p, inv, current, e.getSlot(), click)) e.setCancelled(true); - }else { - if (pair.getKey().onClickCursor(p, inv, current, e.getCursor(), e.getSlot())) e.setCancelled(true); - } - }catch (Exception ex) { - e.setCancelled(true); - Lang.ERROR_OCCURED.send(p, ex.getMessage() + " in " + pair.getKey().getClass().getSimpleName()); - BeautyQuests.logger.severe("An error occurred when " + p.getName() + " clicked in inventory " + pair.getKey().getClass().getSimpleName() + " at slot " + e.getSlot(), ex); - } - } - - public static void onDrag(InventoryDragEvent e) { - if (g.get(e.getWhoClicked()) == null) return; - e.setCancelled(true); - } - - public static void onClose(InventoryCloseEvent e) { - Player p = (Player) e.getPlayer(); - if (close){ - close = false; - return; - } - if (g.containsKey(p)) { - Pair<CustomInventory, Inventory> pair = g.get(p); - if (!e.getInventory().equals(pair.getValue())) return; - switch (pair.getKey().onClose(p, e.getInventory())) { - case REMOVE: - remove(p); - break; - case REOPEN: - new BukkitRunnable() { - @Override - public void run(){ - p.openInventory(e.getInventory()); - } - }.runTaskLater(BeautyQuests.getInstance(), 1L); - break; - case CONFIRM: - new BukkitRunnable() { - @Override - public void run(){ - create(p, new ConfirmGUI(() -> { - remove(p); - p.closeInventory(); - }, () -> { - g.put(p, pair); - p.openInventory(e.getInventory()); - }, Lang.INDICATION_CLOSE.toString())); - } - }.runTaskLater(BeautyQuests.getInstance(), 1L); - break; - case NOTHING: - break; - } - } - } - - public static void onOpen(InventoryOpenEvent e) { - if (!e.isCancelled()) return; - HumanEntity p = e.getPlayer(); - if (g.containsKey(p)) { - BeautyQuests.logger.warning("The opening of a BeautyQuests menu for player " + p.getName() + " has been cancelled by another plugin."); - } - } - - - public static void closeWithoutExit(Player p){ - if (!g.containsKey(p)) return; - if (p.getOpenInventory().getType() == InventoryType.CRAFTING){ - return; - } - close = true; - p.closeInventory(); - } - - public static void closeAndExit(Player p){ - remove(p); - p.closeInventory(); - } - - - private static void remove(Player p){ - g.remove(p); - } - - public static void closeAll(){ - for (Iterator<Player> iterator = g.keySet().iterator(); iterator.hasNext();) { - Player p = iterator.next(); - iterator.remove(); - p.closeInventory(); - } - } - - public static void put(Player p, CustomInventory cinv, Inventory inv){ - g.put(p, new Pair<CustomInventory, Inventory>(cinv, inv)); - } - - public static boolean isInSystem(Player p){ - return g.containsKey(p); - } - - public static void openInventory(Player p){ - p.openInventory(g.get(p).getValue()); - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java index 78b2024c..7c45236a 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java @@ -1,6 +1,6 @@ package fr.skytasul.quests.gui.blocks; -import static fr.skytasul.quests.gui.ItemUtils.item; +import static fr.skytasul.quests.api.gui.ItemUtils.item; import java.util.Collection; import java.util.List; import java.util.UUID; @@ -8,8 +8,8 @@ import java.util.function.Function; import org.bukkit.DyeColor; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.CountableObject; import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; @@ -33,7 +33,7 @@ public void finish(List<MutableCountableObject<BQBlock>> objects) { public void createObject(Function<MutableCountableObject<BQBlock>, ItemStack> callback) { new SelectBlockGUI(true, (type, amount) -> { callback.apply(CountableObject.createMutable(UUID.randomUUID(), type, amount)); - }).create(p); + }).open(player); } @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 1b65c0d4..4541dfc4 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 @@ -1,208 +1,170 @@ package fr.skytasul.quests.gui.blocks; -import static fr.skytasul.quests.gui.ItemUtils.item; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.function.BiConsumer; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.MaterialParser; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.layout.Button; +import fr.skytasul.quests.api.gui.layout.ClickEvent; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.MaterialParser; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; import fr.skytasul.quests.utils.types.BQBlock; -public class SelectBlockGUI implements CustomInventory{ - - private static final int AMOUNT_SLOT = 1; - private static final int NAME_SLOT = 2; - private static final int TYPE_SLOT = 4; - private static final int DATA_SLOT = 5; - private static final int TAG_SLOT = 6; - private static final int FINISH_SLOT = 8; - - private ItemStack done = item(XMaterial.DIAMOND, Lang.done.toString()); - - private boolean allowAmount; +public class SelectBlockGUI extends LayoutedGUI.LayoutedRowsGUI { + private BiConsumer<BQBlock, Integer> run; - - public Inventory inv; - + private XMaterial type = XMaterial.STONE; private String customName = null; private String blockData = null; private String tag = null; private int amount = 1; - + public SelectBlockGUI(boolean allowAmount, BiConsumer<BQBlock, Integer> run) { - this.allowAmount = allowAmount; + super(Lang.INVENTORY_BLOCK.toString(), new HashMap<>(), StandardCloseBehavior.REOPEN, 1); this.run = run; - } - - public String name() { - return Lang.INVENTORY_BLOCK.toString(); - } - - public CustomInventory openLastInv(Player p) { - p.openInventory(inv); - return this; - } - - @Override - public Inventory open(Player p){ - inv = Bukkit.createInventory(null, 9, name()); - + if (allowAmount) - inv.setItem(AMOUNT_SLOT, item(XMaterial.REDSTONE, Lang.Amount.format(amount))); - inv.setItem(NAME_SLOT, - item(XMaterial.NAME_TAG, Lang.blockName.toString(), QuestOption.formatNullableValue(null, true))); - if (NMS.getMCVersion() >= 13) inv.setItem(DATA_SLOT, item(XMaterial.COMMAND_BLOCK, Lang.blockData.toString(), Lang.NotSet.toString())); - if (NMS.getMCVersion() >= 13) inv.setItem(TAG_SLOT, item(XMaterial.FILLED_MAP, Lang.blockTag.toString(), QuestOption.formatDescription(Lang.blockTagLore.toString()), "", Lang.NotSet.toString())); - inv.setItem(FINISH_SLOT, done.clone()); - updateTypeItem(); - - return inv = p.openInventory(inv).getTopInventory(); - } + buttons.put(1, Button.create(XMaterial.REDSTONE, () -> Lang.Amount.format(amount), Collections.emptyList(), + this::amountClick)); + buttons.put(2, Button.create(XMaterial.NAME_TAG, Lang.blockName.toString(), + Arrays.asList(QuestOption.formatNullableValue(customName, customName == null)), this::nameClick)); + buttons.put(4, new Button() { - private void updateTypeItem() { - inv.setItem(TYPE_SLOT, item(type, Lang.materialName.format(type.name()))); - if (inv.getItem(TYPE_SLOT) == null || inv.getItem(TYPE_SLOT).getType() == Material.AIR) { // means that the material cannot be treated as an inventory item (ex: fire) - inv.setItem(TYPE_SLOT, item(XMaterial.STONE, Lang.materialName.format(type.name()), QuestOption.formatDescription(Lang.materialNotItemLore.format(type.name())))); + @Override + public void click(@NotNull ClickEvent event) { + typeClick(event); + } + + @Override + public void place(@NotNull Inventory inventory, int slot) { + inventory.setItem(slot, ItemUtils.item(type, Lang.materialName.format(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.format(type.name()), + QuestOption.formatDescription(Lang.materialNotItemLore.format(type.name())))); + } + if (tag == null) + ItemUtils.addEnchant(inventory.getItem(slot), Enchantment.DURABILITY, 1); + } + + }); + if (MinecraftVersion.MAJOR >= 13) { + buttons.put(5, Button.create(() -> { + ItemStack item = ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.blockData.toString(), + QuestOption.formatNullableValue(blockData, blockData == null)); + if (blockData != null) + ItemUtils.addEnchant(item, Enchantment.DAMAGE_ALL, 1); + return item; + }, this::dataClick)); + + buttons.put(6, Button.create(() -> { + ItemStack item = ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.blockTag.toString(), + QuestOption.formatDescription(Lang.blockTagLore.toString()), "", + QuestOption.formatNullableValue(tag, tag == null)); + if (tag != null) + ItemUtils.addEnchant(item, Enchantment.DAMAGE_ALL, 1); + return item; + }, this::tagClick)); } - if (tag == null) ItemUtils.addEnchant(inv.getItem(TYPE_SLOT), Enchantment.DURABILITY, 1); + + buttons.put(8, Button.create(ItemUtils.itemDone, this::doneClick)); } - - private void resetBlockData() { - if (blockData == null) return; - blockData = null; - ItemStack item = inv.getItem(DATA_SLOT); - ItemUtils.removeEnchant(item, Enchantment.DURABILITY); - ItemUtils.lore(item, Lang.NotSet.toString()); + + private void amountClick(ClickEvent event) { + Lang.BLOCKS_AMOUNT.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { + amount = obj; + event.refreshItemReopen(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); } - - private void resetTag() { - if (tag == null) return; - tag = null; - ItemStack item = inv.getItem(TAG_SLOT); - ItemUtils.removeEnchant(item, Enchantment.DURABILITY); - ItemUtils.lore(item, QuestOption.formatDescription(Lang.blockTagLore.toString()), "", Lang.NotSet.toString()); + + private void nameClick(ClickEvent event) { + Lang.BLOCK_NAME.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { + customName = obj; + event.refreshItemReopen(); + }).passNullIntoEndConsumer().start(); } - - @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { - switch (slot){ - - default: - break; - - case AMOUNT_SLOT: - Lang.BLOCKS_AMOUNT.send(p); - new TextEditor<>(p, () -> openLastInv(p), obj -> { - amount = obj; - ItemUtils.name(current, Lang.Amount.format(amount)); - openLastInv(p); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); - break; - - case NAME_SLOT: - Lang.BLOCK_NAME.send(p); - new TextEditor<String>(p, () -> openLastInv(p), obj -> { - customName = obj; - ItemUtils.lore(current, QuestOption.formatNullableValue(customName, customName == null)); - openLastInv(p); - }).passNullIntoEndConsumer().enter(); - break; - - case TYPE_SLOT: - Lang.BLOCK_NAME.send(p); - new TextEditor<>(p, () -> openLastInv(p), type -> { - this.type = type; - if (blockData != null) { - try { - Bukkit.createBlockData(type.parseMaterial(), blockData); - }catch (Exception ex) { - Lang.INVALID_BLOCK_DATA.send(p, blockData, type.name()); - resetBlockData(); - } - } - resetTag(); - updateTypeItem(); - openLastInv(p); - }, MaterialParser.BLOCK_PARSER).enter(); - break; - - case DATA_SLOT: - Lang.BLOCK_DATA.send(p, String.join(", ", NMS.getNMS().getAvailableBlockProperties(type.parseMaterial()))); - new TextEditor<>(p, () -> openLastInv(p), obj -> { - String tmp = "[" + obj + "]"; + + private void typeClick(ClickEvent event) { + Lang.BLOCK_NAME.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, type -> { + this.type = type; + if (blockData != null) { try { - Bukkit.createBlockData(type.parseMaterial(), tmp); - blockData = tmp; - ItemUtils.lore(current, blockData); - ItemUtils.addEnchant(current, Enchantment.DURABILITY, 1); - if (tag != null) { - resetTag(); - updateTypeItem(); - } - }catch (Exception ex) { - Lang.INVALID_BLOCK_DATA.send(p, tmp, type.name()); - } - openLastInv(p); - }, () -> { - resetBlockData(); - openLastInv(p); - }).useStrippedMessage().enter(); - break; - - case TAG_SLOT: - Lang.BLOCK_TAGS.send(p, String.join(", ", NMS.getNMS().getAvailableBlockTags())); - new TextEditor<>(p, () -> openLastInv(p), obj -> { - NamespacedKey key = NamespacedKey.fromString((String) obj); - if (key == null || Bukkit.getTag("blocks", key, Material.class) == null) { - Lang.INVALID_BLOCK_TAG.send(p, obj); - }else { - tag = (String) obj; - type = XMaterial.STONE; - ItemUtils.lore(current, QuestOption.formatDescription(Lang.blockTagLore.toString()), "", Lang.optionValue.format(tag)); - ItemUtils.addEnchant(current, Enchantment.DURABILITY, 1); - resetBlockData(); - updateTypeItem(); + Bukkit.createBlockData(type.parseMaterial(), blockData); + } catch (Exception ex) { + Lang.INVALID_BLOCK_DATA.send(event.getPlayer(), blockData, type.name()); + blockData = null; } - openLastInv(p); - }).useStrippedMessage().enter(); - break; + } + event.refreshGuiReopen(); + }, MaterialParser.BLOCK_PARSER).start(); + } - case FINISH_SLOT: - Inventories.closeAndExit(p); - BQBlock block; - if (blockData != null) { - block = new Post1_13.BQBlockData(customName, Bukkit.createBlockData(type.parseMaterial(), blockData)); - }else if (tag != null) { - block = new Post1_13.BQBlockTag(customName, tag); - }else { - block = new BQBlock.BQBlockMaterial(customName, type); + private void dataClick(ClickEvent event) { + Lang.BLOCK_DATA.send(event.getPlayer(), + String.join(", ", NMS.getNMS().getAvailableBlockProperties(type.parseMaterial()))); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { + String tmp = "[" + obj + "]"; + try { + Bukkit.createBlockData(type.parseMaterial(), tmp); + blockData = tmp; + tag = null; + } catch (Exception ex) { + Lang.INVALID_BLOCK_DATA.send(event.getPlayer(), tmp, type.name()); } - run.accept(block, amount); - break; - - } - return true; + event.refreshGuiReopen(); + }, () -> { + blockData = null; + event.refreshGuiReopen(); + }).useStrippedMessage().start(); } - @Override - public CloseBehavior onClose(Player p, Inventory inv){ - return CloseBehavior.REOPEN; + private void tagClick(ClickEvent event) { + Lang.BLOCK_TAGS.send(event.getPlayer(), String.join(", ", NMS.getNMS().getAvailableBlockTags())); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { + NamespacedKey key = NamespacedKey.fromString((String) obj); + if (key == null || Bukkit.getTag("blocks", key, Material.class) == null) { + Lang.INVALID_BLOCK_TAG.send(event.getPlayer(), obj); + } else { + tag = (String) obj; + type = XMaterial.STONE; + blockData = null; + } + event.refreshGuiReopen(); + }).useStrippedMessage().start(); + } + + private void doneClick(ClickEvent event) { + event.close(); + BQBlock block; + if (blockData != null) { + block = new Post1_13.BQBlockData(customName, Bukkit.createBlockData(type.parseMaterial(), blockData)); + } else if (tag != null) { + block = new Post1_13.BQBlockTag(customName, tag); + } else { + block = new BQBlock.BQBlockMaterial(customName, type); + } + run.accept(block, amount); } -} \ No newline at end of file +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/BucketTypeGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/BucketTypeGUI.java index a085e708..c4b58532 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/BucketTypeGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/BucketTypeGUI.java @@ -5,11 +5,11 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ChooseGUI; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ChooseGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.stages.StageBucket.BucketType; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class BucketTypeGUI extends ChooseGUI<BucketType>{ @@ -40,7 +40,7 @@ public void finish(BucketType object){ @Override public CloseBehavior onClose(Player p, Inventory inv) { Utils.runSync(cancel); - return CloseBehavior.NOTHING; + return StandardCloseBehavior.NOTHING; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java index 9abd9894..3f4592ce 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java @@ -8,13 +8,14 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.CustomInventory; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.CustomInventory.CloseBehavior; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.types.Command; @@ -78,7 +79,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli this.cmd = cmd; inv.getItem(SLOT_FINISH).setType(Material.DIAMOND); p.openInventory(inv); - }, () -> p.openInventory(inv), null).useStrippedMessage().enter(); + }, () -> p.openInventory(inv), null).useStrippedMessage().start(); break; case SLOT_CONSOLE: @@ -94,7 +95,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli new TextEditor<>(p, () -> p.openInventory(inv), x -> { delay = x; p.openInventory(inv); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; case SLOT_FINISH: @@ -111,7 +112,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli @Override public CloseBehavior onClose(Player p, Inventory inv) { Utils.runSync(cancel); - return CloseBehavior.NOTHING; + return StandardCloseBehavior.NOTHING; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java index da4dd37c..98f78a51 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java @@ -1,7 +1,5 @@ package fr.skytasul.quests.gui.creation; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.bukkit.Bukkit; @@ -12,29 +10,27 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.QuestCreateEvent; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.QuestOptionCreator; import fr.skytasul.quests.api.options.UpdatableOptionSet; import fr.skytasul.quests.api.options.UpdatableOptionSet.Updatable; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.CustomInventory; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.StagesGUI; -import fr.skytasul.quests.options.*; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; +import fr.skytasul.quests.options.OptionName; +import fr.skytasul.quests.players.PlayerQuestDatasImplementation; +import fr.skytasul.quests.structure.QuestBranchImplementation; +import fr.skytasul.quests.structure.StageControllerImplementation; public class FinishGUI extends UpdatableOptionSet<Updatable> implements CustomInventory { @@ -62,7 +58,7 @@ public Inventory open(Player p){ String invName = Lang.INVENTORY_DETAILS.toString(); if (session.isEdition()) { invName = invName + " #" + session.getQuestEdited().getID(); - if (NMS.getMCVersion() <= 8 && invName.length() > 32) invName = Lang.INVENTORY_DETAILS.toString(); // 32 characters limit in 1.8 + if (MinecraftVersion.MAJOR <= 8 && invName.length() > 32) invName = Lang.INVENTORY_DETAILS.toString(); // 32 characters limit in 1.8 } inv = Bukkit.createInventory(null, (int) Math.ceil((QuestOptionCreator.creators.values().stream().mapToInt(creator -> creator.slot).max().getAsInt() + 1) / 9D) * 9, invName); @@ -170,22 +166,22 @@ private void finish(){ boolean keepPlayerDatas = Boolean.TRUE.equals(this.keepPlayerDatas); Quest qu; if (session.isEdition()) { - DebugUtils.logMessage( + QuestsPlugin.getPlugin().getLoggerExpanded().debug( "Editing quest " + session.getQuestEdited().getID() + " with keep datas: " + keepPlayerDatas); session.getQuestEdited().remove(false, false); qu = new Quest(session.getQuestEdited().getID(), session.getQuestEdited().getFile()); }else { int id = -1; if (session.hasCustomID()) { - if (QuestsAPI.getQuests().getQuests().stream().anyMatch(x -> x.getID() == session.getCustomID())) { - BeautyQuests.logger.warning("Cannot create quest with custom ID " + session.getCustomID() + " because another quest with this ID already exists."); + if (QuestsAPI.getAPI().getQuestsManager().getQuests().stream().anyMatch(x -> x.getID() == session.getCustomID())) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot create quest with custom ID " + session.getCustomID() + " because another quest with this ID already exists."); }else { id = session.getCustomID(); - BeautyQuests.logger.warning("A quest will be created with custom ID " + id + "."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("A quest will be created with custom ID " + id + "."); } } if (id == -1) - id = QuestsAPI.getQuests().getFreeQuestID(); + id = QuestsAPI.getAPI().getQuestsManager().getFreeQuestID(); qu = new Quest(id); } @@ -193,7 +189,7 @@ private void finish(){ if (option.hasCustomValue()) qu.addOption(option); } - QuestBranch mainBranch = new QuestBranch(qu.getBranchesManager()); + QuestBranchImplementation mainBranch = new QuestBranchImplementation(qu.getBranchesManager()); qu.getBranchesManager().addBranch(mainBranch); boolean failure = loadBranch(mainBranch, session.getMainGUI()); @@ -206,27 +202,27 @@ private void finish(){ if (session.areStagesEdited()) { if (keepPlayerDatas) { - BeautyQuests.logger.warning("Players quests datas will be kept for quest #" + qu.getID() + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Players quests datas will be kept for quest #" + qu.getId() + " - this may cause datas issues."); } else BeautyQuests.getInstance().getPlayersManager().removeQuestDatas(session.getQuestEdited()) - .whenComplete(BeautyQuests.logger + .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded() .logError("An error occurred while removing player datas after quest edition", p)); } - QuestsAPI.getQuests().addQuest(qu); + QuestsAPI.getAPI().getQuestsManager().addQuest(qu); Utils.sendMessage(p, ((!session.isEdition()) ? Lang.SUCCESFULLY_CREATED : Lang.SUCCESFULLY_EDITED).toString(), qu.getName(), qu.getBranchesManager().getBranchesAmount()); Utils.playPluginSound(p, "ENTITY_VILLAGER_YES", 1); - BeautyQuests.logger.info("New quest created: " + qu.getName() + ", ID " + qu.getID() + ", by " + p.getName()); + QuestsPlugin.getPlugin().getLoggerExpanded().info("New quest created: " + qu.getName() + ", ID " + qu.getId() + ", by " + p.getName()); if (session.isEdition()) { - BeautyQuests.getInstance().getLogger().info("Quest " + qu.getName() + " has been edited"); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Quest " + qu.getName() + " has been edited"); if (failure) BeautyQuests.getInstance().createQuestBackup(qu.getFile().toPath(), "Error occurred while editing"); } try { qu.saveToFile(); }catch (Exception e) { Lang.ERROR_OCCURED.send(p, "initial quest save"); - BeautyQuests.logger.severe("Error when trying to save newly created quest.", e); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when trying to save newly created quest.", e); } if (keepPlayerDatas) { @@ -234,18 +230,18 @@ private void finish(){ PlayerAccount account = PlayersManager.getPlayerAccount(p); if (account == null) continue; if (account.hasQuestDatas(qu)) { - PlayerQuestDatas datas = account.getQuestDatas(qu); + PlayerQuestDatasImplementation datas = account.getQuestDatas(qu); datas.questEdited(); if (datas.getBranch() == -1) continue; - QuestBranch branch = qu.getBranchesManager().getBranch(datas.getBranch()); + QuestBranchImplementation branch = qu.getBranchesManager().getBranch(datas.getBranch()); if (datas.isInEndingStages()) { - branch.getEndingStages().keySet().forEach(stage -> stage.joins(account, p)); + branch.getEndingStages().keySet().forEach(stage -> stage.joins(account, player)); }else branch.getRegularStage(datas.getStage()).joins(account, p); } } } - QuestsAPI.propagateQuestsHandlers(handler -> { + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> { if (session.isEdition()) handler.questEdit(qu, session.getQuestEdited(), keepPlayerDatas); else handler.questCreate(qu); @@ -255,16 +251,16 @@ private void finish(){ Inventories.closeAndExit(p); } - private boolean loadBranch(QuestBranch branch, StagesGUI gui) { + private boolean loadBranch(QuestBranchImplementation branch, StagesGUI gui) { boolean failure = false; for (StageCreation<?> creation : gui.getStageCreations()) { try{ - AbstractStage stage = creation.finish(branch); + AbstractStage stage = createStage(creation, branch); if (creation.isEndingStage()) { StagesGUI newGUI = creation.getLeadingBranch(); - QuestBranch newBranch = null; + QuestBranchImplementation newBranch = null; if (!newGUI.isEmpty()){ - newBranch = new QuestBranch(branch.getBranchesManager()); + newBranch = new QuestBranchImplementation(branch.getBranchesManager()); branch.getBranchesManager().addBranch(newBranch); failure |= loadBranch(newBranch, newGUI); } @@ -273,12 +269,19 @@ private boolean loadBranch(QuestBranch branch, StagesGUI gui) { }catch (Exception ex) { failure = true; Lang.ERROR_OCCURED.send(p, " lineToStage"); - BeautyQuests.logger.severe("An error occurred wheh creating branch from GUI.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred wheh creating branch from GUI.", ex); } } return failure; } + public <T extends AbstractStage> T createStage(StageCreation<T> creation, QuestBranchImplementation branch) { + StageControllerImplementation<T> controller = new StageControllerImplementation<>(branch, creation.getType()); + T stage = creation.finish(controller); + controller.setStage(stage); + return stage; + } + private void setStagesEdited() { keepPlayerDatas = false; int resetSlot = QuestOptionCreator.calculateSlot(6); @@ -314,38 +317,5 @@ protected UpdatableItem(int slot) { super(slot); } } - - public static void initialize(){ - DebugUtils.logMessage("Initlializing default quest options."); - - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("pool", 9, OptionQuestPool.class, OptionQuestPool::new, null)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("name", 10, OptionName.class, OptionName::new, null)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("description", 12, OptionDescription.class, OptionDescription::new, null)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("customItem", 13, OptionQuestItem.class, OptionQuestItem::new, QuestsConfiguration.getItemMaterial(), "customMaterial")); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("confirmMessage", 15, OptionConfirmMessage.class, OptionConfirmMessage::new, null)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("hologramText", 17, OptionHologramText.class, OptionHologramText::new, Lang.HologramText.toString())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("bypassLimit", 18, OptionBypassLimit.class, OptionBypassLimit::new, false)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("startableFromGUI", 19, OptionStartable.class, OptionStartable::new, false)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("failOnDeath", 20, OptionFailOnDeath.class, OptionFailOnDeath::new, false)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("cancellable", 21, OptionCancellable.class, OptionCancellable::new, true)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("cancelActions", 22, OptionCancelRewards.class, OptionCancelRewards::new, new ArrayList<>())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("hologramLaunch", 25, OptionHologramLaunch.class, OptionHologramLaunch::new, QuestsConfiguration.getHoloLaunchItem())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("hologramLaunchNo", 26, OptionHologramLaunchNo.class, OptionHologramLaunchNo::new, QuestsConfiguration.getHoloLaunchNoItem())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("scoreboard", 27, OptionScoreboardEnabled.class, OptionScoreboardEnabled::new, true)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("hideNoRequirements", 28, OptionHideNoRequirements.class, OptionHideNoRequirements::new, false)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("auto", 29, OptionAutoQuest.class, OptionAutoQuest::new, false)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("repeatable", 30, OptionRepeatable.class, OptionRepeatable::new, false, "multiple")); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("timer", 31, OptionTimer.class, OptionTimer::new, QuestsConfiguration.getTimeBetween())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("visibility", 32, OptionVisibility.class, OptionVisibility::new, Arrays.asList(OptionVisibility.VisibilityLocation.values()), "hid", "hide")); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("endSound", 34, OptionEndSound.class, OptionEndSound::new, QuestsConfiguration.getFinishSound())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("firework", 35, OptionFirework.class, OptionFirework::new, QuestsConfiguration.getDefaultFirework())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("requirements", 36, OptionRequirements.class, OptionRequirements::new, new ArrayList<>())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("startRewards", 38, OptionStartRewards.class, OptionStartRewards::new, new ArrayList<>(), "startRewardsList")); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("startMessage", 39, OptionStartMessage.class, OptionStartMessage::new, QuestsConfiguration.getPrefix() + Lang.STARTED_QUEST.toString())); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("starterNPC", 40, OptionStarterNPC.class, OptionStarterNPC::new, null, "starterID")); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("startDialog", 41, OptionStartDialog.class, OptionStartDialog::new, null)); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("endRewards", 43, OptionEndRewards.class, OptionEndRewards::new, new ArrayList<>(), "rewardsList")); - QuestsAPI.registerQuestOption(new QuestOptionCreator<>("endMsg", 44, OptionEndMessage.class, OptionEndMessage::new, QuestsConfiguration.getPrefix() + Lang.FINISHED_BASE.toString())); - } } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java index a068396e..980d8ffa 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java @@ -11,12 +11,13 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.CustomInventory; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.CustomInventory.CloseBehavior; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.misc.ItemCreatorGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class ItemsGUI implements CustomInventory { @@ -66,8 +67,8 @@ public boolean onClickCursor(Player p, Inventory inv, ItemStack current, ItemSta if (none.equals(current)){ inv.setItem(slot, cursor); Utils.runSync(() -> { - p.setItemOnCursor(null); - addItem(p, cursor, slot); + player.setItemOnCursor(null); + addItem(player, cursor, slot); }); return true; }else Utils.runSync(() -> items.put(slot, inv.getItem(slot))); @@ -86,7 +87,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli Inventories.put(p, this, inv); p.openInventory(inv); } - }, true).create(p); + }, true).open(p); }else { if (click.isLeftClick() || (click.isRightClick() && current.getAmount() == 1)) { Utils.runSync(() -> { @@ -102,7 +103,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli @Override public CloseBehavior onClose(Player p, Inventory inv) { - return CloseBehavior.REOPEN; + return StandardCloseBehavior.REOPEN; } } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java index d66fd7de..0d0ed75c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java @@ -1,9 +1,8 @@ package fr.skytasul.quests.gui.creation; import org.bukkit.entity.Player; -import fr.skytasul.quests.gui.Inventories; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.gui.creation.stages.StagesGUI; -import fr.skytasul.quests.structure.Quest; public class QuestCreationSession { @@ -57,12 +56,12 @@ public StagesGUI getMainGUI() { public void openMainGUI(Player p) { if (mainGUI == null) mainGUI = new StagesGUI(this); - Inventories.create(p, mainGUI); + mainGUI.open(p); } public void openFinishGUI(Player p) { if (finishGUI == null) finishGUI = new FinishGUI(this); - Inventories.create(p, finishGUI); + finishGUI.open(p); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java deleted file mode 100644 index b34f255f..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestObjectGUI.java +++ /dev/null @@ -1,136 +0,0 @@ -package fr.skytasul.quests.gui.creation; - -import java.util.Collection; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.bukkit.DyeColor; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.objects.QuestObject; -import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectCreator; -import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.requirements.RequirementCreator; -import fr.skytasul.quests.api.rewards.RewardCreator; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.requirements.EquipmentRequirement; -import fr.skytasul.quests.requirements.LevelRequirement; -import fr.skytasul.quests.requirements.PermissionsRequirement; -import fr.skytasul.quests.requirements.QuestRequirement; -import fr.skytasul.quests.requirements.ScoreboardRequirement; -import fr.skytasul.quests.requirements.logical.LogicalOrRequirement; -import fr.skytasul.quests.rewards.*; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; - -public class QuestObjectGUI<T extends QuestObject> extends ListGUI<T> { - - private String name; - private Collection<QuestObjectCreator<T>> creators; - private Consumer<List<T>> end; - - public QuestObjectGUI(@NotNull String name, @NotNull QuestObjectLocation objectLocation, - @NotNull Collection<@NotNull QuestObjectCreator<T>> creators, @NotNull Consumer<@NotNull List<T>> end, - @NotNull List<T> objects) { - super(name, DyeColor.CYAN, (List<T>) objects.stream().map(QuestObject::clone).collect(Collectors.toList())); - this.name = name; - this.creators = creators.stream() - .filter(creator -> creator.isAllowed(objectLocation)) - .filter(creator -> creator.canBeMultiple() - || objects.stream().noneMatch(object -> object.getCreator() == creator)) - .collect(Collectors.toList()); - this.end = end; - } - - @Override - public ItemStack getObjectItemStack(QuestObject object) { - return object.getItemStack(); - } - - @Override - protected ClickType getRemoveClick(T object) { - return object.getRemoveClick(); - } - - @Override - protected void removed(T object) { - if (!object.getCreator().canBeMultiple()) creators.add(object.getCreator()); - } - - @Override - public void createObject(Function<T, ItemStack> callback) { - new PagedGUI<QuestObjectCreator<T>>(name, DyeColor.CYAN, creators) { - - @Override - public ItemStack getItemStack(QuestObjectCreator<T> object) { - return object.getItem(); - } - - @Override - public void click(QuestObjectCreator<T> existing, ItemStack item, ClickType clickType) { - T object = existing.newObject(); - if (!existing.canBeMultiple()) creators.remove(existing); - object.click( - new QuestObjectClickEvent(p, QuestObjectGUI.this, callback.apply(object), clickType, true, object)); - } - - @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(QuestObjectGUI.super::reopen); - return CloseBehavior.NOTHING; - } - - }.create(p); - } - - @Override - public void clickObject(QuestObject existing, ItemStack item, ClickType clickType) { - existing.click(new QuestObjectClickEvent(p, this, item, clickType, false, existing)); - } - - @Override - public void finish(List<T> objects) { - end.accept(objects); - } - - public static void initialize(){ - DebugUtils.logMessage("Initlializing default rewards."); - - QuestsAPI.getRewards().register(new RewardCreator("commandReward", CommandReward.class, ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.command.toString()), CommandReward::new)); - QuestsAPI.getRewards().register(new RewardCreator("itemReward", ItemReward.class, ItemUtils.item(XMaterial.STONE_SWORD, Lang.rewardItems.toString()), ItemReward::new)); - QuestsAPI.getRewards().register(new RewardCreator("removeItemsReward", RemoveItemsReward.class, ItemUtils.item(XMaterial.CHEST, Lang.rewardRemoveItems.toString()), RemoveItemsReward::new)); - QuestsAPI.getRewards().register(new RewardCreator("textReward", MessageReward.class, ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.endMessage.toString()), MessageReward::new)); - QuestsAPI.getRewards().register(new RewardCreator("tpReward", TeleportationReward.class, ItemUtils.item(XMaterial.ENDER_PEARL, Lang.location.toString()), TeleportationReward::new, false)); - QuestsAPI.getRewards().register(new RewardCreator("expReward", XPReward.class, ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.rewardXP.toString()), XPReward::new)); - QuestsAPI.getRewards().register(new RewardCreator("checkpointReward", CheckpointReward.class, ItemUtils.item(XMaterial.NETHER_STAR, Lang.rewardCheckpoint.toString()), CheckpointReward::new, false, QuestObjectLocation.STAGE)); - QuestsAPI.getRewards().register(new RewardCreator("questStopReward", QuestStopReward.class, ItemUtils.item(XMaterial.BARRIER, Lang.rewardStopQuest.toString()), QuestStopReward::new, false, QuestObjectLocation.STAGE)); - QuestsAPI.getRewards().register(new RewardCreator("requirementDependentReward", RequirementDependentReward.class, ItemUtils.item(XMaterial.REDSTONE, Lang.rewardWithRequirements.toString()), RequirementDependentReward::new, true).setCanBeAsync(true)); - QuestsAPI.getRewards().register(new RewardCreator("randomReward", RandomReward.class, ItemUtils.item(XMaterial.EMERALD, Lang.rewardRandom.toString()), RandomReward::new, true).setCanBeAsync(true)); - QuestsAPI.getRewards().register(new RewardCreator("wait", WaitReward.class, ItemUtils.item(XMaterial.CLOCK, Lang.rewardWait.toString()), WaitReward::new, true).setCanBeAsync(true)); - if (NMS.getMCVersion() >= 9) - QuestsAPI.getRewards().register(new RewardCreator("titleReward", TitleReward.class, - ItemUtils.item(XMaterial.NAME_TAG, Lang.rewardTitle.toString()), TitleReward::new, false)); - - DebugUtils.logMessage("Initlializing default requirements."); - - QuestsAPI.getRequirements().register(new RequirementCreator("logicalOr", LogicalOrRequirement.class, ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.RLOR.toString()), LogicalOrRequirement::new)); - QuestsAPI.getRequirements().register(new RequirementCreator("questRequired", QuestRequirement.class, ItemUtils.item(XMaterial.ARMOR_STAND, Lang.RQuest.toString()), QuestRequirement::new)); - QuestsAPI.getRequirements().register(new RequirementCreator("levelRequired", LevelRequirement.class, ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RLevel.toString()), LevelRequirement::new)); - QuestsAPI.getRequirements().register(new RequirementCreator("permissionRequired", PermissionsRequirement.class, ItemUtils.item(XMaterial.PAPER, Lang.RPermissions.toString()), PermissionsRequirement::new)); - QuestsAPI.getRequirements().register(new RequirementCreator("scoreboardRequired", ScoreboardRequirement.class, ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.RScoreboard.toString()), ScoreboardRequirement::new)); - if (NMS.getMCVersion() >= 9) - QuestsAPI.getRequirements().register(new RequirementCreator("equipmentRequired", EquipmentRequirement.class, ItemUtils.item(XMaterial.CHAINMAIL_HELMET, Lang.REquipment.toString()), EquipmentRequirement::new)); - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java index b333cf7c..157e31dc 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java @@ -3,11 +3,10 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.StageRunnable.StageRunnableClick; import fr.skytasul.quests.utils.types.NumberedList; -import fr.skytasul.quests.utils.types.Pair; public class Line { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 6c3da616..726c1847 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -11,20 +11,20 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.StageType; -import fr.skytasul.quests.gui.CustomInventory; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.gui.creation.stages.StageRunnable.StageRunnableClick; -import fr.skytasul.quests.stages.*; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.structure.QuestBranchImplementation; public class StagesGUI implements CustomInventory { @@ -102,7 +102,7 @@ private void setStageCreate(Line line, boolean branches){ line.setItem(0, stageCreate.clone(), (p, item) -> { line.setItem(0, null, null, true, false); int i = 0; - for (StageType<?> type : QuestsAPI.getStages()) { + for (StageType<?> type : QuestsAPI.getAPI().getStages()) { if (type.isValid()) { line.setItem(++i, type.getItem(), (p1, item1) -> { runClick(line, type, branches).start(p1); @@ -186,7 +186,7 @@ public void run(Player p, ItemStack item, ClickType click) { if (branches){ if (creation.getLeadingBranch() == null) creation.setLeadingBranch(new StagesGUI(session, this)); - line.setItem(14, ItemUtils.item(XMaterial.FILLED_MAP, Lang.newBranch.toString()), (p, item) -> Inventories.create(p, creation.getLeadingBranch())); + line.setItem(14, ItemUtils.item(XMaterial.FILLED_MAP, Lang.newBranch.toString()), (p, item) -> Inventories.open(p, creation.getLeadingBranch())); } if (line.getLine() != 0 && line.getLine() != 15) updateLineManageLore(getLine(line.getLine() - 1)); @@ -246,7 +246,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli }else Lang.QUEST_EDIT_CANCEL.send(p); } }else { // branch inventory = previous branch button - Inventories.create(p, previousBranch); + Inventories.open(p, previousBranch); } } }else { @@ -259,8 +259,8 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli @Override public CloseBehavior onClose(Player p, Inventory inv){ - if (isEmpty() || stop) return CloseBehavior.REMOVE; - return CloseBehavior.REOPEN; + if (isEmpty() || stop) return StandardCloseBehavior.REMOVE; + return StandardCloseBehavior.REOPEN; } private void refresh() { @@ -282,9 +282,9 @@ public List<StageCreation> getStageCreations() { return stages; } - private void editBranch(QuestBranch branch){ + private void editBranch(QuestBranchImplementation branch){ for (AbstractStage stage : branch.getRegularStages()){ - Line line = getLine(stage.getID()); + Line line = getLine(stage.getId()); @SuppressWarnings ("rawtypes") StageCreation creation = runClick(line, stage.getType(), false); creation.edit(stage); @@ -292,7 +292,7 @@ private void editBranch(QuestBranch branch){ } int i = 15; - for (Entry<AbstractStage, QuestBranch> en : branch.getEndingStages().entrySet()){ + for (Entry<AbstractStage, QuestBranchImplementation> en : branch.getEndingStages().entrySet()){ Line line = getLine(i); @SuppressWarnings ("rawtypes") StageCreation creation = runClick(line, en.getKey().getType(), true); @@ -306,49 +306,4 @@ private void editBranch(QuestBranch branch){ } } - - - private static final ItemStack stageNPC = ItemUtils.item(XMaterial.OAK_SIGN, Lang.stageNPC.toString()); - private static final ItemStack stageItems = ItemUtils.item(XMaterial.CHEST, Lang.stageBring.toString()); - private static final ItemStack stageMobs = ItemUtils.item(XMaterial.WOODEN_SWORD, Lang.stageMobs.toString()); - private static final ItemStack stageMine = ItemUtils.item(XMaterial.WOODEN_PICKAXE, Lang.stageMine.toString()); - private static final ItemStack stagePlace = ItemUtils.item(XMaterial.OAK_STAIRS, Lang.stagePlace.toString()); - private static final ItemStack stageChat = ItemUtils.item(XMaterial.PLAYER_HEAD, Lang.stageChat.toString()); - private static final ItemStack stageInteract = ItemUtils.item(XMaterial.STICK, Lang.stageInteract.toString()); - private static final ItemStack stageFish = ItemUtils.item(XMaterial.COD, Lang.stageFish.toString()); - private static final ItemStack stageMelt = ItemUtils.item(XMaterial.FURNACE, Lang.stageMelt.toString()); - private static final ItemStack stageEnchant = ItemUtils.item(XMaterial.ENCHANTING_TABLE, Lang.stageEnchant.toString()); - private static final ItemStack stageCraft = ItemUtils.item(XMaterial.CRAFTING_TABLE, Lang.stageCraft.toString()); - private static final ItemStack stageBucket = ItemUtils.item(XMaterial.BUCKET, Lang.stageBucket.toString()); - private static final ItemStack stageLocation = ItemUtils.item(XMaterial.MINECART, Lang.stageLocation.toString()); - private static final ItemStack stagePlayTime = ItemUtils.item(XMaterial.CLOCK, Lang.stagePlayTime.toString()); - private static final ItemStack stageBreed = ItemUtils.item(XMaterial.WHEAT, Lang.stageBreedAnimals.toString()); - private static final ItemStack stageTame = ItemUtils.item(XMaterial.CARROT, Lang.stageTameAnimals.toString()); - private static final ItemStack stageDeath = ItemUtils.item(XMaterial.SKELETON_SKULL, Lang.stageDeath.toString()); - private static final ItemStack stageDealDamage = ItemUtils.item(XMaterial.REDSTONE, Lang.stageDealDamage.toString()); - private static final ItemStack stageEatDrink = ItemUtils.item(XMaterial.COOKED_PORKCHOP, Lang.stageEatDrink.toString()); - - public static void initialize(){ - DebugUtils.logMessage("Initlializing default stage types."); - - QuestsAPI.getStages().register(new StageType<>("NPC", StageNPC.class, Lang.Talk.name(), StageNPC::deserialize, stageNPC, StageNPC.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("ITEMS", StageBringBack.class, Lang.Items.name(), StageBringBack::deserialize, stageItems, StageBringBack.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("MOBS", StageMobs.class, Lang.Mobs.name(), StageMobs::deserialize, stageMobs, StageMobs.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("MINE", StageMine.class, Lang.Mine.name(), StageMine::deserialize, stageMine, StageMine.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("PLACE_BLOCKS", StagePlaceBlocks.class, Lang.Place.name(), StagePlaceBlocks::deserialize, stagePlace, StagePlaceBlocks.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("CHAT", StageChat.class, Lang.Chat.name(), StageChat::deserialize, stageChat, StageChat.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("INTERACT", StageInteract.class, Lang.Interact.name(), StageInteract::deserialize, stageInteract, StageInteract.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("FISH", StageFish.class, Lang.Fish.name(), StageFish::deserialize, stageFish, StageFish.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("MELT", StageMelt.class, Lang.Melt.name(), StageMelt::deserialize, stageMelt, StageMelt.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("ENCHANT", StageEnchant.class, Lang.Enchant.name(), StageEnchant::deserialize, stageEnchant, StageEnchant.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("CRAFT", StageCraft.class, Lang.Craft.name(), StageCraft::deserialize, stageCraft, StageCraft.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("BUCKET", StageBucket.class, Lang.Bucket.name(), StageBucket::deserialize, stageBucket, StageBucket.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("LOCATION", StageLocation.class, Lang.Location.name(), StageLocation::deserialize, stageLocation, StageLocation.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("PLAY_TIME", StagePlayTime.class, Lang.PlayTime.name(), StagePlayTime::deserialize, stagePlayTime, StagePlayTime.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("BREED", StageBreed.class, Lang.Breed.name(), StageBreed::deserialize, stageBreed, StageBreed.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("TAME", StageTame.class, Lang.Tame.name(), StageTame::deserialize, stageTame, StageTame.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("DEATH", StageDeath.class, Lang.Death.name(), StageDeath::deserialize, stageDeath, StageDeath.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("DEAL_DAMAGE", StageDealDamage.class, Lang.DealDamage.name(), StageDealDamage::deserialize, stageDealDamage, StageDealDamage.Creator::new)); - QuestsAPI.getStages().register(new StageType<>("EAT_DRINK", StageEatDrink.class, Lang.EatDrink.name(), StageEatDrink::new, stageEatDrink, StageEatDrink.Creator::new)); - } } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java index 34ca9fd4..d2f28d30 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java @@ -7,28 +7,32 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; -public class BranchesGUI implements CustomInventory { // WIP +public class BranchesGUI extends CustomInventory { // WIP private Branch main = new Branch(null); - private Inventory inv; - private Branch shown; private int xOffset = 0; @Override - public Inventory open(Player p) { - inv = Bukkit.createInventory(null, 54, "Branches"); - - inv.setItem(49, ItemUtils.item(XMaterial.DIAMOND_BLOCK, "§bBack one branch")); + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 54, "Branches"); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + inventory.setItem(49, ItemUtils.item(XMaterial.DIAMOND_BLOCK, "§bBack one branch")); - inv.setItem(52, ItemUtils.item(XMaterial.ARROW, "§aScroll left")); - inv.setItem(53, ItemUtils.item(XMaterial.ARROW, "§aScroll right")); + inventory.setItem(52, ItemUtils.item(XMaterial.ARROW, "§aScroll left")); + inventory.setItem(53, ItemUtils.item(XMaterial.ARROW, "§aScroll right")); main.things.add(new Thing()); main.things.add(new Thing()); @@ -44,8 +48,6 @@ public Inventory open(Player p) { main.choices.add(branch); setBranch(main); - - return p.openInventory(inv).getTopInventory(); } public void refresh() { @@ -55,7 +57,7 @@ public void refresh() { private void setBranch(Branch branch) { this.shown = branch; for (int i = 0; i < 45; i++) { - inv.clear(i); + getInventory().clear(i); } int y = 2; @@ -73,11 +75,13 @@ private void displayBranch(Branch branch, int start, int xOffset, boolean showBr } for (int i = xOffset; i < to; i++) { IThing thing = branch.things.get(i); - inv.setItem(start + i - xOffset, thing.getItem(i == to - 1 ? branch.choices.isEmpty() ? ThingType.END : ThingType.BRANCHING : ThingType.NORMAL)); + getInventory().setItem(start + i - xOffset, thing.getItem( + i == to - 1 ? branch.choices.isEmpty() ? ThingType.END : ThingType.BRANCHING : ThingType.NORMAL)); } if (!showBranches) return; if (branch.choices.isEmpty()) { // no branch at the end - inv.setItem(start + to - xOffset, ItemUtils.item(XMaterial.SLIME_BALL, "§eCreate next thing", "§8> LEFT CLICK : §7Create normal thing", "§8> RIGHT CLICK : §7Create choices")); + getInventory().setItem(start + to - xOffset, ItemUtils.item(XMaterial.SLIME_BALL, "§eCreate next thing", + "§8> LEFT CLICK : §7Create normal thing", "§8> RIGHT CLICK : §7Create choices")); }else { int i = 0; for (Branch endBranch : branch.choices) { @@ -85,7 +89,7 @@ private void displayBranch(Branch branch, int start, int xOffset, boolean showBr i++; } for (; i < 5; i++) { - inv.setItem(i * 9 + to - xOffset, ItemUtils.item(XMaterial.SLIME_BALL, "§6Create choice")); + getInventory().setItem(i * 9 + to - xOffset, ItemUtils.item(XMaterial.SLIME_BALL, "§6Create choice")); } } } @@ -95,7 +99,7 @@ public void create(Consumer<IThing> thing) { } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { if (slot == 52) { if (xOffset > 0) { xOffset--; @@ -151,8 +155,8 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - return CloseBehavior.REMOVE; + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REMOVE; } static class Branch { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java deleted file mode 100644 index 973865ba..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ConfirmGUI.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.skytasul.quests.gui.misc; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; - -public class ConfirmGUI implements CustomInventory { - - private Runnable yes, no; - private String indication, lore; - - public ConfirmGUI(Runnable yes, Runnable no, String indication) { - this(yes, no, indication, null); - } - - public ConfirmGUI(Runnable yes, Runnable no, String indication, String lore) { - this.yes = yes; - this.no = no; - this.indication = indication; - this.lore = lore; - } - - public Inventory open(Player p){ - Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_CONFIRM.toString()); - - inv.setItem(1, ItemUtils.item(XMaterial.LIME_DYE, Lang.confirmYes.toString())); - inv.setItem(2, ItemUtils.item(XMaterial.PAPER, indication, lore == null ? null : new String[] { lore })); - inv.setItem(3, ItemUtils.item(XMaterial.RED_DYE, Lang.confirmNo.toString())); - - return p.openInventory(inv).getTopInventory(); - } - - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click){ - Inventories.closeAndExit(p); - if (slot == 1) { - yes.run(); - }else if (slot == 3) { - no.run(); - } - return true; - } - - public CloseBehavior onClose(Player p, Inventory inv){ - return CloseBehavior.REOPEN; - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java index 70344230..10e4dc54 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java @@ -9,10 +9,10 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.gui.templates.StaticPagedGUI; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.gui.templates.StaticPagedGUI; +import fr.skytasul.quests.api.localization.Lang; public class DamageCausesGUI extends ListGUI<DamageCause> { @@ -55,7 +55,8 @@ public ItemStack getObjectItemStack(DamageCause object) { @Override public void createObject(Function<DamageCause, ItemStack> callback) { - new StaticPagedGUI<DamageCause>(Lang.INVENTORY_DAMAGE_CAUSES_LIST.toString(), DyeColor.ORANGE, MAPPED_ITEMS, cause -> callback.apply(cause), DamageCause::name).create(p); + new StaticPagedGUI<DamageCause>(Lang.INVENTORY_DAMAGE_CAUSES_LIST.toString(), DyeColor.ORANGE, MAPPED_ITEMS, + callback::apply, DamageCause::name).open(player); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java index e4d6e7b5..5ebe2a05 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java @@ -1,27 +1,22 @@ package fr.skytasul.quests.gui.misc; -import java.util.Objects; import org.bukkit.DyeColor; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.Repairable; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; public class ItemComparisonGUI extends PagedGUI<ItemComparison> { private ItemComparisonMap comparisons; public ItemComparisonGUI(ItemComparisonMap comparisons, Runnable validate) { - super(Lang.INVENTORY_ITEM_COMPARISONS.toString(), DyeColor.LIME, QuestsAPI.getItemComparisons(), x -> validate.run(), + super(Lang.INVENTORY_ITEM_COMPARISONS.toString(), DyeColor.LIME, QuestsAPI.getAPI().getItemComparisons(), x -> validate.run(), null); this.comparisons = comparisons; } @@ -37,49 +32,4 @@ public void click(ItemComparison existing, ItemStack item, ClickType clickType) ItemUtils.set(item, comparisons.toggle(existing)); } - public static void initialize() { - QuestsAPI.registerItemComparison(new ItemComparison("bukkit", Lang.comparisonBukkit.toString(), - Lang.comparisonBukkitLore.toString(), ItemStack::isSimilar).setEnabledByDefault()); - QuestsAPI.registerItemComparison(new ItemComparison("customBukkit", Lang.comparisonCustomBukkit.toString(), - Lang.comparisonCustomBukkitLore.toString(), Utils::isSimilar)); - QuestsAPI.registerItemComparison(new ItemComparison("material", Lang.comparisonMaterial.toString(), - Lang.comparisonMaterialLore.toString(), (item1, item2) -> { - if (item2.getType() != item1.getType()) - return false; - if (item1.getType().getMaxDurability() > 0 || NMS.getMCVersion() >= 13) - return true; - return item2.getDurability() == item1.getDurability(); - })); - QuestsAPI.registerItemComparison(new ItemComparison("name", Lang.comparisonName.toString(), - Lang.comparisonNameLore.toString(), (item1, item2) -> { - ItemMeta meta1 = item1.getItemMeta(); - ItemMeta meta2 = item2.getItemMeta(); - return (meta1.hasDisplayName() == meta2.hasDisplayName()) - && Objects.equals(meta1.getDisplayName(), meta2.getDisplayName()); - }).setMetaNeeded()); - QuestsAPI.registerItemComparison(new ItemComparison("lore", Lang.comparisonLore.toString(), - Lang.comparisonLoreLore.toString(), (item1, item2) -> { - ItemMeta meta1 = item1.getItemMeta(); - ItemMeta meta2 = item2.getItemMeta(); - return (meta1.hasLore() == meta2.hasLore()) && Objects.equals(meta1.getLore(), meta2.getLore()); - }).setMetaNeeded()); - QuestsAPI.registerItemComparison(new ItemComparison("enchants", Lang.comparisonEnchants.toString(), - Lang.comparisonEnchantsLore.toString(), (item1, item2) -> { - ItemMeta meta1 = item1.getItemMeta(); - ItemMeta meta2 = item2.getItemMeta(); - return (meta1.hasEnchants() == meta2.hasEnchants()) - && Objects.equals(meta1.getEnchants(), meta2.getEnchants()); - }).setMetaNeeded()); - QuestsAPI.registerItemComparison(new ItemComparison("repair", Lang.comparisonRepairCost.toString(), - Lang.comparisonRepairCostLore.toString(), (item1, item2) -> { - ItemMeta meta1 = item1.getItemMeta(); - if (!(meta1 instanceof Repairable)) - return true; - ItemMeta meta2 = item2.getItemMeta(); - if (!(meta2 instanceof Repairable)) - return true; - return ((Repairable) meta1).getRepairCost() == ((Repairable) meta2).getRepairCost(); - }).setMetaNeeded()); - } - } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java index 7a1a40c0..b2d4953e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java @@ -11,19 +11,18 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.TextListEditor; -import fr.skytasul.quests.editors.checkers.MaterialParser; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; - -public class ItemCreatorGUI implements CustomInventory { - - private Inventory inv; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.TextListEditor; +import fr.skytasul.quests.api.editors.checkers.MaterialParser; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; + +public class ItemCreatorGUI extends CustomInventory { + private Player p; private Consumer<ItemStack> run; private boolean allowCancel; @@ -40,56 +39,56 @@ public ItemCreatorGUI(Consumer<ItemStack> end, boolean allowCancel){ private boolean quest = false; private boolean flags = false; + @Override + protected Inventory instanciate(@NotNull Player player) { + this.p = player; + return Bukkit.createInventory(null, 18, Lang.INVENTORY_CREATOR.toString()); + } @Override - public Inventory open(Player p) { - this.p = p; - inv = Bukkit.createInventory(null, 18, Lang.INVENTORY_CREATOR.toString()); - - inv.setItem(0, ItemUtils.item(XMaterial.GRASS_BLOCK, Lang.itemType.toString())); - inv.setItem(1, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1))); - inv.setItem(2, ItemUtils.itemSwitch(Lang.itemFlags.toString(), false)); - inv.setItem(3, ItemUtils.item(XMaterial.NAME_TAG, Lang.itemName.toString())); - inv.setItem(4, ItemUtils.item(XMaterial.FEATHER, Lang.itemLore.toString())); - inv.setItem(6, ItemUtils.item(XMaterial.BOOK, Lang.itemQuest.toString() + " §c" + Lang.No.toString())); - if (allowCancel) inv.setItem(8, ItemUtils.itemCancel); - inv.setItem(17, ItemUtils.itemDone); - inv.getItem(17).setType(Material.COAL); - - inv = p.openInventory(inv).getTopInventory(); - return inv; + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + inventory.setItem(0, ItemUtils.item(XMaterial.GRASS_BLOCK, Lang.itemType.toString())); + inventory.setItem(1, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1))); + inventory.setItem(2, ItemUtils.itemSwitch(Lang.itemFlags.toString(), false)); + inventory.setItem(3, ItemUtils.item(XMaterial.NAME_TAG, Lang.itemName.toString())); + inventory.setItem(4, ItemUtils.item(XMaterial.FEATHER, Lang.itemLore.toString())); + inventory.setItem(6, ItemUtils.item(XMaterial.BOOK, Lang.itemQuest.toString() + " §c" + Lang.No.toString())); + if (allowCancel) + inventory.setItem(8, ItemUtils.itemCancel); + inventory.setItem(17, ItemUtils.itemDone); + inventory.getItem(17).setType(Material.COAL); } - private void reopen(){ - p.openInventory(inv); - refresh(); + private void reopen() { + reopen(p); } private void refresh(){ if (type != null){ - inv.setItem(13, build()); - if (inv.getItem(17).getType() != Material.DIAMOND) inv.getItem(17).setType(Material.DIAMOND); + getInventory().setItem(13, build()); + if (getInventory().getItem(17).getType() != Material.DIAMOND) + getInventory().getItem(17).setType(Material.DIAMOND); } } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { switch (slot){ case 0: Lang.CHOOSE_ITEM_TYPE.send(p); - new TextEditor<>(p, () -> reopen(), obj -> { + new TextEditor<>(p, this::reopen, obj -> { type = obj; reopen(); - }, MaterialParser.ITEM_PARSER).enter(); + }, MaterialParser.ITEM_PARSER).start(); break; case 1: Lang.CHOOSE_ITEM_AMOUNT.send(p); - new TextEditor<>(p, () -> reopen(), obj -> { + new TextEditor<>(p, this::reopen, obj -> { amount = /*Math.min(obj, 64)*/ obj; ItemUtils.name(current, Lang.Amount.format(amount)); reopen(); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; case 2: @@ -99,10 +98,10 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli case 3: Lang.CHOOSE_ITEM_NAME.send(p); - new TextEditor<String>(p, () -> reopen(), obj -> { + new TextEditor<String>(p, this::reopen, obj -> { name = obj; reopen(); - }).enter(); + }).start(); break; case 4: @@ -110,7 +109,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli new TextListEditor(p, list -> { lore = list; reopen(); - }, lore).enter(); + }, lore).start(); break; case 6: @@ -125,13 +124,13 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli break; case 8: - Inventories.closeAndExit(p); + close(p); run.accept(null); break; case 17: //VALIDATE if (current.getType() == Material.DIAMOND){ - Inventories.closeAndExit(p); + close(p); run.accept(build()); } break; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java index 9d6fd670..2eb5137e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java @@ -8,13 +8,15 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.ItemUtils; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.gui.creation.ItemsGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -public class ItemGUI implements CustomInventory { +public class ItemGUI extends CustomInventory { private Consumer<ItemStack> end; private Runnable cancel; @@ -25,30 +27,32 @@ public ItemGUI(Consumer<ItemStack> end, Runnable cancel) { } @Override - public Inventory open(Player p){ - Inventory inv = Bukkit.createInventory(null, InventoryType.DROPPER, Lang.INVENTORY_ITEM.toString()); - + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, InventoryType.DROPPER, Lang.INVENTORY_ITEM.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { ItemStack separator = ItemUtils.itemSeparator(DyeColor.LIGHT_BLUE); for (int i = 0; i < 9; i++){ if (i == 4){ - inv.setItem(i, ItemsGUI.none); - }else inv.setItem(i, separator); + inventory.setItem(i, ItemsGUI.none); + } else + inventory.setItem(i, separator); } - - return p.openInventory(inv).getTopInventory(); } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click){ + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { if (slot != 4) return true; new ItemCreatorGUI((obj) -> { end.accept(obj); - }, false).create(p); + }, false).open(p); return true; } @Override - public boolean onClickCursor(Player p, Inventory inv, ItemStack current, ItemStack cursor, int slot){ + public boolean onClickCursor(Player p, ItemStack current, ItemStack cursor, int slot) { if (slot != 4) return true; p.setItemOnCursor(null); end.accept(cursor); @@ -56,9 +60,8 @@ public boolean onClickCursor(Player p, Inventory inv, ItemStack current, ItemSta } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(cancel); - return CloseBehavior.NOTHING; + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(cancel); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java index 3265d3da..aa03ad8a 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java @@ -6,11 +6,10 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.options.OptionRequirements; import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class ListBook{ @@ -21,9 +20,9 @@ public static void openQuestBook(Player p){ im.setTitle("Quests list"); im.setAuthor("BeautyQuests"); - QuestsAPI.getQuests().getQuests().stream().sorted().forEach(qu -> { + QuestsAPI.getAPI().getQuestsManager().getQuests().stream().sorted().forEach(qu -> { StringBuilder stb = new StringBuilder(formatLine(Lang.BOOK_NAME.toString(), qu.getName()) - + formatLine("ID", qu.getID() + "") + + formatLine("ID", qu.getId() + "") + ((qu.hasOption(OptionStarterNPC.class)) ? formatLine(Lang.BOOK_STARTER.toString(), qu.getOption(OptionStarterNPC.class).getValue().getName()) : "") //+ formatLine(Lang.BOOK_REWARDS.toString(), qu.getRewards().exp + " XP §3" + Lang.And.toString() + " §1" + qu.getRewards().itemsSize() + " " + Lang.Item.toString()) + formatLine(Lang.BOOK_SEVERAL.toString(), (qu.isRepeatable()) ? Lang.Yes.toString() : Lang.No.toString()) @@ -32,10 +31,12 @@ public static void openQuestBook(Player p){ + formatLine(Lang.BOOK_REQUIREMENTS.toString(), qu.getOptionValueOrDef(OptionRequirements.class).size() + "") + "\n" + formatLine(Lang.BOOK_STAGES.toString(), "") - + qu.getBranchesManager().getBranches().stream().mapToInt(QuestBranch::getStageSize).sum() + " stages in " + qu.getBranchesManager().getBranchesAmount() + " branches"); + + qu.getBranchesManager().getBranches().stream().mapToInt(branch -> branch.getRegularStages().size()) + .sum() + + " stages in " + qu.getBranchesManager().getBranches().size() + " branches"); im.addPage(stb.toString()); }); - if (QuestsAPI.getQuests().getQuests().isEmpty()) { + if (QuestsAPI.getAPI().getQuestsManager().getQuests().isEmpty()) { im.addPage(Lang.BOOK_NOQUEST.toString()); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index 12ebf95a..e1fc3f87 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -7,18 +7,20 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.utils.types.Title; -public class TitleGUI implements CustomInventory { +public class TitleGUI extends CustomInventory { private static final int SLOT_TITLE = 0; private static final int SLOT_SUBTITLE = 1; @@ -87,17 +89,20 @@ public void setFadeOut(int fadeOut) { } @Override - public Inventory open(Player p) { - inv = Bukkit.createInventory(null, 9, Lang.INVENTORY_EDIT_TITLE.toString()); - - inv.setItem(SLOT_TITLE, ItemUtils.item(XMaterial.NAME_TAG, Lang.title_title.toString())); - inv.setItem(SLOT_SUBTITLE, ItemUtils.item(XMaterial.NAME_TAG, Lang.title_subtitle.toString())); - inv.setItem(SLOT_FADE_IN, ItemUtils.item(XMaterial.CLOCK, Lang.title_fadeIn.toString())); - inv.setItem(SLOT_STAY, ItemUtils.item(XMaterial.CLOCK, Lang.title_stay.toString())); - inv.setItem(SLOT_FADE_OUT, ItemUtils.item(XMaterial.CLOCK, Lang.title_fadeOut.toString())); + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 9, Lang.INVENTORY_EDIT_TITLE.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + inventory.setItem(SLOT_TITLE, ItemUtils.item(XMaterial.NAME_TAG, Lang.title_title.toString())); + inventory.setItem(SLOT_SUBTITLE, ItemUtils.item(XMaterial.NAME_TAG, Lang.title_subtitle.toString())); + inventory.setItem(SLOT_FADE_IN, ItemUtils.item(XMaterial.CLOCK, Lang.title_fadeIn.toString())); + inventory.setItem(SLOT_STAY, ItemUtils.item(XMaterial.CLOCK, Lang.title_stay.toString())); + inventory.setItem(SLOT_FADE_OUT, ItemUtils.item(XMaterial.CLOCK, Lang.title_fadeOut.toString())); - inv.setItem(7, ItemUtils.itemCancel); - inv.setItem(8, ItemUtils.itemDone.toMutableStack()); + inventory.setItem(7, ItemUtils.itemCancel); + inventory.setItem(8, ItemUtils.itemDone.toMutableStack()); // updating lores setTitle(title); @@ -106,35 +111,32 @@ public Inventory open(Player p) { setStay(stay); setFadeOut(fadeOut); updateFinishState(); - - inv = p.openInventory(inv).getTopInventory(); - return inv; } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player player, ItemStack current, int slot, ClickType click) { switch (slot) { case SLOT_TITLE: - startStringEditor(p, Lang.TITLE_TITLE.toString(), this::setTitle); + startStringEditor(player, Lang.TITLE_TITLE.toString(), this::setTitle); break; case SLOT_SUBTITLE: - startStringEditor(p, Lang.TITLE_SUBTITLE.toString(), this::setSubtitle); + startStringEditor(player, Lang.TITLE_SUBTITLE.toString(), this::setSubtitle); break; case SLOT_FADE_IN: - startIntEditor(p, Lang.TITLE_FADEIN.toString(), this::setFadeIn); + startIntEditor(player, Lang.TITLE_FADEIN.toString(), this::setFadeIn); break; case SLOT_STAY: - startIntEditor(p, Lang.TITLE_STAY.toString(), this::setStay); + startIntEditor(player, Lang.TITLE_STAY.toString(), this::setStay); break; case SLOT_FADE_OUT: - startIntEditor(p, Lang.TITLE_FADEOUT.toString(), this::setFadeOut); + startIntEditor(player, Lang.TITLE_FADEOUT.toString(), this::setFadeOut); break; case 7: - Inventories.closeAndExit(p); + close(player); end.accept(null); break; case 8: - Inventories.closeAndExit(p); + close(player); end.accept(new Title(title, subtitle, fadeIn, stay, fadeOut)); break; default: @@ -144,30 +146,29 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(() -> end.accept(null)); - return CloseBehavior.REMOVE; + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(() -> end.accept(null)); } private void startStringEditor(Player p, String helpMsg, Consumer<String> setter) { - Utils.sendMessage(p, helpMsg); + MessageUtils.sendPrefixedMessage(p, helpMsg); new TextEditor<String>(p, () -> { p.openInventory(inv); }, msg -> { setter.accept(msg); updateFinishState(); p.openInventory(inv); - }).passNullIntoEndConsumer().enter(); + }).passNullIntoEndConsumer().start(); } private void startIntEditor(Player p, String helpMsg, Consumer<Integer> setter) { - Utils.sendMessage(p, helpMsg); + MessageUtils.sendPrefixedMessage(p, helpMsg); new TextEditor<>(p, () -> { p.openInventory(inv); }, msg -> { setter.accept(msg); p.openInventory(inv); - }, NumberParser.INTEGER_PARSER_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_POSITIVE).start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java index 2e0c0647..b05618ce 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java @@ -9,14 +9,14 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; public class EntityTypeGUI extends PagedGUI<EntityType>{ @@ -52,13 +52,13 @@ public ItemStack getItemStack(EntityType object){ @Override public void click(EntityType existing, ItemStack item, ClickType clickType){ - Inventories.closeAndExit(p); + close(player); run.accept(existing); } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - return CloseBehavior.REOPEN; + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REOPEN; } private static String getName(EntityType object) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java index e1513270..2efe9050 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobSelectionGUI.java @@ -4,13 +4,13 @@ import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.api.mobs.Mob; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.MobFactory; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.mobs.Mob; public class MobSelectionGUI extends PagedGUI<MobFactory<?>> { @@ -28,15 +28,14 @@ public ItemStack getItemStack(MobFactory<?> object) { @Override public void click(MobFactory<?> existing, ItemStack item, ClickType clickType) { - existing.itemClick(p, mobData -> { + existing.itemClick(player, mobData -> { end.accept(mobData == null ? null : new Mob(existing, mobData)); }); } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(() -> end.accept(null)); - return CloseBehavior.REMOVE; + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(() -> end.accept(null)); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java index 31478fc9..8b38cce9 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java @@ -9,14 +9,14 @@ import org.bukkit.DyeColor; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.LeveledMobFactory; -import fr.skytasul.quests.api.mobs.Mob; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.mobs.Mob; +import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.types.CountableObject; import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; @@ -39,28 +39,28 @@ public void finish(List<MutableCountableObject<Mob<?>>> objects) { public void clickObject(MutableCountableObject<Mob<?>> mob, ItemStack item, ClickType click) { super.clickObject(mob, item, click); if (click == ClickType.SHIFT_LEFT) { - Lang.MOB_NAME.send(p); - new TextEditor<>(p, super::reopen, name -> { + Lang.MOB_NAME.send(player); + new TextEditor<>(player, super::reopen, name -> { mob.getObject().setCustomName((String) name); setItems(); reopen(); - }).passNullIntoEndConsumer().enter(); + }).passNullIntoEndConsumer().start(); } else if (click == ClickType.LEFT) { - Lang.MOB_AMOUNT.send(p); - new TextEditor<>(p, super::reopen, amount -> { + Lang.MOB_AMOUNT.send(player); + new TextEditor<>(player, super::reopen, amount -> { mob.setAmount(amount); setItems(); reopen(); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); } else if (click == ClickType.SHIFT_RIGHT) { if (mob.getObject().getFactory() instanceof LeveledMobFactory) { - new TextEditor<>(p, super::reopen, level -> { + new TextEditor<>(player, super::reopen, level -> { mob.getObject().setMinLevel(level); setItems(); reopen(); - }, new NumberParser<>(Double.class, true, false)).enter(); + }, new NumberParser<>(Double.class, true, false)).start(); } else { - Utils.playPluginSound(p.getLocation(), "ENTITY_VILLAGER_NO", 0.6f); + QuestUtils.playPluginSound(player.getLocation(), "ENTITY_VILLAGER_NO", 0.6f); } } else if (click == ClickType.RIGHT) { remove(mob); @@ -74,7 +74,7 @@ public void createObject(Function<MutableCountableObject<Mob<?>>, ItemStack> cal reopen(); else callback.apply(CountableObject.createMutable(UUID.randomUUID(), mob, 1)); - }).create(p); + }).open(player); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java deleted file mode 100644 index ddf1a562..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NPCGUI.java +++ /dev/null @@ -1,137 +0,0 @@ -package fr.skytasul.quests.gui.npc; - -import java.util.function.Consumer; -import org.bukkit.Bukkit; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.WaitClick; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; - -public class NPCGUI implements CustomInventory{ - - private static final ItemStack nameItem = ItemUtils.item(XMaterial.NAME_TAG, Lang.name.toString()); - private static final ItemStack move = ItemUtils.item(XMaterial.MINECART, Lang.move.toString(), Lang.moveLore.toString()); - public static ItemStack validMove = ItemUtils.item(XMaterial.EMERALD, Lang.moveItem.toString()); - - private Consumer<BQNPC> end; - private Runnable cancel; - - private Inventory inv; - private EntityType en; - private String name; - private String skin; - - public NPCGUI(Consumer<BQNPC> end, Runnable cancel) { - this.end = end; - this.cancel = cancel; - } - - public CustomInventory openLastInv(Player p) { - p.openInventory(inv); - return this; - } - - @Override - public Inventory open(Player p){ - inv = Bukkit.createInventory(null, 9, Lang.INVENTORY_NPC.toString()); - - inv.setItem(0, move.clone()); - inv.setItem(1, nameItem.clone()); - setName("§cno name selected"); - setSkin("Knight"); - setType(EntityType.PLAYER); - inv.setItem(7, ItemUtils.itemCancel); - inv.setItem(8, ItemUtils.itemDone); - - inv = p.openInventory(inv).getTopInventory(); - return inv; - } - - private void setName(String name) { - this.name = name; - ItemUtils.lore(inv.getItem(1), Lang.optionValue.format(name)); - } - - private void setType(EntityType type) { - this.en = type; - if (en == EntityType.PLAYER) { - inv.setItem(5, ItemUtils.skull(Lang.type.toString(), null, Lang.optionValue.format("player"))); - }else inv.setItem(5, ItemUtils.item(Utils.mobItem(en), Lang.type.toString(), Lang.optionValue.format(en.getName()))); - } - - private void setSkin(String skin) { - this.skin = skin; - inv.setItem(3, ItemUtils.skull(Lang.skin.toString(), skin, Lang.optionValue.format(skin))); - } - - @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click){ - switch (slot){ - - case 0: - new WaitClick(p, () -> openLastInv(p), validMove.clone(), () -> openLastInv(p)).enter(); - break; - - case 1: - Lang.NPC_NAME.send(p); - new TextEditor<String>(p, () -> openLastInv(p), obj -> { - setName(obj); - openLastInv(p); - }).enter(); - break; - - case 3: - Lang.NPC_SKIN.send(p); - Inventories.closeWithoutExit(p); - new TextEditor<String>(p, () -> openLastInv(p), obj -> { - if (obj != null) setSkin(obj); - openLastInv(p); - }).useStrippedMessage().enter(); - break; - - case 5: - Inventories.create(p, new EntityTypeGUI(en -> { - setType(en); - Inventories.put(p, openLastInv(p), inv); - }, x -> x != null && QuestsAPI.getNPCsManager().isValidEntityType(x))); - break; - - case 7: - Inventories.closeAndExit(p); - cancel.run(); - break; - - case 8: - Inventories.closeAndExit(p); - try { - end.accept(QuestsAPI.getNPCsManager().createNPC(p.getLocation(), en, name, skin)); - }catch (Exception ex) { - ex.printStackTrace(); - Lang.ERROR_OCCURED.send(p, "npc creation " + ex.getMessage()); - cancel.run(); - } - break; - - } - return true; - } - - @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(cancel); - return CloseBehavior.NOTHING; - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java new file mode 100644 index 00000000..a5b23c64 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -0,0 +1,133 @@ +package fr.skytasul.quests.gui.npc; + +import java.util.function.Consumer; +import org.bukkit.Bukkit; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.WaitClick; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.gui.mobs.EntityTypeGUI; + +public class NpcCreateGUI extends CustomInventory { + + private static final ItemStack nameItem = ItemUtils.item(XMaterial.NAME_TAG, Lang.name.toString()); + private static final ItemStack move = ItemUtils.item(XMaterial.MINECART, Lang.move.toString(), Lang.moveLore.toString()); + public static ItemStack validMove = ItemUtils.item(XMaterial.EMERALD, Lang.moveItem.toString()); + + private Consumer<BQNPC> end; + private Runnable cancel; + + private EntityType en; + private String name; + private String skin; + + public NpcCreateGUI(Consumer<BQNPC> end, Runnable cancel) { + this.end = end; + this.cancel = cancel; + } + + @Override + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 9, Lang.INVENTORY_NPC.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + inventory.setItem(0, move.clone()); + inventory.setItem(1, nameItem.clone()); + setName("§cno name selected"); + setSkin("Knight"); + setType(EntityType.PLAYER); + inventory.setItem(7, ItemUtils.itemCancel); + inventory.setItem(8, ItemUtils.itemDone); + } + + private void setName(String name) { + this.name = name; + ItemUtils.lore(getInventory().getItem(1), Lang.optionValue.format(name)); + } + + private void setType(EntityType type) { + this.en = type; + if (en == EntityType.PLAYER) { + getInventory().setItem(5, ItemUtils.skull(Lang.type.toString(), null, Lang.optionValue.format("player"))); + } else + getInventory().setItem(5, + ItemUtils.item(Utils.mobItem(en), Lang.type.toString(), Lang.optionValue.format(en.getName()))); + } + + private void setSkin(String skin) { + this.skin = skin; + getInventory().setItem(3, ItemUtils.skull(Lang.skin.toString(), skin, Lang.optionValue.format(skin))); + } + + @Override + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + switch (slot){ + + case 0: + new WaitClick(p, () -> reopen(p), validMove.clone(), () -> reopen(p)).start(); + break; + + case 1: + Lang.NPC_NAME.send(p); + new TextEditor<String>(p, () -> reopen(p), obj -> { + setName(obj); + reopen(p); + }).start(); + break; + + case 3: + Lang.NPC_SKIN.send(p); + new TextEditor<String>(p, () -> reopen(p), obj -> { + if (obj != null) setSkin(obj); + reopen(p); + }).useStrippedMessage().start(); + break; + + case 5: + new EntityTypeGUI(en -> { + setType(en); + reopen(p); + }, x -> x != null && QuestsAPI.getAPI().getNPCsManager().isValidEntityType(x)).open(p); + break; + + case 7: + close(p); + cancel.run(); + break; + + case 8: + close(p); + try { + end.accept(QuestsAPI.getAPI().getNPCsManager().createNPC(p.getLocation(), en, name, skin)); + }catch (Exception ex) { + ex.printStackTrace(); + Lang.ERROR_OCCURED.send(p, "npc creation " + ex.getMessage()); + cancel.run(); + } + break; + + } + return true; + } + + @Override + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(cancel); + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java new file mode 100644 index 00000000..bab96abf --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -0,0 +1,54 @@ +package fr.skytasul.quests.gui.npc; + +import java.util.function.Consumer; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.SelectNPC; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.layout.Button; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI.Builder; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BQNPC; + +public final class NpcSelectGUI { + + private NpcSelectGUI() {} + + public static ItemStack createNPC = ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.createNPC.toString()); + public static ItemStack selectNPC = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); + + public static @NotNull CustomInventory select(@NotNull Runnable cancel, @NotNull Consumer<@NotNull BQNPC> end) { + return select(cancel, end, false); + } + + public static @NotNull CustomInventory selectNullable(@NotNull Runnable cancel, + @NotNull Consumer<@Nullable BQNPC> end) { + return select(cancel, end, true); + } + + private static CustomInventory select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, + boolean nullable) { + Builder builder = LayoutedGUI.newBuilder().addButton(1, Button.create(createNPC, event -> { + new NpcCreateGUI(end, event::reopen).open(event.getPlayer()); + })).addButton(3, Button.create(selectNPC, event -> { + new SelectNPC(event.getPlayer(), event::reopen, end).start(); + })); + if (nullable) + builder.addButton(2, Button.create(ItemUtils.itemNone, event -> { + event.close(); + end.accept(null); + })); + return builder + .setInventoryType(InventoryType.HOPPER) + .setName(Lang.INVENTORY_SELECT.toString()) + .setCloseBehavior(new DelayCloseBehavior(cancel)) + .build(); + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java deleted file mode 100644 index aa5ba627..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/SelectGUI.java +++ /dev/null @@ -1,83 +0,0 @@ -package fr.skytasul.quests.gui.npc; - -import java.util.function.Consumer; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.editors.SelectNPC; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; - -public class SelectGUI implements CustomInventory{ - - public static ItemStack createNPC = ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.createNPC.toString()); - public static ItemStack selectNPC = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); - - private Runnable cancel; - private Consumer<BQNPC> run; - private boolean nullable; - - public Inventory inv; - - public SelectGUI(Runnable cancel, Consumer<BQNPC> run) { - this.cancel = cancel; - this.run = run; - } - - public SelectGUI setNullable() { - this.nullable = true; - return this; - } - - public CustomInventory openLastInv(Player p) { - p.openInventory(inv); - return this; - } - - @Override - public Inventory open(Player p){ - inv = Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_SELECT.toString()); - - inv.setItem(1, createNPC.clone()); - inv.setItem(3, selectNPC.clone()); - if (nullable) inv.setItem(2, ItemUtils.item(XMaterial.BARRIER, "§cNone")); - - inv = p.openInventory(inv).getTopInventory(); - return inv; - } - - @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { - switch (slot){ - - case 1: - new NPCGUI(run, () -> Inventories.put(p, openLastInv(p), inv)).create(p); - break; - - case 2: - Inventories.closeAndExit(p); - run.accept(null); - break; - - case 3: - new SelectNPC(p, () -> openLastInv(p), run).enter(); - break; - } - return true; - } - - @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(cancel); - return CloseBehavior.NOTHING; - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index 25be4d10..a45af9d6 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -11,19 +11,21 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.ColorParser; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.ColorParser; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.compatibility.Post1_13; -import fr.skytasul.quests.utils.nms.NMS; -public class ParticleEffectGUI implements CustomInventory { +public class ParticleEffectGUI extends CustomInventory { private static final int SLOT_SHAPE = 1; private static final int SLOT_PARTICLE = 3; @@ -33,7 +35,7 @@ public class ParticleEffectGUI implements CustomInventory { static final List<Particle> PARTICLES = Arrays.stream(Particle.values()).filter(particle -> { if (particle.getDataType() == Void.class) return true; - if (NMS.getMCVersion() >= 13) return particle.getDataType() == Post1_13.getDustOptionClass(); + if (MinecraftVersion.MAJOR >= 13) return particle.getDataType() == Post1_13.getDustOptionClass(); return false; }).collect(Collectors.toList()); @@ -61,28 +63,30 @@ public ParticleEffectGUI(Consumer<ParticleEffect> end, Particle particle, Partic } @Override - public Inventory open(Player p) { - if (inv == null) { - inv = Bukkit.createInventory(null, 9, Lang.INVENTORY_PARTICLE_EFFECT.toString()); - - inv.setItem(SLOT_SHAPE, ItemUtils.item(XMaterial.FIREWORK_STAR, Lang.particle_shape.toString(), Lang.optionValue.format(shape))); - inv.setItem(SLOT_PARTICLE, ItemUtils.item(XMaterial.PAPER, Lang.particle_type.toString(), Lang.optionValue.format(particle))); - if (ParticleEffect.canHaveColor(particle)) setColorItem(); - - inv.setItem(SLOT_CANCEL, ItemUtils.itemCancel); - inv.setItem(SLOT_FINISH, ItemUtils.itemDone); - } - return inv = p.openInventory(inv).getTopInventory(); + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 9, Lang.INVENTORY_PARTICLE_EFFECT.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + inventory.setItem(SLOT_SHAPE, + ItemUtils.item(XMaterial.FIREWORK_STAR, Lang.particle_shape.toString(), Lang.optionValue.format(shape))); + inventory.setItem(SLOT_PARTICLE, + ItemUtils.item(XMaterial.PAPER, Lang.particle_type.toString(), Lang.optionValue.format(particle))); + if (ParticleEffect.canHaveColor(particle)) + setColorItem(); + + inventory.setItem(SLOT_CANCEL, ItemUtils.itemCancel); + inventory.setItem(SLOT_FINISH, ItemUtils.itemDone); } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(() -> end.accept(null)); - return CloseBehavior.REMOVE; + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(() -> end.accept(null)); } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { switch (slot) { case SLOT_SHAPE: @@ -103,8 +107,8 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli inv.setItem(SLOT_COLOR, null); } } - ParticleEffectGUI.this.create(p); - }).allowCancel().create(p); + ParticleEffectGUI.this.open(p); + }).allowCancel().open(p); break; case SLOT_COLOR: @@ -115,7 +119,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli color = newColor; ItemUtils.lore(current, getColorLore()); reopen.run(); - }, ColorParser.PARSER).enter(); + }, ColorParser.PARSER).start(); } break; diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java index 296b17b1..b9218cbb 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java @@ -8,10 +8,10 @@ import org.bukkit.Particle; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.StaticPagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.StaticPagedGUI; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.ParticleEffect; public class ParticleListGUI extends StaticPagedGUI<Particle> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java index 41cc4ff0..603c74e9 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java @@ -8,15 +8,18 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.WorldParser; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.WorldParser; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.utils.types.Permission; -public class PermissionGUI implements CustomInventory { +public class PermissionGUI extends CustomInventory { private String perm, world = null; private boolean take = false; @@ -31,40 +34,43 @@ public PermissionGUI(Consumer<Permission> end, Permission existingPerm) { } @Override - public Inventory open(Player p) { - Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_PERMISSION.toString()); - - inv.setItem(0, ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.perm.toString(), perm == null ? Lang.NotSet.toString() : "§b" + perm)); - inv.setItem(1, ItemUtils.item(XMaterial.FILLED_MAP, Lang.world.toString(), world == null ? Lang.worldGlobal.toString() : "§b" + world)); - inv.setItem(2, ItemUtils.itemSwitch(Lang.permRemove.toString(), take, Lang.permRemoveLore.toString())); + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_PERMISSION.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + inventory.setItem(0, ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.perm.toString(), + perm == null ? Lang.NotSet.toString() : "§b" + perm)); + inventory.setItem(1, ItemUtils.item(XMaterial.FILLED_MAP, Lang.world.toString(), + world == null ? Lang.worldGlobal.toString() : "§b" + world)); + inventory.setItem(2, ItemUtils.itemSwitch(Lang.permRemove.toString(), take, Lang.permRemoveLore.toString())); ItemStack done = ItemUtils.itemDone.toMutableStack(); if (perm == null) done.setType(Material.COAL); - inv.setItem(4, done); - - return p.openInventory(inv).getTopInventory(); + inventory.setItem(4, done); } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { switch (slot) { case 0: Lang.CHOOSE_PERM_REWARD.send(p); - new TextEditor<String>(p, () -> p.openInventory(inv), x -> { - inv.getItem(4).setType(Material.DIAMOND); - updatePerm(p, x, inv); + new TextEditor<String>(p, () -> reopen(p), x -> { + getInventory().getItem(4).setType(Material.DIAMOND); + updatePerm(p, x); }, () -> { - inv.getItem(4).setType(Material.COAL); - updatePerm(p, null, inv); - }).useStrippedMessage().enter(); + getInventory().getItem(4).setType(Material.COAL); + updatePerm(p, null); + }).useStrippedMessage().start(); break; case 1: Lang.CHOOSE_PERM_WORLD.send(p); - new TextEditor<>(p, () -> p.openInventory(inv), worldS -> { - updateWorld(p, worldS.getName(), inv); + new TextEditor<>(p, () -> reopen(p), worldS -> { + updateWorld(p, worldS.getName()); }, () -> { - updateWorld(p, null, inv); - }, new WorldParser()).enter(); + updateWorld(p, null); + }, new WorldParser()).start(); break; case 2: take = ItemUtils.toggle(current); @@ -77,21 +83,21 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli return true; } - private void updatePerm(Player p, String perm, Inventory inv) { + private void updatePerm(Player p, String perm) { this.perm = perm; - ItemUtils.lore(inv.getItem(0), perm == null ? Lang.NotSet.toString() : "§b" + perm); - p.openInventory(inv); + ItemUtils.lore(getInventory().getItem(0), perm == null ? Lang.NotSet.toString() : "§b" + perm); + reopen(p); } - private void updateWorld(Player p, String name, Inventory inv){ + private void updateWorld(Player p, String name) { world = name; - ItemUtils.lore(inv.getItem(1), world == null ? Lang.worldGlobal.toString() : "§b" + world); - p.openInventory(inv); + ItemUtils.lore(getInventory().getItem(1), world == null ? Lang.worldGlobal.toString() : "§b" + world); + reopen(p); } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - return CloseBehavior.REOPEN; + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REOPEN; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java index c4a8e9dd..5eaefc9a 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java @@ -7,9 +7,9 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.utils.types.Permission; public class PermissionListGUI extends ListGUI<Permission> { @@ -29,7 +29,7 @@ public ItemStack getObjectItemStack(Permission object) { public void createObject(Function<Permission, ItemStack> callback) { new PermissionGUI(perm -> { callback.apply(perm); - }, null).create(p); + }, null).open(player); } @Override @@ -37,7 +37,7 @@ public void clickObject(Permission object, ItemStack item, ClickType clickType) new PermissionGUI(perm -> { updateObject(object, perm); reopen(); - }, object).create(p); + }, object).open(player); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index 0c2e8c66..f155e073 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -9,25 +9,25 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.DurationParser; +import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.DurationParser; -import fr.skytasul.quests.editors.checkers.DurationParser.MinecraftTimeUnit; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.npc.SelectGUI; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.gui.npc.NpcSelectGUI; -public class PoolEditGUI implements CustomInventory { +public class PoolEditGUI extends CustomInventory { private static final int SLOT_NPC = 1; private static final int SLOT_HOLOGRAM = 2; @@ -63,7 +63,7 @@ public PoolEditGUI(Runnable end, QuestPool editing) { questsPerLaunch = editing.getQuestsPerLaunch(); redoAllowed = editing.isRedoAllowed(); timeDiff = editing.getTimeDiff(); - npcID = editing.getNPCID(); + npcID = editing.getNpcId(); avoidDuplicates = editing.doAvoidDuplicates(); requirements = editing.getRequirements(); } @@ -93,11 +93,6 @@ private String[] getRequirementsLore() { return new String[] { "", QuestOption.formatDescription(Lang.requirements.format(requirements.size())) }; } - private void reopen(Player p, Inventory inv, boolean reimplement) { - if (reimplement) Inventories.put(p, this, inv); - p.openInventory(inv); - } - private void handleDoneButton(Inventory inv) { boolean newState = /*name != null &&*/ npcID != -1; if (newState == canFinish) return; @@ -106,9 +101,12 @@ private void handleDoneButton(Inventory inv) { } @Override - public Inventory open(Player p) { - Inventory inv = Bukkit.createInventory(null, 18, Lang.INVENTORY_POOL_CREATE.toString()); - + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 18, Lang.INVENTORY_POOL_CREATE.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inv) { inv.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString(), getNPCLore())); inv.setItem(SLOT_HOLOGRAM, ItemUtils.item(XMaterial.OAK_SIGN, Lang.poolEditHologramText.toString(), getHologramLore())); inv.setItem(SLOT_MAX_QUESTS, ItemUtils.item(XMaterial.REDSTONE, Lang.poolMaxQuests.toString(), getMaxQuestsLore())); @@ -121,52 +119,50 @@ public Inventory open(Player p) { inv.setItem(SLOT_CANCEL, ItemUtils.itemCancel); inv.setItem(SLOT_CREATE, ItemUtils.item(XMaterial.CHARCOAL, Lang.done.toString())); handleDoneButton(inv); - - return p.openInventory(inv).getTopInventory(); } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { switch (slot) { case SLOT_NPC: - new SelectGUI(() -> reopen(p, inv, true), npc -> { + NpcSelectGUI.select(() -> reopen(p), npc -> { npcID = npc.getId(); ItemUtils.lore(current, getNPCLore()); - handleDoneButton(inv); - reopen(p, inv, true); - }).create(p); + handleDoneButton(getInventory()); + reopen(p); + }).open(p); break; case SLOT_HOLOGRAM: Lang.POOL_HOLOGRAM_TEXT.send(p); - new TextEditor<String>(p, () -> reopen(p, inv, false), msg -> { + new TextEditor<String>(p, () -> reopen(p), msg -> { hologram = msg; ItemUtils.lore(current, getHologramLore()); - reopen(p, inv, false); - }).passNullIntoEndConsumer().enter(); + reopen(p); + }).passNullIntoEndConsumer().start(); break; case SLOT_MAX_QUESTS: Lang.POOL_MAXQUESTS.send(p); - new TextEditor<>(p, () -> reopen(p, inv, false), msg -> { + new TextEditor<>(p, () -> reopen(p), msg -> { maxQuests = msg; ItemUtils.lore(current, getMaxQuestsLore()); - reopen(p, inv, false); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + reopen(p); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; case SLOT_QUESTS_PER_LAUNCH: Lang.POOL_QUESTS_PER_LAUNCH.send(p); - new TextEditor<>(p, () -> reopen(p, inv, false), msg -> { + new TextEditor<>(p, () -> reopen(p), msg -> { questsPerLaunch = msg; ItemUtils.lore(current, getQuestsPerLaunchLore()); - reopen(p, inv, false); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + reopen(p); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; case SLOT_TIME: Lang.POOL_TIME.send(p); - new TextEditor<>(p, () -> reopen(p, inv, false), msg -> { + new TextEditor<>(p, () -> reopen(p), msg -> { timeDiff = msg * 1000; ItemUtils.lore(current, getTimeLore()); - reopen(p, inv, false); - }, new DurationParser(MinecraftTimeUnit.SECOND, MinecraftTimeUnit.DAY)).enter(); + reopen(p); + }, new DurationParser(MinecraftTimeUnit.SECOND, MinecraftTimeUnit.DAY)).start(); break; case SLOT_REDO: redoAllowed = ItemUtils.toggle(current); @@ -175,11 +171,11 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli avoidDuplicates = ItemUtils.toggle(current); break; case SLOT_REQUIREMENTS: - QuestsAPI.getRequirements().createGUI(QuestObjectLocation.POOL, requirements -> { + QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.POOL, requirements -> { PoolEditGUI.this.requirements = requirements; ItemUtils.lore(current, getRequirementsLore()); - reopen(p, inv, true); - }, requirements).create(p); + reopen(p); + }, requirements).open(p); break; case SLOT_CANCEL: diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java index 8a425a12..379607ab 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java @@ -6,14 +6,15 @@ import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.pools.QuestPool; public class PoolsManageGUI extends PagedGUI<QuestPool> { @@ -32,17 +33,17 @@ public ItemStack getItemStack(QuestPool object) { public void click(QuestPool existing, ItemStack clicked, ClickType click) { if (click == ClickType.MIDDLE) { if (existing != null) { - BeautyQuests.getInstance().getPoolsManager().removePool(existing.getID()); - get().create(p); + BeautyQuests.getInstance().getPoolsManager().removePool(existing.getId()); + get().open(player); } }else { - new PoolEditGUI(() -> get().create(p), existing).create(p); + new PoolEditGUI(() -> get().open(player), existing).open(player); } } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - return CloseBehavior.REMOVE; + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REMOVE; } public static PoolsManageGUI get() { diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java index 273754b0..810d0668 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java @@ -2,61 +2,36 @@ import java.util.Collection; import java.util.Comparator; +import java.util.Objects; import java.util.function.Consumer; -import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.quests.Quest; public class ChooseQuestGUI extends PagedGUI<Quest> { - private Consumer<Quest> run; - private boolean canSkip; - - public CustomInventory openLastInv(Player p) { - p.openInventory(inv); - return this; - } - - public ChooseQuestGUI(Collection<Quest> quests, Consumer<Quest> run) { - this(quests, run, false); - } + private @NotNull Consumer<Quest> run; + private @Nullable Runnable cancel; - public ChooseQuestGUI(Collection<Quest> quests, Consumer<Quest> run, boolean canSkip) { + private ChooseQuestGUI(@NotNull Collection<@NotNull Quest> quests, @NotNull Consumer<@NotNull Quest> run, + @Nullable Runnable cancel) { super(Lang.INVENTORY_CHOOSE.toString(), DyeColor.MAGENTA, quests); - Validate.notNull(run, "Runnable cannot be null"); super.objects.sort(Comparator.naturalOrder()); - this.run = run; - this.canSkip = canSkip; - } - - @Override - public Inventory open(Player p){ - if (objects.size() == 0) { - run.accept(null); - return null; - } else if (objects.size() == 1 && canSkip && QuestsConfiguration.skipNpcGuiIfOnlyOneQuest()) { - run.accept(objects.get(0)); - return null; - } - - return super.open(p); - } - - @Override - public CloseBehavior onClose(Player p, Inventory inv){ - return CloseBehavior.REMOVE; + this.run = Objects.requireNonNull(run); + this.cancel = cancel; } @Override @@ -66,8 +41,36 @@ public ItemStack getItemStack(Quest object) { @Override public void click(Quest existing, ItemStack item, ClickType clickType) { - if (inv != null) Inventories.closeAndExit(p); + close(player); run.accept(existing); } + @Override + public @NotNull CloseBehavior onClose(@NotNull Player player) { + if (cancel != null) + return new DelayCloseBehavior(cancel); + return StandardCloseBehavior.REMOVE; + } + + public static void choose(@NotNull Player player, @NotNull Collection<@NotNull Quest> quests, + @NotNull Consumer<@Nullable Quest> run, @Nullable Runnable cancel, boolean canSkip) { + choose(player, quests, run, cancel, canSkip, null); + } + + public static void choose(@NotNull Player player, @NotNull Collection<@NotNull Quest> quests, + @NotNull Consumer<@Nullable Quest> run, @Nullable Runnable cancel, boolean canSkip, + @Nullable Consumer<@NotNull ChooseQuestGUI> guiConsumer) { + if (quests.isEmpty()) { + if (cancel != null) + cancel.run(); + } else if (quests.size() == 1 && canSkip && QuestsConfiguration.skipNpcGuiIfOnlyOneQuest()) { + run.accept(quests.iterator().next()); + } else { + ChooseQuestGUI gui = new ChooseQuestGUI(quests, run, cancel); + if (guiConsumer != null) + guiConsumer.accept(gui); + gui.open(player); + } + } + } \ 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 a60507a4..23bd2383 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 @@ -10,24 +10,25 @@ import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.dialogs.Message; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.types.Dialogable; +import fr.skytasul.quests.api.utils.ChatColorUtils; import fr.skytasul.quests.gui.quests.DialogHistoryGUI.WrappedDialogable; -import fr.skytasul.quests.gui.templates.PagedGUI; import fr.skytasul.quests.options.OptionStartDialog; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.utils.ChatUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.types.Message; +import fr.skytasul.quests.utils.QuestUtils; public class DialogHistoryGUI extends PagedGUI<WrappedDialogable> { @@ -63,13 +64,13 @@ public void click(WrappedDialogable existing, ItemStack item, ClickType clickTyp if (existing.page > 0) { existing.page--; changed = true; - Utils.playPluginSound(p, "ENTITY_BAT_TAKEOFF", 0.4f, 1.5f); + QuestUtils.playPluginSound(player, "ENTITY_BAT_TAKEOFF", 0.4f, 1.5f); } }else if (clickType.isRightClick()) { if (existing.page + 1 < existing.pages.size()) { existing.page++; changed = true; - Utils.playPluginSound(p, "ENTITY_BAT_TAKEOFF", 0.4f, 1.7f); + QuestUtils.playPluginSound(player, "ENTITY_BAT_TAKEOFF", 0.4f, 1.7f); } } @@ -77,9 +78,9 @@ public void click(WrappedDialogable existing, ItemStack item, ClickType clickTyp } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(end); - return CloseBehavior.NOTHING; + public CloseBehavior onClose(Player p) { + QuestUtils.runSync(end); + return StandardCloseBehavior.NOTHING; } public static Stream<Dialogable> getDialogableStream(PlayerQuestDatas datas, Quest quest) { @@ -112,12 +113,12 @@ class WrappedDialogable { WrappedDialogable(Dialogable dialogable) { this.dialogable = dialogable; - List<Message> messages = dialogable.getDialog().messages; + List<Message> messages = dialogable.getDialog().getMessages(); List<List<String>> lines = new ArrayList<>(messages.size()); for (int i = 0; i < messages.size(); i++) { Message msg = messages.get(i); String formatted = msg.formatMessage(player, dialogable.getDialog().getNPCName(dialogable.getNPC()), i, messages.size()); - lines.add(ChatUtils.wordWrap(formatted, 40, 100)); + lines.add(ChatColorUtils.wordWrap(formatted, 40, 100)); } if (lines.isEmpty()) { 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 2eb7ac4f..23454786 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 @@ -11,66 +11,70 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.ConfirmGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.misc.ConfirmGUI; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.PlayerListCategory; import fr.skytasul.quests.options.OptionStartable; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.players.PlayerAccountImplementation; +import fr.skytasul.quests.utils.QuestUtils; -public class PlayerListGUI implements CustomInventory { +public class PlayerListGUI extends CustomInventory { - private static final String UNSELECTED_PREFIX = "§7○ "; + static final String UNSELECTED_PREFIX = "§7○ "; private static final String SELECTED_PREFIX = "§b§l● "; private Inventory inv; private Player open; - private PlayerAccount acc; + private PlayerAccountImplementation acc; private boolean hide; private int page = 0; - private Category cat = Category.NONE; + private @Nullable PlayerListCategory cat = null; private List<Quest> quests; - public PlayerListGUI(PlayerAccount acc) { + public PlayerListGUI(PlayerAccountImplementation acc) { this(acc, true); } - public PlayerListGUI(PlayerAccount acc, boolean hide) { + public PlayerListGUI(PlayerAccountImplementation acc, boolean hide) { this.acc = acc; this.hide = hide; } @Override - public Inventory open(Player p) { - open = p; - inv = Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc.getOfflinePlayer().getName())); + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc.getOfflinePlayer().getName())); + } + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { setBarItem(0, ItemUtils.itemLaterPage); setBarItem(4, ItemUtils.itemNextPage); - for (Category enabledCat : QuestsConfiguration.getMenuConfig().getEnabledTabs()) { - setBarItem(enabledCat.slot, enabledCat.item); + for (PlayerListCategory enabledCat : QuestsConfiguration.getMenuConfig().getEnabledTabs()) { + setBarItem(enabledCat.getSlot(), + ItemUtils.item(enabledCat.getMaterial(), UNSELECTED_PREFIX + enabledCat.getName())); } - if (Category.IN_PROGRESS.isEnabled()) { - setCategory(Category.IN_PROGRESS); - if (quests.isEmpty() && QuestsConfiguration.getMenuConfig().isNotStartedTabOpenedWhenEmpty() && Category.NOT_STARTED.isEnabled()) setCategory(Category.NOT_STARTED); - }else if (Category.NOT_STARTED.isEnabled()) { - setCategory(Category.NOT_STARTED); - }else setCategory(Category.FINISHED); - - inv = p.openInventory(inv).getTopInventory(); - return inv; + if (PlayerListCategory.IN_PROGRESS.isEnabled()) { + setCategory(PlayerListCategory.IN_PROGRESS); + if (quests.isEmpty() && QuestsConfiguration.getMenuConfig().isNotStartedTabOpenedWhenEmpty() && PlayerListCategory.NOT_STARTED.isEnabled()) setCategory(PlayerListCategory.NOT_STARTED); + }else if (PlayerListCategory.NOT_STARTED.isEnabled()) { + setCategory(PlayerListCategory.NOT_STARTED); + }else setCategory(PlayerListCategory.FINISHED); } private void setQuests(List<Quest> quests) { @@ -78,15 +82,16 @@ private void setQuests(List<Quest> quests) { quests.sort(null); } - private void setCategory(Category category){ + private void setCategory(PlayerListCategory category){ if (cat == category) return; - if (cat != Category.NONE) toggleCategorySelected(); + if (cat != null) + toggleCategorySelected(); cat = category; page = 0; toggleCategorySelected(); setItems(); - DyeColor color = cat == Category.FINISHED ? DyeColor.GREEN: (cat == Category.IN_PROGRESS ? DyeColor.YELLOW : DyeColor.RED); + DyeColor color = cat == PlayerListCategory.FINISHED ? DyeColor.GREEN: (cat == PlayerListCategory.IN_PROGRESS ? DyeColor.YELLOW : DyeColor.RED); for (int i = 0; i < 5; i++) inv.setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); } @@ -95,8 +100,8 @@ private void setItems(){ switch (cat){ case FINISHED: - displayQuests(QuestsAPI.getQuests().getQuestsFinished(acc, hide), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, Source.MENU).formatDescription(); + displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide), qu -> { + List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); if (QuestsConfiguration.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { if (!lore.isEmpty()) lore.add(null); lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); @@ -106,8 +111,8 @@ private void setItems(){ break; case IN_PROGRESS: - displayQuests(QuestsAPI.getQuests().getQuestsStarted(acc, true, false), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, Source.MENU).formatDescription(); + displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false), qu -> { + List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); boolean hasDialogs = QuestsConfiguration.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs(); boolean cancellable = QuestsConfiguration.getMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); @@ -121,8 +126,10 @@ private void setItems(){ break; case NOT_STARTED: - displayQuests(QuestsAPI.getQuests().getQuestsNotStarted(acc, hide, true).stream().filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.isLauncheable(acc.getPlayer(), acc, false)).collect(Collectors.toList()), qu -> { - return createQuestItem(qu, new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, Source.MENU).formatDescription()); + displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() + .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) + .collect(Collectors.toList()), qu -> { + return createQuestItem(qu, new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription()); }); break; @@ -140,8 +147,8 @@ private void displayQuests(List<Quest> quests, Function<Quest, ItemStack> itemPr try { item = itemProvider.apply(qu); }catch (Exception ex) { - item = ItemUtils.item(XMaterial.BARRIER, "§cError - Quest #" + qu.getID()); - BeautyQuests.logger.severe("An error ocurred when creating item of quest " + qu.getID() + " for account " + acc.abstractAcc.getIdentifier(), ex); + item = ItemUtils.item(XMaterial.BARRIER, "§cError - Quest #" + qu.getId()); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred when creating item of quest " + qu.getId() + " for account " + acc.abstractAcc.getIdentifier(), ex); } setMainItem(i - page * 35, item); } @@ -161,7 +168,7 @@ private int setBarItem(int barSlot, ItemStack is){ } private ItemStack createQuestItem(Quest qu, List<String> lore) { - return ItemUtils.nameAndLore(qu.getQuestItem().clone(), open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu.getName(), qu.getID()) : Lang.formatNormal.format(qu.getName()), lore); + return ItemUtils.nameAndLore(qu.getQuestItem().clone(), open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu.getName(), qu.getId()) : Lang.formatNormal.format(qu.getName()), lore); } private void toggleCategorySelected() { @@ -181,8 +188,7 @@ private void toggleCategorySelected() { @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { - PlayerListGUI thiz = this; + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { switch (slot % 9){ case 8: int barSlot = (slot - 8) / 9; @@ -200,7 +206,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli case 1: case 2: case 3: - Category category = Category.values()[barSlot]; + PlayerListCategory category = PlayerListCategory.values()[barSlot]; if (category.isEnabled()) setCategory(category); break; @@ -213,31 +219,24 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli default: int id = (int) (slot - (Math.floor(slot * 1D / 9D) * 2) + page * 35); Quest qu = quests.get(id); - if (cat == Category.NOT_STARTED) { + if (cat == PlayerListCategory.NOT_STARTED) { if (!qu.getOptionValueOrDef(OptionStartable.class)) break; if (!acc.isCurrent()) break; Player target = acc.getPlayer(); - if (qu.isLauncheable(target, acc, true)) { + if (qu.canStart(target, true)) { p.closeInventory(); qu.attemptStart(target); } }else { if (click.isRightClick()) { if (QuestsConfiguration.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { - Utils.playPluginSound(p, "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); - new DialogHistoryGUI(acc, qu, () -> { - Inventories.put(p, thiz, inv); - p.openInventory(inv); - }).create(p); + QuestUtils.playPluginSound(p, "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); + new DialogHistoryGUI(acc, qu, () -> reopen(p)).open(p); } }else if (click.isLeftClick()) { - if (QuestsConfiguration.getMenuConfig().allowPlayerCancelQuest() && cat == Category.IN_PROGRESS && qu.isCancellable()) { - Inventories.create(p, new ConfirmGUI(() -> { - qu.cancelPlayer(acc); - }, () -> { - p.openInventory(inv); - Inventories.put(p, thiz, inv); - }, Lang.INDICATION_CANCEL.format(qu.getName()))); + if (QuestsConfiguration.getMenuConfig().allowPlayerCancelQuest() && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { + ConfirmGUI.confirm(() -> qu.cancelPlayer(acc), () -> reopen(p), + Lang.INDICATION_CANCEL.format(qu.getName())).open(p); } } } @@ -248,47 +247,8 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli } @Override - public CloseBehavior onClose(Player p, Inventory inv){ - return CloseBehavior.REMOVE; - } - - public enum Category { - NONE, - FINISHED( - 1, - XMaterial.WRITTEN_BOOK, - Lang.finisheds.toString()), - IN_PROGRESS( - 2, - XMaterial.BOOK, - Lang.inProgress.toString()), - NOT_STARTED( - 3, - XMaterial.WRITABLE_BOOK, - Lang.notStarteds.toString()); - - private int slot; - private ItemStack item; - - private Category() {} - - private Category(int slot, XMaterial material, String name) { - this.slot = slot; - this.item = ItemUtils.item(material, UNSELECTED_PREFIX + name); - } - - public boolean isEnabled() { - return QuestsConfiguration.getMenuConfig().getEnabledTabs().contains(this); - } - - public static Category fromString(String name) { - try { - Category cat = Category.valueOf(name.toUpperCase()); - if (cat != NONE) return cat; - }catch (IllegalArgumentException ex) {} - return null; - } - + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REMOVE; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java index a8fbfe8c..1627c1db 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/QuestsListGUI.java @@ -5,15 +5,15 @@ import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; public class QuestsListGUI extends PagedGUI<Quest> { @@ -22,27 +22,27 @@ public class QuestsListGUI extends PagedGUI<Quest> { public QuestsListGUI(Consumer<Quest> run, PlayerAccount acc, boolean started, boolean notStarted, boolean finished){ super(Lang.INVENTORY_QUESTS_LIST.toString(), DyeColor.CYAN, new ArrayList<>(), null, Quest::getName); if (acc != null){ - if (started) super.objects.addAll(QuestsAPI.getQuests().getQuestsStarted(acc)); - if (notStarted) super.objects.addAll(QuestsAPI.getQuests().getQuestsNotStarted(acc, false, true)); - if (finished) super.objects.addAll(QuestsAPI.getQuests().getQuestsFinished(acc, false)); - }else super.objects.addAll(QuestsAPI.getQuests().getQuests()); + if (started) super.objects.addAll(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc)); + if (notStarted) super.objects.addAll(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, false, true)); + if (finished) super.objects.addAll(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, false)); + }else super.objects.addAll(QuestsAPI.getAPI().getQuestsManager().getQuests()); this.run = run; } @Override public ItemStack getItemStack(Quest qu){ - return ItemUtils.nameAndLore(qu.getQuestItem().clone(), "§6§l§o" + qu.getName() + " §r§e#" + qu.getID(), qu.getDescription()); + return ItemUtils.nameAndLore(qu.getQuestItem().clone(), "§6§l§o" + qu.getName() + " §r§e#" + qu.getId(), qu.getDescription()); } @Override public void click(Quest existing, ItemStack item, ClickType clickType){ - Inventories.closeAndExit(p); + close(player); run.accept(existing); } @Override - public CloseBehavior onClose(Player p, Inventory inv){ - return CloseBehavior.REMOVE; + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REMOVE; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java deleted file mode 100644 index e3d1eafd..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/ChooseGUI.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.skytasul.quests.gui.templates; - -import java.util.List; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.gui.CustomInventory; - -public abstract class ChooseGUI<T> implements CustomInventory { - - private List<T> available; - - public ChooseGUI(List<T> available){ - this.available = available; - } - - public Inventory open(Player p){ - Inventory inv = Bukkit.createInventory(null, (int) Math.ceil(available.size() * 1.0 / 9.0)*9, name()); - - for (int i = 0; i < available.size(); i++) { - inv.setItem(i, getItemStack(available.get(i))); - } - - return p.openInventory(inv).getTopInventory(); - } - - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click){ - finish(available.get(slot)); - return true; - } - - @Override - public CloseBehavior onClose(Player p, Inventory inv) { - return CloseBehavior.REOPEN; - } - - /** - * @return Inventory's name - */ - public abstract String name(); - - /** - * @param object existing object to represent - * @return ItemStack who represents the object - */ - - public abstract ItemStack getItemStack(T object); - - /** - * Called when the player click on an item - */ - public abstract void finish(T object); - -} diff --git a/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java b/core/src/main/java/fr/skytasul/quests/mobs/Mob.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java rename to core/src/main/java/fr/skytasul/quests/mobs/Mob.java index 0e3d919a..2ad3ec9a 100644 --- a/core/src/main/java/fr/skytasul/quests/api/mobs/Mob.java +++ b/core/src/main/java/fr/skytasul/quests/mobs/Mob.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.mobs; +package fr.skytasul.quests.mobs; import java.text.DecimalFormat; import java.text.NumberFormat; @@ -10,8 +10,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.mobs.LeveledMobFactory; +import fr.skytasul.quests.api.mobs.MobFactory; +import fr.skytasul.quests.api.utils.Utils; public class Mob<D> implements Cloneable { @@ -73,7 +75,7 @@ public void setMinLevel(@Nullable Double minLevel) { try { return Utils.mobItem(factory.getEntityType(data)); }catch (Exception ex) { - BeautyQuests.logger.warning("Unknow entity type for mob " + factory.getName(data), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unknow entity type for mob " + factory.getName(data), ex); return XMaterial.SPONGE; } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionAutoQuest.java b/core/src/main/java/fr/skytasul/quests/options/OptionAutoQuest.java index e4948d96..b78d81fa 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionAutoQuest.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionAutoQuest.java @@ -1,7 +1,7 @@ package fr.skytasul.quests.options; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; -import fr.skytasul.quests.utils.Lang; public class OptionAutoQuest extends QuestOptionBoolean { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionBypassLimit.java b/core/src/main/java/fr/skytasul/quests/options/OptionBypassLimit.java index 73c174ae..780f8f65 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionBypassLimit.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionBypassLimit.java @@ -1,7 +1,7 @@ package fr.skytasul.quests.options; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; -import fr.skytasul.quests.utils.Lang; public class OptionBypassLimit extends QuestOptionBoolean { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java index 4adf8761..5f059c48 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java @@ -6,13 +6,13 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.objects.QuestObjectGUI; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.gui.creation.QuestObjectGUI; -import fr.skytasul.quests.utils.Lang; public class OptionCancelRewards extends QuestOptionRewards { @@ -36,11 +36,11 @@ public String getItemDescription() { @Override public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - new QuestObjectGUI<>(Lang.INVENTORY_CANCEL_ACTIONS.toString(), QuestObjectLocation.CANCELLING, QuestsAPI.getRewards().getCreators().stream().filter(x -> !x.canBeAsync()).collect(Collectors.toList()), objects -> { + new QuestObjectGUI<>(Lang.INVENTORY_CANCEL_ACTIONS.toString(), QuestObjectLocation.CANCELLING, QuestsAPI.getAPI().getRewards().getCreators().stream().filter(x -> !x.canBeAsync()).collect(Collectors.toList()), objects -> { setValue(objects); ItemUtils.lore(item, getLore()); gui.reopen(p); - }, getValue()).create(p); + }, getValue()).open(p); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java b/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java index f27ad42d..05d690f0 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.options; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionBoolean; -import fr.skytasul.quests.utils.Lang; public class OptionCancellable extends QuestOptionBoolean { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java index 8d4bb931..4341fdcb 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java @@ -3,9 +3,9 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; -import fr.skytasul.quests.utils.Lang; public class OptionConfirmMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java index a388b5f4..b1ff6dfd 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java @@ -7,11 +7,11 @@ import com.cryptomorin.xseries.XMaterial; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; public class OptionDescription extends QuestOptionString implements QuestDescriptionProvider { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java index 3be49b39..e4c64314 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java @@ -2,8 +2,8 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; -import fr.skytasul.quests.utils.Lang; public class OptionEndMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java index a6e58bff..2febe195 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java @@ -5,13 +5,13 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.Utils; public class OptionEndRewards extends QuestOptionRewards implements QuestDescriptionProvider { @@ -41,7 +41,7 @@ public String getItemDescription() { public List<String> provideDescription(QuestDescriptionContext context) { if (!context.getPlayerAccount().isCurrent()) return null; if (!context.getDescriptionOptions().showRewards()) return null; - if (context.getCategory() == Category.FINISHED) return null; + if (context.getCategory() == PlayerListCategory.FINISHED) return null; List<String> rewards = getValue().stream() .map(x -> x.getDescription(context.getPlayerAccount().getPlayer())) diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java index 52e8f96a..54d124c3 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java @@ -2,8 +2,8 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; -import fr.skytasul.quests.utils.Lang; public class OptionEndSound extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java index 6d1a87e4..74d335d6 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java @@ -3,10 +3,10 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.players.PlayerAccountImplementation; public class OptionFailOnDeath extends QuestOptionBoolean implements Listener { @@ -22,7 +22,7 @@ public String getDescription() { @EventHandler public void onDeath(PlayerDeathEvent e) { - PlayerAccount acc = PlayersManager.getPlayerAccount(e.getEntity()); + PlayerAccountImplementation acc = PlayersManager.getPlayerAccount(e.getEntity()); if (acc == null) return; if (getAttachedQuest().hasStarted(acc)) { getAttachedQuest().cancelPlayer(acc); diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java index c18cad7d..ce82a043 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java @@ -10,12 +10,12 @@ import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class OptionFirework extends QuestOption<FireworkMeta> { @@ -81,7 +81,7 @@ public boolean clickCursor(FinishGUI gui, Player p, ItemStack item, ItemStack cu if (cursorMeta instanceof FireworkMeta) { setValue((FireworkMeta) cursorMeta); ItemUtils.lore(item, getLore()); - Utils.runSync(() -> p.setItemOnCursor(null)); + Utils.runSync(() -> player.setItemOnCursor(null)); Lang.FIREWORK_EDITED.send(p); }else { Lang.FIREWORK_INVALID.send(p); diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHideNoRequirements.java b/core/src/main/java/fr/skytasul/quests/options/OptionHideNoRequirements.java index 87dbaf1b..5580160d 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHideNoRequirements.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHideNoRequirements.java @@ -1,7 +1,7 @@ package fr.skytasul.quests.options; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; -import fr.skytasul.quests.utils.Lang; public class OptionHideNoRequirements extends QuestOptionBoolean { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java index f9c0c698..70d9b54a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java @@ -2,9 +2,9 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionItem; -import fr.skytasul.quests.utils.Lang; public class OptionHologramLaunch extends QuestOptionItem { @@ -29,7 +29,7 @@ public String getItemDescription() { @Override public boolean shouldDisplay(OptionSet options) { - return QuestsAPI.hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; + return QuestsAPI.getAPI().hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java index b5326465..fd0715ca 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java @@ -2,9 +2,9 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionItem; -import fr.skytasul.quests.utils.Lang; public class OptionHologramLaunchNo extends QuestOptionItem { @@ -29,7 +29,7 @@ public String getItemDescription() { @Override public boolean shouldDisplay(OptionSet options) { - return QuestsAPI.hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; + return QuestsAPI.getAPI().hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java index 5e6fd46a..ae031c85 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java @@ -4,9 +4,9 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; -import fr.skytasul.quests.utils.Lang; public class OptionHologramText extends QuestOptionString { @@ -36,7 +36,7 @@ public String getItemDescription() { @Override public boolean shouldDisplay(OptionSet options) { - return !QuestsConfiguration.isTextHologramDisabled() && QuestsAPI.hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; + return !QuestsConfiguration.isTextHologramDisabled() && QuestsAPI.getAPI().hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionName.java b/core/src/main/java/fr/skytasul/quests/options/OptionName.java index 5353df56..118faff7 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionName.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionName.java @@ -2,8 +2,8 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; -import fr.skytasul.quests.utils.Lang; public class OptionName extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java index 46bc9276..6ce3a889 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java @@ -6,14 +6,14 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.MaterialParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.MaterialParser; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class OptionQuestItem extends QuestOption<ItemStack> { @@ -71,12 +71,12 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c gui.inv.setItem(slot, ItemUtils.nameAndLore(getValue().clone(), Lang.customMaterial.toString(), getLore())); } gui.reopen(p); - }, MaterialParser.ANY_PARSER).passNullIntoEndConsumer().enter(); + }, MaterialParser.ANY_PARSER).passNullIntoEndConsumer().start(); } @Override public boolean clickCursor(FinishGUI gui, Player p, ItemStack item, ItemStack cursor, int slot) { - Utils.runSync(() -> p.setItemOnCursor(null)); + Utils.runSync(() -> player.setItemOnCursor(null)); setValue(cursor); ItemUtils.nameAndLore(cursor, Lang.customMaterial.toString(), getLore()); return false; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java index c582cd3b..56c3cbeb 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java @@ -11,19 +11,19 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.structure.QuestImplementation; +import fr.skytasul.quests.structure.pools.QuestPoolImplementation; -public class OptionQuestPool extends QuestOption<QuestPool> { +public class OptionQuestPool extends QuestOption<QuestPoolImplementation> { @Override - public void attach(Quest quest) { + public void attach(QuestImplementation quest) { super.attach(quest); if (getValue() != null) getValue().addQuest(quest); } @@ -36,7 +36,7 @@ public void detach() { @Override public Object save() { - return getValue().getID(); + return getValue().getId(); } @Override @@ -45,7 +45,7 @@ public void load(ConfigurationSection config, String key) { } @Override - public QuestPool cloneValue(QuestPool value) { + public QuestPoolImplementation cloneValue(QuestPoolImplementation value) { return value; } @@ -53,7 +53,7 @@ private List<String> getLore() { List<String> lore = new ArrayList<>(5); lore.add(formatDescription(Lang.questPoolLore.toString())); lore.add(""); - lore.add(formatValue(getValue() == null ? null : "#" + getValue().getID())); + lore.add(formatValue(getValue() == null ? null : "#" + getValue().getId())); if (hasCustomValue()) { lore.add(""); lore.add("§8" + Lang.ClickShiftRight.toString() + " > §d" + Lang.Reset.toString()); @@ -73,26 +73,26 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c ItemUtils.lore(item, getLore()); gui.reopen(p); }else { - new PagedGUI<QuestPool>(Lang.INVENTORY_POOLS_LIST.toString(), DyeColor.CYAN, BeautyQuests.getInstance().getPoolsManager().getPools(), list -> gui.reopen(p), null) { + new PagedGUI<QuestPoolImplementation>(Lang.INVENTORY_POOLS_LIST.toString(), DyeColor.CYAN, BeautyQuests.getInstance().getPoolsManager().getPools(), list -> gui.reopen(p), null) { @Override - public ItemStack getItemStack(QuestPool object) { + public ItemStack getItemStack(QuestPoolImplementation object) { return object.getItemStack(Lang.poolChoose.toString()); } @Override - public void click(QuestPool existing, ItemStack poolItem, ClickType click) { + public void click(QuestPoolImplementation existing, ItemStack poolItem, ClickType click) { setValue(existing); ItemUtils.lore(item, getLore()); - gui.reopen(p); + gui.reopen(player); } @Override public CloseBehavior onClose(Player p, Inventory inv) { Bukkit.getScheduler().runTask(BeautyQuests.getInstance(), () -> gui.reopen(p)); - return CloseBehavior.NOTHING; + return StandardCloseBehavior.NOTHING; } - }.create(p); + }.open(p); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java b/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java index 5fea8a23..a14400e6 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java @@ -2,11 +2,11 @@ import java.util.ArrayList; import java.util.List; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.PlayerListCategory; public class OptionRepeatable extends QuestOptionBoolean implements QuestDescriptionProvider { @@ -22,7 +22,7 @@ public String getDescription() { @Override public List<String> provideDescription(QuestDescriptionContext context) { - if (context.getCategory() != Category.FINISHED) return null; + if (context.getCategory() != PlayerListCategory.FINISHED) return null; List<String> lore = new ArrayList<>(4); if (context.getQuest().testTimer(context.getPlayerAccount(), false)) { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java index 5f500670..922eed8a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java @@ -6,15 +6,15 @@ import java.util.stream.Collectors; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.options.QuestOptionObject; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementCreator; -import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.Utils; public class OptionRequirements extends QuestOptionObject<AbstractRequirement, RequirementCreator> implements QuestDescriptionProvider { @@ -30,7 +30,7 @@ protected String getSizeString(int size) { @Override protected QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getObjectsRegistry() { - return QuestsAPI.getRequirements(); + return QuestsAPI.getAPI().getRequirements(); } @Override @@ -52,7 +52,7 @@ public String getItemDescription() { public List<String> provideDescription(QuestDescriptionContext context) { if (!context.getPlayerAccount().isCurrent()) return null; if (!context.getDescriptionOptions().showRequirements()) return null; - if (context.getCategory() != Category.NOT_STARTED) return null; + if (context.getCategory() != PlayerListCategory.NOT_STARTED) return null; List<String> requirements = getValue().stream() .map(x -> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionScoreboardEnabled.java b/core/src/main/java/fr/skytasul/quests/options/OptionScoreboardEnabled.java index d8d70ac3..0462160d 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionScoreboardEnabled.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionScoreboardEnabled.java @@ -1,7 +1,7 @@ package fr.skytasul.quests.options; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; -import fr.skytasul.quests.utils.Lang; public class OptionScoreboardEnabled extends QuestOptionBoolean { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java index b7c428c8..40b61c58 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java @@ -6,17 +6,17 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.DialogEditor; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.types.Dialogable; -import fr.skytasul.quests.editors.DialogEditor; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.types.Dialog; -import fr.skytasul.quests.utils.types.DialogRunner; public class OptionStartDialog extends QuestOption<Dialog> implements Dialogable { @@ -64,7 +64,7 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c new DialogEditor(p, () -> { ItemUtils.lore(item, getLore()); gui.reopen(p); - }, getValue()).enter(); + }, getValue()).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java index 7474ab2d..ccf8db51 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java @@ -2,8 +2,8 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; -import fr.skytasul.quests.utils.Lang; public class OptionStartMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java index 2494374a..b3cbd3fa 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java @@ -2,9 +2,9 @@ import java.util.ArrayList; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.utils.Lang; public class OptionStartRewards extends QuestOptionRewards { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java index 835a2229..175ed6cf 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java @@ -2,11 +2,11 @@ import java.util.Arrays; import java.util.List; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.PlayerListCategory; public class OptionStartable extends QuestOptionBoolean implements QuestDescriptionProvider { @@ -25,7 +25,7 @@ public String getDescription() { @Override public List<String> provideDescription(QuestDescriptionContext context) { - if (context.getCategory() != Category.NOT_STARTED || !context.getPlayerAccount().isCurrent()) return null; + if (context.getCategory() != PlayerListCategory.NOT_STARTED || !context.getPlayerAccount().isCurrent()) return null; return context.getQuest().isLauncheable(context.getPlayerAccount().getPlayer(), context.getPlayerAccount(), false) ? STARTABLE : NOT_STARTABLE; } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 9c5b8a7a..069ded68 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -8,13 +8,13 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.gui.npc.SelectGUI; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.gui.npc.NpcSelectGUI; public class OptionStarterNPC extends QuestOption<BQNPC> { @@ -29,7 +29,7 @@ public Object save() { @Override public void load(ConfigurationSection config, String key) { - setValue(QuestsAPI.getNPCsManager().getById(config.getInt(key))); + setValue(QuestsAPI.getAPI().getNPCsManager().getById(config.getInt(key))); } @Override @@ -53,11 +53,11 @@ public ItemStack getItemStack(OptionSet options) { @Override public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - new SelectGUI(() -> gui.reopen(p), npc -> { + new NpcSelectGUI(() -> gui.reopen(p), npc -> { setValue(npc); ItemUtils.lore(item, getLore(gui)); gui.reopen(p); - }).setNullable().create(p); + }).setNullable().open(p); } @Override 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 ec6b49cf..8b4c2023 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java @@ -5,14 +5,14 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.DurationParser.MinecraftTimeUnit; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class OptionTimer extends QuestOption<Integer> { @@ -60,7 +60,7 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c resetValue(); ItemUtils.lore(item, getLore()); gui.reopen(p); - }, MinecraftTimeUnit.MINUTE.getParser()).enter(); + }, MinecraftTimeUnit.MINUTE.getParser()).start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java index 5ad84173..3247dccf 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java @@ -14,20 +14,21 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.options.OptionVisibility.VisibilityLocation; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -public class OptionVisibility extends QuestOption<List<VisibilityLocation>> { +public class OptionVisibility extends QuestOption<List<QuestVisibilityLocation>> { @Override public Object save() { - return getValue().stream().map(VisibilityLocation::name).collect(Collectors.toList()); + return getValue().stream().map(QuestVisibilityLocation::name).collect(Collectors.toList()); } @Override @@ -35,17 +36,17 @@ public void load(ConfigurationSection config, String key) { if (config.isBoolean(key)) { setValue(Collections.emptyList()); // migration from before 0.20, where it was the "hide" option }else { - setValue(config.getStringList(key).stream().map(VisibilityLocation::valueOf).collect(Collectors.toList())); + setValue(config.getStringList(key).stream().map(QuestVisibilityLocation::valueOf).collect(Collectors.toList())); } } @Override - public List<VisibilityLocation> cloneValue(List<VisibilityLocation> value) { + public List<QuestVisibilityLocation> cloneValue(List<QuestVisibilityLocation> value) { return new ArrayList<>(value); } private String[] getLore() { - return new String[] { formatDescription(Lang.optionVisibilityLore.toString()), "", formatValue(getValue().stream().map(VisibilityLocation::getName).collect(Collectors.joining(", "))) }; + return new String[] { formatDescription(Lang.optionVisibilityLore.toString()), "", formatValue(getValue().stream().map(QuestVisibilityLocation::getName).collect(Collectors.joining(", "))) }; } @Override @@ -58,12 +59,12 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c new VisibilityGUI(() -> { ItemUtils.lore(item, getLore()); gui.reopen(p); - }).create(p); + }).open(p); } - class VisibilityGUI implements CustomInventory { + class VisibilityGUI extends CustomInventory { - private EnumMap<VisibilityLocation, Boolean> locations = new EnumMap<>(VisibilityLocation.class); + private EnumMap<QuestVisibilityLocation, Boolean> locations = new EnumMap<>(QuestVisibilityLocation.class); private Runnable reopen; public VisibilityGUI(Runnable reopen) { @@ -75,7 +76,7 @@ public Inventory open(Player p) { Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_VISIBILITY.toString()); for (int i = 0; i < 4; i++) { - VisibilityLocation loc = VisibilityLocation.values()[i]; + QuestVisibilityLocation loc = QuestVisibilityLocation.values()[i]; boolean visible = getValue().contains(loc); locations.put(loc, visible); inv.setItem(i, ItemUtils.itemSwitch(loc.getName(), visible)); @@ -86,9 +87,9 @@ public Inventory open(Player p) { } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { if (slot >= 0 && slot < 4) { - locations.put(VisibilityLocation.values()[slot], ItemUtils.toggle(current)); + locations.put(QuestVisibilityLocation.values()[slot], ItemUtils.toggle(current)); }else if (slot == 4) { setValue(locations.entrySet().stream().filter(Entry::getValue).map(Entry::getKey).collect(Collectors.toList())); reopen.run(); @@ -97,27 +98,8 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(reopen); - return CloseBehavior.NOTHING; - } - - } - - public enum VisibilityLocation { - TAB_NOT_STARTED(Lang.visibility_notStarted.toString()), - TAB_IN_PROGRESS(Lang.visibility_inProgress.toString()), - TAB_FINISHED(Lang.visibility_finished.toString()), - MAPS(Lang.visibility_maps.toString()); - - private final String name; - - private VisibilityLocation(String name) { - this.name = name; - } - - public String getName() { - return name; + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(reopen); } } diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayersManager.java b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java similarity index 73% rename from core/src/main/java/fr/skytasul/quests/players/PlayersManager.java rename to core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java index 97684e5d..7e3c56d3 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -23,40 +23,44 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.data.SavableData; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.players.accounts.AbstractAccount; import fr.skytasul.quests.players.accounts.UUIDAccount; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.compatibility.Accounts; import fr.skytasul.quests.utils.compatibility.MissingDependencyException; -public abstract class PlayersManager { +public abstract class AbstractPlayersManager implements PlayersManager { - protected final @NotNull Map<Player, PlayerAccount> cachedAccounts = new HashMap<>(); + protected final @NotNull Map<Player, PlayerAccountImplementation> cachedAccounts = new HashMap<>(); protected final @NotNull Set<@NotNull SavableData<?>> accountDatas = new HashSet<>(); private boolean loaded = false; public abstract void load(@NotNull AccountFetchRequest request); - public abstract void unloadAccount(@NotNull PlayerAccount acc); + public abstract void unloadAccount(@NotNull PlayerAccountImplementation acc); - protected abstract @NotNull CompletableFuture<Void> removeAccount(@NotNull PlayerAccount acc); + protected abstract @NotNull CompletableFuture<Void> removeAccount(@NotNull PlayerAccountImplementation acc); public abstract @NotNull CompletableFuture<Integer> removeQuestDatas(@NotNull Quest quest); - public abstract @NotNull PlayerQuestDatas createPlayerQuestDatas(@NotNull PlayerAccount acc, @NotNull Quest quest); + public abstract @NotNull PlayerQuestDatasImplementation createPlayerQuestDatas(@NotNull PlayerAccountImplementation acc, + @NotNull Quest quest); - public abstract @NotNull PlayerPoolDatas createPlayerPoolDatas(@NotNull PlayerAccount acc, @NotNull QuestPool pool); + public abstract @NotNull PlayerPoolDatasImplementation createPlayerPoolDatas(@NotNull PlayerAccountImplementation acc, + @NotNull QuestPool pool); - public @NotNull CompletableFuture<Void> playerQuestDataRemoved(@NotNull PlayerQuestDatas datas) { + public @NotNull CompletableFuture<Void> playerQuestDataRemoved(@NotNull PlayerQuestDatasImplementation datas) { return CompletableFuture.completedFuture(null); } - public @NotNull CompletableFuture<Void> playerPoolDataRemoved(@NotNull PlayerPoolDatas datas) { + public @NotNull CompletableFuture<Void> playerPoolDataRemoved(@NotNull PlayerPoolDatasImplementation datas) { return CompletableFuture.completedFuture(null); } @@ -69,21 +73,24 @@ public boolean isLoaded() { return loaded; } + @Override public abstract void save(); + @Override public void addAccountData(@NotNull SavableData<?> data) { if (loaded) throw new IllegalStateException("Cannot add account data after players manager has been loaded"); - if (PlayerAccount.FORBIDDEN_DATA_ID.contains(data.getId())) + if (PlayerAccountImplementation.FORBIDDEN_DATA_ID.contains(data.getId())) throw new IllegalArgumentException("Forbidden account data id " + data.getId()); if (accountDatas.stream().anyMatch(x -> x.getId().equals(data.getId()))) throw new IllegalArgumentException("Another account data already exists with the id " + data.getId()); if (data.getDataType().isPrimitive()) throw new IllegalArgumentException("Primitive account data types are not supported"); accountDatas.add(data); - DebugUtils.logMessage("Registered account data " + data.getId()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Registered account data " + data.getId()); } + @Override public @NotNull Collection<@NotNull SavableData<?>> getAccountDatas() { return accountDatas; } @@ -117,11 +124,11 @@ public void addAccountData(@NotNull SavableData<?> data) { try{ return Accounts.createAccountFromUUID(uuid); }catch (UnsupportedOperationException ex){ - BeautyQuests.logger.warning("Can't migrate an UUID account to a hooked one."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Can't migrate an UUID account to a hooked one."); } }else return new UUIDAccount(uuid); }catch (IllegalArgumentException ex){ - BeautyQuests.logger.warning("Account identifier " + identifier + " is not valid."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Account identifier " + identifier + " is not valid."); } } return null; @@ -131,7 +138,7 @@ public synchronized void loadPlayer(@NotNull Player p) { cachedPlayerNames.put(p.getUniqueId(), p.getName()); long time = System.currentTimeMillis(); - DebugUtils.logMessage("Loading player " + p.getName() + "..."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Loading player " + p.getName() + "..."); cachedAccounts.remove(p); Bukkit.getScheduler().runTaskAsynchronously(BeautyQuests.getInstance(), () -> { for (int i = 1; i >= 0; i--) { @@ -139,18 +146,18 @@ public synchronized void loadPlayer(@NotNull Player p) { if (!tryLoad(p, time)) return; } catch (Exception ex) { - BeautyQuests.logger.severe("An error ocurred while trying to load datas of " + p.getName() + ".", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred while trying to load datas of " + p.getName() + ".", ex); } if (i > 0) - BeautyQuests.logger.severe("Doing " + i + " more attempt."); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Doing " + i + " more attempt."); } - BeautyQuests.logger.severe("Datas of " + p.getName() + " have failed to load. This may cause MANY issues."); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Datas of " + p.getName() + " have failed to load. This may cause MANY issues."); }); } private boolean tryLoad(@NotNull Player p, long time) { if (!p.isOnline()) { - BeautyQuests.logger + QuestsPlugin.getPlugin().getLoggerExpanded() .warning("Player " + p.getName() + " has quit the server while loading its datas. This may be a bug."); return false; } @@ -159,22 +166,22 @@ private boolean tryLoad(@NotNull Player p, long time) { load(request); if (!request.isFinished() || request.getAccount() == null) { - BeautyQuests.logger.severe("The account of " + p.getName() + " has not been properly loaded."); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("The account of " + p.getName() + " has not been properly loaded."); return true; } if (!p.isOnline()) { if (request.isAccountCreated()) { - DebugUtils.logMessage( + QuestsPlugin.getPlugin().getLoggerExpanded().debug( "New account registered for " + p.getName() + "... but deleted as player left before loading."); removeAccount(request.getAccount()).whenComplete( - BeautyQuests.logger.logError("An error occurred while removing newly created account")); + QuestsPlugin.getPlugin().getLoggerExpanded().logError("An error occurred while removing newly created account")); } return false; } if (request.isAccountCreated()) - DebugUtils.logMessage( + QuestsPlugin.getPlugin().getLoggerExpanded().debug( "New account registered for " + p.getName() + " (" + request.getAccount().abstractAcc.getIdentifier() + "), index " + request.getAccount().index + " via " + DebugUtils.stackTraces(2, 4)); @@ -188,37 +195,38 @@ private boolean tryLoad(@NotNull Player p, long time) { if (request.getLoadedFrom() != null) loadMessage += " | Loaded from " + request.getLoadedFrom(); - DebugUtils.logMessage(loadMessage); + QuestsPlugin.getPlugin().getLoggerExpanded().debug(loadMessage); if (p.isOnline()) { Bukkit.getPluginManager() .callEvent(new PlayerAccountJoinEvent(request.getAccount(), request.isAccountCreated())); } else { - BeautyQuests.logger.warning( + QuestsPlugin.getPlugin().getLoggerExpanded().warning( "Player " + p.getName() + " has quit the server while loading its datas. This may be a bug."); if (request.isAccountCreated()) removeAccount(request.getAccount()).whenComplete( - BeautyQuests.logger.logError("An error occurred while removing newly created account")); + QuestsPlugin.getPlugin().getLoggerExpanded().logError("An error occurred while removing newly created account")); } }); return false; } public synchronized void unloadPlayer(@NotNull Player p) { - PlayerAccount acc = cachedAccounts.get(p); + PlayerAccountImplementation acc = cachedAccounts.get(p); if (acc == null) return; - DebugUtils.logMessage("Unloading player " + p.getName() + "... (" + acc.getQuestsDatas().size() + " quests, " + acc.getPoolDatas().size() + " pools)"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Unloading player " + p.getName() + "... (" + acc.getQuestsDatas().size() + " quests, " + acc.getPoolDatas().size() + " pools)"); Bukkit.getPluginManager().callEvent(new PlayerAccountLeaveEvent(acc)); unloadAccount(acc); cachedAccounts.remove(p); } - public @UnknownNullability PlayerAccount getAccount(@NotNull Player p) { - if (QuestsAPI.getNPCsManager().isNPC(p)) return null; + @Override + public @UnknownNullability PlayerAccountImplementation getAccount(@NotNull Player p) { + if (QuestsAPI.getAPI().getNPCsManager().isNPC(p)) return null; if (!p.isOnline()) { - BeautyQuests.logger.severe("Trying to fetch the account of an offline player (" + p.getName() + ")"); - DebugUtils.logMessage("(via " + DebugUtils.stackTraces(2, 5) + ")"); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Trying to fetch the account of an offline player (" + p.getName() + ")"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("(via " + DebugUtils.stackTraces(2, 5) + ")"); } return cachedAccounts.get(p); @@ -228,16 +236,6 @@ public synchronized void unloadPlayer(@NotNull Player p) { private static Gson gson = new Gson(); private static long lastOnlineFailure = 0; - /** - * @deprecated use {@link BeautyQuests#getPlayersManager()} - */ - @Deprecated - public static PlayersManager manager; // TODO remove, changed in 0.20.1 - - public static @UnknownNullability PlayerAccount getPlayerAccount(@NotNull Player p) { - return BeautyQuests.getInstance().getPlayersManager().getAccount(p); - } - public static synchronized @Nullable String getPlayerName(@NotNull UUID uuid) { if (cachedPlayerNames.containsKey(uuid)) return cachedPlayerNames.get(uuid); @@ -246,7 +244,7 @@ public synchronized void unloadPlayer(@NotNull Player p) { if (Bukkit.getOnlineMode()) { try { if (System.currentTimeMillis() - lastOnlineFailure < 30_000) { - DebugUtils.logMessage("Trying to fetch a name from an UUID but it failed within 30 seconds."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Trying to fetch a name from an UUID but it failed within 30 seconds."); return null; } @@ -259,12 +257,12 @@ public synchronized void unloadPlayer(@NotNull Player p) { JsonElement nameElement = profile.get("name"); if (nameElement == null) { name = null; - DebugUtils.logMessage("Cannot find name for UUID " + uuid.toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Cannot find name for UUID " + uuid.toString()); } else { name = nameElement.getAsString(); } } catch (Exception e) { - BeautyQuests.logger.warning("Cannot connect to the mojang servers. UUIDs cannot be parsed."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot connect to the mojang servers. UUIDs cannot be parsed."); lastOnlineFailure = System.currentTimeMillis(); return null; } @@ -284,7 +282,7 @@ public static class AccountFetchRequest { private boolean finished = false; private boolean created; - private PlayerAccount account; + private PlayerAccountImplementation account; private String loadedFrom; public AccountFetchRequest(OfflinePlayer player, long joinTimestamp, boolean allowCreation, boolean shouldCache) { @@ -339,7 +337,7 @@ public String getDebugPlayerName() { * @param account account that has been loaded * @param from source of the saved account */ - public void loaded(PlayerAccount account, String from) { + public void loaded(PlayerAccountImplementation account, String from) { ensureAvailable(); this.account = account; this.loadedFrom = from; @@ -354,7 +352,7 @@ public void loaded(PlayerAccount account, String from) { * * @param account account that has been created */ - public void created(PlayerAccount account) { + public void created(PlayerAccountImplementation account) { if (!mustCreateMissing()) throw new IllegalStateException( "This method cannot be called as this request does not allow account creation"); @@ -384,7 +382,7 @@ public boolean isFinished() { return finished; } - public PlayerAccount getAccount() { + public PlayerAccountImplementation getAccount() { return account; } diff --git a/core/src/main/java/fr/skytasul/quests/players/AdminMode.java b/core/src/main/java/fr/skytasul/quests/players/AdminMode.java index 0e591c7f..b6b9d578 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AdminMode.java +++ b/core/src/main/java/fr/skytasul/quests/players/AdminMode.java @@ -8,9 +8,9 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.ParticleEffect; -import fr.skytasul.quests.utils.nms.NMS; public class AdminMode { @@ -20,7 +20,7 @@ public class AdminMode { private static ParticleEffect leaveParticle; static { - if (NMS.getMCVersion() >= 9) { + if (MinecraftVersion.MAJOR >= 9) { enterParticle = new ParticleEffect(Particle.FLAME, null, null); leaveParticle = new ParticleEffect(Particle.SMOKE_NORMAL, null, null); } @@ -29,18 +29,18 @@ public class AdminMode { public static void toggle(CommandSender sender){ if (senders.add(sender)) { Lang.ADMIN_MODE_ENTERED.send(sender); - if (sender instanceof Player && NMS.getMCVersion() >= 9) + if (sender instanceof Player && MinecraftVersion.MAJOR >= 9) enterParticle.sendParticle(((Player) sender).getEyeLocation(), getAdminPlayers(), 1, 1, 1, 15); }else { senders.remove(sender); Lang.ADMIN_MODE_LEFT.send(sender); - if (sender instanceof Player && NMS.getMCVersion() >= 9 && senders.stream().anyMatch(Player.class::isInstance)) + if (sender instanceof Player && MinecraftVersion.MAJOR >= 9 && senders.stream().anyMatch(Player.class::isInstance)) leaveParticle.sendParticle(((Player) sender).getEyeLocation(), getAdminPlayers(), 1, 1, 1, 15); } } public static void broadcast(String message){ - BeautyQuests.getInstance().getLoggerHandler().write("[ADMIN]: " + message); + BeautyQuests.getInstance().getLoggerExpanded().getHandler().write("[ADMIN]: " + message); for (CommandSender p : senders){ p.sendMessage("§e" + message); } diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerAccount.java b/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java similarity index 69% rename from core/src/main/java/fr/skytasul/quests/players/PlayerAccount.java rename to core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java index ecc96b88..7ce4c08e 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerAccount.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java @@ -14,22 +14,25 @@ import org.jetbrains.annotations.UnmodifiableView; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.data.SavableData; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerPoolDatas; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.players.accounts.AbstractAccount; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.Utils; -public class PlayerAccount { +public class PlayerAccountImplementation implements PlayerAccount { public static final List<String> FORBIDDEN_DATA_ID = Arrays.asList("identifier", "quests", "pools"); public final AbstractAccount abstractAcc; - protected final Map<Integer, PlayerQuestDatas> questDatas = new HashMap<>(); - protected final Map<Integer, PlayerPoolDatas> poolDatas = new HashMap<>(); + protected final Map<Integer, PlayerQuestDatasImplementation> questDatas = new HashMap<>(); + protected final Map<Integer, PlayerPoolDatasImplementation> poolDatas = new HashMap<>(); protected final Map<SavableData<?>, Object> additionalDatas = new HashMap<>(); protected final int index; - protected PlayerAccount(@NotNull AbstractAccount account, int index) { + protected PlayerAccountImplementation(@NotNull AbstractAccount account, int index) { this.abstractAcc = account; this.index = index; } @@ -37,6 +40,7 @@ protected PlayerAccount(@NotNull AbstractAccount account, int index) { /** * @return if this account is currently used by the player (if true, {@link #getPlayer()} cannot return a null player) */ + @Override public boolean isCurrent() { return abstractAcc.isCurrent(); } @@ -44,6 +48,7 @@ public boolean isCurrent() { /** * @return the OfflinePlayer instance attached to this account (no matter if the player is online or not, or if the account is the currently used) */ + @Override public @NotNull OfflinePlayer getOfflinePlayer() { return abstractAcc.getOfflinePlayer(); } @@ -51,88 +56,103 @@ public boolean isCurrent() { /** * @return the Player instance who own this account. If the account is not which in use by the player ({@link #isCurrent()}), this will return null. */ + @Override public @Nullable Player getPlayer() { return abstractAcc.getPlayer(); } + @Override public boolean hasQuestDatas(@NotNull Quest quest) { - return questDatas.containsKey(quest.getID()); + return questDatas.containsKey(quest.getId()); } - public @Nullable PlayerQuestDatas getQuestDatasIfPresent(@NotNull Quest quest) { - return questDatas.get(quest.getID()); + @Override + public @Nullable PlayerQuestDatasImplementation getQuestDatasIfPresent(@NotNull Quest quest) { + return questDatas.get(quest.getId()); } - public @NotNull PlayerQuestDatas getQuestDatas(@NotNull Quest quest) { - PlayerQuestDatas datas = questDatas.get(quest.getID()); + @Override + public @NotNull PlayerQuestDatasImplementation getQuestDatas(@NotNull Quest quest) { + PlayerQuestDatasImplementation datas = questDatas.get(quest.getId()); if (datas == null) { datas = BeautyQuests.getInstance().getPlayersManager().createPlayerQuestDatas(this, quest); - questDatas.put(quest.getID(), datas); + questDatas.put(quest.getId(), datas); } return datas; } + @Override public @NotNull CompletableFuture<PlayerQuestDatas> removeQuestDatas(@NotNull Quest quest) { - return removeQuestDatas(quest.getID()); + return removeQuestDatas(quest.getId()); } + @Override public @NotNull CompletableFuture<PlayerQuestDatas> removeQuestDatas(int id) { - PlayerQuestDatas removed = questDatas.remove(id); + PlayerQuestDatasImplementation removed = questDatas.remove(id); if (removed == null) return CompletableFuture.completedFuture(null); return BeautyQuests.getInstance().getPlayersManager().playerQuestDataRemoved(removed).thenApply(__ -> removed); } - protected @Nullable PlayerQuestDatas removeQuestDatasSilently(int id) { + protected @Nullable PlayerQuestDatasImplementation removeQuestDatasSilently(int id) { return questDatas.remove(id); } + @Override public @UnmodifiableView @NotNull Collection<@NotNull PlayerQuestDatas> getQuestsDatas() { - return questDatas.values(); + return (Collection) questDatas.values(); } + @Override public boolean hasPoolDatas(@NotNull QuestPool pool) { - return poolDatas.containsKey(pool.getID()); + return poolDatas.containsKey(pool.getId()); } - public @NotNull PlayerPoolDatas getPoolDatas(@NotNull QuestPool pool) { - PlayerPoolDatas datas = poolDatas.get(pool.getID()); + @Override + public @NotNull PlayerPoolDatasImplementation getPoolDatas(@NotNull QuestPool pool) { + PlayerPoolDatasImplementation datas = poolDatas.get(pool.getId()); if (datas == null) { datas = BeautyQuests.getInstance().getPlayersManager().createPlayerPoolDatas(this, pool); - poolDatas.put(pool.getID(), datas); + poolDatas.put(pool.getId(), datas); } return datas; } + @Override public @NotNull CompletableFuture<PlayerPoolDatas> removePoolDatas(@NotNull QuestPool pool) { - return removePoolDatas(pool.getID()); + return removePoolDatas(pool.getId()); } + @Override public @NotNull CompletableFuture<PlayerPoolDatas> removePoolDatas(int id) { - PlayerPoolDatas removed = poolDatas.remove(id); + PlayerPoolDatasImplementation removed = poolDatas.remove(id); if (removed == null) return CompletableFuture.completedFuture(null); return BeautyQuests.getInstance().getPlayersManager().playerPoolDataRemoved(removed).thenApply(__ -> removed); } + @Override public @UnmodifiableView @NotNull Collection<@NotNull PlayerPoolDatas> getPoolDatas() { - return poolDatas.values(); + return (Collection) poolDatas.values(); } + @Override public <T> @Nullable T getData(@NotNull SavableData<T> data) { if (!BeautyQuests.getInstance().getPlayersManager().getAccountDatas().contains(data)) throw new IllegalArgumentException("The " + data.getId() + " account data has not been registered."); return (T) additionalDatas.getOrDefault(data, data.getDefaultValue()); } + @Override public <T> void setData(@NotNull SavableData<T> data, @Nullable T value) { if (!BeautyQuests.getInstance().getPlayersManager().getAccountDatas().contains(data)) throw new IllegalArgumentException("The " + data.getId() + " account data has not been registered."); additionalDatas.put(data, value); } + @Override public void resetDatas() { additionalDatas.clear(); } @@ -145,7 +165,7 @@ public boolean equals(Object object) { return false; if (object.getClass() != this.getClass()) return false; - return abstractAcc.equals(((PlayerAccount) object).abstractAcc); + return abstractAcc.equals(((PlayerAccountImplementation) object).abstractAcc); } @Override @@ -158,24 +178,27 @@ public int 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 + ")"; } public void serialize(@NotNull ConfigurationSection config) { config.set("identifier", abstractAcc.getIdentifier()); - config.set("quests", questDatas.isEmpty() ? null : Utils.serializeList(questDatas.values(), PlayerQuestDatas::serialize)); - config.set("pools", poolDatas.isEmpty() ? null : Utils.serializeList(poolDatas.values(), PlayerPoolDatas::serialize)); + config.set("quests", questDatas.isEmpty() ? null : Utils.serializeList(questDatas.values(), PlayerQuestDatasImplementation::serialize)); + config.set("pools", poolDatas.isEmpty() ? null : Utils.serializeList(poolDatas.values(), PlayerPoolDatasImplementation::serialize)); additionalDatas.entrySet().forEach(entry -> { config.set(entry.getKey().getId(), entry.getValue()); }); diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatas.java b/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatasImplementation.java similarity index 57% rename from core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatas.java rename to core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatasImplementation.java index c82d7f2e..be0779f8 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatas.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerPoolDatasImplementation.java @@ -5,52 +5,60 @@ import java.util.Map; import java.util.Set; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.players.PlayerPoolDatas; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.structure.pools.QuestPoolImplementation; -public class PlayerPoolDatas { +public class PlayerPoolDatasImplementation implements PlayerPoolDatas { - protected final PlayerAccount acc; + protected final PlayerAccountImplementation acc; protected final int poolID; private long lastGive; private Set<Integer> completedQuests; - public PlayerPoolDatas(PlayerAccount acc, int poolID) { + public PlayerPoolDatasImplementation(PlayerAccountImplementation acc, int poolID) { this(acc, poolID, 0, new HashSet<>()); } - public PlayerPoolDatas(PlayerAccount acc, int poolID, long lastGive, Set<Integer> completedQuests) { + public PlayerPoolDatasImplementation(PlayerAccountImplementation acc, int poolID, long lastGive, Set<Integer> completedQuests) { this.acc = acc; this.poolID = poolID; this.lastGive = lastGive; this.completedQuests = completedQuests; } - public PlayerAccount getAccount() { + @Override + public PlayerAccountImplementation getAccount() { return acc; } + @Override public int getPoolID() { return poolID; } - public QuestPool getPool() { + @Override + public QuestPoolImplementation getPool() { return BeautyQuests.getInstance().getPoolsManager().getPool(poolID); } + @Override public long getLastGive() { return lastGive; } + @Override public void setLastGive(long lastGive) { this.lastGive = lastGive; } + @Override public Set<Integer> getCompletedQuests() { return completedQuests; } + @Override public void setCompletedQuests(Set<Integer> completedQuests) { this.completedQuests = completedQuests; updatedCompletedQuests(); @@ -68,8 +76,8 @@ public Map<String, Object> serialize() { return map; } - public static PlayerPoolDatas deserialize(PlayerAccount acc, Map<String, Object> map) { - PlayerPoolDatas datas = new PlayerPoolDatas(acc, (int) map.get("poolID")); + public static PlayerPoolDatasImplementation deserialize(PlayerAccountImplementation acc, Map<String, Object> map) { + PlayerPoolDatasImplementation datas = new PlayerPoolDatasImplementation(acc, (int) map.get("poolID")); datas.lastGive = Utils.parseLong(map.get("lastGive")); datas.completedQuests = (Set<Integer>) map.get("completedQuests"); return datas; diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatas.java b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java similarity index 72% rename from core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatas.java rename to core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java index df9a9cd2..f0701f69 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatas.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java @@ -3,17 +3,18 @@ import java.util.HashMap; import java.util.Map; import java.util.StringJoiner; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.quests.DialogHistoryGUI; import fr.skytasul.quests.options.OptionStartDialog; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Utils; -public class PlayerQuestDatas { +public class PlayerQuestDatasImplementation implements PlayerQuestDatas { - protected final PlayerAccount acc; + protected final PlayerAccountImplementation acc; protected final int questID; private int finished; @@ -25,7 +26,7 @@ public class PlayerQuestDatas { private Boolean hasDialogsCached = null; - public PlayerQuestDatas(PlayerAccount acc, int questID) { + public PlayerQuestDatasImplementation(PlayerAccountImplementation acc, int questID) { this.acc = acc; this.questID = questID; this.finished = 0; @@ -35,7 +36,7 @@ public PlayerQuestDatas(PlayerAccount acc, int questID) { this.additionalDatas = new HashMap<>(); } - public PlayerQuestDatas(PlayerAccount acc, int questID, long timer, int finished, int branch, int stage, Map<String, Object> additionalDatas, String questFlow) { + public PlayerQuestDatasImplementation(PlayerAccountImplementation acc, int questID, long timer, int finished, int branch, int stage, Map<String, Object> additionalDatas, String questFlow) { this.acc = acc; this.questID = questID; this.finished = finished; @@ -44,112 +45,131 @@ public PlayerQuestDatas(PlayerAccount acc, int questID, long timer, int finished this.stage = stage; this.additionalDatas = additionalDatas == null ? new HashMap<>() : additionalDatas; if (questFlow != null) this.questFlow.add(questFlow); - if (branch != -1 && stage == -1) BeautyQuests.logger.warning("Incorrect quest " + questID + " datas for " + acc.debugName()); + if (branch != -1 && stage == -1) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Incorrect quest " + questID + " datas for " + acc.debugName()); } + @Override public Quest getQuest() { - return QuestsAPI.getQuests().getQuest(questID); + return QuestsAPI.getAPI().getQuestsManager().getQuest(questID); } + @Override public int getQuestID() { return questID; } + @Override public boolean isFinished() { return finished > 0; } + @Override public void incrementFinished() { finished++; } + @Override public int getTimesFinished() { return finished; } + @Override public long getTimer() { return timer; } + @Override public void setTimer(long timer) { this.timer = timer; } + @Override public int getBranch() { return branch; } + @Override public void setBranch(int branch) { this.branch = branch; } + @Override public int getStage() { return stage; } + @Override public void setStage(int stage) { this.stage = stage; } + @Override public boolean hasStarted() { return branch != -1; } + @Override public boolean isInQuestEnd() { return branch == -2; } + @Override public void setInQuestEnd() { setBranch(-2); } + @Override public boolean isInEndingStages() { return stage == -2; } + @Override public void setInEndingStages() { setStage(-2); } + @Override public <T> T getAdditionalData(String key) { return (T) additionalDatas.get(key); } + @Override public <T> T setAdditionalData(String key, T value) { return (T) (value == null ? additionalDatas.remove(key) : additionalDatas.put(key, value)); } + @Override public Map<String, Object> getStageDatas(int stage) { return getAdditionalData("stage" + stage); } + @Override public void setStageDatas(int stage, Map<String, Object> datas) { setAdditionalData("stage" + stage, datas); } + @Override public long getStartingTime() { return getAdditionalData("starting_time"); } + @Override public void setStartingTime(long time) { setAdditionalData("starting_time", time == 0 ? null : time); } + @Override public String getQuestFlow() { return questFlow.toString(); } - public void addQuestFlow(AbstractStage finished) { - String stageID; - if (finished.getQuestBranch().isRegularStage(finished)) { - stageID = Integer.toString(finished.getID()); - }else { - stageID = "E" + finished.getStoredID(); - } - questFlow.add(finished.getQuestBranch().getID() + ":" + stageID); + @Override + public void addQuestFlow(StageController finished) { + questFlow.add(finished.getBranch().getId() + ":" + finished.getFlowId()); hasDialogsCached = null; } + @Override public void resetQuestFlow() { questFlow = new StringJoiner(";"); hasDialogsCached = null; @@ -181,8 +201,8 @@ public Map<String, Object> serialize() { return map; } - public static PlayerQuestDatas deserialize(PlayerAccount acc, Map<String, Object> map) { - PlayerQuestDatas datas = new PlayerQuestDatas(acc, (int) map.get("questID")); + public static PlayerQuestDatasImplementation deserialize(PlayerAccountImplementation acc, Map<String, Object> map) { + PlayerQuestDatasImplementation datas = new PlayerQuestDatasImplementation(acc, (int) map.get("questID")); if (map.containsKey("finished")) datas.finished = ((boolean) map.get("finished")) ? 1 : 0; // TODO remove, outdated since 0.19 if (map.containsKey("timesFinished")) datas.finished = (int) map.get("timesFinished"); if (map.containsKey("timer")) datas.timer = Utils.parseLong(map.get("timer")); 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 03f07093..0b3432dc 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java @@ -23,19 +23,19 @@ 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; import fr.skytasul.quests.api.data.SavableData; -import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.utils.CustomizedObjectTypeAdapter; import fr.skytasul.quests.players.accounts.AbstractAccount; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.CustomizedObjectTypeAdapter; import fr.skytasul.quests.utils.Database; -import fr.skytasul.quests.utils.DebugUtils; +import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.ThrowingConsumer; -import fr.skytasul.quests.utils.Utils; -public class PlayersManagerDB extends PlayersManager { +public class PlayersManagerDB extends AbstractPlayersManager { public final String ACCOUNTS_TABLE; public final String QUESTS_DATAS_TABLE; @@ -100,7 +100,7 @@ public void addAccountData(SavableData<?> data) { .collect(Collectors.joining(", ", "UPDATE " + ACCOUNTS_TABLE + " SET ", " WHERE `id` = ?")); } - private void retrievePlayerDatas(PlayerAccount acc) { + private void retrievePlayerDatas(PlayerAccountImplementation acc) { try (Connection connection = db.getConnection()) { try (PreparedStatement statement = connection.prepareStatement(getQuestsData)) { statement.setInt(1, acc.index); @@ -134,7 +134,7 @@ private void retrievePlayerDatas(PlayerAccount acc) { } } } catch (SQLException ex) { - BeautyQuests.logger.severe("An error occurred while fetching account datas of " + acc.debugName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while fetching account datas of " + acc.debugName(), ex); } } @@ -148,7 +148,7 @@ public void load(AccountFetchRequest request) { while (result.next()) { AbstractAccount abs = createAccountFromIdentifier(result.getString("identifier")); if (abs.isCurrent()) { - PlayerAccount account = new PlayerAccountDB(abs, result.getInt("id")); + PlayerAccountImplementation account = new PlayerAccountDB(abs, result.getInt("id")); result.close(); try { // in order to ensure that, if the player was previously connected to another server, @@ -184,12 +184,12 @@ public void load(AccountFetchRequest request) { request.notLoaded(); } } catch (SQLException ex) { - BeautyQuests.logger.severe("An error occurred while loading account of " + request.getDebugPlayerName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while loading account of " + request.getDebugPlayerName(), ex); } } @Override - protected CompletableFuture<Void> removeAccount(PlayerAccount acc) { + protected CompletableFuture<Void> removeAccount(PlayerAccountImplementation acc) { return CompletableFuture.runAsync(() -> { try (Connection connection = db.getConnection(); PreparedStatement statement = connection.prepareStatement(deleteAccount)) { @@ -202,12 +202,12 @@ protected CompletableFuture<Void> removeAccount(PlayerAccount acc) { } @Override - public PlayerQuestDatas createPlayerQuestDatas(PlayerAccount acc, Quest quest) { - return new PlayerQuestDatasDB(acc, quest.getID()); + public PlayerQuestDatasImplementation createPlayerQuestDatas(PlayerAccountImplementation acc, Quest quest) { + return new PlayerQuestDatasDB(acc, quest.getId()); } @Override - public CompletableFuture<Void> playerQuestDataRemoved(PlayerQuestDatas datas) { + public CompletableFuture<Void> playerQuestDataRemoved(PlayerQuestDatasImplementation datas) { return CompletableFuture.runAsync(() -> { try (Connection connection = db.getConnection(); PreparedStatement statement = connection.prepareStatement(removeQuestData)) { @@ -222,12 +222,12 @@ public CompletableFuture<Void> playerQuestDataRemoved(PlayerQuestDatas datas) { } @Override - public PlayerPoolDatas createPlayerPoolDatas(PlayerAccount acc, QuestPool pool) { - return new PlayerPoolDatasDB(acc, pool.getID()); + public PlayerPoolDatasImplementation createPlayerPoolDatas(PlayerAccountImplementation acc, QuestPool pool) { + return new PlayerPoolDatasDB(acc, pool.getId()); } @Override - public CompletableFuture<Void> playerPoolDataRemoved(PlayerPoolDatas datas) { + public CompletableFuture<Void> playerPoolDataRemoved(PlayerPoolDatasImplementation datas) { return CompletableFuture.runAsync(() -> { try (Connection connection = db.getConnection(); PreparedStatement statement = connection.prepareStatement(removePoolData)) { @@ -245,13 +245,13 @@ public CompletableFuture<Integer> removeQuestDatas(Quest quest) { return CompletableFuture.supplyAsync(() -> { try (Connection connection = db.getConnection(); PreparedStatement statement = connection.prepareStatement(removeExistingQuestDatas)) { - for (PlayerAccount acc : cachedAccounts.values()) { - PlayerQuestDatasDB datas = (PlayerQuestDatasDB) acc.removeQuestDatasSilently(quest.getID()); + for (PlayerAccountImplementation acc : cachedAccounts.values()) { + PlayerQuestDatasDB datas = (PlayerQuestDatasDB) acc.removeQuestDatasSilently(quest.getId()); if (datas != null) datas.stop(); } - statement.setInt(1, quest.getID()); + statement.setInt(1, quest.getId()); int amount = statement.executeUpdate(); - DebugUtils.logMessage("Removed " + amount + " in-database quest datas for quest " + quest.getID()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removed " + amount + " in-database quest datas for quest " + quest.getId()); return amount; } catch (SQLException ex) { throw new DataException("Failed to remove quest datas from database.", ex); @@ -353,7 +353,7 @@ private void createTables() throws SQLException { if (!columns.contains("quest_flow")) { // 0.19 statement.execute("ALTER TABLE " + QUESTS_DATAS_TABLE + " ADD COLUMN quest_flow VARCHAR(8000) DEFAULT NULL"); - BeautyQuests.logger.info("Updated database with quest_flow column."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Updated database with quest_flow column."); } if (!columns.contains("additional_datas") || columns.contains("stage_0_datas")) { // 0.20 @@ -361,10 +361,10 @@ private void createTables() throws SQLException { if (!columns.contains("additional_datas")) { statement.execute("ALTER TABLE " + QUESTS_DATAS_TABLE + " ADD COLUMN `additional_datas` longtext DEFAULT NULL AFTER `current_stage`"); - BeautyQuests.logger.info("Updated table " + QUESTS_DATAS_TABLE + " with additional_datas column."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Updated table " + QUESTS_DATAS_TABLE + " with additional_datas column."); } - Utils.runAsync(this::migrateOldQuestDatas); + QuestUtils.runAsync(this::migrateOldQuestDatas); } }); @@ -373,7 +373,7 @@ private void createTables() throws SQLException { if (!columns.contains(data.getWrappedData().getColumnName().toLowerCase())) { statement.execute("ALTER TABLE " + ACCOUNTS_TABLE + " ADD COLUMN " + data.getColumnDefinition()); - BeautyQuests.logger.info("Updated database by adding the missing " + data.getWrappedData().getColumnName() + " column in the player accounts table."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Updated database by adding the missing " + data.getWrappedData().getColumnName() + " column in the player accounts table."); } } }); @@ -388,14 +388,14 @@ private void upgradeTable(Connection connection, String tableName, ThrowingConsu } } if (columns.isEmpty()) { - BeautyQuests.logger.severe("Cannot check integrity of SQL table " + tableName); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot check integrity of SQL table " + tableName); }else { columnsConsumer.accept(columns); } } private void migrateOldQuestDatas() { - BeautyQuests.logger.info("---- CAUTION ----\n" + QuestsPlugin.getPlugin().getLoggerExpanded().info("---- CAUTION ----\n" + "BeautyQuests will now migrate old quest datas in database to the newest format.\n" + "This may take a LONG time. Players should NOT enter the server during this time, " + "or serious data loss can occur."); @@ -408,7 +408,7 @@ private void migrateOldQuestDatas() { + " ON R1.account_id = R2.account_id" + " AND R1.quest_id = R2.quest_id" + " AND R1.id < R2.id;"); - if (deletedDuplicates > 0) BeautyQuests.logger.info("Deleted " + deletedDuplicates + " duplicated rows in the " + QUESTS_DATAS_TABLE + " table."); + if (deletedDuplicates > 0) QuestsPlugin.getPlugin().getLoggerExpanded().info("Deleted " + deletedDuplicates + " duplicated rows in the " + QUESTS_DATAS_TABLE + " table."); int batchCount = 0; PreparedStatement migration = connection.prepareStatement("UPDATE " + QUESTS_DATAS_TABLE + " SET `additional_datas` = ? WHERE `id` = ?"); @@ -426,9 +426,9 @@ private void migrateOldQuestDatas() { migration.addBatch(); batchCount++; } - BeautyQuests.logger.info("Migrating " + batchCount + "quest datas..."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Migrating " + batchCount + "quest datas..."); int migrated = migration.executeBatch().length; - BeautyQuests.logger.info("Migrated " + migrated + " quest datas."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Migrated " + migrated + " quest datas."); statement.execute("ALTER TABLE " + QUESTS_DATAS_TABLE + " DROP COLUMN `stage_0_datas`," @@ -436,11 +436,11 @@ private void migrateOldQuestDatas() { + " DROP COLUMN `stage_2_datas`," + " DROP COLUMN `stage_3_datas`," + " DROP COLUMN `stage_4_datas`;"); - BeautyQuests.logger.info("Updated database by deleting old stage_[0::4]_datas columns."); - BeautyQuests.logger.info("---- CAUTION ----\n" + QuestsPlugin.getPlugin().getLoggerExpanded().info("Updated database by deleting old stage_[0::4]_datas columns."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("---- CAUTION ----\n" + "The data migration succeeded. Players can now safely connect."); }catch (SQLException ex) { - BeautyQuests.logger.severe("---- CAUTION ----\n" + QuestsPlugin.getPlugin().getLoggerExpanded().severe("---- CAUTION ----\n" + "The plugin failed to migrate old quest datas in database.", ex); } } @@ -470,14 +470,14 @@ public static synchronized String migrate(Database db, PlayersManagerYAML yaml) int amount = 0, failed = 0; yaml.loadAllAccounts(); - for (PlayerAccount acc : yaml.loadedAccounts.values()) { + for (PlayerAccountImplementation acc : yaml.loadedAccounts.values()) { try { insertAccount.setInt(1, acc.index); insertAccount.setString(2, acc.abstractAcc.getIdentifier()); insertAccount.setString(3, acc.getOfflinePlayer().getUniqueId().toString()); insertAccount.executeUpdate(); - for (Entry<Integer, PlayerQuestDatas> entry : acc.questDatas.entrySet()) { + for (Entry<Integer, PlayerQuestDatasImplementation> entry : acc.questDatas.entrySet()) { insertQuestData.setInt(1, acc.index); insertQuestData.setInt(2, entry.getKey()); insertQuestData.setInt(3, entry.getValue().getTimesFinished()); @@ -491,7 +491,7 @@ public static synchronized String migrate(Database db, PlayersManagerYAML yaml) insertQuestData.executeUpdate(); } - for (Entry<Integer, PlayerPoolDatas> entry : acc.poolDatas.entrySet()) { + for (Entry<Integer, PlayerPoolDatasImplementation> entry : acc.poolDatas.entrySet()) { insertPoolData.setInt(1, acc.index); insertPoolData.setInt(2, entry.getKey()); insertPoolData.setLong(3, entry.getValue().getLastGive()); @@ -501,7 +501,7 @@ public static synchronized String migrate(Database db, PlayersManagerYAML yaml) amount++; }catch (Exception ex) { - BeautyQuests.logger.severe("Failed to migrate datas for account " + acc.debugName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Failed to migrate datas for account " + acc.debugName(), ex); failed++; } } @@ -515,11 +515,11 @@ public static synchronized String migrate(Database db, PlayersManagerYAML yaml) } @Override - public void unloadAccount(PlayerAccount acc) { - Utils.runAsync(() -> saveAccount(acc, true)); + public void unloadAccount(PlayerAccountImplementation acc) { + QuestUtils.runAsync(() -> saveAccount(acc, true)); } - public void saveAccount(PlayerAccount acc, boolean stop) { + public void saveAccount(PlayerAccountImplementation acc, boolean stop) { acc.getQuestsDatas() .stream() .map(PlayerQuestDatasDB.class::cast) @@ -530,7 +530,7 @@ protected static String getCompletedQuestsString(Set<Integer> completedQuests) { return completedQuests.isEmpty() ? null : completedQuests.stream().map(x -> Integer.toString(x)).collect(Collectors.joining(";")); } - public class PlayerQuestDatasDB extends PlayerQuestDatas { + public class PlayerQuestDatasDB extends PlayerQuestDatasImplementation { private static final int DATA_QUERY_TIMEOUT = 15; private static final int DATA_FLUSHING_TIME = 10; @@ -541,11 +541,11 @@ public class PlayerQuestDatasDB extends PlayerQuestDatas { private boolean disabled = false; private int dbId = -1; - public PlayerQuestDatasDB(PlayerAccount acc, int questID) { + public PlayerQuestDatasDB(PlayerAccountImplementation acc, int questID) { super(acc, questID); } - public PlayerQuestDatasDB(PlayerAccount acc, int questID, ResultSet result) throws SQLException { + public PlayerQuestDatasDB(PlayerAccountImplementation acc, int questID, ResultSet result) throws SQLException { super( acc, questID, @@ -590,7 +590,7 @@ public <T> T setAdditionalData(String key, T value) { } @Override - public void addQuestFlow(AbstractStage finished) { + public void addQuestFlow(StageController finished) { super.addQuestFlow(finished); setDataStatement(updateFlow, getQuestFlow(), true); } @@ -635,19 +635,19 @@ public void run() { statement.setQueryTimeout(DATA_QUERY_TIMEOUT); statement.executeUpdate(); if (entry.getValue() == null && !allowNull) { - BeautyQuests.logger.warning("Setting an illegal NULL value in statement \"" + dataStatement + "\" for account " + acc.index + " and quest " + questID); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Setting an illegal NULL value in statement \"" + dataStatement + "\" for account " + acc.index + " and quest " + questID); } } } catch (Exception ex) { - BeautyQuests.logger.severe("An error occurred while updating a player's quest datas.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while updating a player's quest datas.", ex); }finally { dbLock.unlock(); } }else { - BeautyQuests.logger.severe("Cannot acquire database lock for quest " + questID + ", player " + acc.getNameAndID()); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot acquire database lock for quest " + questID + ", player " + acc.getNameAndID()); } }catch (InterruptedException ex) { - BeautyQuests.logger.severe("Interrupted database locking.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Interrupted database locking.", ex); Thread.currentThread().interrupt(); } } @@ -669,14 +669,14 @@ protected void flushAll(boolean stop) { run.cancel(); run.run(); }); - if (!cachedDatas.isEmpty()) BeautyQuests.logger.warning("Still waiting values in quest data " + questID + " for account " + acc.index + " despite flushing all."); + if (!cachedDatas.isEmpty()) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Still waiting values in quest data " + questID + " for account " + acc.index + " despite flushing all."); if (stop) disabled = true; datasLock.unlock(); }else { - BeautyQuests.logger.severe("Cannot acquire database lock to save all datas of quest " + questID + ", player " + acc.getNameAndID()); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot acquire database lock to save all datas of quest " + questID + ", player " + acc.getNameAndID()); } }catch (InterruptedException ex) { - BeautyQuests.logger.severe("Interrupted database locking.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Interrupted database locking.", ex); Thread.currentThread().interrupt(); } } @@ -693,7 +693,7 @@ protected void stop() { } private void createDataRow(Connection connection) throws SQLException { - DebugUtils.logMessage("Inserting DB row of quest " + questID + " for account " + acc.index); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Inserting DB row of quest " + questID + " for account " + acc.index); try (PreparedStatement insertStatement = connection.prepareStatement(insertQuestData, new String[] {"id"})) { insertStatement.setInt(1, acc.index); insertStatement.setInt(2, questID); @@ -705,19 +705,19 @@ private void createDataRow(Connection connection) throws SQLException { if (!generatedKeys.next()) throw new DataException("Generated keys ResultSet is empty"); dbId = generatedKeys.getInt(1); - DebugUtils.logMessage("Created row " + dbId + " for quest " + questID + ", account " + acc.index); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Created row " + dbId + " for quest " + questID + ", account " + acc.index); } } } - public class PlayerPoolDatasDB extends PlayerPoolDatas { + public class PlayerPoolDatasDB extends PlayerPoolDatasImplementation { - public PlayerPoolDatasDB(PlayerAccount acc, int poolID) { + public PlayerPoolDatasDB(PlayerAccountImplementation acc, int poolID) { super(acc, poolID); } - public PlayerPoolDatasDB(PlayerAccount acc, int poolID, long lastGive, Set<Integer> completedQuests) { + public PlayerPoolDatasDB(PlayerAccountImplementation acc, int poolID, long lastGive, Set<Integer> completedQuests) { super(acc, poolID, lastGive, completedQuests); } @@ -752,13 +752,13 @@ private void updateData(String dataStatement, Object data) { statement.executeUpdate(); } }catch (SQLException ex) { - BeautyQuests.logger.severe("An error occurred while updating a player's pool datas.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while updating a player's pool datas.", ex); } } } - public class PlayerAccountDB extends PlayerAccount { + public class PlayerAccountDB extends PlayerAccountImplementation { public PlayerAccountDB(AbstractAccount account, int index) { super(account, index); @@ -775,7 +775,7 @@ public <T> void setData(SavableData<T> data, T value) { statement.setInt(2, index); statement.executeUpdate(); }catch (SQLException ex) { - BeautyQuests.logger.severe("An error occurred while saving account data " + data.getId() + " to database", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while saving account data " + data.getId() + " to database", ex); } } @@ -789,7 +789,7 @@ public void resetDatas() { statement.setInt(1, index); statement.executeUpdate(); }catch (SQLException ex) { - BeautyQuests.logger.severe("An error occurred while resetting account " + index + " datas from database", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while resetting account " + index + " datas from database", ex); } } } 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 0231aea4..1dcad579 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java @@ -23,21 +23,22 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.data.SavableData; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.players.accounts.AbstractAccount; import fr.skytasul.quests.players.accounts.GhostAccount; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.pools.QuestPool; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.utils.QuestUtils; -public class PlayersManagerYAML extends PlayersManager { +public class PlayersManagerYAML extends AbstractPlayersManager { private static final int ACCOUNTS_THRESHOLD = 1000; - private final Cache<Integer, PlayerAccount> unloadedAccounts = CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build(); + private final Cache<Integer, PlayerAccountImplementation> unloadedAccounts = CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build(); - protected final Map<Integer, PlayerAccount> loadedAccounts = new HashMap<>(); + protected final Map<Integer, PlayerAccountImplementation> loadedAccounts = new HashMap<>(); private final Map<Integer, String> identifiersIndex = Collections.synchronizedMap(new HashMap<>()); private final File directory = new File(BeautyQuests.getInstance().getDataFolder(), "players"); @@ -53,7 +54,7 @@ public void load(AccountFetchRequest request) { String identifier = super.getIdentifier(request.getOfflinePlayer()); if (identifiersIndex.containsValue(identifier)) { int id = Utils.getKeyByValue(identifiersIndex, identifier); - PlayerAccount acc; + PlayerAccountImplementation acc; // 1. get the account if it's already loaded acc = loadedAccounts.get(id); @@ -92,7 +93,7 @@ public void load(AccountFetchRequest request) { } } else if (request.mustCreateMissing()) { AbstractAccount absacc = super.createAbstractAccount(request.getOnlinePlayer()); - PlayerAccount acc = new PlayerAccount(absacc, lastAccountID + 1); + PlayerAccountImplementation acc = new PlayerAccountImplementation(absacc, lastAccountID + 1); if (request.shouldCache()) addAccount(acc); @@ -103,20 +104,20 @@ public void load(AccountFetchRequest request) { } @Override - protected CompletableFuture<Void> removeAccount(PlayerAccount acc) { + protected CompletableFuture<Void> removeAccount(PlayerAccountImplementation acc) { loadedAccounts.remove(acc.index); identifiersIndex.remove(acc.index); return CompletableFuture.runAsync(() -> removePlayerFile(acc.index)); } @Override - public PlayerQuestDatas createPlayerQuestDatas(PlayerAccount acc, Quest quest) { - return new PlayerQuestDatas(acc, quest.getID()); + public PlayerQuestDatasImplementation createPlayerQuestDatas(PlayerAccountImplementation acc, Quest quest) { + return new PlayerQuestDatasImplementation(acc, quest.getId()); } @Override - public PlayerPoolDatas createPlayerPoolDatas(PlayerAccount acc, QuestPool pool) { - return new PlayerPoolDatas(acc, pool.getID()); + public PlayerPoolDatasImplementation createPlayerPoolDatas(PlayerAccountImplementation acc, QuestPool pool) { + return new PlayerPoolDatasImplementation(acc, pool.getId()); } @Override @@ -125,7 +126,7 @@ public CompletableFuture<Integer> removeQuestDatas(Quest quest) { loadAllAccounts(); int amount = 0; - for (PlayerAccount account : loadedAccounts.values()) { + for (PlayerAccountImplementation account : loadedAccounts.values()) { try { if (account.removeQuestDatas(quest).get() != null) { // we can use the .get() method as the CompletableFuture created by the YAML players manager is @@ -148,30 +149,30 @@ public boolean hasAccounts(Player p) { return identifiersIndex.containsValue(getIdentifier(p)); } - private synchronized PlayerAccount createPlayerAccount(String identifier, int index) { + private synchronized PlayerAccountImplementation createPlayerAccount(String identifier, int index) { Validate.notNull(identifier, "Identifier cannot be null (index: " + index + ")"); AbstractAccount abs = super.createAccountFromIdentifier(identifier); if (abs == null) { - BeautyQuests.logger.info("Player account with identifier " + identifier + " is not enabled, but will be kept in the data file."); - return new PlayerAccount(new GhostAccount(identifier), index); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Player account with identifier " + identifier + " is not enabled, but will be kept in the data file."); + return new PlayerAccountImplementation(new GhostAccount(identifier), index); } - return new PlayerAccount(abs, index); + return new PlayerAccountImplementation(abs, index); } void loadAllAccounts() { - BeautyQuests.getInstance().getLogger().warning("CAUTION - BeautyQuests will now load every single player data into the server's memory. We HIGHLY recommend the server to be restarted at the end of the operation. Be prepared to experience some lags."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("CAUTION - BeautyQuests will now load every single player data into the server's memory. We HIGHLY recommend the server to be restarted at the end of the operation. Be prepared to experience some lags."); for (Entry<Integer, String> entry : identifiersIndex.entrySet()) { if (loadedAccounts.containsKey(entry.getKey())) continue; try { - PlayerAccount acc = loadFromFile(entry.getKey(), false); + PlayerAccountImplementation acc = loadFromFile(entry.getKey(), false); if (acc == null) acc = createPlayerAccount(entry.getValue(), entry.getKey()); addAccount(acc); }catch (Exception ex) { - BeautyQuests.logger.severe("An error occured when loading player account " + entry.getKey(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occured when loading player account " + entry.getKey(), ex); } } - BeautyQuests.getInstance().getLogger().info("Total loaded accounts: " + loadedAccounts.size()); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Total loaded accounts: " + loadedAccounts.size()); } public void debugDuplicate() { @@ -183,27 +184,27 @@ public void debugDuplicate() { loadAllAccounts(); int amount = 0; - Map<String, List<PlayerAccount>> playerAccounts = new HashMap<>(); - for (PlayerAccount acc : loadedAccounts.values()) { - List<PlayerAccount> list = playerAccounts.get(acc.abstractAcc.getIdentifier()); + Map<String, List<PlayerAccountImplementation>> playerAccounts = new HashMap<>(); + for (PlayerAccountImplementation acc : loadedAccounts.values()) { + List<PlayerAccountImplementation> list = playerAccounts.get(acc.abstractAcc.getIdentifier()); if (list == null) { list = new ArrayList<>(); playerAccounts.put(acc.abstractAcc.getIdentifier(), list); } list.add(acc); } - BeautyQuests.getInstance().getLogger().info(playerAccounts.size() + " unique identifiers."); + QuestsPlugin.getPlugin().getLoggerExpanded().info(playerAccounts.size() + " unique identifiers."); List<String> removed = new ArrayList<>(); - for (Entry<String, List<PlayerAccount>> en : playerAccounts.entrySet()) { + for (Entry<String, List<PlayerAccountImplementation>> en : playerAccounts.entrySet()) { if (removed.contains(en.getKey())) System.out.println("CRITICAL - Already removed " + en.getKey()); - List<PlayerAccount> list = en.getValue(); + List<PlayerAccountImplementation> list = en.getValue(); int maxID = 0; int maxSize = 0; for (int i = 0; i < list.size(); i++) { - PlayerAccount acc = list.get(i); + PlayerAccountImplementation acc = list.get(i); if (acc.questDatas.size() > maxSize) { maxID = i; maxSize = acc.questDatas.size(); @@ -211,7 +212,7 @@ public void debugDuplicate() { } for (int i = 0; i < list.size(); i++) { if (i != maxID) { - PlayerAccount acc = list.get(i); + PlayerAccountImplementation acc = list.get(i); int index = Utils.getKeyByValue(loadedAccounts, acc); loadedAccounts.remove(index); identifiersIndex.remove(index); @@ -222,8 +223,8 @@ public void debugDuplicate() { removed.add(en.getKey()); } - BeautyQuests.getInstance().getLogger().info(amount + " duplicated accounts removeds. Total loaded accounts/identifiers: " + loadedAccounts.size() + "/" + identifiersIndex.size()); - BeautyQuests.getInstance().getLogger().info("Now scanning for remaining duplicated accounts..."); + 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(); @@ -232,38 +233,38 @@ public void debugDuplicate() { System.out.println(size + " accounts with identifier " + id); } } - if (dup) BeautyQuests.getInstance().getLogger().warning("There is still duplicated accounts."); - BeautyQuests.getInstance().getLogger().info("Operation complete."); + if (dup) QuestsPlugin.getPlugin().getLoggerExpanded().warning("There is still duplicated accounts."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Operation complete."); } - private synchronized void addAccount(PlayerAccount acc) { + private synchronized void addAccount(PlayerAccountImplementation acc) { Validate.notNull(acc); loadedAccounts.put(acc.index, acc); identifiersIndex.put(acc.index, acc.abstractAcc.getIdentifier()); if (acc.index >= lastAccountID) lastAccountID = acc.index; } - private PlayerAccount loadFromFile(int index, boolean msg) { + private PlayerAccountImplementation loadFromFile(int index, boolean msg) { File file = new File(directory, index + ".yml"); if (!file.exists()) return null; - DebugUtils.logMessage("Loading account #" + index + ". Last file edition: " + new Date(file.lastModified()).toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Loading account #" + index + ". Last file edition: " + new Date(file.lastModified()).toString()); YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(file); return loadFromConfig(index, playerConfig); } - private PlayerAccount loadFromConfig(int index, ConfigurationSection datas) { + private PlayerAccountImplementation loadFromConfig(int index, ConfigurationSection datas) { String identifier = datas.getString("identifier"); if (identifier == null) { - BeautyQuests.logger.warning("No identifier found in file for index " + index + "."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("No identifier found in file for index " + index + "."); identifier = identifiersIndex.get(index); } - PlayerAccount acc = createPlayerAccount(identifier, index); + PlayerAccountImplementation acc = createPlayerAccount(identifier, index); for (Map<?, ?> questConfig : datas.getMapList("quests")) { - PlayerQuestDatas questDatas = PlayerQuestDatas.deserialize(acc, (Map<String, Object>) questConfig); + PlayerQuestDatasImplementation questDatas = PlayerQuestDatasImplementation.deserialize(acc, (Map<String, Object>) questConfig); acc.questDatas.put(questDatas.questID, questDatas); } for (Map<?, ?> poolConfig : datas.getMapList("pools")) { - PlayerPoolDatas questDatas = PlayerPoolDatas.deserialize(acc, (Map<String, Object>) poolConfig); + PlayerPoolDatasImplementation questDatas = PlayerPoolDatasImplementation.deserialize(acc, (Map<String, Object>) poolConfig); acc.poolDatas.put(questDatas.getPoolID(), questDatas); } for (SavableData<?> data : accountDatas) { @@ -274,7 +275,7 @@ private PlayerAccount loadFromConfig(int index, ConfigurationSection datas) { return acc; } - public void savePlayerFile(PlayerAccount acc) throws IOException { + public void savePlayerFile(PlayerAccountImplementation acc) throws IOException { File file = new File(directory, acc.index + ".yml"); file.createNewFile(); YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(file); @@ -287,11 +288,11 @@ public void removePlayerFile(int index) { if (file.exists()) { try { Files.delete(file.toPath()); - DebugUtils.logMessage("Removed " + file.getName()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removed " + file.getName()); }catch (IOException e) { e.printStackTrace(); } - }else DebugUtils.logMessage("Can't remove " + file.getName() + ": file does not exist"); + }else QuestsPlugin.getPlugin().getLoggerExpanded().debug("Can't remove " + file.getName() + ": file does not exist"); } @Override @@ -308,14 +309,14 @@ public void load() { identifiersIndex.put(index, config.getString(path)); if (index >= lastAccountID) lastAccountID = index; }catch (Exception ex) { - BeautyQuests.logger.severe("An error occured while loading player account. Data: " + config.get(key), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occured while loading player account. Data: " + config.get(key), ex); } } } - DebugUtils.logMessage(loadedAccounts.size() + " accounts loaded and " + identifiersIndex.size() + " identifiers."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug(loadedAccounts.size() + " accounts loaded and " + identifiersIndex.size() + " identifiers."); if (identifiersIndex.size() >= ACCOUNTS_THRESHOLD) { - BeautyQuests.logger.warning( + QuestsPlugin.getPlugin().getLoggerExpanded().warning( "⚠ WARNING - " + identifiersIndex.size() + " players are registered on this server." + " It is recommended to switch to a SQL database setup in order to keep proper performances and scalability." + " In order to do that, setup your database credentials in config.yml (without enabling it) and run the command" @@ -325,32 +326,32 @@ public void load() { @Override public synchronized void save() { - DebugUtils.logMessage("Saving " + loadedAccounts.size() + " loaded accounts and " + identifiersIndex.size() + " identifiers."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Saving " + loadedAccounts.size() + " loaded accounts and " + identifiersIndex.size() + " identifiers."); BeautyQuests.getInstance().getDataFile().set("players", identifiersIndex); // as the save can take a few seconds and MAY be done asynchronously, // it is possible that the "loadedAccounts" map is being edited concurrently. // therefore, we create a new list to avoid this issue. - ArrayList<PlayerAccount> accountToSave = new ArrayList<>(loadedAccounts.values()); - for (PlayerAccount acc : accountToSave) { + ArrayList<PlayerAccountImplementation> accountToSave = new ArrayList<>(loadedAccounts.values()); + for (PlayerAccountImplementation acc : accountToSave) { try { savePlayerFile(acc); }catch (Exception e) { - BeautyQuests.logger.severe("An error ocurred while trying to save " + acc.debugName() + " account file", e); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred while trying to save " + acc.debugName() + " account file", e); } } } @Override - public void unloadAccount(PlayerAccount acc) { + public void unloadAccount(PlayerAccountImplementation acc) { loadedAccounts.remove(acc.index); unloadedAccounts.put(acc.index, acc); - Utils.runAsync(() -> { + QuestUtils.runAsync(() -> { try { savePlayerFile(acc); }catch (IOException e) { - BeautyQuests.logger.warning("An error ocurred while saving player file " + acc.debugName(), e); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An error ocurred while saving player file " + acc.debugName(), e); } }); } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java index ecb3225a..396e7167 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java @@ -11,14 +11,14 @@ import org.bukkit.inventory.ItemStack; import com.sucy.skill.api.classes.RPGClass; import com.sucy.skill.api.player.PlayerClass; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.compatibility.SkillAPI; public class ClassRequirement extends AbstractRequirement { @@ -87,7 +87,7 @@ public ItemStack getItemStack(RPGClass object) { public void click(RPGClass existing, ItemStack item, ClickType clickType) { callback.apply(existing); } - }.create(p); + }.open(player); } @Override @@ -96,7 +96,7 @@ public void finish(List<RPGClass> objects) { event.reopenGUI(); } - }.create(event.getPlayer()); + }.open(event.getPlayer()); } @Override @@ -118,7 +118,7 @@ public void load(ConfigurationSection section) { for (String s : section.getStringList("classes")) { RPGClass classe = com.sucy.skill.SkillAPI.getClasses().get(s.toLowerCase()); if (classe == null) { - BeautyQuests.getInstance().getLogger().warning("Class with name " + s + " no longer exists."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Class with name " + s + " no longer exists."); continue; } classes.add(classe); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java index 6029c1c6..0dd86fc9 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java @@ -10,14 +10,14 @@ import com.cryptomorin.xseries.XMaterial; import com.google.common.collect.ImmutableMap; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.StaticPagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; import fr.skytasul.quests.gui.misc.ItemGUI; -import fr.skytasul.quests.gui.templates.StaticPagedGUI; -import fr.skytasul.quests.utils.Lang; public class EquipmentRequirement extends AbstractRequirement { @@ -68,11 +68,11 @@ public void itemClick(QuestObjectClickEvent event) { slot = newSlot; item = newItem; - new ItemComparisonGUI(comparisons, event::reopenGUI).create(event.getPlayer()); + new ItemComparisonGUI(comparisons, event::reopenGUI).open(event.getPlayer()); - }, event::cancel).create(event.getPlayer()); + }, event::cancel).open(event.getPlayer()); - }).allowCancel().create(event.getPlayer()); + }).allowCancel().open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java index a7ad8523..e9f0f6a5 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java @@ -14,14 +14,14 @@ import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.FactionColl; import com.massivecraft.factions.entity.MPlayer; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.compatibility.Factions; public class FactionRequirement extends AbstractRequirement { @@ -83,7 +83,7 @@ public ItemStack getItemStack(Faction object) { public void click(Faction existing, ItemStack item, ClickType clickType) { callback.apply(existing); } - }.create(p); + }.open(player); } @Override @@ -92,7 +92,7 @@ public void finish(List<Faction> objects) { event.reopenGUI(); } - }.create(event.getPlayer()); + }.open(event.getPlayer()); } @Override @@ -111,7 +111,7 @@ public void load(ConfigurationSection section) { super.load(section); for (String s : section.getStringList("factions")) { if (!FactionColl.get().containsId(s)) { - BeautyQuests.getInstance().getLogger().warning("Faction with ID " + s + " no longer exists."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Faction with ID " + s + " no longer exists."); continue; } factions.add(FactionColl.get().get(s)); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java index 94d8620b..d158b816 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java @@ -2,13 +2,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.utils.ComparisonMethod; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.utils.compatibility.Jobs; public class JobLevelRequirement extends TargetNumberRequirement { @@ -67,7 +67,7 @@ public void itemClick(QuestObjectClickEvent event) { new TextEditor<String>(event.getPlayer(), event::cancel, obj -> { jobName = obj; super.itemClick(event); - }).useStrippedMessage().enter(); + }).useStrippedMessage().start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java index 36890f75..74928685 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.requirements; 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.utils.ComparisonMethod; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.ComparisonMethod; public class LevelRequirement extends TargetNumberRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java index 46642534..662bce57 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.requirements; 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.utils.ComparisonMethod; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.utils.compatibility.McCombatLevel; public class McCombatLevelRequirement extends TargetNumberRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java index a3e134b7..365c1add 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java @@ -2,13 +2,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.utils.ComparisonMethod; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.utils.compatibility.McMMO; public class McMMOSkillRequirement extends TargetNumberRequirement { @@ -63,7 +63,7 @@ public void itemClick(QuestObjectClickEvent event) { }, (obj) -> { this.skillName = obj; super.itemClick(event); - }).useStrippedMessage().enter(); + }).useStrippedMessage().start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java index 88393c1c..7076b48d 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java @@ -2,13 +2,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.Actionnable; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.compatibility.Vault; public class MoneyRequirement extends AbstractRequirement implements Actionnable { @@ -59,7 +59,7 @@ public void itemClick(QuestObjectClickEvent event) { new TextEditor<>(event.getPlayer(), event::cancel, obj -> { this.money = obj; event.reopenGUI(); - }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java index cb9a06c5..9a7f074e 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java @@ -9,13 +9,13 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.utils.Lang; public class PermissionsRequirement extends AbstractRequirement { @@ -60,23 +60,23 @@ public ItemStack getObjectItemStack(Permission object) { @Override public void createObject(Function<Permission, ItemStack> callback) { - Lang.CHOOSE_PERM_REQUIRED.send(p); - new TextEditor<String>(p, () -> p.openInventory(inv), obj -> { + Lang.CHOOSE_PERM_REQUIRED.send(player); + new TextEditor<String>(player, this::reopen, obj -> { callback.apply(Permission.fromString(obj)); - }).useStrippedMessage().enter(); + }).useStrippedMessage().start(); } @Override public void finish(List<Permission> objects) { permissions = objects; - Lang.CHOOSE_PERM_REQUIRED_MESSAGE.send(p); - new TextEditor<String>(p, event::reopenGUI, obj -> { + Lang.CHOOSE_PERM_REQUIRED_MESSAGE.send(player); + new TextEditor<String>(player, event::reopenGUI, obj -> { setCustomReason(obj); event.reopenGUI(); - }).passNullIntoEndConsumer().enter(); + }).passNullIntoEndConsumer().start(); } - }.create(event.getPlayer()); + }.open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java index 099fa6ea..255b0605 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java @@ -3,16 +3,15 @@ import java.math.BigDecimal; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.utils.ComparisonMethod; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.ComparisonMethod; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; @@ -53,13 +52,14 @@ public boolean test(Player p){ if (signum == 1) return comparison == ComparisonMethod.GREATER || comparison == ComparisonMethod.GREATER_OR_EQUAL; if (signum == -1) return comparison == ComparisonMethod.LESS || comparison == ComparisonMethod.LESS_OR_EQUAL; }catch (NumberFormatException e) { - BeautyQuests.logger.severe("Cannot parse placeholder " + rawPlaceholder + " for player " + p.getName() + ": got " + request + ", which is not a number. (" + debugName() + ")"); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot parse placeholder " + rawPlaceholder + " for player " + p.getName() + ": got " + request + ", which is not a number. (" + debugName() + ")"); } return false; } if (comparison == ComparisonMethod.DIFFERENT) return !value.equals(request); String value = this.value; - if (parseValue) value = Utils.finalFormat(p, value, true); + if (parseValue) + value = MessageUtils.finalFormat(p, value, true); return value.equals(request); } @@ -79,16 +79,16 @@ public void setPlaceholder(String placeholder){ if (index == -1) { hook = null; params = placeholder; - BeautyQuests.logger.warning("Usage of invalid placeholder " + placeholder); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Usage of invalid placeholder " + placeholder); }else { String identifier = placeholder.substring(0, index); hook = PlaceholderAPIPlugin.getInstance().getLocalExpansionManager().getExpansion(identifier); params = placeholder.substring(index + 1); if (hook == null) { - BeautyQuests.logger.warning("Cannot find PlaceholderAPI expansion for " + rawPlaceholder); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot find PlaceholderAPI expansion for " + rawPlaceholder); QuestsPlaceholders.waitForExpansion(identifier, expansion -> { hook = expansion; - DebugUtils.logMessage("Found " + rawPlaceholder + " from callback"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Found " + rawPlaceholder + " from callback"); }); } } @@ -148,12 +148,12 @@ public void itemClick(QuestObjectClickEvent event) { new TextEditor<>(event.getPlayer(), null, comp -> { this.comparison = comp == null ? ComparisonMethod.EQUALS : comp; event.reopenGUI(); - }, ComparisonMethod.getComparisonParser()).passNullIntoEndConsumer().enter(); + }, ComparisonMethod.getComparisonParser()).passNullIntoEndConsumer().start(); }catch (NumberFormatException __) { event.reopenGUI(); } - }).enter(); - }).useStrippedMessage().enter(); + }).start(); + }).useStrippedMessage().start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java index 07c305d2..30144985 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java @@ -3,15 +3,14 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class QuestRequirement extends AbstractRequirement { @@ -44,7 +43,7 @@ public String getDefaultDescription(Player p) { } private boolean exists(){ - cached = QuestsAPI.getQuests().getQuest(questId); + cached = QuestsAPI.getAPI().getQuestsManager().getQuest(questId); return cached != null; } @@ -56,22 +55,10 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { - if (QuestsAPI.getQuests().getQuests().isEmpty()) { - event.getGUI().remove(this); + ChooseQuestGUI.choose(event.getPlayer(), QuestsAPI.getAPI().getQuestsManager().getQuests(), quest -> { + this.questId = quest.getId(); event.reopenGUI(); - return; - } - - new ChooseQuestGUI(QuestsAPI.getQuests().getQuests(), quest -> { - this.questId = quest.getID(); - event.reopenGUI(); - }) { - @Override - public fr.skytasul.quests.gui.CustomInventory.CloseBehavior onClose(Player p, org.bukkit.inventory.Inventory inv) { - Utils.runSync(event::remove); - return CloseBehavior.NOTHING; - } - }.create(event.getPlayer()); + }, event::remove, false); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java index b6d6497d..8f9a6fe1 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java @@ -4,14 +4,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import com.sk89q.worldguard.protection.regions.ProtectedRegion; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; public class RegionRequirement extends AbstractRequirement { @@ -34,7 +33,7 @@ private void setRegionName(String regionName) { this.regionName = regionName; if (worldName != null) { region = BQWorldGuard.getInstance().getRegion(regionName, Bukkit.getWorld(worldName)); - if (region == null) BeautyQuests.logger.warning("Region " + regionName + " no longer exist in world " + worldName); + if (region == null) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Region " + regionName + " no longer exist in world " + worldName); } } @@ -58,10 +57,10 @@ public void itemClick(QuestObjectClickEvent event) { this.regionName = region.getId(); event.reopenGUI(); }else { - Utils.sendMessage(p, Lang.REGION_DOESNT_EXIST.toString()); + Lang.REGION_DOESNT_EXIST.send(p); event.remove(); } - }).useStrippedMessage().enter(); + }).useStrippedMessage().start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java index a16c41a6..b0f7506c 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java @@ -4,14 +4,14 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.scoreboard.Objective; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.ScoreboardObjectiveParser; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.ScoreboardObjectiveParser; -import fr.skytasul.quests.utils.ComparisonMethod; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.ComparisonMethod; public class ScoreboardRequirement extends TargetNumberRequirement { @@ -67,7 +67,7 @@ public void itemClick(QuestObjectClickEvent event) { }, () -> { event.getGUI().remove(this); event.reopenGUI(); - }, new ScoreboardObjectiveParser()).enter(); + }, new ScoreboardObjectiveParser()).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java index a4a41f21..e3614ead 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.requirements; 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.utils.ComparisonMethod; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.utils.compatibility.SkillAPI; public class SkillAPILevelRequirement extends TargetNumberRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java index 8ebf3fef..7e7e530c 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java @@ -5,13 +5,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; public class LogicalOrRequirement extends AbstractRequirement { @@ -46,10 +46,10 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { - QuestsAPI.getRequirements().createGUI(QuestObjectLocation.OTHER, requirements -> { + QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.OTHER, requirements -> { this.requirements = requirements; event.reopenGUI(); - }, requirements).create(event.getPlayer()); + }, requirements).open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java index 96bfae57..6da48436 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java @@ -4,17 +4,17 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.utils.QuestUtils; public class CheckpointReward extends AbstractReward { @@ -49,9 +49,9 @@ public List<String> give(Player p) { public void applies(Player p) { try { - Utils.giveRewards(p, actions); + QuestUtils.giveRewards(p, actions); } catch (InterruptingBranchException e) { - BeautyQuests.logger.warning("Trying to interrupt branching in a checkpoint reward (useless). " + toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to interrupt branching in a checkpoint reward (useless). " + toString()); } } @@ -68,10 +68,10 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { - QuestsAPI.getRewards().createGUI(Lang.INVENTORY_CHECKPOINT_ACTIONS.toString(), QuestObjectLocation.CHECKPOINT, rewards -> { + QuestsAPI.getAPI().getRewards().createGUI(Lang.INVENTORY_CHECKPOINT_ACTIONS.toString(), QuestObjectLocation.CHECKPOINT, rewards -> { actions = rewards; event.reopenGUI(); - }, actions, null).create(event.getPlayer()); + }, actions, null).open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index ad09b20c..90f565ff 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -9,15 +9,14 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.CommandGUI; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.types.Command; public class CommandReward extends AbstractReward { @@ -53,11 +52,11 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { - Inventories.create(event.getPlayer(), new ListGUI<Command>(Lang.INVENTORY_COMMANDS_LIST.toString(), DyeColor.ORANGE, commands) { + new ListGUI<Command>(Lang.INVENTORY_COMMANDS_LIST.toString(), DyeColor.ORANGE, commands) { @Override public void createObject(Function<Command, ItemStack> callback) { - new CommandGUI(callback::apply, this::reopen).create(p); + new CommandGUI(callback::apply, this::reopen).open(player); } @Override @@ -65,7 +64,7 @@ public void clickObject(Command object, ItemStack item, ClickType clickType) { new CommandGUI(command -> { updateObject(object, command); reopen(); - }, this::reopen).setFromExistingCommand(object).create(p); + }, this::reopen).setFromExistingCommand(object).open(player); } @Override @@ -79,7 +78,7 @@ public void finish(List<Command> objects) { event.reopenGUI(); } - }); + }.open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java index 0ca67b2e..587d77f4 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java @@ -6,12 +6,12 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.ItemsGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class ItemReward extends AbstractReward { @@ -54,7 +54,7 @@ public void itemClick(QuestObjectClickEvent event) { new ItemsGUI(items -> { this.items = items; event.reopenGUI(); - }, items).create(event.getPlayer()); + }, items).open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java index 0e08bf43..f16a973d 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java @@ -3,12 +3,12 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.MessageUtils; public class MessageReward extends AbstractReward { @@ -23,7 +23,7 @@ public MessageReward(String customDescription, String text) { @Override public List<String> give(Player p) { - Utils.sendOffMessage(p, text); + MessageUtils.sendOffMessage(p, text); return null; } @@ -44,7 +44,7 @@ public void itemClick(QuestObjectClickEvent event) { new TextEditor<String>(event.getPlayer(), event::cancel, obj -> { this.text = obj; event.reopenGUI(); - }).enter(); + }).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java index 42128c7b..4f9d2606 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java @@ -4,12 +4,12 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.compatibility.Vault; public class MoneyReward extends AbstractReward { @@ -53,7 +53,7 @@ public void itemClick(QuestObjectClickEvent event) { new TextEditor<>(event.getPlayer(), event::cancel, obj -> { money = obj; event.reopenGUI(); - }, new NumberParser<>(Double.class, false, true)).enter(); + }, new NumberParser<>(Double.class, false, true)).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java index e55e1396..e027aa5b 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java @@ -7,8 +7,8 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.permissions.PermissionListGUI; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.types.Permission; public class PermissionReward extends AbstractReward { @@ -48,7 +48,7 @@ public void itemClick(QuestObjectClickEvent event) { new PermissionListGUI(permissions, permissions -> { PermissionReward.this.permissions = permissions; event.reopenGUI(); - }).create(event.getPlayer()); + }).open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java b/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java index 67d35b77..ffefe0c7 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/QuestStopReward.java @@ -2,11 +2,11 @@ import java.util.List; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.utils.DebugUtils; public class QuestStopReward extends AbstractReward { @@ -22,7 +22,7 @@ public void itemClick(QuestObjectClickEvent event) {} @Override public List<String> give(Player p) throws InterruptingBranchException { if (getAttachedQuest() == null) { - DebugUtils.logMessage("No attached quest for " + debugName()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("No attached quest for " + debugName()); } else { getAttachedQuest().cancelPlayer(PlayersManager.getPlayerAccount(p)); throw new InterruptingBranchException(); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java index f3c99d14..0e5b9ad5 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java @@ -8,16 +8,16 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.utils.Lang; public class RandomReward extends AbstractReward { @@ -40,7 +40,7 @@ public void setMinMax(int min, int max) { this.max = Math.max(min, max); if (max > rewards.size()) - BeautyQuests.logger.warning("Random reward with max amount (" + max + ") greater than amount of rewards available (" + rewards.size() + ") in " + debugName()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Random reward with max amount (" + max + ") greater than amount of rewards available (" + rewards.size() + ") in " + debugName()); } @Override @@ -58,7 +58,7 @@ public List<String> give(Player p) { List<String> messages = reward.give(p); if (messages != null) msg.addAll(messages); }catch (Exception ex) { - BeautyQuests.logger.severe("Error when giving random reward " + reward.getName() + " to " + p.getName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when giving random reward " + reward.getName() + " to " + p.getName(), ex); } } @@ -96,10 +96,10 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { if (event.isInCreation() || event.getClick().isLeftClick()) { - QuestsAPI.getRewards().createGUI(QuestObjectLocation.OTHER, rewards -> { + QuestsAPI.getAPI().getRewards().createGUI(QuestObjectLocation.OTHER, rewards -> { this.rewards = rewards; event.reopenGUI(); - }, rewards).create(event.getPlayer()); + }, rewards).open(event.getPlayer()); }else if (event.getClick().isRightClick()) { Lang.REWARD_EDITOR_RANDOM_MIN.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopenGUI, min -> { @@ -107,8 +107,8 @@ public void itemClick(QuestObjectClickEvent event) { new TextEditor<>(event.getPlayer(), event::reopenGUI, max -> { setMinMax(min, max == null ? min : max); event.reopenGUI(); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).passNullIntoEndConsumer().enter(); - }, NumberParser.INTEGER_PARSER_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).passNullIntoEndConsumer().start(); + }, NumberParser.INTEGER_PARSER_POSITIVE).start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java index 876a65cc..e4b594be 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java @@ -9,13 +9,13 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.ItemsGUI; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class RemoveItemsReward extends AbstractReward { @@ -68,9 +68,9 @@ public void itemClick(QuestObjectClickEvent event) { new ItemsGUI(items -> { this.items = items; event.reopenGUI(); - }, items).create(event.getPlayer()); + }, items).open(event.getPlayer()); }else if (event.getClick().isRightClick()) { - new ItemComparisonGUI(comparisons, event::reopenGUI).create(event.getPlayer()); + new ItemComparisonGUI(comparisons, event::reopenGUI).open(event.getPlayer()); } } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 92ca6b11..037431f2 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -1,31 +1,29 @@ package fr.skytasul.quests.rewards; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.layout.Button; +import fr.skytasul.quests.api.gui.layout.ClickEvent; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.utils.QuestUtils; public class RequirementDependentReward extends AbstractReward { @@ -59,7 +57,8 @@ public void detach() { @Override public List<String> give(Player p) throws InterruptingBranchException { - if (requirements.stream().allMatch(requirement -> requirement.test(p))) return Utils.giveRewards(p, rewards); + if (requirements.stream().allMatch(requirement -> requirement.test(p))) + return QuestUtils.giveRewards(p, rewards); return null; } @@ -88,58 +87,40 @@ public String getDefaultDescription(Player p) { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); + loreBuilder.addDescription(Lang.rewards.format(rewards.size())); loreBuilder.addDescription(Lang.requirements.format(requirements.size())); } @Override public void itemClick(QuestObjectClickEvent event) { - new CustomInventory() { - - private Inventory inv; - - @Override - public Inventory open(Player p) { - inv = Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_REWARDS_WITH_REQUIREMENTS.toString()); - - inv.setItem(0, ItemUtils.item(XMaterial.NETHER_STAR, "§b" + Lang.requirements.format(requirements.size()))); - inv.setItem(1, ItemUtils.item(XMaterial.CHEST, "§a" + Lang.rewards.format(rewards.size()))); - - inv.setItem(4, ItemUtils.itemDone); - - return inv = p.openInventory(inv).getTopInventory(); - } - - private void reopen() { - Inventories.put(event.getPlayer(), this, inv); - event.getPlayer().openInventory(inv); - } - - @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { - switch (slot) { - case 0: - QuestsAPI.getRequirements().createGUI(QuestObjectLocation.OTHER, requirements -> { - RequirementDependentReward.this.requirements = requirements; - ItemUtils.name(current, "§b" + Lang.requirements.format(requirements.size())); - reopen(); - }, requirements).create(p); - break; - case 1: - QuestsAPI.getRewards().createGUI(QuestObjectLocation.OTHER, rewards -> { - RequirementDependentReward.this.rewards = rewards; - ItemUtils.name(current, "§a" + Lang.rewards.format(rewards.size())); - reopen(); - }, rewards).create(p); - break; - case 4: - event.reopenGUI(); - break; - } - return false; - } - }.create(event.getPlayer()); + LayoutedGUI.newBuilder() + .addButton(0, + Button.create(XMaterial.NETHER_STAR, () -> "§b" + Lang.requirements.format(requirements.size()), + Collections.emptyList(), this::editRequirements)) + .addButton(1, + Button.create(XMaterial.CHEST, () -> "§a" + Lang.rewards.format(rewards.size()), + Collections.emptyList(), this::editRewards)) + .addButton(4, Button.create(ItemUtils.itemDone, __ -> event.reopenGUI())) + .setName(Lang.INVENTORY_REWARDS_WITH_REQUIREMENTS.toString()) + .setCloseBehavior(StandardCloseBehavior.REOPEN) + .build() + .open(event.getPlayer()); } + private void editRequirements(ClickEvent event) { + QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.OTHER, newRequirements -> { + RequirementDependentReward.this.requirements = newRequirements; + event.refreshItemReopen(); + }, requirements).open(event.getPlayer()); + } + + private void editRewards(ClickEvent event) { + QuestsAPI.getAPI().getRewards().createGUI(QuestObjectLocation.OTHER, newRewards -> { + RequirementDependentReward.this.rewards = newRewards; + event.refreshItemReopen(); + }, rewards).open(event.getPlayer()); + } + @Override public void save(ConfigurationSection section) { super.save(section); 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 4caab831..b0d8e932 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java @@ -4,13 +4,14 @@ 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.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.editors.WaitClick; -import fr.skytasul.quests.gui.npc.NPCGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.gui.npc.NpcCreateGUI; +import fr.skytasul.quests.utils.QuestUtils; public class TeleportationReward extends AbstractReward { @@ -24,8 +25,8 @@ public TeleportationReward(String customDescription, Location teleportation) { } @Override - public List<String> give(Player p) { - Utils.runOrSync(() -> p.teleport(teleportation)); + public List<String> give(Player player) { + QuestUtils.runOrSync(() -> player.teleport(teleportation)); return null; } @@ -43,10 +44,10 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { Lang.MOVE_TELEPORT_POINT.send(event.getPlayer()); - new WaitClick(event.getPlayer(), event::cancel, NPCGUI.validMove.clone(), () -> { + new WaitClick(event.getPlayer(), event::cancel, NpcCreateGUI.validMove.clone(), () -> { teleportation = event.getPlayer().getLocation(); event.reopenGUI(); - }).enter(); + }).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java index adc1aab9..c6b98353 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java @@ -36,7 +36,7 @@ public void itemClick(QuestObjectClickEvent event) { title = newTitle; event.reopenGUI(); - }).edit(title).create(event.getPlayer()); + }).edit(title).open(event.getPlayer()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java index 216b4dc9..1b8ff869 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java @@ -3,12 +3,12 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.utils.Lang; public class WaitReward extends AbstractReward { @@ -38,7 +38,7 @@ public void itemClick(QuestObjectClickEvent event) { new TextEditor<>(event.getPlayer(), event::cancel, obj -> { delay = obj; event.reopenGUI(); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index f85f0208..6ecad0f0 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -5,13 +5,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.compatibility.SkillAPI; @@ -52,12 +52,12 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { - Utils.sendMessage(event.getPlayer(), Lang.XP_GAIN.toString(), exp); + MessageUtils.sendPrefixedMessage(event.getPlayer(), Lang.XP_GAIN.toString(), exp); new TextEditor<>(event.getPlayer(), event::cancel, obj -> { - Utils.sendMessage(event.getPlayer(), Lang.XP_EDITED.toString(), exp, obj); + MessageUtils.sendPrefixedMessage(event.getPlayer(), Lang.XP_EDITED.toString(), exp, obj); exp = obj; event.reopenGUI(); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java index 227ff3a9..68097bdf 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java @@ -17,22 +17,23 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.gui.quests.PlayerListGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.ChatUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.ChatColorUtils; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.PlayerListCategory; public class Scoreboard extends BukkitRunnable implements Listener { private static final Pattern QUEST_PLACEHOLDER = Pattern.compile("\\{quest_(.+)\\}"); - private static final int maxLength = NMS.getMCVersion() >= 13 ? 1024 : 30; + private static final int maxLength = MinecraftVersion.MAJOR >= 13 ? 1024 : 30; private PlayerAccount acc; private Player p; @@ -57,7 +58,7 @@ public class Scoreboard extends BukkitRunnable implements Listener { lines.add(new Line(line)); } - launched = QuestsAPI.getQuests().getQuestsStarted(acc, false, true); + launched = QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, false, true); hid = !manager.isWorldAllowed(p.getWorld().getName()); @@ -186,7 +187,7 @@ public void setShownQuest(Quest quest, boolean errorWhenUnknown) { if (!quest.isScoreboardEnabled()) return; if (!launched.contains(quest)) { if (errorWhenUnknown) { - launched = QuestsAPI.getQuests().getQuestsStarted(acc, false, true); + launched = QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, false, true); if (!launched.contains(quest)) throw new IllegalArgumentException("Quest is not running for player."); }else return; } @@ -220,7 +221,7 @@ private void updateBoard(boolean update, boolean time) { break; } }catch (Exception ex) { - BeautyQuests.logger.warning("An error occured while refreshing scoreboard line " + i + " for " + p.getName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An error occured while refreshing scoreboard line " + i + " for " + p.getName(), ex); linesStrings.add("§c§lline error"); } } @@ -306,11 +307,11 @@ private boolean tryRefresh(boolean time) { lines = Collections.emptyList(); lastValue = null; } else { - text = Utils.finalFormat(p, text, true); + text = MessageUtils.finalFormat(p, text, true); if (text.equals(lastValue)) return false; - lines = ChatUtils.wordWrap(text, param.getMaxLength() == 0 ? 30 : param.getMaxLength(), maxLength); + lines = ChatColorUtils.wordWrap(text, param.getMaxLength() == 0 ? 30 : param.getMaxLength(), maxLength); lastValue = text; } @@ -360,7 +361,7 @@ private String formatQuestPlaceholders(String text) { if (optionalDescription.isPresent()) { if (lazyContext == null) lazyContext = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), - shown, acc, PlayerListGUI.Category.IN_PROGRESS, Source.SCOREBOARD); + shown, acc, PlayerListCategory.IN_PROGRESS, DescriptionSource.SCOREBOARD); replacement = String.join("\n", optionalDescription.get().provideDescription(lazyContext)); } else { if (manager.hideUnknownQuestPlaceholders()) { diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardLine.java b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardLine.java index bf6209a9..f78d2a3b 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardLine.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardLine.java @@ -2,7 +2,7 @@ import java.util.Map; import org.apache.commons.lang.Validate; -import fr.skytasul.quests.utils.ChatUtils; +import fr.skytasul.quests.api.utils.ChatColorUtils; import net.md_5.bungee.api.ChatColor; public class ScoreboardLine { @@ -14,7 +14,7 @@ public class ScoreboardLine { public ScoreboardLine(String value) { Validate.notNull(value); this.value = ChatColor.translateAlternateColorCodes('&', - ChatUtils.translateHexColorCodes(value + ChatColorUtils.translateHexColorCodes(value .replace("{questName}", "{quest_name}") .replace("{questDescription}", "{quest_advancement}"))); } diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java index e28cb0c0..df594da3 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java @@ -20,11 +20,11 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsHandler; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.DebugUtils; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; public class ScoreboardManager implements Listener, QuestsHandler { @@ -126,7 +126,7 @@ public void load() { lines.clear(); for (Map<?, ?> map : config.getMapList("lines")) { if (lines.size() == 15) { - BeautyQuests.logger.warning("Limit of 15 scoreboard lines reached - please delete some in scoreboard.yml"); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Limit of 15 scoreboard lines reached - please delete some in scoreboard.yml"); break; } try { @@ -135,7 +135,7 @@ public void load() { ex.printStackTrace(); } } - DebugUtils.logMessage("Registered " + lines.size() + " lines in scoreboard"); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Registered " + lines.size() + " lines in scoreboard"); scoreboards = new HashMap<>(); forceHiddenState = new HashMap<>(); @@ -146,7 +146,7 @@ public void load() { public void unload(){ HandlerList.unregisterAll(this); for (Scoreboard s : scoreboards.values()) s.cancel(); - if (!scoreboards.isEmpty()) BeautyQuests.getInstance().getLogger().info(scoreboards.size() + " scoreboards deleted."); + if (!scoreboards.isEmpty()) QuestsPlugin.getPlugin().getLoggerExpanded().info(scoreboards.size() + " scoreboards deleted."); scoreboards.clear(); scoreboards = null; forceHiddenState.clear(); @@ -190,33 +190,32 @@ public void questRemove(Quest quest) { } @Override - public void questFinish(PlayerAccount acc, Player p, Quest quest) { + public void questFinish(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; - questEvent(acc, p, x -> x.questRemove(quest)); + questEvent(acc, x -> x.questRemove(quest)); } @Override public void questReset(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; - questEvent(acc, null, x -> x.questRemove(quest)); + questEvent(acc, x -> x.questRemove(quest)); } @Override - public void questUpdated(PlayerAccount acc, Player p, Quest quest) { + public void questUpdated(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; - questEvent(acc, p, x -> x.setShownQuest(quest, true)); + questEvent(acc, x -> x.setShownQuest(quest, true)); } @Override - public void questStart(PlayerAccount acc, Player p, Quest quest) { + public void questStart(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; - questEvent(acc, p, x -> x.questAdd(quest)); + questEvent(acc, x -> x.questAdd(quest)); } - private void questEvent(PlayerAccount acc, Player p, Consumer<Scoreboard> consumer) { - if (p == null) p = acc.getPlayer(); - if (p != null) { - Scoreboard scoreboard = scoreboards.get(p); + private void questEvent(PlayerAccount acc, Consumer<Scoreboard> consumer) { + if (acc.isCurrent()) { + Scoreboard scoreboard = scoreboards.get(acc.getPlayer()); if (scoreboard != null) consumer.accept(scoreboard); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java index 46fe067c..c902614c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java @@ -12,20 +12,21 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardEntryEvent; import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardExitEvent; @@ -42,8 +43,8 @@ public class StageArea extends AbstractStage implements Locatable.PreciseLocatab private Locatable.Located center = null; private long lastCenter = 0; - public StageArea(QuestBranch branch, String regionName, String worldName, boolean exit) { - super(branch); + public StageArea(StageController controller, String regionName, String worldName, boolean exit) { + super(controller); World w = Bukkit.getWorld(worldName); Validate.notNull(w, "No world with specified name (\"" + worldName + "\")"); @@ -95,12 +96,12 @@ public void onRegionExit(WorldGuardExitEvent e) { } @Override - public String descriptionLine(PlayerAccount acc, Source source){ - return Utils.format(Lang.SCOREBOARD_REG.toString(), region.getId()); + public String descriptionLine(PlayerAccount acc, DescriptionSource source){ + return MessageUtils.format(Lang.SCOREBOARD_REG.toString(), region.getId()); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, Source source){ + public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new String[]{region.getId()}; } @@ -116,7 +117,7 @@ public Located getLocated() { .add(region.getMinimumPoint())) // midpoint .add(0.5, 0.5, 0.5); - center = Locatable.Located.create(centerLoc); + center = Locatable.Located.open(centerLoc); lastCenter = System.currentTimeMillis(); } return center; @@ -137,7 +138,7 @@ public void serialize(ConfigurationSection section) { section.set("exit", exit); } - public static StageArea deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageArea deserialize(ConfigurationSection section, StageController controller) { return new StageArea(branch, section.getString("region"), section.getString("world"), section.getBoolean("exit", false)); } @@ -179,7 +180,7 @@ private void launchRegionEditor(Player p, boolean first) { if (first) remove(); } reopenGUI(p, false); - }).useStrippedMessage().enter(); + }).useStrippedMessage().start(); } @Override @@ -196,7 +197,7 @@ public void edit(StageArea stage) { } @Override - public StageArea finishStage(QuestBranch branch) { + public StageArea finishStage(StageController controller) { return new StageArea(branch, regionName, worldName, exit); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java index d954163f..e7bd2b61 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java @@ -6,16 +6,16 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityBreedEvent; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractEntityStage; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; public class StageBreed extends AbstractEntityStage { - public StageBreed(QuestBranch branch, EntityType entity, int amount) { + public StageBreed(StageController controller, EntityType entity, int amount) { super(branch, entity, amount); } @@ -28,11 +28,11 @@ public void onBreed(EntityBreedEvent e) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_BREED.format(getMobsLeft(acc)); } - public static StageBreed deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageBreed deserialize(ConfigurationSection section, StageController controller) { String type = section.getString("entityType"); return new StageBreed(branch, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); } @@ -49,7 +49,7 @@ protected boolean canUseEntity(EntityType type) { } @Override - protected StageBreed finishStage(QuestBranch branch) { + protected StageBreed finishStage(StageController controller) { return new StageBreed(branch, entity, amount); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 2404c72c..8fc00d14 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -12,16 +12,16 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.ItemsGUI; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class StageBringBack extends StageNPC{ @@ -33,8 +33,8 @@ public class StageBringBack extends StageNPC{ protected final String splitted; protected final String line; - public StageBringBack(QuestBranch branch, ItemStack[] items, String customMessage, ItemComparisonMap comparisons) { - super(branch); + public StageBringBack(StageController controller, ItemStack[] items, String customMessage, ItemComparisonMap comparisons) { + super(controller); this.customMessage = customMessage; this.comparisons = comparisons; @@ -46,15 +46,15 @@ public StageBringBack(QuestBranch branch, ItemStack[] items, String customMessag String[] array = new String[items.length]; // create messages on beginning for (int i = 0; i < array.length; i++){ - array[i] = QuestsConfiguration.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfiguration.getItemAmountColor(), QuestsConfiguration.showDescriptionItemsXOne(Source.FORCESPLIT)); + array[i] = QuestsConfiguration.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfiguration.getItemAmountColor(), QuestsConfiguration.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)); } - splitted = Utils.descriptionLines(Source.FORCESPLIT, array); - if (QuestsConfiguration.showDescriptionItemsXOne(Source.FORCESPLIT)){ + splitted = Utils.descriptionLines(DescriptionSource.FORCESPLIT, array); + if (QuestsConfiguration.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)){ for (int i = 0; i < array.length; i++){ array[i] = QuestsConfiguration.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfiguration.getItemAmountColor(), false); } } - line = Utils.descriptionLines(Source.FORCELINE, array); + line = Utils.descriptionLines(DescriptionSource.FORCELINE, array); } public boolean checkItems(Player p, boolean msg){ @@ -92,12 +92,12 @@ protected String getMessage() { } @Override - public String descriptionLine(PlayerAccount acc, Source source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source){ return Utils.format(Lang.SCOREBOARD_ITEMS.toString() + " " + (QuestsConfiguration.splitDescription(source) ? splitted : line), npcName()); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, Source source){ + protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source){ return new String[]{QuestsConfiguration.splitDescription(source) ? splitted : line, npcName()}; } @@ -146,7 +146,7 @@ public void serialize(ConfigurationSection section) { if (!comparisons.getNotDefault().isEmpty()) section.createSection("itemComparisons", comparisons.getNotDefault()); } - public static StageBringBack deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageBringBack deserialize(ConfigurationSection section, StageController controller) { ItemStack[] items = section.getList("items").toArray(new ItemStack[0]); String customMessage = section.getString("customMessage", null); ItemComparisonMap comparisons; @@ -175,19 +175,19 @@ public AbstractCreator(Line line, boolean ending) { new ItemsGUI(items -> { setItems(items); reopenGUI(p, true); - }, items).create(p); + }, items).open(p); }); line.setItem(9, stageMessage, (p, item) -> { new TextEditor<String>(p, () -> reopenGUI(p, false), x -> { setMessage(x); reopenGUI(p, false); - }).passNullIntoEndConsumer().enter(); + }).passNullIntoEndConsumer().start(); }); line.setItem(10, stageComparison, (p, item) -> { new ItemComparisonGUI(comparisons, () -> { setComparisons(comparisons); reopenGUI(p, true); - }).create(p); + }).open(p); }); } @@ -211,7 +211,7 @@ public void start(Player p) { new ItemsGUI(items -> { setItems(items); super.start(p); - }, Collections.emptyList()).create(p); + }, Collections.emptyList()).open(p); } @Override @@ -231,7 +231,7 @@ public Creator(Line line, boolean ending) { } @Override - protected StageBringBack createStage(QuestBranch branch) { + protected StageBringBack createStage(StageController controller) { return new StageBringBack(branch, items.toArray(new ItemStack[0]), message, comparisons); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 1dfdad00..75434f21 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -10,28 +10,27 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.BucketTypeGUI; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; public class StageBucket extends AbstractStage { private BucketType bucket; private int amount; - public StageBucket(QuestBranch branch, BucketType bucket, int amount) { - super(branch); + public StageBucket(StageController controller, BucketType bucket, int amount) { + super(controller); this.bucket = bucket; this.amount = amount; } @@ -70,12 +69,12 @@ protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_BUCKET.format(Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), amount, false)); } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, Source source) { + protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Supplier[] { () -> Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), amount, false) }; } @@ -85,7 +84,7 @@ protected void serialize(ConfigurationSection section) { section.set("amount", amount); } - public static StageBucket deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageBucket deserialize(ConfigurationSection section, StageController controller) { return new StageBucket(branch, BucketType.valueOf(section.getString("bucket")), section.getInt("amount")); } @@ -123,7 +122,7 @@ public static BucketType fromMaterial(XMaterial type) { public static BucketType[] getAvailable() { if (AVAILABLE == null) { - AVAILABLE = NMS.getMCVersion() >= 17 ? values() : new BucketType[] {WATER, LAVA, MILK}; + AVAILABLE = MinecraftVersion.MAJOR >= 17 ? values() : new BucketType[] {WATER, LAVA, MILK}; // inefficient? yes. But it's christmas and I don't want to work on this anymore, plus there will // probably not be more bucket types in the future } @@ -144,13 +143,13 @@ public Creator(Line line, boolean ending) { new TextEditor<>(p, () -> reopenGUI(p, true), obj -> { setAmount(obj); reopenGUI(p, true); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); }); line.setItem(7, ItemUtils.item(XMaterial.BUCKET, Lang.editBucketType.toString()), (p, item) -> { new BucketTypeGUI(() -> reopenGUI(p, true), bucket -> { setBucket(bucket); reopenGUI(p, true); - }).create(p); + }).open(p); }); } @@ -176,8 +175,8 @@ public void start(Player p) { new TextEditor<>(p, cancel, obj -> { setAmount(obj); reopenGUI(p, true); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); - }).create(p); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); + }).open(p); } @Override @@ -188,7 +187,7 @@ public void edit(StageBucket stage) { } @Override - public StageBucket finishStage(QuestBranch branch) { + public StageBucket finishStage(StageController controller) { return new StageBucket(branch, bucket, amount); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index 2893595a..c713604c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -7,16 +7,16 @@ import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class StageChat extends AbstractStage{ @@ -27,8 +27,8 @@ public class StageChat extends AbstractStage{ private boolean command; - public StageChat(QuestBranch branch, String text, boolean cancel, boolean ignoreCase, boolean placeholders) { - super(branch); + public StageChat(StageController controller, String text, boolean cancel, boolean ignoreCase, boolean placeholders) { + super(controller); Validate.notNull(text, "Text cannot be null"); this.text = text; @@ -40,12 +40,12 @@ public StageChat(QuestBranch branch, String text, boolean cancel, boolean ignore } @Override - public String descriptionLine(PlayerAccount acc, Source source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source){ return Lang.SCOREBOARD_CHAT.format(text); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, Source source){ + protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source){ return new String[]{text}; } @@ -91,7 +91,7 @@ public void serialize(ConfigurationSection section) { if (!placeholders) section.set("placeholders", false); } - public static StageChat deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageChat deserialize(ConfigurationSection section, StageController controller) { return new StageChat(branch, section.getString("writeText"), section.getBoolean("cancel", true), section.getBoolean("ignoreCase", false), section.getBoolean("placeholders", true)); } @@ -158,7 +158,7 @@ public void edit(StageChat stage) { } @Override - public StageChat finishStage(QuestBranch branch) { + public StageChat finishStage(StageController controller) { return new StageChat(branch, text, cancel, ignoreCase, placeholders); } @@ -171,7 +171,7 @@ private void launchEditor(Player p) { obj = obj.replace("{SLASH}", "/"); setText(obj); reopenGUI(p, false); - }).enter(); + }).start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index af27d2af..0ccba14e 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -14,18 +14,18 @@ import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.events.internal.BQCraftEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; import fr.skytasul.quests.gui.misc.ItemGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; /** * @author SkytAsul, ezeiger92, TheBusyBiscuit @@ -35,8 +35,8 @@ public class StageCraft extends AbstractStage { private ItemStack result; private final ItemComparisonMap comparisons; - public StageCraft(QuestBranch branch, ItemStack result, ItemComparisonMap comparisons) { - super(branch); + public StageCraft(StageController controller, ItemStack result, ItemComparisonMap comparisons) { + super(controller); this.result = result; this.comparisons = comparisons; if (result.getAmount() == 0) result.setAmount(1); @@ -134,12 +134,12 @@ private int getPlayerAmount(PlayerAccount acc) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source){ + protected String descriptionLine(PlayerAccount acc, DescriptionSource source){ return Lang.SCOREBOARD_CRAFT.format(Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false)); } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, Source source) { + protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Supplier[] { () -> Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false) }; } @@ -150,7 +150,7 @@ protected void serialize(ConfigurationSection section) { if (!comparisons.getNotDefault().isEmpty()) section.createSection("itemComparisons", comparisons.getNotDefault()); } - public static StageCraft deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageCraft deserialize(ConfigurationSection section, StageController controller) { return new StageCraft(branch, ItemStack.deserialize(section.getConfigurationSection("result").getValues(false)), section.contains("itemComparisons") ? new ItemComparisonMap(section.getConfigurationSection("itemComparisons")) : new ItemComparisonMap()); } @@ -180,13 +180,13 @@ public Creator(Line line, boolean ending) { new ItemGUI((is) -> { setItem(is); reopenGUI(p, true); - }, () -> reopenGUI(p, true)).create(p); + }, () -> reopenGUI(p, true)).open(p); }); line.setItem(COMPARISONS_SLOT, ItemUtils.item(XMaterial.PRISMARINE_SHARD, Lang.stageItemsComparison.toString()), (p, item) -> { new ItemComparisonGUI(comparisons, () -> { setComparisons(comparisons); reopenGUI(p, true); - }).create(p); + }).open(p); }); } @@ -206,7 +206,7 @@ public void start(Player p) { new ItemGUI(is -> { setItem(is); reopenGUI(p, true); - }, removeAndReopen(p, true)).create(p); + }, removeAndReopen(p, true)).open(p); } @Override @@ -217,7 +217,7 @@ public void edit(StageCraft stage) { } @Override - public StageCraft finishStage(QuestBranch branch) { + public StageCraft finishStage(StageController controller) { return new StageCraft(branch, item, comparisons); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index 2d099462..62d7694d 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -16,21 +16,21 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.projectiles.ProjectileSource; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.mobs.Mob; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.ListGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.mobs.MobSelectionGUI; -import fr.skytasul.quests.gui.templates.ListGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.mobs.Mob; @SuppressWarnings ("rawtypes") public class StageDealDamage extends AbstractStage { @@ -40,8 +40,8 @@ public class StageDealDamage extends AbstractStage { private final String targetMobsString; - public StageDealDamage(QuestBranch branch, double damage, List<Mob> targetMobs) { - super(branch); + public StageDealDamage(StageController controller, double damage, List<Mob> targetMobs) { + super(controller); this.damage = damage; this.targetMobs = targetMobs; @@ -87,12 +87,12 @@ public void onDamage(EntityDamageByEntityEvent event) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return (targetMobs == null || targetMobs.isEmpty() ? Lang.SCOREBOARD_DEAL_DAMAGE_ANY : Lang.SCOREBOARD_DEAL_DAMAGE_MOBS).format(descriptionFormat(acc, source)); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, Source source) { + protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Object[] { (Supplier<String>) () -> Integer.toString(super.<Double>getData(acc, "amount").intValue()), targetMobsString }; } @@ -103,7 +103,7 @@ protected void serialize(ConfigurationSection section) { section.set("targetMobs", targetMobs.stream().map(Mob::serialize).collect(Collectors.toList())); } - public static StageDealDamage deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageDealDamage deserialize(ConfigurationSection section, StageController controller) { return new StageDealDamage(branch, section.getDouble("damage"), section.contains("targetMobs") ? section.getMapList("targetMobs").stream().map(map -> Mob.deserialize((Map) map)).collect(Collectors.toList()) : null); @@ -125,7 +125,7 @@ public Creator(Line line, boolean ending) { new TextEditor<>(p, () -> reopenGUI(p, false), newDamage -> { setDamage(newDamage); reopenGUI(p, false); - }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).start(); }); line.setItem(SLOT_MOBS, ItemUtils.item(XMaterial.BLAZE_SPAWN_EGG, Lang.stageDealDamageMobs.toString(), QuestOption.formatNullableValue(Lang.EntityTypeAny.toString(), true)), (p, item) -> { @@ -134,7 +134,7 @@ public Creator(Line line, boolean ending) { @Override public void finish(List<Mob> objects) { setTargetMobs(objects.isEmpty() ? null : objects); - reopenGUI(p, true); + reopenGUI(player, true); } @Override @@ -144,10 +144,10 @@ public ItemStack getObjectItemStack(Mob object) { @Override public void createObject(Function<Mob, ItemStack> callback) { - new MobSelectionGUI(callback::apply).create(p); + new MobSelectionGUI(callback::apply).open(player); } - }.create(p); + }.open(p); }); } @@ -176,11 +176,11 @@ public void start(Player p) { new TextEditor<>(p, removeAndReopen(p, false), newDamage -> { setDamage(newDamage); reopenGUI(p, false); - }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).start(); } @Override - protected StageDealDamage finishStage(QuestBranch branch) { + protected StageDealDamage finishStage(StageController controller) { return new StageDealDamage(branch, damage, targetMobs); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java index 073ae63b..5365a7c4 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java @@ -10,22 +10,22 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.PlayerDeathEvent; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.misc.DamageCausesGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; public class StageDeath extends AbstractStage { private List<DamageCause> causes; - public StageDeath(QuestBranch branch, List<DamageCause> causes) { - super(branch); + public StageDeath(StageController controller, List<DamageCause> causes) { + super(controller); this.causes = causes; } @@ -44,7 +44,7 @@ public void onPlayerDeath(PlayerDeathEvent event) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_DIE.toString(); } @@ -53,7 +53,7 @@ protected void serialize(ConfigurationSection section) { if (!causes.isEmpty()) section.set("causes", causes.stream().map(DamageCause::name).collect(Collectors.toList())); } - public static StageDeath deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageDeath deserialize(ConfigurationSection section, StageController controller) { List<DamageCause> causes; if (section.contains("causes")) { causes = section.getStringList("causes").stream().map(DamageCause::valueOf).collect(Collectors.toList()); @@ -76,7 +76,7 @@ public Creator(Line line, boolean ending) { new DamageCausesGUI(causes, newCauses -> { setCauses(newCauses); reopenGUI(p, true); - }).create(p); + }).open(p); }); } @@ -98,7 +98,7 @@ public void edit(StageDeath stage) { } @Override - protected StageDeath finishStage(QuestBranch branch) { + protected StageDeath finishStage(StageController controller) { return new StageDeath(branch, causes); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java index be19d264..d68d2571 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java @@ -7,28 +7,28 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.CountableObject; public class StageEatDrink extends AbstractItemStage { - public StageEatDrink(QuestBranch branch, List<CountableObject<ItemStack>> objects, ItemComparisonMap comparisons) { + public StageEatDrink(StageController controller, List<CountableObject<ItemStack>> objects, ItemComparisonMap comparisons) { super(branch, objects, comparisons); } - public StageEatDrink(ConfigurationSection section, QuestBranch branch) { + public StageEatDrink(ConfigurationSection section, StageController controller) { super(branch, section); } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_EAT_DRINK.format(super.descriptionLine(acc, source)); } @@ -51,7 +51,7 @@ protected ItemStack getEditItem() { } @Override - protected StageEatDrink finishStage(QuestBranch branch, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { + protected StageEatDrink finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageEatDrink(branch, items, comparisons); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java index 14a39b66..48059868 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java @@ -9,23 +9,23 @@ import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.CountableObject; public class StageEnchant extends AbstractItemStage { - public StageEnchant(QuestBranch branch, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { + public StageEnchant(StageController controller, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { super(branch, fishes, comparisons); } - public StageEnchant(QuestBranch branch, ConfigurationSection section) { + public StageEnchant(StageController controller, ConfigurationSection section) { super(branch, section); } @@ -43,11 +43,11 @@ public void onEnchant(EnchantItemEvent e) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_ENCHANT.format(super.descriptionLine(acc, source)); } - public static StageEnchant deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageEnchant deserialize(ConfigurationSection section, StageController controller) { return new StageEnchant(branch, section); } @@ -65,7 +65,7 @@ protected ItemStack getEditItem() { } @Override - protected StageEnchant finishStage(QuestBranch branch, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { + protected StageEnchant finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageEnchant(branch, items, comparisons); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java index 4c5ee4e2..6bce7349 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java @@ -11,23 +11,23 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.CountableObject; public class StageFish extends AbstractItemStage { - public StageFish(QuestBranch branch, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { + public StageFish(StageController controller, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { super(branch, fishes, comparisons); } - public StageFish(QuestBranch branch, ConfigurationSection section) { + public StageFish(StageController controller, ConfigurationSection section) { super(branch, section); } @@ -44,11 +44,11 @@ public void onFish(PlayerFishEvent e){ } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_FISH.format(super.descriptionLine(acc, source)); } - public static StageFish deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageFish deserialize(ConfigurationSection section, StageController controller) { return new StageFish(branch, section); } @@ -66,7 +66,7 @@ protected ItemStack getEditItem() { } @Override - protected StageFish finishStage(QuestBranch branch, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { + protected StageFish finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageFish(branch, items, comparisons); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java index 6dfa9d75..8a4ad23a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java @@ -16,24 +16,23 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.WaitBlockClick; +import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.editors.WaitBlockClick; -import fr.skytasul.quests.gui.CustomInventory; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.blocks.SelectBlockGUI; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.BQLocation; @@ -46,16 +45,16 @@ public class StageInteract extends AbstractStage implements Locatable.MultipleLo private Located.LocatedBlock locatedBlock; - public StageInteract(QuestBranch branch, boolean leftClick, BQLocation location) { - super(branch); + public StageInteract(StageController controller, boolean leftClick, BQLocation location) { + super(controller); this.left = leftClick; this.lc = new BQLocation(location.getWorldName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); this.block = null; } - public StageInteract(QuestBranch branch, boolean leftClick, BQBlock block) { - super(branch); + public StageInteract(StageController controller, boolean leftClick, BQBlock block) { + super(controller); this.left = leftClick; this.block = block; @@ -81,7 +80,7 @@ public Located getLocated() { if (locatedBlock == null) { Block realBlock = lc.getMatchingBlock(); if (realBlock != null) - locatedBlock = Located.LocatedBlock.create(realBlock); + locatedBlock = Located.LocatedBlock.open(realBlock); } return locatedBlock; } @@ -96,7 +95,7 @@ public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { @EventHandler public void onInteract(PlayerInteractEvent e){ if (e.getClickedBlock() == null) return; - if (NMS.getMCVersion() >= 9 && e.getHand() != EquipmentSlot.HAND) return; + if (MinecraftVersion.MAJOR >= 9 && e.getHand() != EquipmentSlot.HAND) return; if (left){ if (e.getAction() != Action.LEFT_CLICK_BLOCK) return; @@ -107,7 +106,7 @@ public void onInteract(PlayerInteractEvent e){ }else if (block != null) { if (!block.applies(e.getClickedBlock())) return; }else { - BeautyQuests.logger.warning("No block nor location set for " + toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("No block nor location set for " + toString()); return; } @@ -119,7 +118,7 @@ public void onInteract(PlayerInteractEvent e){ } @Override - protected String descriptionLine(PlayerAccount acc, Source source){ + protected String descriptionLine(PlayerAccount acc, DescriptionSource source){ return lc == null ? Lang.SCOREBOARD_INTERACT_MATERIAL.format(block.getName()) : Lang.SCOREBOARD_INTERACT.format(lc.getBlockX() + " " + lc.getBlockY() + " " + lc.getBlockZ()); } @@ -131,7 +130,7 @@ protected void serialize(ConfigurationSection section) { }else section.set("location", lc.serialize()); } - public static StageInteract deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageInteract deserialize(ConfigurationSection section, StageController controller) { if (section.contains("location")) { return new StageInteract(branch, section.getBoolean("leftClick"), BQLocation.deserialize(section.getConfigurationSection("location").getValues(false))); }else { @@ -167,11 +166,11 @@ public void setLeftClick(boolean leftClick) { public void setLocation(Location location) { if (this.location == null) { line.setItem(7, ItemUtils.item(XMaterial.COMPASS, Lang.blockLocation.toString()), (p, item) -> { - Lang.CLICK_BLOCK.send(p); - new WaitBlockClick(p, () -> reopenGUI(p, false), obj -> { + Lang.CLICK_BLOCK.send(player); + new WaitBlockClick(player, () -> reopenGUI(player, false), obj -> { setLocation(obj); - reopenGUI(p, false); - }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).enter(); + reopenGUI(player, false); + }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); }); } line.editItem(7, ItemUtils.lore(line.getItem(7), QuestOption.formatDescription(Utils.locationToString(location)))); @@ -183,8 +182,8 @@ public void setMaterial(BQBlock block) { line.setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), (p, item) -> { new SelectBlockGUI(false, (newBlock, __) -> { setMaterial(newBlock); - reopenGUI(p, true); - }).create(p); + reopenGUI(player, true); + }).open(player); }); } line.editItem(7, ItemUtils.lore(line.getItem(7), Lang.optionValue.format(block.getName()))); @@ -200,13 +199,13 @@ public void start(Player p) { new WaitBlockClick(p, cancel, obj -> { setLocation(obj); reopenGUI(p, true); - }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).enter(); + }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); }, () -> { new SelectBlockGUI(false, (newBlock, __) -> { setMaterial(newBlock); reopenGUI(p, true); - }).create(p); - }).create(p); + }).open(p); + }).open(p); } @Override @@ -219,7 +218,7 @@ public void edit(StageInteract stage) { } @Override - public StageInteract finishStage(QuestBranch branch) { + public StageInteract finishStage(StageController controller) { if (location != null) { return new StageInteract(branch, leftClick, new BQLocation(location)); }else return new StageInteract(branch, leftClick, block); 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 2c375508..e7f2c5ae 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -8,24 +8,24 @@ import org.bukkit.event.player.PlayerMoveEvent; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.WaitClick; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.checkers.PatternParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.WaitClick; -import fr.skytasul.quests.editors.checkers.NumberParser; -import fr.skytasul.quests.editors.checkers.PatternParser; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.gui.npc.NPCGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.BQLocation; @@ -39,8 +39,8 @@ public class StageLocation extends AbstractStage implements Locatable.PreciseLoc private String descMessage; - public StageLocation(QuestBranch branch, BQLocation lc, int radius, boolean gps) { - super(branch); + public StageLocation(StageController controller, BQLocation lc, int radius, boolean gps) { + super(controller); this.lc = lc; this.radius = radius; this.radiusSquared = radius * radius; @@ -106,8 +106,8 @@ public void start(PlayerAccount acc) { } @Override - public void end(PlayerAccount acc) { - super.end(acc); + public void ended(PlayerAccount acc) { + super.ended(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); if (QuestsConfiguration.handleGPS() && gps) GPS.stopCompass(p); @@ -115,12 +115,12 @@ public void end(PlayerAccount acc) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source){ + protected String descriptionLine(PlayerAccount acc, DescriptionSource source){ return descMessage; } @Override - protected Object[] descriptionFormat(PlayerAccount acc, Source source) { + protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Object[] { lc.getBlockX(), lc.getBlockY(), lc.getBlockZ(), lc.getWorldName() }; } @@ -131,7 +131,7 @@ protected void serialize(ConfigurationSection section) { if (!gps) section.set("gps", false); } - public static StageLocation deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageLocation deserialize(ConfigurationSection section, StageController controller) { return new StageLocation(branch, BQLocation.deserialize(section.getConfigurationSection("location").getValues(false)), section.getInt("radius"), section.getBoolean("gps", true)); } @@ -155,21 +155,21 @@ public Creator(Line line, boolean ending) { new TextEditor<>(p, () -> reopenGUI(p, false), x -> { setRadius(x); reopenGUI(p, false); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).enter(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); }); line.setItem(SLOT_LOCATION, ItemUtils.item(XMaterial.STICK, Lang.stageLocationLocation.toString()), (p, item) -> { Lang.LOCATION_GO.send(p); - new WaitClick(p, () -> reopenGUI(p, false), NPCGUI.validMove, () -> { + new WaitClick(p, () -> reopenGUI(p, false), NpcCreateGUI.validMove, () -> { setLocation(new BQLocation(p.getLocation())); reopenGUI(p, false); - }).enter(); + }).start(); }); line.setItem(SLOT_WORLD_PATTERN, ItemUtils.item(XMaterial.NAME_TAG, Lang.stageLocationWorldPattern.toString(), QuestOption.formatDescription(Lang.stageLocationWorldPatternLore.toString())), (p, item) -> { Lang.LOCATION_WORLDPATTERN.send(p); new TextEditor<>(p, () -> reopenGUI(p, false), pattern -> { setPattern(pattern); reopenGUI(p, false); - }, PatternParser.PARSER).passNullIntoEndConsumer().enter(); + }, PatternParser.PARSER).passNullIntoEndConsumer().start(); }); if (QuestsConfiguration.handleGPS()) line.setItem(SLOT_GPS, ItemUtils.itemSwitch(Lang.stageGPS.toString(), gps), (p, item) -> setGPS(ItemUtils.toggle(item)), true, true); @@ -207,11 +207,11 @@ private BQLocation getBQLocation() { public void start(Player p) { super.start(p); Lang.LOCATION_GO.send(p); - new WaitClick(p, removeAndReopen(p, false), NPCGUI.validMove, () -> { + new WaitClick(p, removeAndReopen(p, false), NpcCreateGUI.validMove, () -> { setLocation(p.getLocation()); setRadius(5); reopenGUI(p, false); - }).enter(); + }).start(); } @Override @@ -224,7 +224,7 @@ public void edit(StageLocation stage) { } @Override - public StageLocation finishStage(QuestBranch branch) { + public StageLocation finishStage(StageController controller) { return new StageLocation(branch, getBQLocation(), radius, gps); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java index 74284d1e..208648c0 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java @@ -8,23 +8,23 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.CountableObject; public class StageMelt extends AbstractItemStage { - public StageMelt(QuestBranch branch, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { + public StageMelt(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { super(branch, items, comparisons); } - public StageMelt(QuestBranch branch, ConfigurationSection section) { + public StageMelt(StageController controller, ConfigurationSection section) { super(branch, section); } @@ -34,11 +34,11 @@ public void onMelt(FurnaceExtractEvent event) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_MELT.format(super.descriptionLine(acc, source)); } - public static StageMelt deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageMelt deserialize(ConfigurationSection section, StageController controller) { return new StageMelt(branch, section); } @@ -56,7 +56,7 @@ protected ItemStack getEditItem() { } @Override - protected StageMelt finishStage(QuestBranch branch, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { + protected StageMelt finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageMelt(branch, items, comparisons); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index 8295866c..e3b6d08c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -20,17 +20,17 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.CountableObject; @@ -39,7 +39,7 @@ public class StageMine extends AbstractCountableBlockStage implements Locatable. private boolean placeCancelled; - public StageMine(QuestBranch branch, List<CountableObject<BQBlock>> blocks) { + public StageMine(StageController controller, List<CountableObject<BQBlock>> blocks) { super(branch, blocks); } @@ -52,7 +52,7 @@ public void setPlaceCancelled(boolean cancelPlaced) { } @Override - public String descriptionLine(PlayerAccount acc, Source source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source){ return Lang.SCOREBOARD_MINE.format(super.descriptionLine(acc, source)); } @@ -111,7 +111,7 @@ protected void serialize(ConfigurationSection section) { if (placeCancelled) section.set("placeCancelled", placeCancelled); } - public static StageMine deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageMine deserialize(ConfigurationSection section, StageController controller) { StageMine stage = new StageMine(branch, new ArrayList<>()); stage.deserialize(section); @@ -148,7 +148,7 @@ public void edit(StageMine stage) { } @Override - public StageMine finishStage(QuestBranch branch) { + public StageMine finishStage(StageController controller) { StageMine stage = new StageMine(branch, getImmutableBlocks()); stage.setPlaceCancelled(prevent); return stage; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index 0272b0cf..7b388fc0 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -17,21 +17,21 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.mobs.Mob; +import fr.skytasul.quests.api.events.internal.BQMobDeathEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.AbstractCountableStage; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.mobs.MobsListGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.compatibility.mobs.CompatMobDeathEvent; +import fr.skytasul.quests.mobs.Mob; import fr.skytasul.quests.utils.types.CountableObject; import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; @@ -40,7 +40,7 @@ public class StageMobs extends AbstractCountableStage<Mob<?>> implements Locatab private boolean shoot = false; - public StageMobs(QuestBranch branch, List<CountableObject<Mob<?>>> mobs) { + public StageMobs(StageController controller, List<CountableObject<Mob<?>>> mobs) { super(branch, mobs); } @@ -53,7 +53,7 @@ public void setShoot(boolean shoot) { } @EventHandler - public void onMobKilled(CompatMobDeathEvent e){ + public void onMobKilled(BQMobDeathEvent e){ if (shoot && e.getBukkitEntity() != null && e.getBukkitEntity().getLastDamageCause() != null && e.getBukkitEntity().getLastDamageCause().getCause() != DamageCause.PROJECTILE) return; @@ -82,7 +82,7 @@ protected boolean objectApplies(Mob<?> object, Object other) { } @Override - public String descriptionLine(PlayerAccount acc, Source source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source){ return Lang.SCOREBOARD_MOBS.format(super.descriptionLine(acc, source)); } @@ -90,7 +90,7 @@ public String descriptionLine(PlayerAccount acc, Source source){ public void start(PlayerAccount acc) { super.start(acc); if (acc.isCurrent() && sendStartMessage()) { - Lang.STAGE_MOBSLIST.send(acc.getPlayer(), (Object[]) super.descriptionFormat(acc, Source.FORCELINE)); + Lang.STAGE_MOBSLIST.send(acc.getPlayer(), (Object[]) super.descriptionFormat(acc, DescriptionSource.FORCELINE)); } } @@ -139,11 +139,11 @@ public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { }) .filter(Objects::nonNull) .sorted(Comparator.comparing(Entry::getValue)) - .<Located>map(entry -> Located.LocatedEntity.create(entry.getKey())) + .<Located>map(entry -> Located.LocatedEntity.open(entry.getKey())) .spliterator(); } - public static StageMobs deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageMobs deserialize(ConfigurationSection section, StageController controller) { StageMobs stage = new StageMobs(branch, new ArrayList<>()); stage.deserialize(section); @@ -163,7 +163,7 @@ public Creator(Line line, boolean ending) { new MobsListGUI(mobs, newMobs -> { setMobs(newMobs); reopenGUI(p, true); - }).create(p); + }).open(p); }); line.setItem(6, ItemUtils.itemSwitch(Lang.mobsKillType.toString(), shoot), (p, item) -> setShoot(ItemUtils.toggle(item))); } @@ -186,11 +186,11 @@ public void start(Player p) { new MobsListGUI(Collections.emptyList(), newMobs -> { setMobs(newMobs); reopenGUI(p, true); - }).create(p); + }).open(p); } @Override - public StageMobs finishStage(QuestBranch branch) { + public StageMobs finishStage(StageController controller) { StageMobs stage = new StageMobs(branch, mobs.stream().map(MutableCountableObject::toImmutable).collect(Collectors.toList())); stage.setShoot(shoot); 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 4377fa81..dcadf8ff 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -17,27 +17,28 @@ import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.AbstractHolograms; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.DialogEditor; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.editors.DialogEditor; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.gui.npc.SelectGUI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.gui.npc.NpcSelectGUI; import fr.skytasul.quests.utils.compatibility.GPS; -import fr.skytasul.quests.utils.types.Dialog; -import fr.skytasul.quests.utils.types.DialogRunner; @LocatableType (types = LocatedType.ENTITY) public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable { @@ -53,8 +54,8 @@ public class StageNPC extends AbstractStage implements Locatable.PreciseLocatabl private List<Player> cached = new ArrayList<>(); protected AbstractHolograms<?>.BQHologram hologram; - public StageNPC(QuestBranch branch) { - super(branch); + public StageNPC(StageController controller) { + super(controller); } private void launchRefreshTask(){ @@ -74,7 +75,7 @@ public void run() { tmp.add(p); } - if (QuestsConfiguration.getHoloTalkItem() != null && QuestsAPI.hasHologramsManager() && QuestsAPI.getHologramsManager().supportItems() && QuestsAPI.getHologramsManager().supportPerPlayerVisibility()) { + if (QuestsConfiguration.getHoloTalkItem() != null && QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility()) { if (hologram == null) createHoloLaunch(); hologram.setPlayersVisible(tmp); hologram.teleport(Utils.upLocationForEntity((LivingEntity) en, 1)); @@ -90,7 +91,7 @@ public void run() { private void createHoloLaunch(){ ItemStack item = QuestsConfiguration.getHoloTalkItem(); - hologram = QuestsAPI.getHologramsManager().createHologram(npc.getLocation(), false); + hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(npc.getLocation(), false); if (QuestsConfiguration.isCustomHologramNameShown() && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) hologram.appendTextLine(item.getItemMeta().getDisplayName()); hologram.appendItem(item); @@ -113,9 +114,9 @@ public int getNPCID() { public void setNPC(int npcID) { this.npcID = npcID; - if (npcID >= 0) this.npc = QuestsAPI.getNPCsManager().getById(npcID); + if (npcID >= 0) this.npc = QuestsAPI.getAPI().getNPCsManager().getById(npcID); if (npc == null) { - BeautyQuests.logger.warning("The NPC " + npcID + " does not exist for " + toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("The NPC " + npcID + " does not exist for " + toString()); }else { initDialogRunner(); } @@ -154,12 +155,12 @@ public Located getLocated() { } @Override - public String descriptionLine(PlayerAccount acc, Source source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source){ return Utils.format(Lang.SCOREBOARD_NPC.toString(), descriptionFormat(acc, source)); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, Source source) { + protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new String[] { npcName() }; } @@ -232,8 +233,8 @@ public void start(PlayerAccount acc) { } @Override - public void end(PlayerAccount acc) { - super.end(acc); + public void ended(PlayerAccount acc) { + super.ended(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); if (dialogRunner != null) dialogRunner.removePlayer(p); @@ -263,7 +264,7 @@ protected void loadDatas(ConfigurationSection section) { if (section.contains("msg")) setDialog(Dialog.deserialize(section.getConfigurationSection("msg"))); if (section.contains("npcID")) { setNPC(section.getInt("npcID")); - }else BeautyQuests.logger.warning("No NPC specified for " + toString()); + }else QuestsPlugin.getPlugin().getLoggerExpanded().warning("No NPC specified for " + toString()); if (section.contains("hid")) hide = section.getBoolean("hid"); } @@ -274,7 +275,7 @@ public void serialize(ConfigurationSection section) { if (hide) section.set("hid", true); } - public static StageNPC deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageNPC deserialize(ConfigurationSection section, StageController controller) { StageNPC st = new StageNPC(branch); st.loadDatas(section); return st; @@ -294,10 +295,10 @@ protected AbstractCreator(Line line, boolean ending) { super(line, ending); line.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString()), (p, item) -> { - new SelectGUI(() -> reopenGUI(p, true), newNPC -> { + new NpcSelectGUI(() -> reopenGUI(p, true), newNPC -> { setNPCId(newNPC.getId()); reopenGUI(p, true); - }).create(p); + }).open(p); }); line.setItem(SLOT_DIALOG, ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.stageText.toString(), Lang.NotSet.toString()), (p, item) -> { @@ -305,7 +306,7 @@ protected AbstractCreator(Line line, boolean ending) { new DialogEditor(p, () -> { setDialog(dialog); reopenGUI(p, false); - }, dialog == null ? dialog = new Dialog() : dialog).enter(); + }, dialog == null ? dialog = new Dialog() : dialog).start(); }, true, true); line.setItem(SLOT_HIDE, ItemUtils.itemSwitch(Lang.stageHide.toString(), hidden), (p, item) -> setHidden(ItemUtils.toggle(item)), true, true); @@ -331,10 +332,10 @@ public void setHidden(boolean hidden) { @Override public void start(Player p) { super.start(p); - new SelectGUI(removeAndReopen(p, true), newNPC -> { + new NpcSelectGUI(removeAndReopen(p, true), newNPC -> { setNPCId(newNPC.getId()); reopenGUI(p, true); - }).create(p); + }).open(p); } @Override @@ -346,7 +347,7 @@ public void edit(T stage) { } @Override - protected final T finishStage(QuestBranch branch) { + protected final T finishStage(StageController controller) { T stage = createStage(branch); stage.setDialog(dialog); stage.setNPC(npcID); @@ -354,7 +355,7 @@ protected final T finishStage(QuestBranch branch) { return stage; } - protected abstract T createStage(QuestBranch branch); + protected abstract T createStage(StageController controller); } @@ -365,7 +366,7 @@ public Creator(Line line, boolean ending) { } @Override - protected StageNPC createStage(QuestBranch branch) { + protected StageNPC createStage(StageController controller) { return new StageNPC(branch); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index 64f189d2..f6fdd174 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -9,25 +9,25 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.CountableObject; public class StagePlaceBlocks extends AbstractCountableBlockStage { - public StagePlaceBlocks(QuestBranch branch, List<CountableObject<BQBlock>> blocks) { + public StagePlaceBlocks(StageController controller, List<CountableObject<BQBlock>> blocks) { super(branch, blocks); } @Override - public String descriptionLine(PlayerAccount acc, Source source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source){ return Lang.SCOREBOARD_PLACE.format(super.descriptionLine(acc, source)); } @@ -41,7 +41,7 @@ public void onPlace(BlockPlaceEvent e) { } } - public static StagePlaceBlocks deserialize(ConfigurationSection section, QuestBranch branch) { + public static StagePlaceBlocks deserialize(ConfigurationSection section, StageController controller) { StagePlaceBlocks stage = new StagePlaceBlocks(branch, new ArrayList<>()); stage.deserialize(section); return stage; @@ -59,7 +59,7 @@ protected ItemStack getBlocksItem() { } @Override - public StagePlaceBlocks finishStage(QuestBranch branch) { + public StagePlaceBlocks finishStage(StageController controller) { return new StagePlaceBlocks(branch, getImmutableBlocks()); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index eef0e642..6944771e 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -10,17 +10,18 @@ import org.bukkit.scheduler.BukkitTask; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.editors.TextEditor; -import fr.skytasul.quests.editors.checkers.DurationParser.MinecraftTimeUnit; -import fr.skytasul.quests.gui.ItemUtils; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; public class StagePlayTime extends AbstractStage { @@ -28,8 +29,8 @@ public class StagePlayTime extends AbstractStage { private Map<PlayerAccount, BukkitTask> tasks = new HashMap<>(); - public StagePlayTime(QuestBranch branch, long ticks) { - super(branch); + public StagePlayTime(StageController controller, long ticks) { + super(controller); this.playTicks = ticks; } @@ -38,12 +39,12 @@ public long getTicksToPlay() { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_PLAY_TIME.format(descriptionFormat(acc, source)); } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, Source source) { + protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Supplier[] { () -> Utils.millisToHumanString(getRemaining(acc) * 50L) }; } @@ -73,7 +74,7 @@ public void leaves(PlayerAccount acc, Player p) { task.cancel(); updateObjective(acc, null, "remainingTime", getRemaining(acc)); }else { - BeautyQuests.logger.warning("Unavailable task in \"Play Time\" stage " + toString() + " for player " + acc.getName()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unavailable task in \"Play Time\" stage " + toString() + " for player " + acc.getName()); } } @@ -93,8 +94,8 @@ protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { } @Override - public void end(PlayerAccount acc) { - super.end(acc); + public void ended(PlayerAccount acc) { + super.ended(acc); tasks.remove(acc).cancel(); } @@ -110,7 +111,7 @@ protected void serialize(ConfigurationSection section) { section.set("playTicks", playTicks); } - public static StagePlayTime deserialize(ConfigurationSection section, QuestBranch branch) { + public static StagePlayTime deserialize(ConfigurationSection section, StageController controller) { return new StagePlayTime(branch, section.getLong("playTicks")); } @@ -126,7 +127,7 @@ public Creator(Line line, boolean ending) { new TextEditor<>(p, () -> reopenGUI(p, false), obj -> { setTicks(obj); reopenGUI(p, false); - }, MinecraftTimeUnit.TICK.getParser()).enter(); + }, MinecraftTimeUnit.TICK.getParser()).start(); }); } @@ -142,7 +143,7 @@ public void start(Player p) { new TextEditor<>(p, removeAndReopen(p, false), obj -> { setTicks(obj); reopenGUI(p, false); - }, MinecraftTimeUnit.TICK.getParser()).enter(); + }, MinecraftTimeUnit.TICK.getParser()).start(); } @Override @@ -152,7 +153,7 @@ public void edit(StagePlayTime stage) { } @Override - public StagePlayTime finishStage(QuestBranch branch) { + public StagePlayTime finishStage(StageController controller) { return new StagePlayTime(branch, ticks); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java index 7e6ebdbd..7ea3fbdc 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java @@ -6,16 +6,16 @@ import org.bukkit.entity.Tameable; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityTameEvent; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractEntityStage; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.structure.QuestBranch; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.Lang; public class StageTame extends AbstractEntityStage { - public StageTame(QuestBranch branch, EntityType entity, int amount) { + public StageTame(StageController controller, EntityType entity, int amount) { super(branch, entity, amount); } @@ -28,11 +28,11 @@ public void onTame(EntityTameEvent e) { } @Override - protected String descriptionLine(PlayerAccount acc, Source source) { + protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_TAME.format(getMobsLeft(acc)); } - public static StageTame deserialize(ConfigurationSection section, QuestBranch branch) { + public static StageTame deserialize(ConfigurationSection section, StageController controller) { String type = section.getString("entityType"); return new StageTame(branch, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); } @@ -49,7 +49,7 @@ protected boolean canUseEntity(EntityType type) { } @Override - protected StageTame finishStage(QuestBranch branch) { + protected StageTame finishStage(StageController controller) { return new StageTame(branch, entity, amount); } diff --git a/core/src/main/java/fr/skytasul/quests/structure/BranchesManager.java b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java similarity index 52% rename from core/src/main/java/fr/skytasul/quests/structure/BranchesManager.java rename to core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java index 45c3ba77..d6e39dac 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/BranchesManager.java +++ b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java @@ -12,67 +12,75 @@ 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.QuestsAPI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.branches.QuestBranch; +import fr.skytasul.quests.api.quests.branches.QuestBranchesManager; -public class BranchesManager{ +public class BranchesManagerImplementation implements QuestBranchesManager { - private @NotNull Map<Integer, QuestBranch> branches = new TreeMap<>(Integer::compare); + private @NotNull Map<Integer, QuestBranchImplementation> branches = new TreeMap<>(Integer::compare); - private final @NotNull Quest quest; + private final @NotNull QuestImplementation quest; - public BranchesManager(@NotNull Quest quest) { + public BranchesManagerImplementation(@NotNull QuestImplementation quest) { this.quest = quest; } - public @NotNull Quest getQuest() { + @Override + public @NotNull QuestImplementation getQuest() { return quest; } - public int getBranchesAmount(){ - return branches.size(); - } - - public void addBranch(@NotNull QuestBranch branch) { + public void addBranch(@NotNull QuestBranchImplementation branch) { Validate.notNull(branch, "Branch cannot be null !"); branches.put(branches.size(), branch); } - public int getID(@NotNull QuestBranch branch) { - for (Entry<Integer, QuestBranch> en : branches.entrySet()){ + @Override + public int getId(@NotNull QuestBranch branch) { + for (Entry<Integer, QuestBranchImplementation> en : branches.entrySet()){ if (en.getValue() == branch) return en.getKey(); } - BeautyQuests.logger.severe("Trying to get the ID of a branch not in manager of quest " + quest.getID()); + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("Trying to get the ID of a branch not in manager of quest " + quest.getId()); return -1; } + @Override public @UnmodifiableView @NotNull Collection<@NotNull QuestBranch> getBranches() { - return branches.values(); + return (Collection) branches.values(); } - public @NotNull QuestBranch getBranch(int id) { + @Override + public @Nullable QuestBranchImplementation getBranch(int id) { return branches.get(id); } - public @Nullable QuestBranch getPlayerBranch(@NotNull PlayerAccount acc) { + @Override + public @Nullable QuestBranchImplementation getPlayerBranch(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(quest)) return null; return branches.get(acc.getQuestDatas(quest).getBranch()); } + @Override public boolean hasBranchStarted(@NotNull PlayerAccount acc, @NotNull QuestBranch branch) { if (!acc.hasQuestDatas(quest)) return false; - return acc.getQuestDatas(quest).getBranch() == branch.getID(); + return acc.getQuestDatas(quest).getBranch() == branch.getId(); } /** * Called internally when the quest is updated for the player - * @param p Player + * + * @param player Player */ - public final void objectiveUpdated(@NotNull Player p, @NotNull PlayerAccount acc) { + public final void objectiveUpdated(@NotNull Player player) { + PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (quest.hasStarted(acc)) { - QuestsAPI.propagateQuestsHandlers(x -> x.questUpdated(acc, p, quest)); + QuestsAPI.getAPI().propagateQuestsHandlers(x -> x.questUpdated(acc, quest)); } } @@ -85,12 +93,12 @@ public void startPlayer(@NotNull PlayerAccount acc) { public void remove(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(quest)) return; - QuestBranch branch = getPlayerBranch(acc); + QuestBranchImplementation branch = getPlayerBranch(acc); if (branch != null) branch.remove(acc, true); } public void remove(){ - for (QuestBranch branch : branches.values()){ + for (QuestBranchImplementation branch : branches.values()){ branch.remove(); } branches.clear(); @@ -102,8 +110,9 @@ public void save(@NotNull ConfigurationSection section) { try { branch.save(branchesSection.createSection(Integer.toString(id))); }catch (Exception ex) { - BeautyQuests.logger.severe("Error when serializing the branch " + id + " for the quest " + quest.getID(), ex); - BeautyQuests.savingFailure = true; + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("Error when serializing the branch " + id + " for the quest " + quest.getId(), ex); + QuestsPlugin.getPlugin().noticeSavingFailure(); } }); } @@ -113,8 +122,8 @@ public String toString() { return "BranchesManager{branches=" + branches.size() + "}"; } - public static @NotNull BranchesManager deserialize(@NotNull ConfigurationSection section, @NotNull Quest qu) { - BranchesManager bm = new BranchesManager(qu); + public static @NotNull BranchesManagerImplementation deserialize(@NotNull ConfigurationSection section, @NotNull QuestImplementation qu) { + BranchesManagerImplementation bm = new BranchesManagerImplementation(qu); ConfigurationSection branchesSection; if (section.isList("branches")) { // migration on 0.19.3: TODO remove @@ -139,30 +148,33 @@ public String toString() { // it is needed to first add all branches to branches manager // in order for branching stages to be able to access all branches // during QuestBranch#load, no matter in which order those branches are loaded - Map<QuestBranch, ConfigurationSection> tmpBranches = new HashMap<>(); + Map<QuestBranchImplementation, ConfigurationSection> tmpBranches = new HashMap<>(); for (String key : branchesSection.getKeys(false)) { try { int id = Integer.parseInt(key); - QuestBranch branch = new QuestBranch(bm); + QuestBranchImplementation branch = new QuestBranchImplementation(bm); bm.branches.put(id, branch); tmpBranches.put(branch, branchesSection.getConfigurationSection(key)); }catch (NumberFormatException ex) { - BeautyQuests.logger.severe("Cannot parse branch ID " + key + " for quest " + qu.getID()); - BeautyQuests.loadingFailure = true; + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("Cannot parse branch ID " + key + " for quest " + qu.getId()); + QuestsPlugin.getPlugin().notifyLoadingFailure(); return null; } } - for (QuestBranch branch : tmpBranches.keySet()) { + for (QuestBranchImplementation branch : tmpBranches.keySet()) { try { if (!branch.load(tmpBranches.get(branch))) { - BeautyQuests.getInstance().getLogger().severe("Error when deserializing the branch " + branch.getID() + " for the quest " + qu.getID() + " (false return)"); - BeautyQuests.loadingFailure = true; + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when deserializing the branch " + + branch.getId() + " for the quest " + qu.getId() + " (false return)"); + QuestsPlugin.getPlugin().notifyLoadingFailure(); return null; } }catch (Exception ex) { - BeautyQuests.logger.severe("Error when deserializing the branch " + branch.getID() + " for the quest " + qu.getID(), ex); - BeautyQuests.loadingFailure = true; + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "Error when deserializing the branch " + branch.getId() + " for the quest " + qu.getId(), ex); + QuestsPlugin.getPlugin().notifyLoadingFailure(); return null; } } diff --git a/core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java new file mode 100644 index 00000000..4f9ec058 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java @@ -0,0 +1,29 @@ +package fr.skytasul.quests.structure; + +import java.util.Objects; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.quests.branches.EndingStage; + +public class EndingStageImplementation implements EndingStage { + + private final @NotNull StageControllerImplementation<?> stage; + private final @Nullable QuestBranchImplementation branch; + + public EndingStageImplementation(@NotNull StageControllerImplementation<?> stage, + @Nullable QuestBranchImplementation branch) { + this.stage = Objects.requireNonNull(stage); + this.branch = Objects.requireNonNull(branch); + } + + @Override + public @NotNull StageControllerImplementation<?> getStage() { + return stage; + } + + @Override + public @Nullable QuestBranchImplementation getBranch() { + return branch; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java deleted file mode 100644 index 4332770a..00000000 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranch.java +++ /dev/null @@ -1,395 +0,0 @@ -package fr.skytasul.quests.structure; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.api.events.PlayerSetStageEvent; -import fr.skytasul.quests.api.requirements.Actionnable; -import fr.skytasul.quests.api.rewards.InterruptingBranchException; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.players.AdminMode; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; - -public class QuestBranch { - - private LinkedHashMap<AbstractStage, QuestBranch> endStages = new LinkedHashMap<>(); - // TODO change this LinkedHashMap to a better option using a list - - private LinkedList<AbstractStage> regularStages = new LinkedList<>(); - - private List<PlayerAccount> asyncReward = new ArrayList<>(5); - - private final @NotNull BranchesManager manager; - - public QuestBranch(@NotNull BranchesManager manager) { - this.manager = manager; - } - - public @NotNull Quest getQuest() { - return manager.getQuest(); - } - - public @NotNull BranchesManager getBranchesManager() { - return manager; - } - - public int getStageSize(){ - return regularStages.size(); - } - - public int getID(){ - return manager.getID(this); - } - - public void addRegularStage(@NotNull AbstractStage stage) { - Validate.notNull(stage, "Stage cannot be null !"); - regularStages.add(stage); - stage.load(); - } - - public void addEndStage(@NotNull AbstractStage stage, @NotNull QuestBranch linked) { - Validate.notNull(stage, "Stage cannot be null !"); - endStages.put(stage, linked); - stage.load(); - } - - public int getID(@NotNull AbstractStage stage) { - return regularStages.indexOf(stage); - } - - public @NotNull List<@NotNull AbstractStage> getRegularStages() { - return regularStages; - } - - public @NotNull AbstractStage getRegularStage(int id) { - return regularStages.get(id); - } - - public boolean isRegularStage(@NotNull AbstractStage stage) { - return regularStages.contains(stage); - } - - public @NotNull LinkedHashMap<AbstractStage, QuestBranch> getEndingStages() { - return endStages; - } - - public @Nullable AbstractStage getEndingStage(int id) { - int i = 0; - for (AbstractStage stage : endStages.keySet()) { - if (i++ == id) return stage; - } - return null; - } - - public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { - PlayerQuestDatas datas; - if (!acc.hasQuestDatas(getQuest()) || (datas = acc.getQuestDatas(getQuest())).getBranch() != getID()) throw new IllegalArgumentException("Account does not have this branch launched"); - if (asyncReward.contains(acc)) return Lang.SCOREBOARD_ASYNC_END.toString(); - if (datas.isInEndingStages()) { - StringBuilder stb = new StringBuilder(); - int i = 0; - for (AbstractStage stage : endStages.keySet()) { - i++; - stb.append(stage.getDescriptionLine(acc, source)); - if (i != endStages.size()){ - stb.append("{nl}"); - stb.append(Lang.SCOREBOARD_BETWEEN_BRANCHES.toString()); - stb.append("{nl}"); - } - } - return stb.toString(); - } - if (datas.getStage() < 0) return "§cerror: no stage set for branch " + getID(); - if (datas.getStage() >= regularStages.size()) return "§cerror: datas do not match"; - return Utils.format(QuestsConfiguration.getStageDescriptionFormat(), datas.getStage() + 1, regularStages.size(), regularStages.get(datas.getStage()).getDescriptionLine(acc, source)); - } - - /** - * Where do the description request come from - */ - public enum Source { - SCOREBOARD, MENU, PLACEHOLDER, FORCESPLIT, FORCELINE; - } - - public boolean hasStageLaunched(@Nullable PlayerAccount acc, @NotNull AbstractStage stage) { - if (acc == null) return false; - if (asyncReward.contains(acc)) return false; - if (!acc.hasQuestDatas(getQuest())) return false; - PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); - if (datas.getBranch() != getID()) return false; - if (!datas.isInEndingStages()) return stage.getID() == datas.getStage(); - return (endStages.keySet().contains(stage)); - } - - public void remove(@NotNull PlayerAccount acc, boolean end) { - if (!acc.hasQuestDatas(getQuest())) return; - PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); - if (end) { - if (datas.isInEndingStages()) { - endStages.keySet().forEach((x) -> x.end(acc)); - }else if (datas.getStage() >= 0 && datas.getStage() < regularStages.size()) getRegularStage(datas.getStage()).end(acc); - } - datas.setBranch(-1); - datas.setStage(-1); - } - - public void start(@NotNull PlayerAccount acc) { - acc.getQuestDatas(getQuest()).setBranch(getID()); - if (!regularStages.isEmpty()){ - setStage(acc, 0); - }else { - setEndingStages(acc, true); - } - } - - public void finishStage(@NotNull Player p, @NotNull AbstractStage stage) { - DebugUtils.logMessage("Next stage for player " + p.getName() + " (coming from " + stage.toString() + ") via " + DebugUtils.stackTraces(1, 3)); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); - if (datas.getBranch() != getID() || (datas.isInEndingStages() && isRegularStage(stage)) || (!datas.isInEndingStages() && datas.getStage() != stage.getID())) { - BeautyQuests.logger.warning("Trying to finish stage " + stage.toString() + " for player " + p.getName() + ", but the player didn't have started it."); - return; - } - AdminMode.broadcast("Player " + p.getName() + " has finished the stage " + getID(stage) + " of quest " + getQuest().getID()); - datas.addQuestFlow(stage); - if (!isRegularStage(stage)){ // ending stage - for (AbstractStage end : endStages.keySet()){ - if (end != stage) end.end(acc); - } - } - datas.setStage(-1); - endStage(acc, stage, () -> { - if (!manager.getQuest().hasStarted(acc)) return; - if (regularStages.contains(stage)){ // not ending stage - continue the branch or finish the quest - int newId = stage.getID() + 1; - if (newId == regularStages.size()){ - if (endStages.isEmpty()){ - remove(acc, false); - getQuest().finish(p); - return; - } - setEndingStages(acc, true); - }else { - setStage(acc, newId); - } - }else { // ending stage - redirect to other branch - remove(acc, false); - QuestBranch branch = endStages.get(stage); - if (branch == null){ - getQuest().finish(p); - return; - } - branch.start(acc); - } - manager.objectiveUpdated(p, acc); - }); - } - - private void endStage(@NotNull PlayerAccount acc, @NotNull AbstractStage stage, @NotNull Runnable runAfter) { - if (acc.isCurrent()){ - Player p = acc.getPlayer(); - stage.end(acc); - stage.getValidationRequirements().stream().filter(Actionnable.class::isInstance).map(Actionnable.class::cast).forEach(x -> x.trigger(p)); - if (stage.hasAsyncEnd()){ - new Thread(() -> { - DebugUtils.logMessage("Using " + Thread.currentThread().getName() + " as the thread for async rewards."); - asyncReward.add(acc); - try { - List<String> given = Utils.giveRewards(p, stage.getRewards()); - if (!given.isEmpty() && QuestsConfiguration.hasStageEndRewardsMessage()) Lang.FINISHED_OBTAIN.send(p, Utils.itemsToFormattedString(given.toArray(new String[0]))); - } catch (InterruptingBranchException ex) { - DebugUtils.logMessage( - "Interrupted branching in async stage end for " + p.getName() + " via " + ex.toString()); - return; - }catch (Exception e) { - Lang.ERROR_OCCURED.send(p, "giving async rewards"); - BeautyQuests.logger.severe("An error occurred while giving stage async end rewards.", e); - } finally { - // by using the try-catch, we ensure that "asyncReward#remove" is called - // otherwise, the player would be completely stuck - asyncReward.remove(acc); - } - Utils.runSync(runAfter); - }, "BQ async stage end " + p.getName()).start(); - }else{ - try { - List<String> given = Utils.giveRewards(p, stage.getRewards()); - if (!given.isEmpty() && QuestsConfiguration.hasStageEndRewardsMessage()) - Lang.FINISHED_OBTAIN.send(p, Utils.itemsToFormattedString(given.toArray(new String[0]))); - runAfter.run(); - } catch (InterruptingBranchException ex) { - DebugUtils.logMessage( - "Interrupted branching in async stage end for " + p.getName() + " via " + ex.toString()); - } - } - }else { - stage.end(acc); - runAfter.run(); - } - } - - public void setStage(@NotNull PlayerAccount acc, int id) { - AbstractStage stage = regularStages.get(id); - Player p = acc.getPlayer(); - if (stage == null){ - if (p != null) Lang.ERROR_OCCURED.send(p, " noStage"); - BeautyQuests.getInstance().getLogger().severe("Error into the StageManager of quest " + getQuest().getName() + " : the stage " + id + " doesn't exists."); - remove(acc, true); - }else { - PlayerQuestDatas questDatas = acc.getQuestDatas(getQuest()); - if (QuestsConfiguration.sendQuestUpdateMessage() && p != null && questDatas.getStage() != -1) Utils.sendMessage(p, Lang.QUEST_UPDATED.toString(), getQuest().getName()); - questDatas.setStage(id); - if (p != null) playNextStage(p); - stage.start(acc); - Bukkit.getPluginManager().callEvent(new PlayerSetStageEvent(acc, getQuest(), stage)); - } - } - - public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { - Player p = acc.getPlayer(); - if (QuestsConfiguration.sendQuestUpdateMessage() && p != null && launchStage) Utils.sendMessage(p, Lang.QUEST_UPDATED.toString(), getQuest().getName()); - PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); - datas.setInEndingStages(); - for (AbstractStage newStage : endStages.keySet()){ - newStage.start(acc); - Bukkit.getPluginManager().callEvent(new PlayerSetStageEvent(acc, getQuest(), newStage)); - } - if (p != null && launchStage) playNextStage(p); - } - - private void playNextStage(@NotNull Player p) { - Utils.playPluginSound(p.getLocation(), QuestsConfiguration.getNextStageSound(), 0.5F); - if (QuestsConfiguration.showNextParticles()) QuestsConfiguration.getParticleNext().send(p, Arrays.asList(p)); - } - - public void remove(){ - regularStages.forEach(AbstractStage::unload); - regularStages.clear(); - endStages.keySet().forEach(AbstractStage::unload); - endStages.clear(); - } - - public void save(@NotNull ConfigurationSection section) { - ConfigurationSection stagesSection = section.createSection("stages"); - int id = 0; - for (AbstractStage stage : regularStages) { - try { - stage.save(stagesSection.createSection(Integer.toString(id++))); - }catch (Exception ex) { - BeautyQuests.logger.severe("Error when serializing the stage " + stage.getID() + " for the quest " + getQuest().getID(), ex); - BeautyQuests.savingFailure = true; - } - } - - int i = 0; - ConfigurationSection endSection = section.createSection("endingStages"); - for (Entry<AbstractStage, QuestBranch> en : endStages.entrySet()){ - try{ - ConfigurationSection stageSection = endSection.createSection(Integer.toString(i++)); - en.getKey().save(stageSection); - QuestBranch branchLinked = en.getValue(); - if (branchLinked != null) stageSection.set("branchLinked", branchLinked.getID()); - }catch (Exception ex){ - BeautyQuests.logger.severe("Error when serializing the ending stage " + en.getKey().getID() + " for the quest " + getQuest().getID(), ex); - BeautyQuests.savingFailure = true; - } - } - } - - @Override - public String toString() { - return "QuestBranch{regularStages=" + regularStages.size() + ",endingStages=" + endStages.size() + "}"; - } - - public boolean load(@NotNull ConfigurationSection section) { - ConfigurationSection stagesSection; - if (section.isList("stages")) { // migration on 0.19.3: TODO remove - List<Map<?, ?>> stages = section.getMapList("stages"); - section.set("stages", null); - stagesSection = section.createSection("stages"); - stages.stream() - .sorted((x, y) -> { - int xid = (Integer) x.get("order"); - int yid = (Integer) y.get("order"); - if (xid < yid) return -1; - if (xid > yid) return 1; - throw new IllegalArgumentException("Two stages with same order " + xid); - }).forEach(branch -> { - int order = (Integer) branch.remove("order"); - stagesSection.createSection(Integer.toString(order), branch); - }); - }else { - stagesSection = section.getConfigurationSection("stages"); - } - - for (int id : stagesSection.getKeys(false).stream().map(Integer::parseInt).sorted().collect(Collectors.toSet())) { - try{ - AbstractStage st = AbstractStage.deserialize(stagesSection.getConfigurationSection(Integer.toString(id)), this); - if (st == null){ - BeautyQuests.getInstance().getLogger().severe("Error when deserializing the stage " + id + " for the quest " + manager.getQuest().getID() + " (stage null)"); - BeautyQuests.loadingFailure = true; - return false; - } - addRegularStage(st); - }catch (Exception ex){ - BeautyQuests.logger.severe("Error when deserializing the stage " + id + " for the quest " + manager.getQuest().getID(), ex); - BeautyQuests.loadingFailure = true; - return false; - } - } - - ConfigurationSection endingStagesSection = null; - if (section.isList("endingStages")) { // migration on 0.19.3: TODO remove - List<Map<?, ?>> endingStages = section.getMapList("endingStages"); - section.set("endingStages", null); - endingStagesSection = section.createSection("endingStages"); - int i = 0; - for (Map<?, ?> stage : endingStages) { - endingStagesSection.createSection(Integer.toString(i++), stage); - } - }else if (section.contains("endingStages")) { - endingStagesSection = section.getConfigurationSection("endingStages"); - } - - if (endingStagesSection != null) { - for (String key : endingStagesSection.getKeys(false)) { - try{ - ConfigurationSection stage = endingStagesSection.getConfigurationSection(key); - AbstractStage st = AbstractStage.deserialize(stage, this); - if (st == null){ - BeautyQuests.getInstance().getLogger().severe("Error when deserializing an ending stage for the quest " + manager.getQuest().getID() + " (stage null)"); - BeautyQuests.loadingFailure = true; - return false; - } - QuestBranch branchLinked = stage.contains("branchLinked") ? manager.getBranch(stage.getInt("branchLinked")) : null; - addEndStage(st, branchLinked); - }catch (Exception ex){ - BeautyQuests.logger.severe("Error when deserializing an ending stage for the quest " + manager.getQuest().getID(), ex); - BeautyQuests.loadingFailure = true; - return false; - } - } - } - - return true; - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java new file mode 100644 index 00000000..b04b133e --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -0,0 +1,422 @@ +package fr.skytasul.quests.structure; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +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.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.events.PlayerSetStageEvent; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.branches.EndingStage; +import fr.skytasul.quests.api.quests.branches.QuestBranch; +import fr.skytasul.quests.api.requirements.Actionnable; +import fr.skytasul.quests.api.rewards.InterruptingBranchException; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.players.AdminMode; +import fr.skytasul.quests.utils.DebugUtils; +import fr.skytasul.quests.utils.QuestUtils; + +public class QuestBranchImplementation implements QuestBranch { + + private final List<EndingStageImplementation> endStages = new ArrayList<>(5); + private final List<StageControllerImplementation> regularStages = new ArrayList<>(15); + + private final List<PlayerAccount> asyncReward = new ArrayList<>(5); + + private final @NotNull BranchesManagerImplementation manager; + + public QuestBranchImplementation(@NotNull BranchesManagerImplementation manager) { + this.manager = manager; + } + + @Override + public @NotNull QuestImplementation getQuest() { + return manager.getQuest(); + } + + @Override + public @NotNull BranchesManagerImplementation getManager() { + return manager; + } + + public int getStageSize(){ + return regularStages.size(); + } + + @Override + public int getId() { + return manager.getId(this); + } + + public void addRegularStage(@NotNull StageControllerImplementation<?> stage) { + Validate.notNull(stage, "Stage cannot be null !"); + regularStages.add(stage); + stage.load(); + } + + public void addEndStage(@NotNull StageControllerImplementation<?> stage, @NotNull QuestBranchImplementation linked) { + Validate.notNull(stage, "Stage cannot be null !"); + endStages.add(new EndingStageImplementation(stage, linked)); + stage.load(); + } + + @Override + public @NotNull @UnmodifiableView List<@NotNull StageController> getRegularStages() { + return (List) regularStages; + } + + @Override + public @NotNull StageControllerImplementation<?> getRegularStage(int id) { + return regularStages.get(id); + } + + @Override + public @NotNull @UnmodifiableView List<EndingStage> getEndingStages() { + return (List) endStages; + } + + @Override + public @NotNull StageController getEndingStage(int id) { + return endStages.get(id).getStage(); // TODO beware index out of bounds + } + + public @Nullable QuestBranchImplementation getLinkedBranch(@NotNull StageController endingStage) { + return endStages.stream().filter(end -> end.getStage().equals(endingStage)).findAny().get().getBranch(); + } + + public int getRegularStageId(StageController stage) { + return regularStages.indexOf(stage); + } + + public int getEndingStageId(StageController stage) { + for (int i = 0; i < endStages.size(); i++) { + EndingStage endingStage = endStages.get(i); + if (endingStage.getStage().equals(stage)) + return i; + } + return -1; + } + + public boolean isEndingStage(StageController stage) { + return endStages.stream().anyMatch(end -> end.getStage().equals(stage)); + } + + @Override + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { + PlayerQuestDatas datas; + if (!acc.hasQuestDatas(getQuest()) || (datas = acc.getQuestDatas(getQuest())).getBranch() != getId()) + throw new IllegalArgumentException("Account does not have this branch launched"); + if (asyncReward.contains(acc)) return Lang.SCOREBOARD_ASYNC_END.toString(); + if (datas.isInEndingStages()) { + StringBuilder stb = new StringBuilder(); + int i = 0; + for (EndingStage ending : endStages) { + i++; + stb.append(ending.getStage().getDescriptionLine(acc, source)); + if (i != endStages.size()){ + stb.append("{nl}"); + stb.append(Lang.SCOREBOARD_BETWEEN_BRANCHES.toString()); + stb.append("{nl}"); + } + } + return stb.toString(); + } + if (datas.getStage() < 0) + return "§cerror: no stage set for branch " + getId(); + if (datas.getStage() >= regularStages.size()) return "§cerror: datas do not match"; + return MessageUtils.format(QuestsConfiguration.getStageDescriptionFormat(), datas.getStage() + 1, + regularStages.size(), regularStages.get(datas.getStage()).getDescriptionLine(acc, source)); + } + + @Override + public boolean hasStageLaunched(@Nullable PlayerAccount acc, @NotNull StageController stage) { + if (acc == null) + return false; + + if (asyncReward.contains(acc)) + return false; + if (!acc.hasQuestDatas(getQuest())) + return false; + + PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); + if (datas.getBranch() != getId()) + return false; + + if (datas.isInEndingStages()) + return isEndingStage(stage); + + return getRegularStageId(stage) == datas.getStage(); + } + + public void remove(@NotNull PlayerAccount acc, boolean end) { + if (!acc.hasQuestDatas(getQuest())) return; + PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); + if (end) { + if (datas.isInEndingStages()) { + endStages.forEach(x -> x.getStage().end(acc)); + } else if (datas.getStage() >= 0 && datas.getStage() < regularStages.size()) + getRegularStage(datas.getStage()).end(acc); + } + datas.setBranch(-1); + datas.setStage(-1); + } + + public void start(@NotNull PlayerAccount acc) { + acc.getQuestDatas(getQuest()).setBranch(getId()); + if (!regularStages.isEmpty()){ + setStage(acc, 0); + }else { + setEndingStages(acc, true); + } + } + + public void finishStage(@NotNull Player p, @NotNull StageControllerImplementation<?> stage) { + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Next stage for player " + p.getName() + " (coming from " + stage.toString() + ") via " + DebugUtils.stackTraces(1, 3)); + PlayerAccount acc = PlayersManager.getPlayerAccount(p); + @NotNull + PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); + if (datas.getBranch() != getId() || (datas.isInEndingStages() && !isEndingStage(stage)) + || (!datas.isInEndingStages() && datas.getStage() != getRegularStageId(stage))) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to finish stage " + stage.toString() + " for player " + p.getName() + ", but the player didn't have started it."); + return; + } + + AdminMode.broadcast("Player " + p.getName() + " has finished the stage " + stage.getFlowId() + " of quest " + + getQuest().getId()); + datas.addQuestFlow(stage); + if (isEndingStage(stage)) { // ending stage + for (EndingStageImplementation end : endStages) { + if (end.getStage() != stage) + end.getStage().end(acc); + } + } + datas.setStage(-1); + endStage(acc, stage, () -> { + if (!manager.getQuest().hasStarted(acc)) return; + if (regularStages.contains(stage)){ // not ending stage - continue the branch or finish the quest + int newId = getRegularStageId(stage) + 1; + if (newId == regularStages.size()){ + if (endStages.isEmpty()){ + remove(acc, false); + getQuest().finish(p); + return; + } + setEndingStages(acc, true); + }else { + setStage(acc, newId); + } + }else { // ending stage - redirect to other branch + remove(acc, false); + QuestBranchImplementation branch = getLinkedBranch(stage); + if (branch == null){ + getQuest().finish(p); + return; + } + branch.start(acc); + } + manager.objectiveUpdated(p); + }); + } + + private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplementation<?> stage, + @NotNull Runnable runAfter) { + if (acc.isCurrent()){ + Player p = acc.getPlayer(); + stage.end(acc); + stage.getStage().getValidationRequirements().stream().filter(Actionnable.class::isInstance) + .map(Actionnable.class::cast).forEach(x -> x.trigger(p)); + if (stage.getStage().hasAsyncEnd()) { + new Thread(() -> { + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Using " + Thread.currentThread().getName() + " as the thread for async rewards."); + asyncReward.add(acc); + try { + List<String> given = QuestUtils.giveRewards(p, stage.getStage().getRewards()); + if (!given.isEmpty() && QuestsConfiguration.hasStageEndRewardsMessage()) + Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); + } catch (InterruptingBranchException ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().debug( + "Interrupted branching in async stage end for " + p.getName() + " via " + ex.toString()); + return; + }catch (Exception e) { + Lang.ERROR_OCCURED.send(p, "giving async rewards"); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while giving stage async end rewards.", e); + } finally { + // by using the try-catch, we ensure that "asyncReward#remove" is called + // otherwise, the player would be completely stuck + asyncReward.remove(acc); + } + QuestUtils.runSync(runAfter); + }, "BQ async stage end " + p.getName()).start(); + }else{ + try { + List<String> given = QuestUtils.giveRewards(p, stage.getStage().getRewards()); + if (!given.isEmpty() && QuestsConfiguration.hasStageEndRewardsMessage()) + Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); + runAfter.run(); + } catch (InterruptingBranchException ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().debug( + "Interrupted branching in async stage end for " + p.getName() + " via " + ex.toString()); + } + } + }else { + stage.end(acc); + runAfter.run(); + } + } + + public void setStage(@NotNull PlayerAccount acc, int id) { + StageControllerImplementation<?> stage = regularStages.get(id); + Player p = acc.getPlayer(); + if (stage == null){ + if (p != null) Lang.ERROR_OCCURED.send(p, " noStage"); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error into the StageManager of quest " + getQuest().getName() + " : the stage " + id + " doesn't exists."); + remove(acc, true); + }else { + PlayerQuestDatas questDatas = acc.getQuestDatas(getQuest()); + if (QuestsConfiguration.sendQuestUpdateMessage() && p != null && questDatas.getStage() != -1) + Lang.QUEST_UPDATED.send(p, getQuest().getName()); + questDatas.setStage(id); + if (p != null) playNextStage(p); + stage.start(acc); + Bukkit.getPluginManager().callEvent(new PlayerSetStageEvent(acc, getQuest(), stage)); + } + } + + public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { + Player p = acc.getPlayer(); + if (QuestsConfiguration.sendQuestUpdateMessage() && p != null && launchStage) + Lang.QUEST_UPDATED.send(p, getQuest().getName()); + PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); + datas.setInEndingStages(); + for (EndingStageImplementation endStage : endStages) { + endStage.getStage().start(acc); + Bukkit.getPluginManager().callEvent(new PlayerSetStageEvent(acc, getQuest(), endStage.getStage())); + } + if (p != null && launchStage) playNextStage(p); + } + + private void playNextStage(@NotNull Player p) { + QuestUtils.playPluginSound(p.getLocation(), QuestsConfiguration.getNextStageSound(), 0.5F); + if (QuestsConfiguration.showNextParticles()) QuestsConfiguration.getParticleNext().send(p, Arrays.asList(p)); + } + + public void remove(){ + regularStages.forEach(StageControllerImplementation::unload); + regularStages.clear(); + endStages.forEach(end -> end.getStage().unload()); + endStages.clear(); + } + + public void save(@NotNull ConfigurationSection section) { + ConfigurationSection stagesSection = section.createSection("stages"); + for (int i = 0; i < regularStages.size(); i++) { + try { + regularStages.get(i).getStage().save(stagesSection.createSection(Integer.toString(i))); + }catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("Error when serializing the stage " + i + " for the quest " + getQuest().getId(), ex); + QuestsPlugin.getPlugin().noticeSavingFailure(); + } + } + + ConfigurationSection endSection = section.createSection("endingStages"); + for (int i = 0; i < endStages.size(); i++) { + EndingStageImplementation en = endStages.get(i); + try{ + ConfigurationSection stageSection = endSection.createSection(Integer.toString(i)); + en.getStage().getStage().save(stageSection); + QuestBranchImplementation branchLinked = en.getBranch(); + if (branchLinked != null) + stageSection.set("branchLinked", branchLinked.getId()); + }catch (Exception ex){ + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("Error when serializing the ending stage " + i + " for the quest " + getQuest().getId(), ex); + QuestsPlugin.getPlugin().noticeSavingFailure(); + } + } + } + + @Override + public String toString() { + return "QuestBranch{regularStages=" + regularStages.size() + ",endingStages=" + endStages.size() + "}"; + } + + public boolean load(@NotNull ConfigurationSection section) { + ConfigurationSection stagesSection; + if (section.isList("stages")) { // migration on 0.19.3: TODO remove + List<Map<?, ?>> stages = section.getMapList("stages"); + section.set("stages", null); + stagesSection = section.createSection("stages"); + stages.stream() + .sorted((x, y) -> { + int xid = (Integer) x.get("order"); + int yid = (Integer) y.get("order"); + if (xid < yid) return -1; + if (xid > yid) return 1; + throw new IllegalArgumentException("Two stages with same order " + xid); + }).forEach(branch -> { + int order = (Integer) branch.remove("order"); + stagesSection.createSection(Integer.toString(order), branch); + }); + }else { + stagesSection = section.getConfigurationSection("stages"); + } + + for (int id : stagesSection.getKeys(false).stream().map(Integer::parseInt).sorted().collect(Collectors.toSet())) { + try{ + addRegularStage(StageControllerImplementation.loadFromConfig(this, + stagesSection.getConfigurationSection(Integer.toString(id)))); + }catch (Exception ex){ + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "Error when deserializing the stage " + id + " for the quest " + manager.getQuest().getId(), ex); + QuestsPlugin.getPlugin().notifyLoadingFailure(); + return false; + } + } + + ConfigurationSection endingStagesSection = null; + if (section.isList("endingStages")) { // migration on 0.19.3: TODO remove + List<Map<?, ?>> endingStages = section.getMapList("endingStages"); + section.set("endingStages", null); + endingStagesSection = section.createSection("endingStages"); + int i = 0; + for (Map<?, ?> stage : endingStages) { + endingStagesSection.createSection(Integer.toString(i++), stage); + } + }else if (section.contains("endingStages")) { + endingStagesSection = section.getConfigurationSection("endingStages"); + } + + if (endingStagesSection != null) { + for (String key : endingStagesSection.getKeys(false)) { + try{ + ConfigurationSection stage = endingStagesSection.getConfigurationSection(key); + QuestBranchImplementation branchLinked = stage.contains("branchLinked") ? manager.getBranch(stage.getInt("branchLinked")) : null; + addEndStage(StageControllerImplementation.loadFromConfig(this, stage), branchLinked); + }catch (Exception ex){ + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "Error when deserializing an ending stage for the quest " + manager.getQuest().getId(), ex); + QuestsPlugin.getPlugin().notifyLoadingFailure(); + return false; + } + } + } + + return true; + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/structure/Quest.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java similarity index 67% rename from core/src/main/java/fr/skytasul/quests/structure/Quest.java rename to core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index f5f03f33..41514534 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/Quest.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -1,6 +1,7 @@ package fr.skytasul.quests.structure; import java.io.File; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -23,40 +24,41 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.PlayerQuestResetEvent; import fr.skytasul.quests.api.events.QuestFinishEvent; import fr.skytasul.quests.api.events.QuestLaunchEvent; import fr.skytasul.quests.api.events.QuestPreLaunchEvent; import fr.skytasul.quests.api.events.QuestRemoveEvent; -import fr.skytasul.quests.api.options.OptionSet; +import fr.skytasul.quests.api.gui.templates.ConfirmGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.QuestOptionCreator; +import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.Actionnable; import fr.skytasul.quests.api.rewards.InterruptingBranchException; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.misc.ConfirmGUI; -import fr.skytasul.quests.gui.quests.PlayerListGUI.Category; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.options.*; -import fr.skytasul.quests.options.OptionVisibility.VisibilityLocation; import fr.skytasul.quests.players.AdminMode; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.players.PlayersManager; import fr.skytasul.quests.rewards.MessageReward; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.utils.QuestUtils; -public class Quest implements Comparable<Quest>, OptionSet, QuestDescriptionProvider { +public class QuestImplementation implements Quest, QuestDescriptionProvider { private static final Pattern PERMISSION_PATTERN = Pattern.compile("^beautyquests\\.start\\.(\\d+)$"); private final int id; private final File file; - private BranchesManager manager; + private BranchesManagerImplementation manager; private List<QuestOption<?>> options = new ArrayList<>(); private List<QuestDescriptionProvider> descriptions = new ArrayList<>(); @@ -65,21 +67,27 @@ public class Quest implements Comparable<Quest>, OptionSet, QuestDescriptionProv public boolean asyncEnd = false; public List<Player> asyncStart = null; - public Quest(int id) { + public QuestImplementation(int id) { this(id, new File(BeautyQuests.getInstance().getQuestsManager().getSaveFolder(), id + ".yml")); } - public Quest(int id, @NotNull File file) { + public QuestImplementation(int id, @NotNull File file) { this.id = id; this.file = file; - this.manager = new BranchesManager(this); + this.manager = new BranchesManagerImplementation(this); this.descriptions.add(this); } public void load() { - QuestsAPI.propagateQuestsHandlers(handler -> handler.questLoaded(this)); + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questLoaded(this)); } + @Override + public boolean isValid() { + return !removed; + } + + @Override public @NotNull List<QuestDescriptionProvider> getDescriptions() { return descriptions; } @@ -89,13 +97,6 @@ public Iterator<QuestOption> iterator() { return (Iterator) options.iterator(); } - public @Nullable <D> D getOptionValueOrDef(@NotNull Class<? extends QuestOption<D>> clazz) { - for (QuestOption<?> option : options) { - if (clazz.isInstance(option)) return (D) option.getValue(); - } - return (D) QuestOptionCreator.creators.get(clazz).defaultValue; - } - @Override public @NotNull <T extends QuestOption<?>> T getOption(@NotNull Class<T> clazz) { for (QuestOption<?> option : options) { @@ -112,6 +113,7 @@ public boolean hasOption(@NotNull Class<? extends QuestOption<?>> clazz) { return false; } + @Override public void addOption(@NotNull QuestOption<?> option) { if (!option.hasCustomValue()) return; options.add(option); @@ -124,6 +126,7 @@ public void addOption(@NotNull QuestOption<?> option) { }); } + @Override public void removeOption(@NotNull Class<? extends QuestOption<?>> clazz) { for (Iterator<QuestOption<?>> iterator = options.iterator(); iterator.hasNext();) { QuestOption<?> option = iterator.next(); @@ -139,7 +142,8 @@ public boolean isRemoved(){ return removed; } - public int getID(){ + @Override + public int getId() { return id; } @@ -147,43 +151,53 @@ public File getFile(){ return file; } + @Override public @Nullable String getName() { return getOptionValueOrDef(OptionName.class); } + @Override public @Nullable String getDescription() { return getOptionValueOrDef(OptionDescription.class); } + @Override public @NotNull ItemStack getQuestItem() { return getOptionValueOrDef(OptionQuestItem.class); } + @Override public boolean isScoreboardEnabled() { return getOptionValueOrDef(OptionScoreboardEnabled.class); } + @Override public boolean isCancellable() { return getOptionValueOrDef(OptionCancellable.class); } + @Override public boolean isRepeatable() { return getOptionValueOrDef(OptionRepeatable.class); } - public boolean isHidden(VisibilityLocation location) { + @Override + public boolean isHidden(QuestVisibilityLocation location) { return !getOptionValueOrDef(OptionVisibility.class).contains(location); } + @Override public boolean isHiddenWhenRequirementsNotMet() { return getOptionValueOrDef(OptionHideNoRequirements.class); } + @Override public boolean canBypassLimit() { return getOptionValueOrDef(OptionBypassLimit.class); } - public @NotNull BranchesManager getBranchesManager() { + @Override + public @NotNull BranchesManagerImplementation getBranchesManager() { return manager; } @@ -191,6 +205,7 @@ public boolean canBypassLimit() { return Utils.millisToHumanString(acc.getQuestDatas(this).getTimer() - System.currentTimeMillis()); } + @Override public boolean hasStarted(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(this)) return false; if (acc.getQuestDatas(this).hasStarted()) return true; @@ -198,34 +213,37 @@ public boolean hasStarted(@NotNull PlayerAccount acc) { return false; } + @Override public boolean hasFinished(@NotNull PlayerAccount acc) { return acc.hasQuestDatas(this) && acc.getQuestDatas(this).isFinished(); } + @Override public boolean cancelPlayer(@NotNull PlayerAccount acc) { PlayerQuestDatas datas = acc.getQuestDatasIfPresent(this); if (datas == null || !datas.hasStarted()) return false; - DebugUtils.logMessage("Cancelling quest " + id + " for player " + acc.getNameAndID()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Cancelling quest " + id + " for player " + acc.getNameAndID()); cancelInternal(acc); return true; } private void cancelInternal(@NotNull PlayerAccount acc) { manager.remove(acc); - QuestsAPI.propagateQuestsHandlers(handler -> handler.questReset(acc, this)); + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questReset(acc, this)); Bukkit.getPluginManager().callEvent(new PlayerQuestResetEvent(acc, this)); if (acc.isCurrent()) { try { - Utils.giveRewards(acc.getPlayer(), getOptionValueOrDef(OptionCancelRewards.class)); + QuestUtils.giveRewards(acc.getPlayer(), getOptionValueOrDef(OptionCancelRewards.class)); } catch (InterruptingBranchException ex) { - BeautyQuests.logger.warning("Trying to interrupt branching in a cancel reward (useless). " + toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to interrupt branching in a cancel reward (useless). " + toString()); } } } + @Override public @NotNull CompletableFuture<Boolean> resetPlayer(@NotNull PlayerAccount acc) { boolean hadDatas = false; CompletableFuture<?> future = null; @@ -233,7 +251,7 @@ private void cancelInternal(@NotNull PlayerAccount acc) { if (acc.hasQuestDatas(this)) { hadDatas = true; - DebugUtils.logMessage("Resetting quest " + id + " for player " + acc.getNameAndID()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Resetting quest " + id + " for player " + acc.getNameAndID()); cancelInternal(acc); future = acc.removeQuestDatas(this); } @@ -245,7 +263,9 @@ && getOption(OptionStartDialog.class).getDialogRunner().removePlayer(acc.getPlay return future == null ? CompletableFuture.completedFuture(hadDatas) : future.thenApply(__ -> true); } - public boolean isLauncheable(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { + @Override + public boolean canStart(@NotNull Player p, boolean sendMessage) { + PlayerAccount acc = PlayersManager.getPlayerAccount(p); if (hasStarted(acc)){ if (sendMessage) Lang.ALREADY_STARTED.send(p); return false; @@ -260,7 +280,7 @@ public boolean testRequirements(@NotNull Player p, @NotNull PlayerAccount acc, b if (!p.hasPermission("beautyquests.start")) return false; if (!testQuestLimit(p, acc, sendMessage)) return false; sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) || (QuestsConfiguration.isRequirementReasonSentOnMultipleQuests() || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); - return Utils.testRequirements(p, getOptionValueOrDef(OptionRequirements.class), sendMessage); + return QuestUtils.testRequirements(p, getOptionValueOrDef(OptionRequirements.class), sendMessage); } public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { @@ -279,7 +299,7 @@ public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boo if (QuestsConfiguration.getMaxLaunchedQuests() == 0) return true; playerMaxLaunchedQuest = QuestsConfiguration.getMaxLaunchedQuests(); } - if (QuestsAPI.getQuests().getStartedSize(acc) >= playerMaxLaunchedQuest) { + if (QuestsAPI.getAPI().getQuestsManager().getStartedSize(acc) >= playerMaxLaunchedQuest) { if (sendMessage) Lang.QUESTS_MAX_LAUNCHED.send(p, playerMaxLaunchedQuest); return false; @@ -315,12 +335,13 @@ public void leave(@NotNull Player p) { } } - public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { + @Override + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { if (!acc.hasQuestDatas(this)) throw new IllegalArgumentException("Account does not have quest datas for quest " + id); if (asyncStart != null && acc.isCurrent() && asyncStart.contains(acc.getPlayer())) return "§7x"; PlayerQuestDatas datas = acc.getQuestDatas(this); if (datas.isInQuestEnd()) return Lang.SCOREBOARD_ASYNC_END.toString(); - QuestBranch branch = manager.getBranch(datas.getBranch()); + QuestBranchImplementation branch = manager.getBranch(datas.getBranch()); if (branch == null) throw new IllegalStateException("Account is in branch " + datas.getBranch() + " in quest " + id + ", which does not actually exist"); return branch.getDescriptionLine(acc, source); } @@ -329,7 +350,7 @@ public void leave(@NotNull Player p) { public @NotNull List<String> provideDescription(QuestDescriptionContext context) { if (!context.getPlayerAccount().isCurrent()) return Collections.emptyList(); - if (context.getCategory() != Category.IN_PROGRESS) + if (context.getCategory() != PlayerListCategory.IN_PROGRESS) return Collections.emptyList(); return Arrays.asList(getDescriptionLine(context.getPlayerAccount(), context.getSource())); @@ -345,17 +366,20 @@ public double getDescriptionPriority() { return 15; } + @Override public @NotNull CompletableFuture<Boolean> attemptStart(@NotNull Player p) { - if (!isLauncheable(p, PlayersManager.getPlayerAccount(p), true)) + if (!canStart(p, true)) return CompletableFuture.completedFuture(false); String confirm; if (QuestsConfiguration.questConfirmGUI() && !"none".equals(confirm = getOptionValueOrDef(OptionConfirmMessage.class))) { CompletableFuture<Boolean> future = new CompletableFuture<>(); - new ConfirmGUI(() -> { + ConfirmGUI.confirm(() -> { start(p); future.complete(true); - }, () -> Inventories.closeAndExit(p), Lang.INDICATION_START.format(getName()), confirm).create(p); + }, () -> { + future.complete(false); + }, Lang.INDICATION_START.format(getName()), confirm).open(p); return future; }else { start(p); @@ -363,10 +387,12 @@ public double getDescriptionPriority() { } } + @Override public void start(@NotNull Player p) { start(p, false); } + @Override public void start(@NotNull Player p, boolean silently) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); if (hasStarted(acc)){ @@ -380,115 +406,123 @@ public void start(@NotNull Player p, boolean silently) { acc.getQuestDatas(this).setTimer(0); if (!silently) { String startMsg = getOptionValueOrDef(OptionStartMessage.class); - if (!"none".equals(startMsg)) Utils.IsendMessage(p, startMsg, true, getName()); + if (!"none".equals(startMsg)) + MessageUtils.sendRawMessage(p, startMsg, true, getName()); } Runnable run = () -> { List<String> msg = Collections.emptyList(); try { - msg = Utils.giveRewards(p, getOptionValueOrDef(OptionStartRewards.class)); + msg = QuestUtils.giveRewards(p, getOptionValueOrDef(OptionStartRewards.class)); } catch (InterruptingBranchException ex) { - BeautyQuests.logger.warning("Trying to interrupt branching in a starting reward (useless). " + toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to interrupt branching in a starting reward (useless). " + toString()); } getOptionValueOrDef(OptionRequirements.class).stream().filter(Actionnable.class::isInstance).map(Actionnable.class::cast).forEach(x -> x.trigger(p)); - if (!silently && !msg.isEmpty()) Utils.sendMessage(p, Lang.FINISHED_OBTAIN.format(Utils.itemsToFormattedString(msg.toArray(new String[0])))); + if (!silently && !msg.isEmpty()) + Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(msg.toArray(new String[0]))); if (asyncStart != null) asyncStart.remove(p); - Utils.runOrSync(() -> { + QuestUtils.runOrSync(() -> { manager.startPlayer(acc); - QuestsAPI.propagateQuestsHandlers(handler -> handler.questStart(acc, p, this)); - Bukkit.getPluginManager().callEvent(new QuestLaunchEvent(p, Quest.this)); + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questStart(acc, this)); + Bukkit.getPluginManager().callEvent(new QuestLaunchEvent(p, QuestImplementation.this)); }); }; if (asyncStart != null){ asyncStart.add(p); - Utils.runAsync(run); + QuestUtils.runAsync(run); }else run.run(); } + @Override public void finish(@NotNull Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); AdminMode.broadcast(p.getName() + " is completing the quest " + id); - PlayerQuestDatas questDatas = acc.getQuestDatas(Quest.this); + PlayerQuestDatas questDatas = acc.getQuestDatas(QuestImplementation.this); Runnable run = () -> { try { - List<String> msg = Utils.giveRewards(p, getOptionValueOrDef(OptionEndRewards.class)); - String obtained = Utils.itemsToFormattedString(msg.toArray(new String[0])); + List<String> msg = QuestUtils.giveRewards(p, getOptionValueOrDef(OptionEndRewards.class)); + String obtained = MessageUtils.itemsToFormattedString(msg.toArray(new String[0])); if (hasOption(OptionEndMessage.class)) { String endMsg = getOption(OptionEndMessage.class).getValue(); - if (!"none".equals(endMsg)) Utils.IsendMessage(p, endMsg, true, obtained); - }else Utils.sendMessage(p, Lang.FINISHED_BASE.format(getName()) + (msg.isEmpty() ? "" : " " + Lang.FINISHED_OBTAIN.format(obtained))); + if (!"none".equals(endMsg)) + MessageUtils.sendRawMessage(p, endMsg, true, obtained); + } else + MessageUtils.sendPrefixedMessage(p, Lang.FINISHED_BASE.format(getName()) + + (msg.isEmpty() ? "" : " " + Lang.FINISHED_OBTAIN.format(obtained))); }catch (Exception ex) { Lang.ERROR_OCCURED.send(p, "reward message"); - BeautyQuests.logger.severe("An error occurred while giving quest end rewards.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while giving quest end rewards.", ex); } - Utils.runOrSync(() -> { + QuestUtils.runOrSync(() -> { manager.remove(acc); questDatas.setBranch(-1); questDatas.incrementFinished(); questDatas.setStartingTime(0); - if (hasOption(OptionQuestPool.class)) getOptionValueOrDef(OptionQuestPool.class).questCompleted(acc, Quest.this); + if (hasOption(OptionQuestPool.class)) getOptionValueOrDef(OptionQuestPool.class).questCompleted(acc, QuestImplementation.this); if (isRepeatable()) { Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, Math.max(0, getOptionValueOrDef(OptionTimer.class))); questDatas.setTimer(cal.getTimeInMillis()); } - Utils.spawnFirework(p.getLocation(), getOptionValueOrDef(OptionFirework.class)); - Utils.playPluginSound(p, getOptionValueOrDef(OptionEndSound.class), 1); + QuestUtils.spawnFirework(p.getLocation(), getOptionValueOrDef(OptionFirework.class)); + QuestUtils.playPluginSound(p, getOptionValueOrDef(OptionEndSound.class), 1); - QuestsAPI.propagateQuestsHandlers(handler -> handler.questFinish(acc, p, this)); - Bukkit.getPluginManager().callEvent(new QuestFinishEvent(p, Quest.this)); + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questFinish(acc, this)); + Bukkit.getPluginManager().callEvent(new QuestFinishEvent(p, QuestImplementation.this)); }); }; if (asyncEnd) { questDatas.setInQuestEnd(); new Thread(() -> { - DebugUtils.logMessage("Using " + Thread.currentThread().getName() + " as the thread for async rewards."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Using " + Thread.currentThread().getName() + " as the thread for async rewards."); run.run(); }, "BQ async end " + p.getName()).start(); }else run.run(); } - public void remove(boolean msg, boolean removeDatas) { - QuestsAPI.getQuests().removeQuest(this); + @Override + public void delete(boolean silently, boolean keepDatas) { + BeautyQuests.getInstance().getQuestsManager().removeQuest(this); unload(); - if (removeDatas) { + if (hasOption(OptionStarterNPC.class)) + getOptionValueOrDef(OptionStarterNPC.class).removeQuest(this); + + if (!keepDatas) { BeautyQuests.getInstance().getPlayersManager().removeQuestDatas(this).whenComplete( - BeautyQuests.logger.logError("An error occurred while removing player datas after quest removal")); + QuestsPlugin.getPlugin().getLoggerExpanded().logError("An error occurred while removing player datas after quest removal")); if (file.exists()) file.delete(); } + removed = true; Bukkit.getPluginManager().callEvent(new QuestRemoveEvent(this)); - if (removeDatas) QuestsAPI.propagateQuestsHandlers(handler -> handler.questRemove(this)); - if (msg) BeautyQuests.getInstance().getLogger().info("The quest \"" + getName() + "\" has been removed"); + if (!keepDatas) + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questRemove(this)); + if (!silently) + QuestsPlugin.getPlugin().getLoggerExpanded().info("The quest \"" + getName() + "\" has been removed"); } public void unload(){ - QuestsAPI.propagateQuestsHandlers(handler -> handler.questUnload(this)); + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questUnload(this)); manager.remove(); options.forEach(QuestOption::detach); } - - @Override - public int compareTo(Quest o) { - return Integer.compare(id, o.id); - } @Override public String toString(){ return "Quest{id=" + id + ", npcID=" + ", branches=" + manager.toString() + ", name=" + getName() + "}"; } - public boolean saveToFile() throws Exception { + public boolean saveToFile() throws IOException { YamlConfiguration fc = new YamlConfiguration(); - BeautyQuests.savingFailure = false; + BeautyQuests.getInstance().resetSavingFailure(); save(fc); - if (BeautyQuests.savingFailure) { - BeautyQuests.logger.warning("An error occurred while saving quest " + id); + if (BeautyQuests.getInstance().hasSavingFailed()) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An error occurred while saving quest " + id); return false; } @@ -499,21 +533,21 @@ public boolean saveToFile() throws Exception { String questData = fc.saveToString(); String oldQuestDatas = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); if (questData.equals(oldQuestDatas)) { - DebugUtils.logMessage("Quest " + id + " was up-to-date."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Quest " + id + " was up-to-date."); return false; }else { - DebugUtils.logMessage("Saving quest " + id + " into " + path.toString()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Saving quest " + id + " into " + path.toString()); Files.write(path, questData.getBytes(StandardCharsets.UTF_8)); return true; } } - private void save(@NotNull ConfigurationSection section) throws Exception { + private void save(@NotNull ConfigurationSection section) { for (QuestOption<?> option : options) { try { if (option.hasCustomValue()) section.set(option.getOptionCreator().id, option.save()); }catch (Exception ex) { - BeautyQuests.logger.warning("An exception occured when saving an option for quest " + id, ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An exception occured when saving an option for quest " + id, ex); } } @@ -522,26 +556,26 @@ private void save(@NotNull ConfigurationSection section) throws Exception { } - public static @Nullable Quest loadFromFile(@NotNull File file) { + public static @Nullable QuestImplementation loadFromFile(@NotNull File file) { try { YamlConfiguration config = new YamlConfiguration(); config.load(file); return deserialize(file, config); }catch (Exception e) { - BeautyQuests.logger.warning("Error when loading quests from data file.", e); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Error when loading quests from data file.", e); return null; } } - private static @Nullable Quest deserialize(@NotNull File file, @NotNull ConfigurationSection map) { + private static @Nullable QuestImplementation deserialize(@NotNull File file, @NotNull ConfigurationSection map) { if (!map.contains("id")) { - BeautyQuests.getInstance().getLogger().severe("Quest doesn't have an id."); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Quest doesn't have an id."); return null; } - Quest qu = new Quest(map.getInt("id"), file); + QuestImplementation qu = new QuestImplementation(map.getInt("id"), file); - qu.manager = BranchesManager.deserialize(map.getConfigurationSection("manager"), qu); + qu.manager = BranchesManagerImplementation.deserialize(map.getConfigurationSection("manager"), qu); if (qu.manager == null) return null; for (String key : map.getKeys(false)) { @@ -552,8 +586,8 @@ private void save(@NotNull ConfigurationSection section) throws Exception { option.load(map, key); qu.addOption(option); }catch (Exception ex) { - BeautyQuests.logger.warning("An exception occured when loading the option " + key + " for quest " + qu.id, ex); - BeautyQuests.loadingFailure = true; + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An exception occured when loading the option " + key + " for quest " + qu.id, ex); + QuestsPlugin.getPlugin().notifyLoadingFailure(); } break; } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestsManager.java b/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java similarity index 64% rename from core/src/main/java/fr/skytasul/quests/structure/QuestsManager.java rename to core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java index 5b611420..6028d558 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestsManager.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java @@ -16,39 +16,43 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.QuestsManager; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.options.OptionStartable; import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.options.OptionVisibility.VisibilityLocation; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.utils.Utils; -public class QuestsManager implements Iterable<Quest> { +public class QuestsManagerImplementation implements QuestsManager { - private final List<Quest> quests = new ArrayList<>(); + private final List<QuestImplementation> quests = new ArrayList<>(); private final AtomicInteger lastID = new AtomicInteger(); private final BeautyQuests plugin; private final File saveFolder; - public QuestsManager(BeautyQuests plugin, int lastID, File saveFolder) throws IOException { + public QuestsManagerImplementation(BeautyQuests plugin, int lastID, File saveFolder) throws IOException { this.plugin = plugin; this.lastID.set(lastID); this.saveFolder = saveFolder; try (Stream<Path> files = Files.walk(saveFolder.toPath(), Integer.MAX_VALUE, FileVisitOption.FOLLOW_LINKS)) { files.filter(Files::isRegularFile).filter(path -> !path.getFileName().toString().contains("backup")).filter(path -> "yml".equalsIgnoreCase(Utils.getFilenameExtension(path.getFileName().toString()).orElse(null))).forEach(path -> { - BeautyQuests.loadingFailure = false; + BeautyQuests.getInstance().resetLoadingFailure(); try { File file = path.toFile(); - Quest quest = Quest.loadFromFile(file); + QuestImplementation quest = QuestImplementation.loadFromFile(file); if (quest != null) { addQuest(quest); - if (BeautyQuests.loadingFailure) plugin.createQuestBackup(path, "Error when loading quest."); + if (BeautyQuests.getInstance().hasLoadingFailed()) + plugin.createQuestBackup(path, "Error when loading quest."); }else plugin.getLogger().severe("Quest from file " + file.getName() + " not activated"); }catch (Exception ex) { - BeautyQuests.logger.severe("An error occurred while loading quest file " + path.getFileName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while loading quest file " + path.getFileName(), ex); } }); } @@ -57,9 +61,9 @@ public QuestsManager(BeautyQuests plugin, int lastID, File saveFolder) throws IO public int getFreeQuestID() { int id = getLastID(); - if (quests.stream().noneMatch(quest -> quest.getID() == id)) return id; + if (quests.stream().noneMatch(quest -> quest.getId() == id)) return id; - BeautyQuests.logger.warning("Quest id " + id + " already taken, this should not happen."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Quest id " + id + " already taken, this should not happen."); incrementLastID(); return getFreeQuestID(); } @@ -72,62 +76,73 @@ public int incrementLastID() { return lastID.incrementAndGet(); } + public int updateAll() throws IOException { + int updated = 0; + for (QuestImplementation quest : quests) { + if (quest.saveToFile()) updated++; + } + return updated; + } + public @NotNull BeautyQuests getPlugin() { return plugin; } + @Override public @NotNull File getSaveFolder() { return saveFolder; } + @Override public @NotNull List<Quest> getQuests() { - return quests; + return (List) quests; } + public @NotNull List<QuestImplementation> getQuestsRaw() { + return quests; + } + public int getQuestsAmount() { return quests.size(); } @Override - public @NotNull Iterator<Quest> iterator() { - return quests.iterator(); - } - - public @Nullable Quest getQuest(int id) { - return quests.stream().filter(x -> x.getID() == id).findAny().orElse(null); + public @Nullable QuestImplementation getQuest(int id) { + return quests.stream().filter(x -> x.getId() == id).findAny().orElse(null); } public void unloadQuests() { - for (Quest quest : quests) { + for (QuestImplementation quest : quests) { try { quest.unload(); }catch (Exception ex) { - BeautyQuests.logger.severe("An error ocurred when unloading quest " + quest.getID(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred when unloading quest " + quest.getId(), ex); } } } public void removeQuest(@NotNull Quest quest) { quests.remove(quest); - if (quest.hasOption(OptionStarterNPC.class)) { - quest.getOption(OptionStarterNPC.class).getValue().removeQuest(quest); - } } + @Override public void addQuest(@NotNull Quest quest) { - lastID.set(Math.max(lastID.get(), quest.getID())); - quests.add(quest); + QuestImplementation qu = (QuestImplementation) quest; + lastID.set(Math.max(lastID.get(), quest.getId())); + quests.add(qu); if (quest.hasOption(OptionStarterNPC.class)) { BQNPC npc = quest.getOptionValueOrDef(OptionStarterNPC.class); if (npc != null) npc.addQuest(quest); } - quest.load(); + qu.load(); } + @Override public @NotNull @Unmodifiable List<Quest> getQuestsStarted(PlayerAccount acc) { return getQuestsStarted(acc, false, false); } + @Override public @NotNull @Unmodifiable List<Quest> getQuestsStarted(@NotNull PlayerAccount acc, boolean hide, boolean withoutScoreboard) { return acc.getQuestsDatas() @@ -135,24 +150,26 @@ public void addQuest(@NotNull Quest quest) { .filter(PlayerQuestDatas::hasStarted) .map(PlayerQuestDatas::getQuest) .filter(Objects::nonNull) - .filter(quest -> !quest.isRemoved()) - .filter(quest -> !hide || !quest.isHidden(VisibilityLocation.TAB_IN_PROGRESS)) + .filter(Quest::isValid) + .filter(quest -> !hide || !quest.isHidden(QuestVisibilityLocation.TAB_IN_PROGRESS)) .filter(quest -> !withoutScoreboard || quest.isScoreboardEnabled()) .collect(Collectors.toList()); } + @Override public void updateQuestsStarted(@NotNull PlayerAccount acc, boolean withoutScoreboard, @NotNull List<Quest> list) { for (Iterator<Quest> iterator = list.iterator(); iterator.hasNext();) { - Quest existing = iterator.next(); + QuestImplementation existing = (QuestImplementation) iterator.next(); if (!existing.hasStarted(acc) || (withoutScoreboard && !existing.isScoreboardEnabled())) iterator.remove(); } - for (Quest qu : quests) { + for (QuestImplementation qu : quests) { if (withoutScoreboard && !qu.isScoreboardEnabled()) continue; if (!list.contains(qu) && qu.hasStarted(acc)) list.add(qu); } } + @Override public int getStartedSize(@NotNull PlayerAccount acc) { return (int) quests .stream() @@ -160,19 +177,21 @@ public int getStartedSize(@NotNull PlayerAccount acc) { .count(); } + @Override public @NotNull @Unmodifiable List<Quest> getQuestsFinished(@NotNull PlayerAccount acc, boolean hide) { return quests .stream() - .filter(quest -> !(hide && quest.isHidden(VisibilityLocation.TAB_FINISHED)) && quest.hasFinished(acc)) + .filter(quest -> !(hide && quest.isHidden(QuestVisibilityLocation.TAB_FINISHED)) && quest.hasFinished(acc)) .collect(Collectors.toList()); } + @Override public @NotNull @Unmodifiable List<Quest> getQuestsNotStarted(@NotNull PlayerAccount acc, boolean hide, boolean clickableAndRedoable) { return quests .stream() .filter(quest -> { - if (hide && quest.isHidden(VisibilityLocation.TAB_NOT_STARTED)) return false; + if (hide && quest.isHidden(QuestVisibilityLocation.TAB_NOT_STARTED)) return false; if (quest.hasStarted(acc)) return false; if (!quest.hasFinished(acc)) return true; return clickableAndRedoable && quest.isRepeatable() && quest.getOptionValueOrDef(OptionStartable.class) && quest.testTimer(acc, false); diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java new file mode 100644 index 00000000..b971517b --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -0,0 +1,216 @@ +package fr.skytasul.quests.structure; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; +import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageHandler; +import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.utils.QuestUtils; + +public class StageControllerImplementation<T extends AbstractStage> implements StageController, Listener { + + private final @NotNull QuestBranchImplementation branch; + private final @NotNull StageType<T> type; + + private @Nullable T stage; + + public StageControllerImplementation(@NotNull QuestBranchImplementation branch, @NotNull StageType<T> type) { + this.branch = Objects.requireNonNull(branch); + this.type = Objects.requireNonNull(type); + } + + public void setStage(@NotNull T stage) { + if (this.stage != null) + throw new IllegalStateException("Stage was already set"); + + type.getStageClass().cast(stage); // to throw ClassCastException if needed + + this.stage = Objects.requireNonNull(stage); + } + + @Override + public @NotNull QuestBranchImplementation getBranch() { + return branch; + } + + @Override + public @NotNull AbstractStage getStage() { + if (stage == null) + throw new IllegalStateException("Stage has not been loaded yet"); + return stage; + } + + @Override + public @NotNull StageType<T> getStageType() { + if (type == null) + throw new IllegalStateException("Stage has not been loaded yet"); + return type; + } + + @Override + public void finishStage(@NotNull Player player) { + QuestUtils.runSync(() -> branch.finishStage(player, this)); + } + + @Override + public boolean hasStarted(@NotNull PlayerAccount acc) { + return branch.hasStageLaunched(acc, this); + } + + @Override + public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nullable Object dataValue) { + PlayerAccount acc = PlayersManager.getPlayerAccount(player); + Map<String, Object> datas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); + Validate.notNull(datas, "Account " + acc.debugName() + " does not have datas for " + toString()); + datas.put(dataKey, dataValue); + acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); + branch.getManager().objectiveUpdated(player); + } + + @Override + public <D> @Nullable D getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { + Map<String, Object> stageDatas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); + return stageDatas == null ? null : (D) stageDatas.get(dataKey); + } + + @Override + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { + if (stage.getCustomText() != null) + return "§e" + MessageUtils.format(stage.getCustomText(), stage.descriptionFormat(acc, source)); + + try { + return stage.descriptionLine(acc, source); + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "An error occurred while getting the description line for player " + acc.getName() + " in " + toString(), + ex); + return "§a" + type.getName(); + } + } + + private void propagateStageHandlers(@NotNull Consumer<@NotNull StageHandler> consumer) { + Consumer<StageHandler> newConsumer = handler -> { + try { + consumer.accept(handler); + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while updating stage handler.", ex); + } + }; + QuestsAPI.getAPI().getQuestsHandlers().forEach(newConsumer); + stage.getOptions().forEach(newConsumer); + } + + public void start(@NotNull PlayerAccount acc) { + if (acc.isCurrent()) + MessageUtils.sendOffMessage(acc.getPlayer(), stage.getStartMessage()); + Map<String, Object> datas = new HashMap<>(); + stage.initPlayerDatas(acc, datas); + acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); + propagateStageHandlers(handler -> handler.stageStart(acc, this)); + stage.started(acc); + } + + public void end(@NotNull PlayerAccount acc) { + acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), null); + propagateStageHandlers(handler -> handler.stageEnd(acc, this)); + stage.ended(acc); + } + + public void joins(@NotNull Player player) { + propagateStageHandlers(handler -> handler.stageJoin(player, this)); + stage.joined(player); + } + + public void leaves(@NotNull Player player) { + propagateStageHandlers(handler -> handler.stageLeave(player, this)); + stage.left(player); + } + + public void load() { + if (stage instanceof Listener) + Bukkit.getPluginManager().registerEvents((Listener) stage, QuestsPlugin.getPlugin()); + propagateStageHandlers(handler -> handler.stageLoad(this)); + stage.load(); + } + + public void unload() { + if (stage instanceof Listener) + HandlerList.unregisterAll((Listener) stage); + propagateStageHandlers(handler -> handler.stageUnload(this)); + stage.unload(); + } + + @EventHandler + public void onJoin(PlayerAccountJoinEvent e) { + if (e.isFirstJoin()) + return; + + if (hasStarted(e.getPlayerAccount())) + joins(e.getPlayer()); + } + + @EventHandler + public void onLeave(PlayerAccountLeaveEvent e) { + if (hasStarted(e.getPlayerAccount())) + leaves(e.getPlayer()); + } + + @Override + public @NotNull String getFlowId() { + if (branch.isEndingStage(this)) + return "E" + branch.getEndingStageId(this); + return Integer.toString(branch.getRegularStageId(this)); + } + + public int getStorageId() { + return branch.isEndingStage(this) ? branch.getEndingStageId(this) : branch.getRegularStageId(this); + } + + @Override + public String toString() { + return "stage " + getFlowId() + " (" + type.getID() + ") of quest " + branch.getQuest().getId() + ", branch " + + branch.getId(); + } + + public static @NotNull StageControllerImplementation<?> loadFromConfig(@NotNull QuestBranchImplementation branch, + @NotNull ConfigurationSection section) { + String typeID = section.getString("stageType"); + + StageType<?> stageType = QuestsAPI.getAPI().getStages().getType(typeID) + .orElseThrow(() -> new IllegalArgumentException("Unknown stage type " + typeID)); + + return loadFromConfig(branch, section, stageType); + } + + private static <T extends AbstractStage> @NotNull StageControllerImplementation<T> loadFromConfig( + @NotNull QuestBranchImplementation branch, @NotNull ConfigurationSection section, StageType<T> type) { + // we need to separate into two methods to trick the generics + + StageControllerImplementation<T> controller = new StageControllerImplementation<>(branch, type); + T stage = type.getLoader().supply(section, controller); + controller.setStage(stage); + stage.load(section); + return controller; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolImplementation.java similarity index 71% rename from core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java rename to core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolImplementation.java index 88a9b171..ab09e33a 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolImplementation.java @@ -11,21 +11,23 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; +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.npcs.BQNPC; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerPoolDatas; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerPoolDatas; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.players.PlayerPoolDatasImplementation; +import fr.skytasul.quests.utils.QuestUtils; -public class QuestPool implements Comparable<QuestPool> { +public class QuestPoolImplementation implements Comparable<QuestPoolImplementation>, QuestPool { private final int id; @@ -41,7 +43,7 @@ public class QuestPool implements Comparable<QuestPool> { BQNPC npc; List<Quest> quests = new ArrayList<>(); - QuestPool(int id, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, List<AbstractRequirement> requirements) { + QuestPoolImplementation(int id, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, List<AbstractRequirement> requirements) { this.id = id; this.npcID = npcID; this.hologram = hologram; @@ -53,68 +55,81 @@ public class QuestPool implements Comparable<QuestPool> { this.requirements = requirements; if (npcID >= 0) { - npc = QuestsAPI.getNPCsManager().getById(npcID); + npc = QuestsAPI.getAPI().getNPCsManager().getById(npcID); if (npc != null) { npc.addPool(this); return; } } - BeautyQuests.logger.warning("Unknown NPC " + npcID + " for quest pool #" + id); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unknown NPC " + npcID + " for quest pool #" + id); } - public int getID() { + @Override + public int getId() { return id; } - public int getNPCID() { + @Override + public int getNpcId() { return npcID; } + @Override public String getHologram() { return hologram; } + @Override public int getMaxQuests() { return maxQuests; } + @Override public int getQuestsPerLaunch() { return questsPerLaunch; } + @Override public boolean isRedoAllowed() { return redoAllowed; } + @Override public long getTimeDiff() { return timeDiff; } + @Override public boolean doAvoidDuplicates() { return avoidDuplicates; } + @Override public List<AbstractRequirement> getRequirements() { return requirements; } + @Override public List<Quest> getQuests() { return quests; } + @Override public void addQuest(Quest quest) { quests.add(quest); } + @Override public void removeQuest(Quest quest) { quests.remove(quest); } @Override - public int compareTo(QuestPool o) { + public int compareTo(QuestPoolImplementation o) { return Integer.compare(id, o.id); } + @Override public ItemStack getItemStack(String action) { return ItemUtils.item(XMaterial.CHEST, Lang.poolItemName.format(id), Lang.poolItemNPC.format(npcID + " (" + (npc == null ? "unknown" : npc.getName()) @@ -126,14 +141,17 @@ public ItemStack getItemStack(String action) { Lang.poolItemHologram.format(hologram == null ? "\n§7 > " + Lang.PoolHologramText.toString() + "\n§7 > " + Lang.defaultValue : hologram), Lang.poolItemAvoidDuplicates.format(avoidDuplicates ? Lang.Enabled : Lang.Disabled), "§7" + Lang.requirements.format(requirements.size()), - Lang.poolItemQuestsList.format(quests.size(), quests.stream().map(x -> "#" + x.getID()).collect(Collectors.joining(", "))), + Lang.poolItemQuestsList.format(quests.size(), + quests.stream().map(x -> "#" + x.getId()).collect(Collectors.joining(", "))), "", action); } + @Override public CompletableFuture<PlayerPoolDatas> resetPlayer(PlayerAccount acc) { return acc.removePoolDatas(this); } + @Override public void resetPlayerTimer(PlayerAccount acc) { if (!acc.hasPoolDatas(this)) return; acc.getPoolDatas(this).setLastGive(0); @@ -141,11 +159,12 @@ public void resetPlayerTimer(PlayerAccount acc) { public void questCompleted(PlayerAccount acc, Quest quest) { if (!avoidDuplicates) return; - PlayerPoolDatas poolDatas = acc.getPoolDatas(this); - poolDatas.getCompletedQuests().add(quest.getID()); + PlayerPoolDatasImplementation poolDatas = (PlayerPoolDatasImplementation) acc.getPoolDatas(this); + poolDatas.getCompletedQuests().add(quest.getId()); poolDatas.updatedCompletedQuests(); } + @Override public boolean canGive(Player p, PlayerAccount acc) { PlayerPoolDatas datas = acc.getPoolDatas(this); @@ -155,20 +174,22 @@ public boolean canGive(Player p, PlayerAccount acc) { try { if (!requirement.test(p)) return false; }catch (Exception ex) { - BeautyQuests.logger.severe("Cannot test requirement " + requirement.getClass().getSimpleName() + " in pool " + id + " for player " + p.getName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot test requirement " + requirement.getClass().getSimpleName() + " in pool " + id + " for player " + p.getName(), ex); return false; } } - List<Quest> notDoneQuests = avoidDuplicates ? quests.stream().filter(quest -> !datas.getCompletedQuests().contains(quest.getID())).collect(Collectors.toList()) : quests; + List<Quest> notDoneQuests = avoidDuplicates ? quests.stream() + .filter(quest -> !datas.getCompletedQuests().contains(quest.getId())).collect(Collectors.toList()) : quests; if (notDoneQuests.isEmpty()) { // all quests completed if (!redoAllowed) return false; - return quests.stream().anyMatch(quest -> quest.isRepeatable() && quest.isLauncheable(p, acc, false)); + return quests.stream().anyMatch(quest -> quest.isRepeatable() && quest.canStart(p, false)); }else if (acc.getQuestsDatas().stream().filter(quest -> quest.hasStarted() && quests.contains(quest.getQuest())).count() >= maxQuests) return false; - return notDoneQuests.stream().anyMatch(quest -> quest.isLauncheable(p, acc, false)); + return notDoneQuests.stream().anyMatch(quest -> quest.canStart(p, false)); } + @Override public CompletableFuture<String> give(Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); PlayerPoolDatas datas = acc.getPoolDatas(this); @@ -193,22 +214,23 @@ public CompletableFuture<String> give(Player p) { } } } catch (InterruptedException ex) { - BeautyQuests.logger.severe("Interrupted!", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Interrupted!", ex); Thread.currentThread().interrupt(); } catch (ExecutionException ex) { - BeautyQuests.logger.severe("Failed to give quests to player " + p.getName() + " from pool " + id, ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Failed to give quests to player " + p.getName() + " from pool " + id, ex); } - return "started quest(s) " + started.stream().map(x -> "#" + x.getID()).collect(Collectors.joining(", ")); + return "started quest(s) " + started.stream().map(x -> "#" + x.getId()).collect(Collectors.joining(", ")); }); } - private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, PlayerPoolDatas datas, boolean hadOne) { - if (!Utils.testRequirements(p, requirements, !hadOne)) + private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, PlayerPoolDatas datas, + boolean hadOne) { + if (!QuestUtils.testRequirements(p, requirements, !hadOne)) return CompletableFuture.completedFuture(new PoolGiveResult("")); List<Quest> notCompleted = avoidDuplicates ? quests.stream() - .filter(quest -> !datas.getCompletedQuests().contains(quest.getID())).collect(Collectors.toList()) : quests; + .filter(quest -> !datas.getCompletedQuests().contains(quest.getId())).collect(Collectors.toList()) : quests; if (notCompleted.isEmpty()) { // all quests completed: we check if the player can redo some of them notCompleted = replenishQuests(datas); @@ -227,8 +249,7 @@ private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, P notStarted = replenishQuests(datas); } - List<Quest> available = - notStarted.stream().filter(quest -> quest.isLauncheable(p, acc, false)).collect(Collectors.toList()); + List<Quest> available = notStarted.stream().filter(quest -> quest.canStart(p, false)).collect(Collectors.toList()); // at this point, "available" contains all quests that the player has not yet completed, that it is // not currently doing and that meet the requirements to launch @@ -236,7 +257,7 @@ private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, P return CompletableFuture.completedFuture(new PoolGiveResult(Lang.POOL_NO_AVAILABLE.toString())); } else { CompletableFuture<PoolGiveResult> future = new CompletableFuture<>(); - Utils.runOrSync(() -> { + QuestUtils.runOrSync(() -> { Quest quest = available.get(ThreadLocalRandom.current().nextInt(available.size())); quest.attemptStart(p).whenComplete((result, exception) -> { if (exception != null) { @@ -260,10 +281,10 @@ private List<Quest> replenishQuests(PlayerPoolDatas datas) { datas.setCompletedQuests(quests .stream() .filter(quest -> !notDoneQuests.contains(quest)) - .map(Quest::getID) + .map(Quest::getId) .collect(Collectors.toSet())); } - DebugUtils.logMessage("Replenished available quests of " + datas.getAccount().getNameAndID() + " for pool " + id); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Replenished available quests of " + datas.getAccount().getNameAndID() + " for pool " + id); return notDoneQuests; } @@ -286,9 +307,9 @@ public void save(ConfigurationSection config) { if (!requirements.isEmpty()) config.set("requirements", SerializableObject.serializeList(requirements)); } - public static QuestPool deserialize(int id, ConfigurationSection config) { + public static QuestPoolImplementation deserialize(int id, ConfigurationSection config) { List<AbstractRequirement> requirements = SerializableObject.deserializeList(config.getMapList("requirements"), AbstractRequirement::deserialize); - return new QuestPool(id, config.getInt("npcID"), config.getString("hologram"), config.getInt("maxQuests"), config.getInt("questsPerLaunch", 1), config.getBoolean("redoAllowed"), config.getLong("timeDiff"), config.getBoolean("avoidDuplicates", true), requirements); + return new QuestPoolImplementation(id, config.getInt("npcID"), config.getString("hologram"), config.getInt("maxQuests"), config.getInt("questsPerLaunch", 1), config.getBoolean("redoAllowed"), config.getLong("timeDiff"), config.getBoolean("avoidDuplicates", true), requirements); } private static class PoolGiveResult { diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManager.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java similarity index 62% rename from core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManager.java rename to core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java index 3c6c1a22..500fb097 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManager.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java @@ -12,18 +12,20 @@ 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.QuestsPlugin; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.pools.QuestPoolsManager; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.options.OptionQuestPool; -public class QuestPoolsManager { +public class QuestPoolsManagerImplementation implements QuestPoolsManager { private File file; private YamlConfiguration config; - private Map<Integer, QuestPool> pools = new HashMap<>(); + private Map<Integer, QuestPoolImplementation> pools = new HashMap<>(); - public QuestPoolsManager(File file) throws IOException { + public QuestPoolsManagerImplementation(File file) throws IOException { this.file = file; if (!file.exists()) { config = new YamlConfiguration(); @@ -35,18 +37,18 @@ public QuestPoolsManager(File file) throws IOException { for (String key : config.getKeys(false)) { try { int id = Integer.parseInt(key); - QuestPool pool = QuestPool.deserialize(id, config.getConfigurationSection(key)); + QuestPoolImplementation pool = QuestPoolImplementation.deserialize(id, config.getConfigurationSection(key)); pools.put(id, pool); } catch (Exception ex) { - BeautyQuests.logger.severe("An exception ocurred while loading quest pool " + key, ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An exception ocurred while loading quest pool " + key, ex); continue; } } } } - public void save(@NotNull QuestPool pool) { - ConfigurationSection section = config.createSection(Integer.toString(pool.getID())); + public void save(@NotNull QuestPoolImplementation pool) { + ConfigurationSection section = config.createSection(Integer.toString(pool.getId())); pool.save(section); try { config.save(file); @@ -55,27 +57,30 @@ public void save(@NotNull QuestPool pool) { } } - public @NotNull QuestPool createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, int maxQuests, + @Override + public @NotNull QuestPoolImplementation createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, + int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, @NotNull List<AbstractRequirement> requirements) { if (editing != null) - editing.unload(); + ((QuestPoolImplementation) editing).unload(); - QuestPool pool = new QuestPool( - editing == null ? pools.keySet().stream().mapToInt(Integer::intValue).max().orElse(-1) + 1 : editing.getID(), + QuestPoolImplementation pool = new QuestPoolImplementation( + editing == null ? pools.keySet().stream().mapToInt(Integer::intValue).max().orElse(-1) + 1 : editing.getId(), npcID, hologram, maxQuests, questsPerLaunch, redoAllowed, timeDiff, avoidDuplicates, requirements); save(pool); - pools.put(pool.getID(), pool); + pools.put(pool.getId(), pool); if (editing != null) { - pool.quests = editing.quests; + pool.quests = editing.getQuests(); pool.quests.forEach(quest -> quest.getOption(OptionQuestPool.class).setValue(pool)); } return pool; } + @Override public void removePool(int id) { - QuestPool pool = pools.remove(id); + QuestPoolImplementation pool = pools.remove(id); if (pool == null) return; pool.unload(); @@ -88,12 +93,14 @@ public void removePool(int id) { } } - public @Nullable QuestPool getPool(int id) { + @Override + public @Nullable QuestPoolImplementation getPool(int id) { return pools.get(id); } + @Override public @NotNull @UnmodifiableView Collection<QuestPool> getPools() { - return pools.values(); + return (Collection) pools.values(); } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/Database.java b/core/src/main/java/fr/skytasul/quests/utils/Database.java index c561dd61..8df58d0c 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Database.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Database.java @@ -9,6 +9,7 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; public class Database implements Closeable { @@ -52,11 +53,11 @@ public ConfigurationSection getConfig() { @Override public void close() { - BeautyQuests.logger.info("Closing database pool..."); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Closing database pool..."); try { ((Closeable) source).close(); }catch (IOException ex) { - BeautyQuests.logger.severe("An error occurred while closing database pool.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while closing database pool.", ex); } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java b/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java index 00b74ebe..e5161e0b 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java @@ -3,7 +3,7 @@ import java.util.HashMap; import java.util.Map; import java.util.StringJoiner; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; public class DebugUtils { @@ -11,10 +11,6 @@ private DebugUtils() {} private static Map<String, Long> errors = new HashMap<>(); - public static void logMessage(String msg){ - BeautyQuests.getInstance().getLoggerHandler().write(msg, "DEBUG"); - } - public static String stackTraces(int from, int to){ StringJoiner joiner = new StringJoiner(" -> "); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); @@ -28,7 +24,7 @@ public static String stackTraces(int from, int to){ public static void printError(String errorMsg, String typeID, int seconds) { Long time = errors.get(typeID); if (time == null || time.longValue() + seconds * 1000 < System.currentTimeMillis()) { - BeautyQuests.logger.warning(errorMsg); + QuestsPlugin.getPlugin().getLoggerExpanded().warning(errorMsg); errors.put(typeID, System.currentTimeMillis()); } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java b/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java index 85cfbe54..2922b4db 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java +++ b/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java @@ -9,6 +9,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; @@ -127,7 +128,7 @@ public static ParticleEffect deserialize(ConfigurationSection data) { } public static boolean canHaveColor(Particle particle) { - if (NMS.getMCVersion() >= 13) return particle.getDataType() == Post1_13.getDustOptionClass(); + if (MinecraftVersion.MAJOR >= 13) return particle.getDataType() == Post1_13.getDustOptionClass(); return particle == Particle.REDSTONE || particle == Particle.SPELL_MOB || particle == Particle.SPELL_MOB_AMBIENT; } @@ -147,7 +148,7 @@ private ParticleType(Particle particle) { if (particle == Particle.NOTE) { colored = true; dustColored = false; - }else if (NMS.getMCVersion() >= 13) { + }else if (MinecraftVersion.MAJOR >= 13) { if (particle.getDataType() == Post1_13.getDustOptionClass()) { colored = true; dustColored = true; diff --git a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java new file mode 100644 index 00000000..d80e3e6b --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -0,0 +1,146 @@ +package fr.skytasul.quests.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Firework; +import org.bukkit.entity.Player; +import org.bukkit.inventory.meta.FireworkMeta; +import org.bukkit.metadata.FixedMetadataValue; +import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.rewards.InterruptingBranchException; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.Utils; + +public class QuestUtils { + + public static void runOrSync(Runnable run) { + if (Bukkit.isPrimaryThread()) { + run.run(); + } else + Bukkit.getScheduler().runTask(BeautyQuests.getInstance(), run); + } + + public static <T> BiConsumer<T, Throwable> runSyncConsumer(Runnable run) { + return (__, ___) -> runSync(run); + } + + public static void runSync(Runnable run) { + Bukkit.getScheduler().runTask(BeautyQuests.getInstance(), run); + } + + public static void runAsync(Runnable run) { + Bukkit.getScheduler().runTaskAsynchronously(BeautyQuests.getInstance(), run); + } + + public static void playPluginSound(Player p, String sound, float volume) { + playPluginSound(p, sound, volume, 1); + } + + public static void playPluginSound(Player p, String sound, float volume, float pitch) { + if (!QuestsConfiguration.playSounds()) + return; + if ("none".equals(sound)) + return; + try { + p.playSound(p.getLocation(), Sound.valueOf(sound), volume, pitch); + } catch (Exception ex) { + if (MinecraftVersion.MAJOR > 8) + p.playSound(p.getLocation(), sound, volume, pitch); + } + } + + public static void playPluginSound(Location lc, String sound, float volume) { + if (!QuestsConfiguration.playSounds()) + return; + try { + lc.getWorld().playSound(lc, Sound.valueOf(sound), volume, 1); + } catch (Exception ex) { + if (MinecraftVersion.MAJOR > 8) + lc.getWorld().playSound(lc, sound, volume, 1); + } + } + + public static String descriptionLines(DescriptionSource source, String... elements) { + if (elements.length == 0) + return Lang.Unknown.toString(); + if (QuestsConfiguration.splitDescription(source) && (!QuestsConfiguration.inlineAlone() || elements.length > 1)) { + return QuestsConfiguration.getDescriptionItemPrefix() + + Utils.buildFromArray(elements, 0, QuestsConfiguration.getDescriptionItemPrefix()); + } + return MessageUtils.itemsToFormattedString(elements, QuestsConfiguration.getItemAmountColor()); + } + + public static void spawnFirework(Location lc, FireworkMeta meta) { + if (!QuestsConfiguration.doFireworks() || meta == null) + return; + runOrSync(() -> { + Consumer<Firework> fwConsumer = fw -> { + fw.setMetadata("questFinish", new FixedMetadataValue(BeautyQuests.getInstance(), true)); + fw.setFireworkMeta(meta); + }; + if (MinecraftVersion.MAJOR >= 12) { + 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 + // before it is sent to the players, as it will not create flickering + } else { + fwConsumer.accept(lc.getWorld().spawn(lc, Firework.class)); + } + }); + } + + public static List<String> giveRewards(Player p, List<AbstractReward> rewards) throws InterruptingBranchException { + InterruptingBranchException interrupting = null; + + List<String> msg = new ArrayList<>(); + for (AbstractReward rew : rewards) { + try { + List<String> messages = rew.give(p); + if (messages != null) + msg.addAll(messages); + } catch (InterruptingBranchException ex) { + if (interrupting != null) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Interrupting the same branch via rewards twice!"); + } else { + interrupting = ex; + } + } catch (Throwable e) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when giving reward " + rew.getName() + " to " + p.getName(), e); + } + } + + if (interrupting != null) + throw interrupting; + return msg; + } + + public static boolean testRequirements(Player p, List<AbstractRequirement> requirements, boolean message) { + for (AbstractRequirement requirement : requirements) { + try { + if (!requirement.test(p)) { + if (message && !requirement.sendReason(p)) + continue; // means a reason has not yet been sent + return false; + } + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "Cannot test requirement " + requirement.getClass().getSimpleName() + " for player " + p.getName(), + ex); + return false; + } + } + return true; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarImplementation.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQBossBarImplementation.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarImplementation.java rename to core/src/main/java/fr/skytasul/quests/utils/compatibility/BQBossBarImplementation.java index 8c188406..4ee82ef2 100644 --- a/core/src/main/java/fr/skytasul/quests/api/bossbar/BQBossBarImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQBossBarImplementation.java @@ -1,19 +1,20 @@ -package fr.skytasul.quests.api.bossbar; +package fr.skytasul.quests.utils.compatibility; import org.bukkit.Bukkit; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.boss.BossBar; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.BossBarManager; -public class BQBossBarImplementation implements BQBossBarManager { +public class BQBossBarImplementation implements BossBarManager { @Override public BQBossBar buildBossBar(String name, BarColor color, BarStyle style) { return new BarImpl(name, color, style); } - private class BarImpl implements BQBossBarManager.BQBossBar { + private class BarImpl implements BossBarManager.BQBossBar { protected BossBar bar; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQItemsAdder.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQItemsAdder.java index 59ba929f..7f966131 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQItemsAdder.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQItemsAdder.java @@ -3,7 +3,7 @@ import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.comparison.ItemComparison; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; import dev.lone.itemsadder.api.CustomStack; public final class BQItemsAdder { @@ -14,11 +14,11 @@ private BQItemsAdder() {} Lang.comparisonItemsAdderLore.toString(), BQItemsAdder::compareItems).setHasPriority(); public static void initialize() { - QuestsAPI.registerItemComparison(COMPARISON); + QuestsAPI.getAPI().registerItemComparison(COMPARISON); } public static void unload() { - QuestsAPI.unregisterItemComparison(COMPARISON); + QuestsAPI.getAPI().unregisterItemComparison(COMPARISON); } public static boolean compareItems(ItemStack item1, ItemStack item2) { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java index 6b7e0e2f..80067af5 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java @@ -13,9 +13,11 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; +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.requirements.RequirementCreator; import fr.skytasul.quests.api.rewards.RewardCreator; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.requirements.ClassRequirement; import fr.skytasul.quests.requirements.FactionRequirement; import fr.skytasul.quests.requirements.JobLevelRequirement; @@ -26,8 +28,6 @@ import fr.skytasul.quests.requirements.SkillAPILevelRequirement; import fr.skytasul.quests.rewards.MoneyReward; import fr.skytasul.quests.rewards.PermissionReward; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.compatibility.maps.BQBlueMap; import fr.skytasul.quests.utils.compatibility.maps.BQDynmap; import fr.skytasul.quests.utils.compatibility.mobs.BQAdvancedSpawners; @@ -44,44 +44,44 @@ public class DependenciesManager implements Listener { - public static final BQDependency znpcs = new BQDependency("ServersNPC", () -> QuestsAPI.setNPCsManager(new BQServerNPCs()), null, plugin -> { + public static final BQDependency znpcs = new BQDependency("ServersNPC", () -> QuestsAPI.getAPI().setNPCsManager(new BQServerNPCs()), null, plugin -> { if (plugin.getClass().getName().equals("io.github.znetworkw.znpcservers.ServersNPC")) // NOSONAR return true; - BeautyQuests.logger.warning("Your version of znpcs (" + plugin.getDescription().getVersion() + ") is not supported by BeautyQuests."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of znpcs (" + plugin.getDescription().getVersion() + ") is not supported by BeautyQuests."); return false; }); public static final BQDependency citizens = new BQDependency("Citizens", () -> { - QuestsAPI.setNPCsManager(new BQCitizens()); - QuestsAPI.registerMobFactory(new CitizensFactory()); + QuestsAPI.getAPI().setNPCsManager(new BQCitizens()); + QuestsAPI.getAPI().registerMobFactory(new CitizensFactory()); }); public static final BQDependency vault = new BQDependency("Vault", () -> { - QuestsAPI.getRewards().register(new RewardCreator("moneyReward", MoneyReward.class, ItemUtils.item(XMaterial.EMERALD, Lang.rewardMoney.toString()), MoneyReward::new)); - QuestsAPI.getRewards().register(new RewardCreator("permReward", PermissionReward.class, ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.rewardPerm.toString()), PermissionReward::new)); - QuestsAPI.getRequirements().register(new RequirementCreator("moneyRequired", MoneyRequirement.class, ItemUtils.item(XMaterial.EMERALD, Lang.RMoney.toString()), MoneyRequirement::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("moneyReward", MoneyReward.class, ItemUtils.item(XMaterial.EMERALD, Lang.rewardMoney.toString()), MoneyReward::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("permReward", PermissionReward.class, ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.rewardPerm.toString()), PermissionReward::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("moneyRequired", MoneyRequirement.class, ItemUtils.item(XMaterial.EMERALD, Lang.RMoney.toString()), MoneyRequirement::new)); }); public static final BQDependency papi = new BQDependency("PlaceholderAPI", () -> { QuestsPlaceholders.registerPlaceholders(BeautyQuests.getInstance().getConfig().getConfigurationSection("startedQuestsPlaceholder")); - QuestsAPI.getRequirements().register(new RequirementCreator("placeholderRequired", PlaceholderRequirement.class, ItemUtils.item(XMaterial.NAME_TAG, Lang.RPlaceholder.toString()), PlaceholderRequirement::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("placeholderRequired", PlaceholderRequirement.class, ItemUtils.item(XMaterial.NAME_TAG, Lang.RPlaceholder.toString()), PlaceholderRequirement::new)); }); public static final BQDependency skapi = new BQDependency("SkillAPI", () -> { - QuestsAPI.getRequirements().register(new RequirementCreator("classRequired", ClassRequirement.class, ItemUtils.item(XMaterial.GHAST_TEAR, Lang.RClass.toString()), ClassRequirement::new)); - QuestsAPI.getRequirements().register(new RequirementCreator("skillAPILevelRequired", SkillAPILevelRequirement.class, ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RSkillAPILevel.toString()), SkillAPILevelRequirement::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("classRequired", ClassRequirement.class, ItemUtils.item(XMaterial.GHAST_TEAR, Lang.RClass.toString()), ClassRequirement::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("skillAPILevelRequired", SkillAPILevelRequirement.class, ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RSkillAPILevel.toString()), SkillAPILevelRequirement::new)); }).addPluginName("ProSkillAPI"); public static final BQDependency cmi = new BQDependency("CMI", () -> { - if (BQCMI.areHologramsEnabled()) QuestsAPI.setHologramsManager(new BQCMI()); + if (BQCMI.areHologramsEnabled()) QuestsAPI.getAPI().setHologramsManager(new BQCMI()); }); - public static final BQDependency boss = new BQDependency("Boss", () -> QuestsAPI.registerMobFactory(new BQBoss()), null, plugin -> { + public static final BQDependency boss = new BQDependency("Boss", () -> QuestsAPI.getAPI().registerMobFactory(new BQBoss()), null, plugin -> { try { Class.forName("org.mineacademy.boss.model.Boss"); }catch (ClassNotFoundException ex) { - BeautyQuests.logger.warning("Your version of Boss (" + plugin.getDescription().getVersion() + ") is not compatible with BeautyQuests."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of Boss (" + plugin.getDescription().getVersion() + ") is not compatible with BeautyQuests."); return false; } return true; @@ -90,18 +90,18 @@ public class DependenciesManager implements Listener { public static final BQDependency mm = new BQDependency("MythicMobs", () -> { try { Class.forName("io.lumine.mythic.api.MythicPlugin"); - QuestsAPI.registerMobFactory(new MythicMobs5()); + QuestsAPI.getAPI().registerMobFactory(new MythicMobs5()); }catch (ClassNotFoundException ex) { - QuestsAPI.registerMobFactory(new MythicMobs()); + QuestsAPI.getAPI().registerMobFactory(new MythicMobs()); } }); - public static final BQDependency advancedspawners = new BQDependency("AdvancedSpawners", () -> QuestsAPI.registerMobFactory(new BQAdvancedSpawners())); + public static final BQDependency advancedspawners = new BQDependency("AdvancedSpawners", () -> QuestsAPI.getAPI().registerMobFactory(new BQAdvancedSpawners())); public static final BQDependency LevelledMobs = - new BQDependency("LevelledMobs", () -> QuestsAPI.registerMobFactory(new BQLevelledMobs())); + new BQDependency("LevelledMobs", () -> QuestsAPI.getAPI().registerMobFactory(new BQLevelledMobs())); - public static final BQDependency holod2 = new BQDependency("HolographicDisplays", () -> QuestsAPI.setHologramsManager(new BQHolographicDisplays2()), null, plugin -> plugin.getClass().getName().equals("com.gmail.filoghost.holographicdisplays.HolographicDisplays")); - public static final BQDependency holod3 = new BQDependency("HolographicDisplays", () -> QuestsAPI.setHologramsManager(new BQHolographicDisplays3()), null, plugin -> { + public static final BQDependency holod2 = new BQDependency("HolographicDisplays", () -> QuestsAPI.getAPI().setHologramsManager(new BQHolographicDisplays2()), null, plugin -> plugin.getClass().getName().equals("com.gmail.filoghost.holographicdisplays.HolographicDisplays")); + public static final BQDependency holod3 = new BQDependency("HolographicDisplays", () -> QuestsAPI.getAPI().setHologramsManager(new BQHolographicDisplays3()), null, plugin -> { if (!plugin.getClass().getName().equals("me.filoghost.holographicdisplays.plugin.HolographicDisplays")) // NOSONAR return false; @@ -109,24 +109,24 @@ public class DependenciesManager implements Listener { Class.forName("me.filoghost.holographicdisplays.api.HolographicDisplaysAPI"); return true; }catch (ClassNotFoundException ex) { - BeautyQuests.logger.warning("Your version of HolographicDisplays is unsupported. Please make sure you are running the LATEST dev build of HolographicDisplays."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of HolographicDisplays is unsupported. Please make sure you are running the LATEST dev build of HolographicDisplays."); return false; } }); - public static final BQDependency decentholograms = new BQDependency("DecentHolograms", () -> QuestsAPI.setHologramsManager(new BQDecentHolograms())); + public static final BQDependency decentholograms = new BQDependency("DecentHolograms", () -> QuestsAPI.getAPI().setHologramsManager(new BQDecentHolograms())); public static final BQDependency sentinel = new BQDependency("Sentinel", BQSentinel::initialize); public static final BQDependency wg = new BQDependency("WorldGuard", BQWorldGuard::initialize, BQWorldGuard::unload); - public static final BQDependency jobs = new BQDependency("Jobs", () -> QuestsAPI.getRequirements().register(new RequirementCreator("jobLevelRequired", JobLevelRequirement.class, ItemUtils.item(XMaterial.LEATHER_CHESTPLATE, Lang.RJobLvl.toString()), JobLevelRequirement::new))); - public static final BQDependency fac = new BQDependency("Factions", () -> QuestsAPI.getRequirements().register(new RequirementCreator("factionRequired", FactionRequirement.class, ItemUtils.item(XMaterial.WITHER_SKELETON_SKULL, Lang.RFaction.toString()), FactionRequirement::new))); + public static final BQDependency jobs = new BQDependency("Jobs", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("jobLevelRequired", JobLevelRequirement.class, ItemUtils.item(XMaterial.LEATHER_CHESTPLATE, Lang.RJobLvl.toString()), JobLevelRequirement::new))); + public static final BQDependency fac = new BQDependency("Factions", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("factionRequired", FactionRequirement.class, ItemUtils.item(XMaterial.WITHER_SKELETON_SKULL, Lang.RFaction.toString()), FactionRequirement::new))); public static final BQDependency acc = new BQDependency("AccountsHook"); - public static final BQDependency dyn = new BQDependency("dynmap", () -> QuestsAPI.registerQuestsHandler(new BQDynmap())); - public static final BQDependency BlueMap = new BQDependency("BlueMap", () -> QuestsAPI.registerQuestsHandler(new BQBlueMap())); + public static final BQDependency dyn = new BQDependency("dynmap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQDynmap())); + public static final BQDependency BlueMap = new BQDependency("BlueMap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQBlueMap())); public static final BQDependency gps = new BQDependency("GPS", GPS::init); - public static final BQDependency mmo = new BQDependency("mcMMO", () -> QuestsAPI.getRequirements().register(new RequirementCreator("mcmmoSklillLevelRequired", McMMOSkillRequirement.class, ItemUtils.item(XMaterial.IRON_CHESTPLATE, Lang.RSkillLvl.toString()), McMMOSkillRequirement::new))); - public static final BQDependency mclvl = new BQDependency("McCombatLevel", () -> QuestsAPI.getRequirements().register(new RequirementCreator("mcmmoCombatLevelRequirement", McCombatLevelRequirement.class, ItemUtils.item(XMaterial.IRON_SWORD, Lang.RCombatLvl.toString()), McCombatLevelRequirement::new))); + public static final BQDependency mmo = new BQDependency("mcMMO", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("mcmmoSklillLevelRequired", McMMOSkillRequirement.class, ItemUtils.item(XMaterial.IRON_CHESTPLATE, Lang.RSkillLvl.toString()), McMMOSkillRequirement::new))); + public static final BQDependency mclvl = new BQDependency("McCombatLevel", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("mcmmoCombatLevelRequirement", McCombatLevelRequirement.class, ItemUtils.item(XMaterial.IRON_SWORD, Lang.RCombatLvl.toString()), McCombatLevelRequirement::new))); public static final BQDependency tokenEnchant = new BQDependency("TokenEnchant", () -> Bukkit.getPluginManager().registerEvents(new BQTokenEnchant(), BeautyQuests.getInstance())); public static final BQDependency ultimateTimber = new BQDependency("UltimateTimber", () -> Bukkit.getPluginManager().registerEvents(new BQUltimateTimber(), BeautyQuests.getInstance())); public static final BQDependency PlayerBlockTracker = new BQDependency("PlayerBlockTracker"); @@ -163,7 +163,7 @@ public List<BQDependency> getDependencies() { public void addDependency(BQDependency dependency) { if (lockDependencies) { - BeautyQuests.logger.severe("Trying to add a BQ dependency for plugin " + dependency.pluginNames + " after final locking."); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Trying to add a BQ dependency for plugin " + dependency.pluginNames + " after final locking."); return; } dependencies.add(dependency); @@ -246,7 +246,7 @@ boolean testCompatibility(boolean after) { Plugin plugin = pluginNames.stream().map(Bukkit.getPluginManager()::getPlugin).filter(x -> x != null && x.isEnabled()).findAny().orElse(null); if (plugin == null) return false; if (isValid != null && !isValid.test(plugin)) return false; - DebugUtils.logMessage("Hooked into " + pluginNames + " v" + plugin.getDescription().getVersion() + (after ? " after primary initialization" : "")); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Hooked into " + pluginNames + " v" + plugin.getDescription().getVersion() + (after ? " after primary initialization" : "")); enabled = true; foundPlugin = plugin; return true; @@ -257,7 +257,7 @@ void initialize() { if (initialize != null) initialize.run(); initialized = true; }catch (Throwable ex) { - BeautyQuests.logger.severe("An error occurred while initializing " + pluginNames.toString() + " integration", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while initializing " + pluginNames.toString() + " integration", ex); enabled = false; } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java index 20d2ce16..2072b0dc 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Paper.java @@ -4,14 +4,14 @@ import java.util.function.Predicate; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.utils.nms.NMS; +import fr.skytasul.quests.api.utils.MinecraftVersion; public final class Paper { private Paper() {} public static void handleDeathItems(PlayerDeathEvent event, Predicate<ItemStack> predicate) { - if (NMS.getMCVersion() < 13) return; + if (MinecraftVersion.MAJOR < 13) return; for (Iterator<ItemStack> iterator = event.getDrops().iterator(); iterator.hasNext();) { ItemStack item = iterator.next(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java index 77c775cf..26c15dc2 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java @@ -22,13 +22,14 @@ import org.bukkit.scheduler.BukkitTask; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayerQuestDatas; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.structure.QuestBranch.Source; -import fr.skytasul.quests.utils.ChatUtils; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.ChatColorUtils; import me.clip.placeholderapi.PlaceholderAPI; import me.clip.placeholderapi.events.ExpansionRegisterEvent; import me.clip.placeholderapi.expansion.PlaceholderExpansion; @@ -63,7 +64,7 @@ static void registerPlaceholders(ConfigurationSection placeholderConfig) { placeholders = new QuestsPlaceholders(placeholderConfig); placeholders.register(); Bukkit.getPluginManager().registerEvents(placeholders, BeautyQuests.getInstance()); - BeautyQuests.getInstance().getLogger().info("Placeholders registered !"); + QuestsPlugin.getPlugin().getLoggerExpanded().info("Placeholders registered !"); } public static void waitForExpansion(String identifier, Consumer<PlaceholderExpansion> callback) { @@ -102,15 +103,21 @@ public List<String> getPlaceholders() { @Override public String onRequest(OfflinePlayer off, String identifier) { - if (identifier.equals("total_amount")) return "" + QuestsAPI.getQuests().getQuestsAmount(); + if (identifier.equals("total_amount")) + return "" + QuestsAPI.getAPI().getQuestsManager().getQuests().size(); if (!off.isOnline()) return "§cerror: offline"; Player p = off.getPlayer(); PlayerAccount acc = PlayersManager.getPlayerAccount(p); if (acc == null) return "§cdatas not loaded"; - if (identifier.equals("player_inprogress_amount")) return "" + acc.getQuestsDatas().stream().filter(PlayerQuestDatas::hasStarted).count(); - if (identifier.equals("player_finished_amount")) return "" + acc.getQuestsDatas().stream().filter(PlayerQuestDatas::isFinished).count(); - if (identifier.equals("player_finished_total_amount")) return "" + acc.getQuestsDatas().stream().mapToInt(PlayerQuestDatas::getTimesFinished).sum(); - if (identifier.equals("started_id_list")) return acc.getQuestsDatas().stream().filter(PlayerQuestDatas::hasStarted).map(x -> Integer.toString(x.getQuestID())).collect(Collectors.joining(";")); + if (identifier.equals("player_inprogress_amount")) + return "" + acc.getQuestsDatas().stream().filter(PlayerQuestDatas::hasStarted).count(); + if (identifier.equals("player_finished_amount")) + return "" + acc.getQuestsDatas().stream().filter(PlayerQuestDatas::isFinished).count(); + if (identifier.equals("player_finished_total_amount")) + return "" + acc.getQuestsDatas().stream().mapToInt(PlayerQuestDatas::getTimesFinished).sum(); + if (identifier.equals("started_id_list")) + return acc.getQuestsDatas().stream().filter(PlayerQuestDatas::hasStarted) + .map(x -> Integer.toString(x.getQuestID())).collect(Collectors.joining(";")); if (identifier.equals("started")) { return acc.getQuestsDatas() @@ -120,7 +127,7 @@ public String onRequest(OfflinePlayer off, String identifier) { .filter(Objects::nonNull) .filter(Quest::isScoreboardEnabled) .map(quest -> { - String desc = quest.getDescriptionLine(acc, Source.PLACEHOLDER); + String desc = quest.getDescriptionLine(acc, DescriptionSource.PLACEHOLDER); return inlineFormat .replace("{questName}", quest.getName()) .replace("{questDescription}", desc); @@ -142,8 +149,8 @@ public String onRequest(OfflinePlayer off, String identifier) { } if (data.left.isEmpty()) { - data.left = QuestsAPI.getQuests().getQuestsStarted(data.acc, false, true); - }else QuestsAPI.getQuests().updateQuestsStarted(acc, true, data.left); + data.left = QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(data.acc, false, true); + }else QuestsAPI.getAPI().getQuestsManager().updateQuestsStarted(acc, true, data.left); try { int i = -1; @@ -160,14 +167,14 @@ public String onRequest(OfflinePlayer off, String identifier) { if (data.left.isEmpty()) return i == -1 || i == 0 ? Lang.SCOREBOARD_NONE.toString() : ""; Quest quest = data.left.get(0); - String desc = quest.getDescriptionLine(acc, Source.PLACEHOLDER); + String desc = quest.getDescriptionLine(acc, DescriptionSource.PLACEHOLDER); String format = noSplit ? inlineFormat : splitFormat; format = format.replace("{questName}", quest.getName()).replace("{questDescription}", desc); if (noSplit) return format; try { - List<String> lines = ChatUtils.wordWrap(format, lineLength); + List<String> lines = ChatColorUtils.wordWrap(format, lineLength); if (i >= lines.size()) return ""; return lines.get(i); }catch (Exception ex) { @@ -175,7 +182,7 @@ public String onRequest(OfflinePlayer off, String identifier) { return "§c" + ex.getMessage(); } }catch (Exception ex) { - BeautyQuests.logger.warning("An error occurred while parsing palceholder " + identifier + " for " + p.getName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An error occurred while parsing palceholder " + identifier + " for " + p.getName(), ex); return "§cinvalid placeholder"; } }finally { @@ -187,11 +194,11 @@ public String onRequest(OfflinePlayer off, String identifier) { int rawId = identifier.indexOf("_raw"); String sid = rawId == -1 ? identifier.substring(12) : identifier.substring(12, rawId); try { - Quest qu = QuestsAPI.getQuests().getQuest(Integer.parseInt(sid)); + Quest qu = QuestsAPI.getAPI().getQuestsManager().getQuest(Integer.parseInt(sid)); if (qu == null) return "§c§lError: unknown quest §o" + sid; if (rawId == -1) { if (qu.hasStarted(acc)) { - return qu.getDescriptionLine(acc, Source.PLACEHOLDER); + return qu.getDescriptionLine(acc, DescriptionSource.PLACEHOLDER); } if (qu.hasFinished(acc)) return Lang.Finished.toString(); return Lang.Not_Started.toString(); @@ -208,7 +215,7 @@ public String onRequest(OfflinePlayer off, String identifier) { if (identifier.startsWith("player_quest_finished_")) { String sid = identifier.substring(22); try { - Quest qu = QuestsAPI.getQuests().getQuest(Integer.parseInt(sid)); + Quest qu = QuestsAPI.getAPI().getQuestsManager().getQuest(Integer.parseInt(sid)); if (qu == null) return "§c§lError: unknown quest §o" + sid; if (!acc.hasQuestDatas(qu)) return "0"; return Integer.toString(acc.getQuestDatas(qu).getTimesFinished()); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/AbstractMapIntegration.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/AbstractMapIntegration.java index a7a73130..0d97b31d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/AbstractMapIntegration.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/AbstractMapIntegration.java @@ -1,13 +1,12 @@ package fr.skytasul.quests.utils.compatibility.maps; import org.bukkit.Location; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsHandler; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.options.OptionVisibility.VisibilityLocation; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.DebugUtils; public abstract class AbstractMapIntegration implements QuestsHandler { @@ -18,7 +17,8 @@ public final void load() { } private void initializeQuests() { - if (QuestsAPI.getQuests() != null) QuestsAPI.getQuests().forEach(this::questLoaded); + if (QuestsAPI.getAPI().getQuestsManager() != null) + QuestsAPI.getAPI().getQuestsManager().getQuests().forEach(this::questLoaded); } @Override @@ -27,14 +27,14 @@ public void questLoaded(Quest quest) { return; if (!quest.hasOption(OptionStarterNPC.class)) return; - if (quest.isHidden(VisibilityLocation.MAPS)) { - DebugUtils.logMessage("No marker created for quest " + quest.getID() + ": quest is hidden"); + if (quest.isHidden(QuestVisibilityLocation.MAPS)) { + QuestsPlugin.getPlugin().getLoggerExpanded().debug("No marker created for quest " + quest.getId() + ": quest is hidden"); return; } Location lc = quest.getOptionValueOrDef(OptionStarterNPC.class).getLocation(); if (lc == null) { - BeautyQuests.logger.warning("Cannot create map marker for quest #" + quest.getID() + " (" + quest.getName() + ")"); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot create map marker for quest #" + quest.getId() + " (" + quest.getName() + ")"); }else { addMarker(quest, lc); } @@ -42,7 +42,7 @@ public void questLoaded(Quest quest) { @Override public void questUnload(Quest quest) { - if (!quest.isHidden(VisibilityLocation.MAPS) && quest.hasOption(OptionStarterNPC.class)) removeMarker(quest); + if (!quest.isHidden(QuestVisibilityLocation.MAPS) && quest.hasOption(OptionStarterNPC.class)) removeMarker(quest); } public abstract boolean isEnabled(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java index 1f2023b7..c32e4597 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java @@ -2,12 +2,11 @@ import java.util.function.Consumer; import org.bukkit.Location; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.DebugUtils; import de.bluecolored.bluemap.api.BlueMapAPI; import de.bluecolored.bluemap.api.BlueMapMap; import de.bluecolored.bluemap.api.BlueMapWorld; @@ -35,12 +34,12 @@ protected void initializeMarkers(Runnable initializeQuests) { .defaultHidden(false) .toggleable(true) .build(); - DebugUtils.logMessage("Enabled BlueMap integration."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Enabled BlueMap integration."); initializeQuests.run(); }catch (Exception e) { - BeautyQuests.logger.severe("An error occurred while loading BlueMap integration.", e); - QuestsAPI.unregisterQuestsHandler(this); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while loading BlueMap integration.", e); + QuestsAPI.getAPI().unregisterQuestsHandler(this); } }); } @@ -64,10 +63,10 @@ protected void addMarker(Quest quest, Location lc) { .icon(QuestsConfiguration.dynmapMarkerIcon(), 0, 0) .position(lc.getBlockX(), lc.getBlockY(), lc.getBlockZ()) .build(); - set.getMarkers().put("qu_" + quest.getID() + "_" + i++, marker); + set.getMarkers().put("qu_" + quest.getId() + "_" + i++, marker); map.getMarkerSets().putIfAbsent(MARKERSET_ID, set); } - DebugUtils.logMessage("Added " + i + " BlueMap markers for quest " + quest.getID()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Added " + i + " BlueMap markers for quest " + quest.getId()); }); }); } @@ -78,7 +77,7 @@ public void removeMarker(Quest quest) { Location lc = quest.getOptionValueOrDef(OptionStarterNPC.class).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); + set.getMarkers().remove("qu_" + quest.getId() + "_" + i); } }); }); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java index 5bb90e4d..16167ff0 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java @@ -7,10 +7,9 @@ import org.dynmap.markers.MarkerAPI; import org.dynmap.markers.MarkerIcon; import org.dynmap.markers.MarkerSet; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.structure.Quest; -import fr.skytasul.quests.utils.DebugUtils; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.quests.Quest; import net.md_5.bungee.api.ChatColor; public class BQDynmap extends AbstractMapIntegration { @@ -53,20 +52,20 @@ public void unload() { public void addMarker(Quest quest, Location lc) { if (markers == null) return; - Marker marker = markers.createMarker("qu_" + quest.getID(), ChatColor.stripColor(quest.getName()), lc.getWorld().getName(), lc.getX(), lc.getBlockY(), lc.getBlockZ(), icon, false); + Marker marker = markers.createMarker("qu_" + quest.getId(), ChatColor.stripColor(quest.getName()), lc.getWorld().getName(), lc.getX(), lc.getBlockY(), lc.getBlockZ(), icon, false); if (marker == null) { - BeautyQuests.logger.severe("Problem when creating marker for quest " + quest.getID()); - }else DebugUtils.logMessage("Marker " + marker.getMarkerID() + " created"); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Problem when creating marker for quest " + quest.getId()); + }else QuestsPlugin.getPlugin().getLoggerExpanded().debug("Marker " + marker.getMarkerID() + " created"); } @Override public void removeMarker(Quest quest) { if (markers == null) return; - Marker marker = markers.findMarker("qu_" + quest.getID()); + Marker marker = markers.findMarker("qu_" + quest.getId()); if (marker == null) { - BeautyQuests.logger.warning("Unable to find marker for quest " + quest.getID()); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unable to find marker for quest " + quest.getId()); }else marker.deleteMarker(); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java index 50e1d6e5..b44b873f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java @@ -7,10 +7,10 @@ import org.bukkit.event.EventHandler; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +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.editors.TextEditor; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.utils.Lang; import gcspawners.AdvancedEntityDeathEvent; public class BQAdvancedSpawners implements MobFactory<String> { @@ -33,7 +33,7 @@ public ItemStack getFactoryItem() { @Override public void itemClick(Player p, Consumer<String> run) { Lang.ADVANCED_SPAWNERS_MOB.send(p); - new TextEditor<>(p, () -> run.accept(null), run).enter(); + new TextEditor<>(p, () -> run.accept(null), run).start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java index b50d3731..40832fa5 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java @@ -15,13 +15,12 @@ import org.mineacademy.boss.api.event.BossDeathEvent; import org.mineacademy.boss.model.Boss; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.MobFactory; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.MinecraftNames; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.Utils; public class BQBoss implements MobFactory<Boss> { @@ -46,10 +45,10 @@ public ItemStack getItemStack(Boss object) { @Override public void click(Boss existing, ItemStack item, ClickType clickType) { - Inventories.closeAndExit(p); + close(); run.accept(existing); } - }.create(p); + }.open(p); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java index 25a6c861..dbc09962 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java @@ -9,8 +9,8 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.mobs.LeveledMobFactory; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; import me.lokka30.levelledmobs.LevelledMobs; @@ -30,7 +30,7 @@ public ItemStack getFactoryItem() { @Override public void itemClick(Player p, Consumer<EntityType> run) { - new EntityTypeGUI(run, x -> x != null && x.isAlive()).create(p); + new EntityTypeGUI(run, x -> x != null && x.isAlive()).open(p); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQWildStacker.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQWildStacker.java index b9c6a18d..044b7463 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQWildStacker.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQWildStacker.java @@ -11,7 +11,7 @@ public class BQWildStacker implements Listener { private BQWildStacker() {} public static void initialize() { - QuestsAPI.registerMobStacker(entity -> { + QuestsAPI.getAPI().registerMobStacker(entity -> { if (entity instanceof LivingEntity && !(entity instanceof Player)) return WildStackerAPI.getEntityAmount((LivingEntity) entity); return 1; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java index 3ce2aab9..3aa42a4e 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java @@ -12,11 +12,11 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +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.gui.ItemUtils; +import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.MinecraftNames; public class BukkitEntityFactory implements MobFactory<EntityType> { @@ -33,7 +33,7 @@ public ItemStack getFactoryItem() { @Override public void itemClick(Player p, Consumer<EntityType> run) { - new EntityTypeGUI(run, x -> x != null).create(p); + new EntityTypeGUI(run, x -> x != null).open(p); } @Override @@ -70,7 +70,7 @@ public List<String> getDescriptiveLore(EntityType data) { public void onEntityKilled(EntityDeathEvent e) { LivingEntity en = e.getEntity(); if (en.getKiller() == null) return; - if (QuestsAPI.getNPCsManager().isNPC(en)) return; + if (QuestsAPI.getAPI().getNPCsManager().isNPC(en)) return; callEvent(e, en.getType(), en, en.getKiller()); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java index b3220a78..e866a0e5 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java @@ -10,11 +10,10 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.inventory.ItemStack; +import fr.skytasul.quests.api.editors.CancellableEditor; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.MobFactory; -import fr.skytasul.quests.editors.CancellableEditor; -import fr.skytasul.quests.gui.npc.SelectGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.gui.npc.NpcSelectGUI; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.NPCDeathEvent; import net.citizensnpcs.api.event.NPCRightClickEvent; @@ -30,29 +29,32 @@ public String getID() { @Override public ItemStack getFactoryItem() { - return SelectGUI.selectNPC; + return NpcSelectGUI.selectNPC; } @Override public void itemClick(Player p, Consumer<NPC> run) { Lang.SELECT_KILL_NPC.send(p); + // we cannot use the SelectNPC editor as it uses the BQNPCManager + // and if it is registered to another NPC plugin it wouldn't work new CancellableEditor(p, () -> run.accept(null)) { - - @EventHandler (priority = EventPriority.LOW) + + @EventHandler(priority = EventPriority.LOW) private void onNPCClick(NPCRightClickEvent e) { - if (e.getClicker() != p) return; + if (e.getClicker() != player) + return; e.setCancelled(true); - leave(e.getClicker()); + stop(); run.accept(e.getNPC()); } - + @Override public void begin() { super.begin(); - Utils.sendMessage(p, Lang.NPC_EDITOR_ENTER.toString()); + Lang.NPC_EDITOR_ENTER.send(p); } - - }.enter(); + + }.start(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java index 976bca45..7b29e8d9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java @@ -11,15 +11,15 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.Utils; import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; import io.lumine.xikage.mythicmobs.mobs.MythicMob; import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderString; @@ -47,17 +47,17 @@ public ItemStack getItemStack(MythicMob object) { mobItem = Utils.mobItem(getEntityType(object)); }catch (Exception ex) { mobItem = XMaterial.SPONGE; - BeautyQuests.logger.warning("Unknow entity type for MythicMob " + object.getInternalName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unknow entity type for MythicMob " + object.getInternalName(), ex); } return ItemUtils.item(mobItem, object.getInternalName()); } @Override public void click(MythicMob existing, ItemStack item, ClickType clickType) { - Inventories.closeAndExit(p); + close(); run.accept(existing); } - }.sortValues(MythicMob::getInternalName).create(p); + }.sortValues(MythicMob::getInternalName).open(p); } @Override @@ -102,7 +102,7 @@ public EntityType getEntityType(MythicMob data) { } if (typeName.contains("BABY_")) typeName = typeName.substring(5); if (typeName.equalsIgnoreCase("MPET")) typeName = data.getConfig().getString("MPet.Anchor"); - if (NMS.getMCVersion() < 11 && typeName.equals("WITHER_SKELETON")) typeName = "SKELETON"; + if (MinecraftVersion.MAJOR < 11 && typeName.equals("WITHER_SKELETON")) typeName = "SKELETON"; EntityType type = EntityType.fromName(typeName); if (type == null) { try { @@ -132,12 +132,12 @@ public void onMythicDeath(MythicMobDeathEvent e) { } public static void sendMythicMobsList(Player p){ - Utils.sendMessage(p, Lang.MYTHICMOB_LIST.toString()); + Lang.MYTHICMOB_LIST.send(p); StringBuilder stb = new StringBuilder("§a"); for (MythicMob mm : io.lumine.xikage.mythicmobs.MythicMobs.inst().getMobManager().getMobTypes()) { stb.append(mm.getInternalName() + "; "); } - Utils.sendMessage(p, stb.toString()); + MessageUtils.sendUnprefixedMessage(p, stb.toString()); } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java index be69ece0..094318ff 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java @@ -12,15 +12,15 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.ItemUtils; -import fr.skytasul.quests.gui.templates.PagedGUI; -import fr.skytasul.quests.utils.Lang; -import fr.skytasul.quests.utils.Utils; -import fr.skytasul.quests.utils.nms.NMS; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.Utils; import io.lumine.mythic.api.mobs.MythicMob; import io.lumine.mythic.api.skills.placeholders.PlaceholderString; import io.lumine.mythic.bukkit.MythicBukkit; @@ -49,17 +49,17 @@ public ItemStack getItemStack(MythicMob object) { mobItem = Utils.mobItem(getEntityType(object)); }catch (Exception ex) { mobItem = XMaterial.SPONGE; - BeautyQuests.logger.warning("Unknow entity type for MythicMob " + object.getInternalName(), ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unknow entity type for MythicMob " + object.getInternalName(), ex); } return ItemUtils.item(mobItem, object.getInternalName()); } @Override public void click(MythicMob existing, ItemStack item, ClickType clickType) { - Inventories.closeAndExit(p); + close(); run.accept(existing); } - }.sortValues(MythicMob::getInternalName).create(p); + }.sortValues(MythicMob::getInternalName).open(p); } @Override @@ -104,7 +104,7 @@ public EntityType getEntityType(MythicMob data) { if (typeName.contains("BABY_")) typeName = typeName.substring(5); if (typeName.equalsIgnoreCase("MPET")) typeName = data.getConfig().getString("MPet.Anchor"); - if (NMS.getMCVersion() < 11 && typeName.equals("WITHER_SKELETON")) typeName = "SKELETON"; + if (MinecraftVersion.MAJOR < 11 && typeName.equals("WITHER_SKELETON")) typeName = "SKELETON"; EntityType type = EntityType.fromName(typeName); if (type == null) { try { @@ -122,7 +122,7 @@ public List<String> getDescriptiveLore(MythicMob data) { QuestOption.formatDescription("Base Damage: " + Objects.toString(data.getDamage())), QuestOption.formatDescription("Base Armor: " + Objects.toString(data.getArmor()))); } catch (Throwable ex) { - BeautyQuests.logger.warning("An error occurred while showing mob description", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An error occurred while showing mob description", ex); return Arrays.asList("§cError when retrieving mob informations"); } } @@ -135,12 +135,12 @@ public void onMythicDeath(MythicMobDeathEvent e) { } public static void sendMythicMobsList(Player p){ - Utils.sendMessage(p, Lang.MYTHICMOB_LIST.toString()); + Lang.MYTHICMOB_LIST.send(p); StringBuilder stb = new StringBuilder("§a"); for (MythicMob mm : MythicBukkit.inst().getMobManager().getMobTypes()) { stb.append(mm.getInternalName() + "; "); } - Utils.sendMessage(p, stb.toString()); + MessageUtils.sendUnprefixedMessage(p, stb.toString()); } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java index 707756e7..18687839 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java @@ -10,8 +10,8 @@ import org.bukkit.event.EventPriority; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration.ClickType; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.npcs.BQNPCsManager; import net.citizensnpcs.Settings; @@ -67,13 +67,13 @@ public void onNPCRemove(NPCRemoveEvent e) { @EventHandler public void onCitizensReload(CitizensReloadEvent e) { - BeautyQuests.logger.warning("Citizens has been reloaded whereas it is highly not recommended for plugins compatibilities. Unexpected behaviors may happen."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Citizens has been reloaded whereas it is highly not recommended for plugins compatibilities. Unexpected behaviors may happen."); npcs.forEach((id, npc) -> { if (npc instanceof BQCitizensNPC) { BQCitizensNPC bqnpc = (BQCitizensNPC) npc; NPC cnpc = CitizensAPI.getNPCRegistry().getById(id); if (cnpc == null) { - BeautyQuests.logger.warning("Unable to find NPC with ID " + id + " after a Citizens reload."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unable to find NPC with ID " + id + " after a Citizens reload."); }else { bqnpc.npc = cnpc; } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java index a95dc52f..67fca6fa 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java @@ -6,9 +6,9 @@ import org.mcmonkey.sentinel.SentinelIntegration; import org.mcmonkey.sentinel.SentinelPlugin; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.players.PlayerAccount; -import fr.skytasul.quests.players.PlayersManager; -import fr.skytasul.quests.structure.Quest; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.players.PlayerAccountImplementation; +import fr.skytasul.quests.structure.QuestImplementation; public class BQSentinel { @@ -39,20 +39,20 @@ public String[] getTargetPrefixes() { public boolean isTarget(LivingEntity ent, String prefix, String value) { switch (prefix) { case "quest_in": - return test(ent, value, Quest::hasStarted); + return test(ent, value, QuestImplementation::hasStarted); case "quest_finished": - return test(ent, value, Quest::hasFinished); + return test(ent, value, QuestImplementation::hasFinished); } return false; } - private boolean test(LivingEntity ent, String value, BiPredicate<Quest, PlayerAccount> test) { + private boolean test(LivingEntity ent, String value, BiPredicate<QuestImplementation, PlayerAccountImplementation> test) { if (ent instanceof Player) { PlayerAccount acc = PlayersManager.getPlayerAccount((Player) ent); if (acc != null) { try { int questID = Integer.parseInt(value); - Quest quest = QuestsAPI.getQuests().getQuest(questID); + Quest quest = QuestsAPI.getAPI().getQuestsManager().getQuest(questID); return quest != null && test.test(quest, acc); }catch (NumberFormatException ex) {} } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java index c0c82eb9..e8c27248 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java @@ -12,13 +12,13 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion; import com.sk89q.worldguard.session.SessionManager; import fr.skytasul.quests.api.QuestsAPI; +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.requirements.RequirementCreator; import fr.skytasul.quests.api.stages.StageType; -import fr.skytasul.quests.gui.ItemUtils; import fr.skytasul.quests.requirements.RegionRequirement; import fr.skytasul.quests.stages.StageArea; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; import fr.skytasul.quests.utils.compatibility.MissingDependencyException; public class BQWorldGuard { @@ -48,7 +48,7 @@ protected BQWorldGuard() { SessionManager sessionManager = com.sk89q.worldguard.WorldGuard.getInstance().getPlatform().getSessionManager(); if (WorldGuardEntryHandler.FACTORY.register(sessionManager)) { handleEntry = true; - DebugUtils.logMessage("Now using WorldGuard entry API."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Now using WorldGuard entry API."); WorldGuardEntryHandler.FACTORY.registerSessions(sessionManager); } @@ -68,7 +68,7 @@ private void disable() { if (handleEntry) { handleEntry = false; WorldGuardEntryHandler.FACTORY.unregister(com.sk89q.worldguard.WorldGuard.getInstance().getPlatform().getSessionManager()); - DebugUtils.logMessage("Unregistered from WorldGuard entry API."); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Unregistered from WorldGuard entry API."); } } @@ -118,9 +118,9 @@ public static void initialize() { Validate.isTrue(instance == null, "BQ WorldGuard integration already initialized."); instance = new BQWorldGuard(); - QuestsAPI.getStages().register(new StageType<>("REGION", StageArea.class, Lang.Find.name(), StageArea::deserialize, + QuestsAPI.getAPI().getStages().register(new StageType<>("REGION", StageArea.class, Lang.Find.name(), StageArea::deserialize, ItemUtils.item(XMaterial.WOODEN_AXE, Lang.stageGoTo.toString()), StageArea.Creator::new)); - QuestsAPI.getRequirements().register(new RequirementCreator("regionRequired", RegionRequirement.class, ItemUtils.item(XMaterial.WOODEN_AXE, Lang.RRegion.toString()), RegionRequirement::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("regionRequired", RegionRequirement.class, ItemUtils.item(XMaterial.WOODEN_AXE, Lang.RRegion.toString()), RegionRequirement::new)); } public static void unload() { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java index bbcb5a1e..44a45a1f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java @@ -53,7 +53,7 @@ public WorldGuardEntryHandler(Session session) { @Override public boolean onCrossBoundary(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) { Player bukkitPlayer = BukkitAdapter.adapt(player); - if (!QuestsAPI.getNPCsManager().isNPC(bukkitPlayer)) { + if (!QuestsAPI.getAPI().getNPCsManager().isNPC(bukkitPlayer)) { Bukkit.getPluginManager().callEvent(new WorldGuardEntryEvent(bukkitPlayer, entered)); Bukkit.getPluginManager().callEvent(new WorldGuardExitEvent(bukkitPlayer, exited)); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerHandler.java b/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerHandler.java index 2ce7dc39..1bcd2136 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerHandler.java +++ b/core/src/main/java/fr/skytasul/quests/utils/logger/LoggerHandler.java @@ -19,7 +19,8 @@ import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.logger.ILoggerHandler; public class LoggerHandler extends Handler implements ILoggerHandler { 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 edee7d1c..82e3de94 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 @@ -4,12 +4,12 @@ import java.lang.reflect.Method; import java.util.List; import java.util.Map; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.meta.ItemMeta; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.ReflectUtils; import io.netty.buffer.ByteBuf; @@ -71,47 +71,25 @@ public static boolean isValid() { return versionValid; } - public static int getMCVersion() { - return versionMajor; - } - - public static int getNMSMinorVersion() { - return versionMinorNMS; - } - - public static String getVersionString() { - return versionString; - } - private static boolean versionValid = false; private static NMS nms; - private static int versionMajor; - private static int versionMinorNMS; - private static String versionString; static { - versionString = Bukkit.getBukkitVersion().split("-R")[0]; - String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3].substring(1); - String[] versions = version.split("_"); - versionMajor = Integer.parseInt(versions[1]); // 1.X - if (versionMajor >= 17) { - // e.g. Bukkit.getBukkitVersion() -> 1.17.1-R0.1-SNAPSHOT - versions = versionString.split("\\."); - versionMinorNMS = versions.length <= 2 ? 0 : Integer.parseInt(versions[2]); - }else versionMinorNMS = Integer.parseInt(versions[2].substring(1)); // 1.X.Y - try { - nms = (NMS) Class.forName("fr.skytasul.quests.utils.nms.v" + version).newInstance(); + nms = (NMS) Class.forName("fr.skytasul.quests.utils.nms.v" + MinecraftVersion.VERSION_NMS).newInstance(); versionValid = true; - BeautyQuests.logger.info("Loaded valid Minecraft version " + version + "."); + QuestsPlugin.getPlugin().getLoggerExpanded() + .info("Loaded valid Minecraft version " + MinecraftVersion.VERSION_NMS + "."); }catch (ClassNotFoundException ex) { - BeautyQuests.logger.warning("The Minecraft version " + version + " is not supported by BeautyQuests."); + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("The Minecraft version " + MinecraftVersion.VERSION_NMS + " is not supported by BeautyQuests."); }catch (Exception ex) { - BeautyQuests.logger.warning("An error ocurred when loading Minecraft Server version " + version + " compatibilities.", ex); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("An error ocurred when loading Minecraft Server version " + + MinecraftVersion.VERSION_NMS + " compatibilities.", ex); } if (!versionValid) { nms = new NullNMS(); - BeautyQuests.logger.warning("Some functionnalities of the plugin have not been enabled."); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Some functionnalities of the plugin have not been enabled."); } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java b/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java index d3745392..7cde80e9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java @@ -14,7 +14,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.Located; import fr.skytasul.quests.api.stages.types.Locatable.Located.LocatedBlock; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.utils.compatibility.Post1_13; public abstract class BQBlock { diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java index 2e4306d9..bb62b176 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java @@ -6,7 +6,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.utils.DebugUtils; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; @@ -30,7 +30,7 @@ public void execute(Player o){ if (parse && DependenciesManager.papi.isEnabled()) formattedcmd = QuestsPlaceholders.setPlaceholders(o, formattedcmd); CommandSender sender = console ? Bukkit.getConsoleSender() : o; Bukkit.dispatchCommand(sender, formattedcmd); - DebugUtils.logMessage(sender.getName() + " performed command " + formattedcmd); + QuestsPlugin.getPlugin().getLoggerExpanded().debug(sender.getName() + " performed command " + formattedcmd); }; if (delay == 0 && Bukkit.isPrimaryThread()) { run.run(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunner.java b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/utils/types/DialogRunner.java rename to core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java index ec662ab5..6d27d8af 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunner.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java @@ -11,13 +11,17 @@ import org.bukkit.scheduler.BukkitTask; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.DialogSendEvent; import fr.skytasul.quests.api.events.DialogSendMessageEvent; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; +import fr.skytasul.quests.api.npcs.dialogs.Message; import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.Lang; -public class DialogRunner { +public class DialogRunnerImplementation implements DialogRunner { private final Dialog dialog; private final BQNPC npc; @@ -29,19 +33,22 @@ public class DialogRunner { private Map<Player, PlayerStatus> players = new HashMap<>(); private Boolean navigationInitiallyPaused = null; - public DialogRunner(Dialog dialog, BQNPC npc) { + public DialogRunnerImplementation(Dialog dialog, BQNPC npc) { this.dialog = dialog; this.npc = npc; } + @Override public void addTest(Predicate<Player> test) { tests.add(test); } + @Override public void addTestCancelling(Predicate<Player> test) { testsCancelling.add(test); } + @Override public void addEndAction(Consumer<Player> action) { endActions.add(action); } @@ -54,13 +61,7 @@ private TestResult test(Player p) { return TestResult.ALLOW; } - /** - * Tests if the player is close enough to the NPC for the dialog to continue. - * <p> - * This is <i>not</i> tested on player click, only for automatic messages with durations. - * @param p Player to check the distance from the NPC - * @return <code>true</code> if the player is close enough to the NPC or if the distance feature is disabled, <code>false</code> otherwise. - */ + @Override public boolean canContinue(Player p) { if (npc == null || QuestsConfiguration.getDialogsConfig().getMaxDistance() == 0) return true; return p.getLocation().distanceSquared(npc.getLocation()) <= QuestsConfiguration.getDialogsConfig().getMaxDistanceSquared(); @@ -68,7 +69,7 @@ public boolean canContinue(Player p) { private void end(Player p) { if (test(p) != TestResult.ALLOW) { - BeautyQuests.logger.warning("Dialog predicates not completed for NPC " + npc.getId() + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Dialog predicates not completed for NPC " + npc.getId() + " whereas the dialog should end. This is a bug."); return; } @@ -76,12 +77,7 @@ private void end(Player p) { endActions.forEach(x -> x.accept(p)); } - /** - * Must be called when the player clicks on the NPC. - * This will send the dialog to the player if conditions are met. - * @param p player which - * @return the result of tests to run this dialog - */ + @Override public TestResult onClick(Player p) { if (QuestsConfiguration.getDialogsConfig().isClickDisabled()) { PlayerStatus status = players.get(p); @@ -97,6 +93,7 @@ public TestResult onClick(Player p) { return handleNext(p, DialogNextReason.NPC_CLICK); } + @Override public TestResult handleNext(Player p, DialogNextReason reason) { TestResult test = test(p); if (test == TestResult.ALLOW) { @@ -120,7 +117,7 @@ public TestResult handleNext(Player p, DialogNextReason reason) { end(p); }else { // when dialog not finished, launch task if needed - Message message = dialog.messages.get(status.lastId); + Message message = dialog.getMessages().get(status.lastId); if (message.getWaitTime() != 0) { status.task = Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), () -> { status.task = null; @@ -151,10 +148,11 @@ public TestResult handleNext(Player p, DialogNextReason reason) { * @return <code>true</code> if the dialog ends following this call, <code>false</code>otherwise */ private boolean send(Player p, PlayerStatus status, DialogNextReason reason) { - if (dialog.messages.isEmpty()) return true; + if (dialog.getMessages().isEmpty()) + return true; int id = ++status.lastId; - boolean endOfDialog = id == dialog.messages.size(); + boolean endOfDialog = id == dialog.getMessages().size(); if (status.runningMsg != null) status.runningMsg.finished(p, endOfDialog, reason != DialogNextReason.AUTO_TIME); @@ -162,7 +160,7 @@ private boolean send(Player p, PlayerStatus status, DialogNextReason reason) { if (endOfDialog) return true; - Message msg = dialog.messages.get(id); + Message msg = dialog.getMessages().get(id); if (msg == null) { p.sendMessage("§cMessage with ID " + id + " does not exist. Please report this to an adminstrator. Method caller: " + DebugUtils.stackTraces(2, 3)); return true; @@ -172,15 +170,17 @@ private boolean send(Player p, PlayerStatus status, DialogNextReason reason) { DialogSendMessageEvent event = new DialogSendMessageEvent(dialog, msg, npc, p); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) - status.runningMsgTask = msg.sendMessage(p, dialog.getNPCName(npc), id, dialog.messages.size()); + status.runningMsgTask = msg.sendMessage(p, dialog.getNPCName(npc), id, dialog.getMessages().size()); return false; } + @Override public boolean isPlayerInDialog(Player p) { return players.containsKey(p); } + @Override public int getPlayerMessage(Player p) { return players.get(p).lastId; } @@ -199,6 +199,7 @@ public PlayerStatus addPlayer(Player player) { return status; } + @Override public boolean removePlayer(Player player) { PlayerStatus status = players.remove(player); if (status == null) return false; @@ -237,22 +238,4 @@ void cancel() { } } - public enum DialogNextReason { - NPC_CLICK, AUTO_TIME, COMMAND, PLUGIN; - } - - public enum TestResult { - ALLOW, DENY, DENY_CANCEL; - - public TestResult accumulate(TestResult other) { - if (this == DENY_CANCEL || other == DENY_CANCEL) return DENY_CANCEL; - if (this == DENY || other == DENY) return DENY; - return ALLOW; - } - - public boolean shouldCancel() { - return this == DENY_CANCEL || this == ALLOW; - } - } - } diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java b/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java index d21d8d7c..657800c9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import fr.skytasul.quests.utils.Utils; +import fr.skytasul.quests.api.utils.Utils; public class NumberedList<T> implements Iterable<T>, Cloneable{ diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Title.java b/core/src/main/java/fr/skytasul/quests/utils/types/Title.java index 10382c1a..adb7690c 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Title.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Title.java @@ -2,7 +2,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.api.localization.Lang; public class Title { diff --git a/pom.xml b/pom.xml index ebe06c7b..b8bc0aa6 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,7 @@ </repositories> <modules> + <module>api</module> <module>core</module> <module>v1_9_R1</module> <module>v1_9_R2</module> From a7812c4fb4f7f39fab786bd3024d39ba0621786c Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 27 Apr 2023 22:20:24 +0200 Subject: [PATCH 13/95] :bug: Fixed several exceptions --- .../main/java/fr/skytasul/quests/gui/templates/ListGUI.java | 2 +- .../java/fr/skytasul/quests/players/PlayersManagerYAML.java | 4 ++-- core/src/main/java/fr/skytasul/quests/utils/Utils.java | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java index b5ecd412..0c4ddb55 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/templates/ListGUI.java @@ -43,7 +43,7 @@ public final ItemStack getItemStack(T object) { @Override public final void click(T existing, ItemStack item, ClickType clickType) { - if (clickType == getRemoveClick(existing)) { + if (existing != null && clickType == getRemoveClick(existing)) { remove(existing); }else { if (existing == null) { 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 0231aea4..eaa9580b 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -12,6 +11,7 @@ import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.apache.commons.lang.Validate; @@ -38,7 +38,7 @@ public class PlayersManagerYAML extends PlayersManager { private final Cache<Integer, PlayerAccount> unloadedAccounts = CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build(); protected final Map<Integer, PlayerAccount> loadedAccounts = new HashMap<>(); - private final Map<Integer, String> identifiersIndex = Collections.synchronizedMap(new HashMap<>()); + private final Map<Integer, String> identifiersIndex = new ConcurrentHashMap<>(); private final File directory = new File(BeautyQuests.getInstance().getDataFolder(), "players"); diff --git a/core/src/main/java/fr/skytasul/quests/utils/Utils.java b/core/src/main/java/fr/skytasul/quests/utils/Utils.java index 0b79209b..65e6fe55 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Utils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Utils.java @@ -19,6 +19,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; @@ -327,7 +328,7 @@ public static <T, E> List<T> getKeysByValue(Map<T, E> map, E value) { return msg; } - private static final Map<Integer, Pattern> REPLACEMENT_PATTERNS = new HashMap<>(); + private static final Map<Integer, Pattern> REPLACEMENT_PATTERNS = new ConcurrentHashMap<>(); private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); public static String format(@NotNull String msg, int i, @NotNull Supplier<Object> replace) { From b3e8c506fb29eeed48b457a6d4b3425af2cdea20 Mon Sep 17 00:00:00 2001 From: Luke Chambers <consolelogluke@gmail.com> Date: Sun, 30 Apr 2023 17:54:57 +0200 Subject: [PATCH 14/95] :heavy_plus_sign: Added MMOItems item comparison --- core/pom.xml | 33 +++++++++++---- .../java/fr/skytasul/quests/utils/Lang.java | 2 + .../compatibility/DependenciesManager.java | 5 ++- .../utils/compatibility/items/BQMMOItems.java | 40 +++++++++++++++++++ core/src/main/resources/locales/en_US.yml | 2 + 5 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/items/BQMMOItems.java diff --git a/core/pom.xml b/core/pom.xml index a99e8825..36d17a76 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -61,14 +61,14 @@ </relocation> </relocations> <filters> - <filter> - <artifact>com.github.cryptomorin:XSeries</artifact> - <includes> - <include>com/cryptomorin/xseries/XMaterial*</include> - <include>com/cryptomorin/xseries/XBlock*</include> - <include>com/cryptomorin/xseries/XPotion*</include> - </includes> - </filter> + <filter> + <artifact>com.github.cryptomorin:XSeries</artifact> + <includes> + <include>com/cryptomorin/xseries/XMaterial*</include> + <include>com/cryptomorin/xseries/XBlock*</include> + <include>com/cryptomorin/xseries/XPotion*</include> + </includes> + </filter> </filters> </configuration> <executions> @@ -162,6 +162,11 @@ <id>bg-repo</id> <url>https://repo.bg-software.com/repository/api/</url> </repository> + <repository> + <id>phoenix</id> + <url>https://nexus.phoenixdevt.fr/repository/maven-public/</url> + </repository> + </repositories> <dependencies> @@ -274,6 +279,18 @@ <version>1.1.7.0.3</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>net.Indyuce</groupId> + <artifactId>MMOItems-API</artifactId> + <version>6.9.4-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> <!-- Required for MMOItems-API to compile --> + <groupId>io.lumine</groupId> + <artifactId>MythicLib-dist</artifactId> + <version>1.5.2-SNAPSHOT</version> + <scope>provided</scope> + </dependency> <dependency> <groupId>com.github.BlueMap-Minecraft</groupId> <artifactId>BlueMapAPI</artifactId> diff --git a/core/src/main/java/fr/skytasul/quests/utils/Lang.java b/core/src/main/java/fr/skytasul/quests/utils/Lang.java index d7efcaa5..91a9b1f9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Lang.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Lang.java @@ -673,6 +673,8 @@ public enum Lang implements Locale { comparisonRepairCostLore("inv.itemComparisons.repairCostLore"), comparisonItemsAdder("inv.itemComparisons.itemsAdder"), comparisonItemsAdderLore("inv.itemComparisons.itemsAdderLore"), + comparisonMmoItems("inv.itemComparisons.mmoItems"), + comparisonMmoItemsLore("inv.itemComparisons.mmoItemsLore"), INVENTORY_EDIT_TITLE("inv.editTitle.name"), title_title("inv.editTitle.title"), diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java index 6b7e0e2f..cf73369a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java @@ -28,6 +28,7 @@ import fr.skytasul.quests.rewards.PermissionReward; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.Lang; +import fr.skytasul.quests.utils.compatibility.items.BQMMOItems; import fr.skytasul.quests.utils.compatibility.maps.BQBlueMap; import fr.skytasul.quests.utils.compatibility.maps.BQDynmap; import fr.skytasul.quests.utils.compatibility.mobs.BQAdvancedSpawners; @@ -133,6 +134,8 @@ public class DependenciesManager implements Listener { public static final BQDependency WildStacker = new BQDependency("WildStacker", BQWildStacker::initialize); public static final BQDependency ItemsAdder = new BQDependency("ItemsAdder", BQItemsAdder::initialize, BQItemsAdder::unload); + public static final BQDependency MMOItems = + new BQDependency("MMOItems", BQMMOItems::initialize, BQMMOItems::unload); //public static final BQDependency par = new BQDependency("Parties"); //public static final BQDependency eboss = new BQDependency("EpicBosses", () -> Bukkit.getPluginManager().registerEvents(new EpicBosses(), BeautyQuests.getInstance())); @@ -153,7 +156,7 @@ public DependenciesManager() { skapi, jobs, fac, mmo, mclvl, // rewards and requirements dyn, BlueMap, // maps cmi, holod2, holod3, decentholograms, // holograms - ItemsAdder // items + ItemsAdder, MMOItems // items )); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/items/BQMMOItems.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/items/BQMMOItems.java new file mode 100644 index 00000000..3251373f --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/items/BQMMOItems.java @@ -0,0 +1,40 @@ +package fr.skytasul.quests.utils.compatibility.items; + +import org.bukkit.inventory.ItemStack; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.comparison.ItemComparison; +import fr.skytasul.quests.utils.Lang; +import net.Indyuce.mmoitems.MMOItems; +import net.Indyuce.mmoitems.api.Type; + +public final class BQMMOItems { + + private BQMMOItems() {} + + private static final ItemComparison COMPARISON = new ItemComparison( + "mmoItems", + Lang.comparisonMmoItems.toString(), + Lang.comparisonMmoItemsLore.toString(), + BQMMOItems::compareMmoItems); + + public static void initialize() { + QuestsAPI.registerItemComparison(COMPARISON); + } + + public static void unload() { + QuestsAPI.unregisterItemComparison(COMPARISON); + } + + private static boolean compareMmoItems(ItemStack item1, ItemStack item2) { + Type type1 = MMOItems.getType(item1); + Type type2 = MMOItems.getType(item2); + if (type1 == null || !type1.equals(type2)) { + return false; + } + + String id1 = MMOItems.getID(item1); + String id2 = MMOItems.getID(item2); + return id1 != null && id1.equals(id2); + } + +} \ No newline at end of file diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 9a9a4af8..6dd09480 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -715,6 +715,8 @@ inv: repairCostLore: Compares repair cost for armors and swords itemsAdder: ItemsAdder itemsAdderLore: Compares ItemsAdder IDs + mmoItems: MMOItems item + mmoItemsLore: Compares MMOItems types and IDs editTitle: name: Edit Title title: §6Title From 5735bdfabc698664ec764c6f987ad2128ca5623b Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 2 May 2023 21:12:24 +0200 Subject: [PATCH 15/95] :construction: Still WIP --- .../quests/api/QuestsConfiguration.java | 128 ++++ .../fr/skytasul/quests/api/QuestsPlugin.java | 1 - .../api/events/internal/BQNPCClickEvent.java | 7 +- .../gui/{CustomInventory.java => Gui.java} | 25 +- .../quests/api/gui/GuiClickEvent.java | 60 ++ .../skytasul/quests/api/gui/GuiManager.java | 4 +- .../fr/skytasul/quests/api/gui/ItemUtils.java | 20 +- .../api/gui/close/OpenCloseBehavior.java | 8 +- .../quests/api/gui/layout/ClickHandler.java | 11 - .../{Button.java => LayoutedButton.java} | 42 +- ...lickEvent.java => LayoutedClickEvent.java} | 4 +- .../api/gui/layout/LayoutedClickHandler.java | 11 + .../quests/api/gui/layout/LayoutedGUI.java | 31 +- .../quests/api/gui/templates/ChooseGUI.java | 11 +- .../quests/api/gui/templates/ConfirmGUI.java | 16 +- .../quests/api/gui/templates/PagedGUI.java | 18 +- .../quests/api/npcs/NpcClickType.java | 13 + .../quests/api/npcs/dialogs/Dialog.java | 2 +- .../api/options/QuestOptionBoolean.java | 2 +- .../quests/api/stages/AbstractStage.java | 4 +- .../api/stages/options/StageOption.java | 2 +- .../types/AbstractCountableBlockStage.java | 12 +- .../stages/types/AbstractCountableStage.java | 68 +- .../api/stages/types/AbstractEntityStage.java | 18 +- .../api/stages/types/AbstractItemStage.java | 12 +- .../skytasul/quests/api/utils}/BQBlock.java | 5 +- .../quests/api/utils}/CountableObject.java | 4 +- .../quests/api/utils/PlayerListCategory.java | 5 - .../fr/skytasul/quests/api/utils/Utils.java | 5 +- .../java/fr/skytasul/quests/BeautyQuests.java | 35 +- .../skytasul/quests/DefaultQuestFeatures.java | 16 +- ...=> QuestsConfigurationImplementation.java} | 635 ++++++++++-------- .../fr/skytasul/quests/QuestsListener.java | 8 +- .../CommandsManagerImplementation.java | 4 +- .../quests/gui/GuiManagerImplementation.java | 16 +- .../skytasul/quests/gui/blocks/BlocksGUI.java | 6 +- .../quests/gui/blocks/SelectBlockGUI.java | 32 +- .../quests/gui/creation/CommandGUI.java | 14 +- .../quests/gui/creation/FinishGUI.java | 8 +- .../quests/gui/creation/ItemsGUI.java | 6 +- .../quests/gui/creation/stages/Line.java | 6 +- .../quests/gui/creation/stages/StagesGUI.java | 4 +- .../skytasul/quests/gui/misc/BranchesGUI.java | 8 +- .../quests/gui/misc/ItemComparisonGUI.java | 2 +- .../quests/gui/misc/ItemCreatorGUI.java | 10 +- .../fr/skytasul/quests/gui/misc/ItemGUI.java | 8 +- .../fr/skytasul/quests/gui/misc/TitleGUI.java | 8 +- .../skytasul/quests/gui/mobs/MobsListGUI.java | 4 +- .../skytasul/quests/gui/npc/NpcCreateGUI.java | 8 +- .../skytasul/quests/gui/npc/NpcSelectGUI.java | 16 +- .../gui/particles/ParticleEffectGUI.java | 9 +- .../quests/gui/permissions/PermissionGUI.java | 10 +- .../quests/gui/pools/PoolEditGUI.java | 13 +- .../quests/gui/quests/ChooseQuestGUI.java | 4 +- .../quests/gui/quests/DialogHistoryGUI.java | 6 +- .../quests/gui/quests/PlayerListGUI.java | 30 +- .../quests/options/OptionCancellable.java | 4 +- .../quests/options/OptionConfirmMessage.java | 4 +- .../quests/options/OptionFirework.java | 4 +- .../quests/options/OptionHologramText.java | 4 +- .../quests/options/OptionVisibility.java | 9 +- .../players/AbstractPlayersManager.java | 10 +- .../rewards/RequirementDependentReward.java | 14 +- .../fr/skytasul/quests/rewards/XPReward.java | 4 +- .../quests/scoreboards/Scoreboard.java | 4 +- .../quests/scoreboards/ScoreboardManager.java | 6 +- .../fr/skytasul/quests/stages/StageArea.java | 4 +- .../quests/stages/StageBringBack.java | 12 +- .../skytasul/quests/stages/StageBucket.java | 6 +- .../fr/skytasul/quests/stages/StageChat.java | 12 +- .../fr/skytasul/quests/stages/StageCraft.java | 6 +- .../skytasul/quests/stages/StageEatDrink.java | 2 +- .../skytasul/quests/stages/StageEnchant.java | 2 +- .../fr/skytasul/quests/stages/StageFish.java | 2 +- .../skytasul/quests/stages/StageInteract.java | 10 +- .../skytasul/quests/stages/StageLocation.java | 14 +- .../fr/skytasul/quests/stages/StageMelt.java | 2 +- .../fr/skytasul/quests/stages/StageMine.java | 14 +- .../fr/skytasul/quests/stages/StageMobs.java | 8 +- .../fr/skytasul/quests/stages/StageNPC.java | 30 +- .../quests/stages/StagePlaceBlocks.java | 4 +- .../structure/QuestBranchImplementation.java | 16 +- .../quests/structure/QuestImplementation.java | 10 +- .../fr/skytasul/quests/utils/QuestUtils.java | 16 +- .../quests/utils/compatibility/Post1_13.java | 2 +- .../utils/compatibility/maps/BQBlueMap.java | 8 +- .../utils/compatibility/maps/BQDynmap.java | 12 +- .../utils/compatibility/npcs/BQCitizens.java | 6 +- .../compatibility/npcs/BQServerNPCs.java | 4 +- .../types/DialogRunnerImplementation.java | 8 +- core/src/main/resources/config.yml | 14 +- 91 files changed, 994 insertions(+), 768 deletions(-) create mode 100644 api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java rename api/src/main/java/fr/skytasul/quests/api/gui/{CustomInventory.java => Gui.java} (70%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java delete mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java rename api/src/main/java/fr/skytasul/quests/api/gui/layout/{Button.java => LayoutedButton.java} (54%) rename api/src/main/java/fr/skytasul/quests/api/gui/layout/{ClickEvent.java => LayoutedClickEvent.java} (85%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickHandler.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/npcs/NpcClickType.java rename {core/src/main/java/fr/skytasul/quests/utils/types => api/src/main/java/fr/skytasul/quests/api/utils}/BQBlock.java (94%) rename {core/src/main/java/fr/skytasul/quests/utils/types => api/src/main/java/fr/skytasul/quests/api/utils}/CountableObject.java (92%) rename core/src/main/java/fr/skytasul/quests/{QuestsConfiguration.java => QuestsConfigurationImplementation.java} (50%) diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java new file mode 100644 index 00000000..5d93217c --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -0,0 +1,128 @@ +package fr.skytasul.quests.api; + +import java.util.Collection; +import java.util.Set; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.npcs.NpcClickType; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.utils.PlayerListCategory; + +public interface QuestsConfiguration { + + static @NotNull QuestsConfiguration getConfig() { + return QuestsPlugin.getPlugin().getConfiguration(); + } + + @NotNull + Quests getQuestsConfig(); + + @NotNull + Dialogs getDialogsConfig(); + + @NotNull + QuestsMenu getQuestsMenuConfig(); + + @NotNull + StageDescription getStageDescriptionConfig(); + + interface Quests { + + int getDefaultTimer(); + + int maxLaunchedQuests(); + + boolean scoreboards(); + + boolean playerQuestUpdateMessage(); + + boolean playerStageStartMessage(); + + boolean questConfirmGUI(); + + boolean sounds(); + + String finishSound(); + + String nextStageSound(); + + boolean fireworks(); + + boolean mobsProgressBar(); + + int progressBarTimeoutSeconds(); + + Collection<NpcClickType> getNpcClicks(); + + boolean skipNpcGuiIfOnlyOneQuest(); + + ItemStack getDefaultQuestItem(); + + XMaterial getPageMaterial(); + + double startParticleDistance(); + + int requirementUpdateTime(); + + boolean requirementReasonOnMultipleQuests(); + + boolean stageEndRewardsMessage(); + + } + + interface Dialogs { + + boolean sendInActionBar(); + + int getDefaultTime(); + + boolean isSkippableByDefault(); + + boolean isClickDisabled(); + + boolean isHistoryEnabled(); + + int getMaxMessagesPerHistoryPage(); + + int getMaxDistance(); + + int getMaxDistanceSquared(); + + String getDefaultPlayerSound(); + + String getDefaultNPCSound(); + + } + + interface QuestsMenu { + + boolean isNotStartedTabOpenedWhenEmpty(); + + boolean allowPlayerCancelQuest(); + + Set<PlayerListCategory> getEnabledTabs(); + + } + + interface StageDescription { + + String getStageDescriptionFormat(); + + String getItemNameColor(); + + String getItemAmountColor(); + + String getSplitPrefix(); + + String getSplitAmountFormat(); + + boolean isAloneSplitAmountShown(); + + boolean isAloneSplitInlined(); + + Set<DescriptionSource> getSplitSources(); + + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java index 600fd7ce..5a04c6e4 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java @@ -2,7 +2,6 @@ import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.commands.CommandsManager; import fr.skytasul.quests.api.editors.EditorManager; import fr.skytasul.quests.api.gui.GuiManager; diff --git a/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java index be030a6d..c6a920b6 100644 --- a/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java @@ -6,15 +6,16 @@ import org.bukkit.event.player.PlayerEvent; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.NpcClickType; public class BQNPCClickEvent extends PlayerEvent implements Cancellable { private final @NotNull BQNPC npc; - private final @NotNull ClickType click; + private final @NotNull NpcClickType click; private boolean cancelled = false; - public BQNPCClickEvent(@NotNull BQNPC npc, @NotNull Player p, @NotNull ClickType click) { + public BQNPCClickEvent(@NotNull BQNPC npc, @NotNull Player p, @NotNull NpcClickType click) { super(p); this.npc = npc; this.click = click; @@ -34,7 +35,7 @@ public void setCancelled(boolean cancelled) { return npc; } - public @NotNull ClickType getClick() { + public @NotNull NpcClickType getClick() { return click; } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/CustomInventory.java b/api/src/main/java/fr/skytasul/quests/api/gui/Gui.java similarity index 70% rename from api/src/main/java/fr/skytasul/quests/api/gui/CustomInventory.java rename to api/src/main/java/fr/skytasul/quests/api/gui/Gui.java index 3764b20f..66da1756 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/CustomInventory.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/Gui.java @@ -1,16 +1,14 @@ package fr.skytasul.quests.api.gui; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -public abstract class CustomInventory { +public abstract class Gui { private @Nullable Inventory inventory; @@ -76,26 +74,9 @@ protected void refresh(@NotNull Player player, @NotNull Inventory inventory) {} /** * Called when clicking on an item * - * @param player Player who clicked - * @param current Item clicked - * @param slot Slot of item clicked - * @param click Type of click - * @return Cancel click + * @param event object containing informations about click action */ - public abstract boolean onClick(@NotNull Player player, @NotNull ItemStack current, int slot, @NotNull ClickType click); - - /** - * Called when clicking on an item <b>with something on the cursor</b> - * - * @param player Player who clicked - * @param current Item clicked - * @param cursor Item on the cursor when click - * @param slot Slot of item clicked - * @return Cancel click - */ - public boolean onClickCursor(@NotNull Player player, @NotNull ItemStack current, @NotNull ItemStack cursor, int slot) { - return true; - } + public abstract void onClick(@NotNull GuiClickEvent event); /** * Called when closing the inventory diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java new file mode 100644 index 00000000..082c24bf --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java @@ -0,0 +1,60 @@ +package fr.skytasul.quests.api.gui; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class GuiClickEvent { + + private final @NotNull Player player; + private final @Nullable ItemStack clicked; + private final @Nullable ItemStack cursor; + private final int slot; + private final @NotNull ClickType click; + + private boolean cancelled; + + public GuiClickEvent(@NotNull Player player, @Nullable ItemStack clicked, @Nullable ItemStack cursor, int slot, + @NotNull ClickType click) { + this.player = player; + this.clicked = clicked; + this.cursor = cursor; + this.slot = slot; + this.click = click; + } + + public @NotNull Player getPlayer() { + return player; + } + + public @Nullable ItemStack getClicked() { + return clicked; + } + + public @Nullable ItemStack getCursor() { + return cursor; + } + + public boolean hasCursor() { + return cursor != null; + } + + public int getSlot() { + return slot; + } + + public @NotNull ClickType getClick() { + return click; + } + + public boolean isCancelled() { + return cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java index f6e1204f..8d315e7e 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java @@ -6,7 +6,7 @@ public interface GuiManager { - void open(@NotNull Player player, @NotNull CustomInventory inventory); + void open(@NotNull Player player, @NotNull Gui inventory); void closeAndExit(@NotNull Player player); @@ -17,6 +17,6 @@ public interface GuiManager { boolean hasGuiOpened(@NotNull Player player); @Nullable - CustomInventory getOpenedGui(@NotNull Player player); + Gui getOpenedGui(@NotNull Player player); } 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 fdfcb552..75a79f26 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 @@ -17,14 +17,16 @@ import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.SkullMeta; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.ChatColorUtils; import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.api.utils.MinecraftVersion; import net.md_5.bungee.api.ChatColor; -public class ItemUtils { +public final class ItemUtils { + + private ItemUtils() {} private static final int LORE_LINE_LENGTH = 40; private static final int LORE_LINE_LENGTH_CRITICAL = 1000; @@ -309,13 +311,15 @@ public static ItemStack removeEnchant(ItemStack is, Enchantment en){ * Immutable ItemStack instance with lore : <i>inv.stages.laterPage</i> and material : <i>pageItem</i> * @see #itemNextPage */ - public static final ImmutableItemStack itemLaterPage = new ImmutableItemStack(item(QuestsConfiguration.getPageMaterial(), Lang.laterPage.toString())); + public static final ImmutableItemStack itemLaterPage = new ImmutableItemStack( + item(QuestsConfiguration.getConfig().getQuestsConfig().pageItem(), Lang.laterPage.toString())); /** * Immutable ItemStack instance with lore : <i>inv.stages.nextPage</i> and material : <i>pageItem</i> * @see #itemLaterPage */ - public static final ImmutableItemStack itemNextPage = new ImmutableItemStack(item(QuestsConfiguration.getPageMaterial(), Lang.nextPage.toString())); + public static final ImmutableItemStack itemNextPage = new ImmutableItemStack( + item(QuestsConfiguration.getConfig().getQuestsConfig().pageItem(), Lang.nextPage.toString())); /** * Immutable ItemStack instance with name : <i>inv.cancel</i> and material : barrier @@ -364,21 +368,21 @@ public static ItemStack itemSwitch(String name, boolean enabled, String... lore) * @param itemSwitch switch item * @return new state of the switch */ - public static boolean toggle(ItemStack itemSwitch){ + public static boolean toggleSwitch(ItemStack itemSwitch){ String name = getName(itemSwitch); boolean toggled = name.charAt(1) != 'a'; // toggling - set(itemSwitch, toggled); + setSwitch(itemSwitch, toggled); return toggled; } /** * Set the state of a switch item, created with {@link #itemSwitch(String, boolean, String...)} - * @see #toggle(ItemStack) + * @see #toggleSwitch(ItemStack) * @param itemSwitch switch item * @param enable new state of the switch * @return same state */ - public static ItemStack set(ItemStack itemSwitch, boolean enable) { + public static ItemStack setSwitch(ItemStack itemSwitch, boolean enable) { if (itemSwitch == null) return null; String name = getName(itemSwitch); name(itemSwitch, (enable ? "§a" : "§7") + name.substring(2)); diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java b/api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java index 0c0655d4..d68b7879 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/close/OpenCloseBehavior.java @@ -2,17 +2,17 @@ import java.util.Objects; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; public class OpenCloseBehavior implements CloseBehavior { - private final @NotNull CustomInventory other; + private final @NotNull Gui other; - public OpenCloseBehavior(@NotNull CustomInventory other) { + public OpenCloseBehavior(@NotNull Gui other) { this.other = Objects.requireNonNull(other); } - public @NotNull CustomInventory getOther() { + public @NotNull Gui getOther() { return other; } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java deleted file mode 100644 index 1f106d48..00000000 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickHandler.java +++ /dev/null @@ -1,11 +0,0 @@ -package fr.skytasul.quests.api.gui.layout; - -import org.jetbrains.annotations.NotNull; - -public interface ClickHandler { - - public static final ClickHandler EMPTY = event -> {}; - - void click(@NotNull ClickEvent event); - -} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/Button.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedButton.java similarity index 54% rename from api/src/main/java/fr/skytasul/quests/api/gui/layout/Button.java rename to api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedButton.java index 5e1dc77a..4eedac24 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/Button.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedButton.java @@ -9,11 +9,11 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; -public interface Button extends ClickHandler { +public interface LayoutedButton extends LayoutedClickHandler { public void place(@NotNull Inventory inventory, int slot); - interface ItemButton extends Button { + interface ItemButton extends LayoutedButton { public @Nullable ItemStack getItem(); @@ -24,12 +24,12 @@ default void place(@NotNull Inventory inventory, int slot) { } - public static @NotNull Button create(@NotNull XMaterial material, @Nullable String name, @Nullable List<String> lore, - @NotNull ClickHandler click) { + public static @NotNull LayoutedButton create(@NotNull XMaterial material, @Nullable String name, @Nullable List<String> lore, + @NotNull LayoutedClickHandler click) { return new ItemButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { click.click(event); } @@ -41,12 +41,12 @@ public void click(@NotNull ClickEvent event) { }; } - public static @NotNull Button create(@NotNull XMaterial material, @Nullable String name, - @NotNull Supplier<@Nullable List<String>> lore, @NotNull ClickHandler click) { + public static @NotNull LayoutedButton create(@NotNull XMaterial material, @Nullable String name, + @NotNull Supplier<@Nullable List<String>> lore, @NotNull LayoutedClickHandler click) { return new ItemButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { click.click(event); } @@ -58,12 +58,12 @@ public void click(@NotNull ClickEvent event) { }; } - public static @NotNull Button create(@NotNull XMaterial material, @NotNull Supplier<@Nullable String> name, - @NotNull Supplier<@Nullable List<String>> lore, @NotNull ClickHandler click) { + public static @NotNull LayoutedButton create(@NotNull XMaterial material, @NotNull Supplier<@Nullable String> name, + @NotNull Supplier<@Nullable List<String>> lore, @NotNull LayoutedClickHandler click) { return new ItemButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { click.click(event); } @@ -75,12 +75,12 @@ public void click(@NotNull ClickEvent event) { }; } - public static @NotNull Button create(@NotNull XMaterial material, @NotNull Supplier<@Nullable String> name, - @Nullable List<String> lore, @NotNull ClickHandler click) { + public static @NotNull LayoutedButton create(@NotNull XMaterial material, @NotNull Supplier<@Nullable String> name, + @Nullable List<String> lore, @NotNull LayoutedClickHandler click) { return new ItemButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { click.click(event); } @@ -92,13 +92,13 @@ public void click(@NotNull ClickEvent event) { }; } - public static @NotNull Button create(@NotNull Supplier<@NotNull XMaterial> material, + public static @NotNull LayoutedButton create(@NotNull Supplier<@NotNull XMaterial> material, @NotNull Supplier<@Nullable String> name, @NotNull Supplier<@Nullable List<String>> lore, - @NotNull ClickHandler click) { + @NotNull LayoutedClickHandler click) { return new ItemButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { click.click(event); } @@ -110,11 +110,11 @@ public void click(@NotNull ClickEvent event) { }; } - public static @NotNull Button create(@NotNull Supplier<@Nullable ItemStack> item, @NotNull ClickHandler click) { + public static @NotNull LayoutedButton create(@NotNull Supplier<@Nullable ItemStack> item, @NotNull LayoutedClickHandler click) { return new ItemButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { click.click(event); } @@ -126,11 +126,11 @@ public void click(@NotNull ClickEvent event) { }; } - public static @NotNull Button create(@Nullable ItemStack item, @NotNull ClickHandler click) { + public static @NotNull LayoutedButton create(@Nullable ItemStack item, @NotNull LayoutedClickHandler click) { return new ItemButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { click.click(event); } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickEvent.java similarity index 85% rename from api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickEvent.java rename to api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickEvent.java index d40d1e7e..45415f73 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/ClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickEvent.java @@ -4,14 +4,14 @@ import org.bukkit.event.inventory.ClickType; import org.jetbrains.annotations.NotNull; -public class ClickEvent { +public class LayoutedClickEvent { private final @NotNull Player player; private final @NotNull LayoutedGUI gui; private final int slot; private final @NotNull ClickType click; - public ClickEvent(@NotNull Player player, @NotNull LayoutedGUI gui, int slot, @NotNull ClickType click) { + public LayoutedClickEvent(@NotNull Player player, @NotNull LayoutedGUI gui, int slot, @NotNull ClickType click) { this.player = player; this.gui = gui; this.slot = slot; diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickHandler.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickHandler.java new file mode 100644 index 00000000..57223009 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickHandler.java @@ -0,0 +1,11 @@ +package fr.skytasul.quests.api.gui.layout; + +import org.jetbrains.annotations.NotNull; + +public interface LayoutedClickHandler { + + public static final LayoutedClickHandler EMPTY = event -> {}; + + void click(@NotNull LayoutedClickEvent event); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java index 3fef7080..bfa98554 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java @@ -6,23 +6,22 @@ import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -public abstract class LayoutedGUI extends CustomInventory { +public abstract class LayoutedGUI extends Gui { protected final @Nullable String name; - protected final @NotNull Map<Integer, Button> buttons; + protected final @NotNull Map<Integer, LayoutedButton> buttons; protected final @NotNull CloseBehavior closeBehavior; - protected LayoutedGUI(@Nullable String name, @NotNull Map<Integer, Button> buttons, + protected LayoutedGUI(@Nullable String name, @NotNull Map<Integer, LayoutedButton> buttons, @NotNull CloseBehavior closeBehavior) { this.name = name; this.buttons = buttons; @@ -35,21 +34,19 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { } @Override - public boolean onClick(@NotNull Player player, @NotNull ItemStack current, int slot, @NotNull ClickType click) { - Button button = buttons.get(slot); + public void onClick(GuiClickEvent event) { + LayoutedButton button = buttons.get(event.getSlot()); if (button == null) - return true; + return; - ClickEvent event = new ClickEvent(player, this, slot, click); - button.click(event); - return true; + button.click(new LayoutedClickEvent(event.getPlayer(), this, event.getSlot(), event.getClick())); } public void refresh(int slot) { if (getInventory() == null) return; - Button button = buttons.get(slot); + LayoutedButton button = buttons.get(slot); if (button == null) return; @@ -69,7 +66,7 @@ public static class LayoutedRowsGUI extends LayoutedGUI { private final int rows; - protected LayoutedRowsGUI(@Nullable String name, @NotNull Map<Integer, Button> buttons, + protected LayoutedRowsGUI(@Nullable String name, @NotNull Map<Integer, LayoutedButton> buttons, @NotNull CloseBehavior closeBehavior, int rows) { super(name, buttons, closeBehavior); Validate.isTrue(rows >= 1); @@ -87,7 +84,7 @@ public static class LayoutedTypeGUI extends LayoutedGUI { private @NotNull InventoryType type; - protected LayoutedTypeGUI(@Nullable String name, @NotNull Map<Integer, Button> buttons, + protected LayoutedTypeGUI(@Nullable String name, @NotNull Map<Integer, LayoutedButton> buttons, @NotNull CloseBehavior closeBehavior, @NotNull InventoryType type) { super(name, buttons, closeBehavior); this.type = Objects.requireNonNull(type); @@ -102,7 +99,7 @@ protected Inventory instanciate(@NotNull Player player) { public static class Builder { - private final Map<Integer, Button> buttons = new HashMap<>(); + private final Map<Integer, LayoutedButton> buttons = new HashMap<>(); private @Nullable Integer rows = null; private @Nullable InventoryType type = null; private @Nullable String name = null; @@ -110,7 +107,7 @@ public static class Builder { private Builder() {} - public @NotNull Builder addButton(int slot, @NotNull Button button) { + public @NotNull Builder addButton(int slot, @NotNull LayoutedButton button) { Validate.isTrue(!buttons.containsKey(slot)); buttons.put(slot, button); return this; diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java index 491985e2..225939a6 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java @@ -3,15 +3,15 @@ import java.util.List; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -public abstract class ChooseGUI<T> extends CustomInventory { +public abstract class ChooseGUI<T> extends Gui { private List<T> available; @@ -32,9 +32,8 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { } @Override - public boolean onClick(Player player, ItemStack current, int slot, ClickType click) { - finish(available.get(slot)); - return true; + public void onClick(GuiClickEvent event) { + finish(available.get(event.getSlot())); } @Override diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java index 695d3a21..64ab55d2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java @@ -7,10 +7,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.gui.layout.Button; -import fr.skytasul.quests.api.gui.layout.ClickHandler; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; +import fr.skytasul.quests.api.gui.layout.LayoutedClickHandler; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; @@ -18,27 +18,27 @@ public final class ConfirmGUI { private ConfirmGUI() {} - public static CustomInventory confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + public static Gui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, @Nullable String @Nullable... lore) { return confirm(yes, no, indication, lore == null ? null : Arrays.asList(lore)); } - public static CustomInventory confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + public static Gui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, @Nullable List<@Nullable String> lore) { return LayoutedGUI.newBuilder() .addButton(1, - Button.create(XMaterial.LIME_DYE, Lang.confirmYes.toString(), Collections.emptyList(), event -> { + LayoutedButton.create(XMaterial.LIME_DYE, Lang.confirmYes.toString(), Collections.emptyList(), event -> { event.close(); if (yes != null) yes.run(); })) .addButton(3, - Button.create(XMaterial.RED_DYE, Lang.confirmNo.toString(), Collections.emptyList(), event -> { + LayoutedButton.create(XMaterial.RED_DYE, Lang.confirmNo.toString(), Collections.emptyList(), event -> { event.close(); if (no != null) no.run(); })) - .addButton(2, Button.create(XMaterial.PAPER, indication, lore, ClickHandler.EMPTY)) + .addButton(2, LayoutedButton.create(XMaterial.PAPER, indication, lore, LayoutedClickHandler.EMPTY)) .setInventoryType(InventoryType.HOPPER) .setName(Lang.INVENTORY_CONFIRM.toString()) .setCloseBehavior(StandardCloseBehavior.REOPEN) diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java index 30c8a310..a8af1068 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java @@ -16,7 +16,8 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.LevenshteinComparator; @@ -27,7 +28,7 @@ * * @param <T> type of objects stocked in the inventory */ -public abstract class PagedGUI<T> extends CustomInventory { +public abstract class PagedGUI<T> extends Gui { private static ItemStack itemSearch = ItemUtils.item(XMaterial.COMPASS, Lang.search.toString()); @@ -157,10 +158,10 @@ public int getObjectSlot(T object){ @Override - public boolean onClick(Player player, ItemStack current, int slot, ClickType click) { - switch (slot % 9){ + public void onClick(GuiClickEvent event) { + switch (event.getSlot() % 9) { case 8: - int barSlot = (slot - 8) / 9; + int barSlot = (event.getSlot() - 8) / 9; switch (barSlot){ case 0: if (page == 0) break; @@ -193,12 +194,11 @@ public boolean onClick(Player player, ItemStack current, int slot, ClickType cli break; default: - int line = (int) Math.floor(slot * 1D / 9D); - int objectSlot = slot - line*2 + page*35; - click(objects.get(objectSlot), current, click); + int line = (int) Math.floor(event.getSlot() * 1D / 9D); + int objectSlot = event.getSlot() - line * 2 + page * 35; + click(objects.get(objectSlot), event.getClicked(), event.getClick()); //inv.setItem(slot, getItemStack(objects.get(objectSlot))); } - return true; } public final void reopen() { diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/NpcClickType.java b/api/src/main/java/fr/skytasul/quests/api/npcs/NpcClickType.java new file mode 100644 index 00000000..0dc6df25 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/NpcClickType.java @@ -0,0 +1,13 @@ +package fr.skytasul.quests.api.npcs; + +public enum NpcClickType { + RIGHT, SHIFT_RIGHT, LEFT, SHIFT_LEFT; + + public static NpcClickType of(boolean left, boolean shift) { + if (left) { + return shift ? SHIFT_LEFT : LEFT; + }else { + return shift ? SHIFT_RIGHT : RIGHT; + } + } +} \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java index 39911182..25ef88a4 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java @@ -100,7 +100,7 @@ public static Dialog deserialize(ConfigurationSection section) { NumberedList<Message> tmpMessages = new NumberedList<>(); for (Map<?, ?> msg : section.getMapList("msgs")) { int id = (int) msg.get("id"); - tmpMessages.set(id, Message.deserialize((Map<String, Object>) msg.get("message"))); + tmpMessages.setSwitch(id, Message.deserialize((Map<String, Object>) msg.get("message"))); } Dialog di = new Dialog(tmpMessages.toList()); if (section.contains("npcName")) di.npcName = section.getString("npcName"); diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java index 55aaecfb..8e74d7fd 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java @@ -42,7 +42,7 @@ public ItemStack getItemStack(OptionSet options) { @Override public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { setValue(!getValue()); - ItemUtils.set(item, getValue()); + ItemUtils.setSwitch(item, getValue()); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index a2d9d452..eed576f4 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -8,7 +8,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.quests.Quest; @@ -91,7 +91,7 @@ public void setCustomText(@Nullable String message) { } public boolean sendStartMessage(){ - return startMessage == null && QuestsConfiguration.sendStageStartMessage(); + return startMessage == null && QuestsConfiguration.getConfig().getQuestsConfig().playerStageStartMessage(); } public boolean hasAsyncEnd() { diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java index b488d149..a412bea8 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java @@ -12,7 +12,7 @@ public abstract class StageOption<T extends AbstractStage> extends SerializableO private final @NotNull Class<T> stageClass; protected StageOption(@NotNull Class<T> stageClass) { - super(QuestsAPI.getStages() + super(QuestsAPI.getAPI().getStages() .getType(stageClass) .orElseThrow(() -> new IllegalArgumentException(stageClass.getName() + "has not been registered as a stage type via the API.")) .getOptionsRegistry()); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java index e55250b3..f27a28b2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java @@ -10,18 +10,18 @@ import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.quests.branches.QuestBranch; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.utils.BQBlock; +import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.gui.blocks.BlocksGUI; -import fr.skytasul.quests.utils.types.BQBlock; -import fr.skytasul.quests.utils.types.CountableObject; -import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; public abstract class AbstractCountableBlockStage extends AbstractCountableStage<BQBlock> { - protected AbstractCountableBlockStage(@NotNull QuestBranch branch, + protected AbstractCountableBlockStage(@NotNull StageController controller, @NotNull List<@NotNull CountableObject<BQBlock>> objects) { - super(branch, objects); + super(controller, objects); } @Override diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index 2a990e0d..0407c441 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -18,18 +18,18 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.BossBarManager.BQBossBar; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.quests.branches.QuestBranch; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.utils.types.CountableObject; -import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; public abstract class AbstractCountableStage<T> extends AbstractStage { @@ -39,23 +39,13 @@ public abstract class AbstractCountableStage<T> extends AbstractStage { private boolean barsEnabled = false; private int cachedSize = 0; - protected AbstractCountableStage(@NotNull QuestBranch branch, @NotNull List<@NotNull CountableObject<T>> objects) { - super(branch); + protected AbstractCountableStage(@NotNull StageController controller, + @NotNull List<@NotNull CountableObject<T>> objects) { + super(controller); this.objects = objects; calculateSize(); } - @Deprecated - protected AbstractCountableStage(QuestBranch branch, Map<Integer, Entry<T, Integer>> objects) { - this(branch, objects.keySet().stream().sorted().map(index -> { - Entry<T, Integer> entry = objects.get(index); - return CountableObject.open(uuidFromLegacyIndex(index), entry.getKey(), entry.getValue()); - }).collect(Collectors.toList())); - - QuestsPlugin.getPlugin().getLoggerExpanded().warning("The stage " + getType().getName() - + " uses an outdated way to store player datas. Please notice its author."); - } - public @NotNull List<@NotNull CountableObject<T>> getObjects() { return objects; } @@ -150,7 +140,7 @@ protected void calculateSize() { } @Override - protected void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { + public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { super.initPlayerDatas(acc, datas); datas.put("remaining", objects.stream() .collect(Collectors.toMap(object -> object.getUUID().toString(), CountableObject::getAmount))); @@ -204,8 +194,8 @@ public boolean event(@NotNull PlayerAccount acc, @NotNull Player p, @UnknownNull } @Override - public void start(@NotNull PlayerAccount acc) { - super.start(acc); + public void started(@NotNull PlayerAccount acc) { + super.started(acc); if (acc.isCurrent()) createBar(acc.getPlayer(), cachedSize); } @@ -222,16 +212,16 @@ public void unload() { } @Override - public void joins(@NotNull PlayerAccount acc, @NotNull Player p) { - super.joins(acc, p); - Map<UUID, Integer> remainings = getPlayerRemainings(acc, true); + public void joined(@NotNull Player p) { + super.joined(p); + Map<UUID, Integer> remainings = getPlayerRemainings(PlayersManager.getPlayerAccount(p), true); if (remainings == null) return; createBar(p, remainings.values().stream().mapToInt(Integer::intValue).sum()); } @Override - public void leaves(@NotNull PlayerAccount acc, @NotNull Player p) { - super.leaves(acc, p); + public void left(@NotNull Player p) { + super.left(p); removeBar(p); } @@ -262,13 +252,6 @@ protected boolean objectApplies(@NotNull T object, @UnknownNullability Object ot protected abstract @NotNull Object serialize(@NotNull T object); protected abstract @NotNull T deserialize(@NotNull Object object); - - /** - * @deprecated for removal, {@link #serialize(ConfigurationSection)} should be used instead. - */ - @Override - @Deprecated - protected void serialize(Map<String, Object> map) {} @Override protected void serialize(@NotNull ConfigurationSection section) { @@ -278,18 +261,6 @@ protected void serialize(@NotNull ConfigurationSection section) { objectSection.set("amount", obj.getAmount()); objectSection.set("object", serialize(obj.getObject())); } - - Map<String, Object> serialized = new HashMap<>(); - serialize(serialized); - Utils.setConfigurationSectionContent(section, serialized); - } - - /** - * @deprecated for removal, {@link #deserialize(ConfigurationSection)} should be used instead. - */ - @Deprecated - protected void deserialize(Map<String, Object> serializedDatas) { - deserialize(Utils.createConfigurationSection(serializedDatas)); } protected void deserialize(@NotNull ConfigurationSection section) { @@ -306,7 +277,7 @@ protected void deserialize(@NotNull ConfigurationSection section) { ConfigurationSection objectSection = objectsSection.getConfigurationSection(key); Object serialized = objectSection.get("object"); if (serialized instanceof ConfigurationSection) serialized = ((ConfigurationSection) serialized).getValues(false); - objects.add(CountableObject.open(uuid, deserialize(serialized), objectSection.getInt("amount"))); + objects.add(CountableObject.create(uuid, deserialize(serialized), objectSection.getInt("amount"))); } } @@ -338,7 +309,8 @@ public BossBar(Player p, int amount) { }else if (cachedSize % 6 == 0) { style = BarStyle.SEGMENTED_6; }else style = BarStyle.SOLID; - bar = QuestsAPI.getBossBarManager().buildBossBar(Lang.MobsProgression.format(branch.getQuest().getName(), 100, 100), BarColor.YELLOW, style); + bar = QuestsAPI.getAPI().getBossBarManager() + .buildBossBar(Lang.MobsProgression.format(getQuest().getName(), 100, 100), BarColor.YELLOW, style); update(amount); } @@ -351,7 +323,7 @@ public void update(int amount) { if (amount >= 0 && amount <= cachedSize) { bar.setProgress((double) (cachedSize - amount) / (double) cachedSize); }else QuestsPlugin.getPlugin().getLoggerExpanded().warning("Amount of objects superior to max objects in " + AbstractCountableStage.this.toString() + " for player " + p.getName() + ": " + amount + " > " + cachedSize); - bar.setTitle(Lang.MobsProgression.format(branch.getQuest().getName(), cachedSize - amount, cachedSize)); + bar.setTitle(Lang.MobsProgression.format(getQuest().getName(), cachedSize - amount, cachedSize)); bar.addPlayer(p); timer(); } @@ -359,7 +331,7 @@ public void update(int amount) { private void timer() { if (QuestsConfiguration.getProgressBarTimeout() <= 0) return; if (timer != null) timer.cancel(); - timer = Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), () -> { + timer = Bukkit.getScheduler().runTaskLater(QuestsPlugin.getPlugin(), () -> { bar.removePlayer(player); timer = null; }, QuestsConfiguration.getProgressBarTimeout() * 20L); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index 7667116a..344a9713 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -21,10 +21,11 @@ import fr.skytasul.quests.api.editors.checkers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; @@ -38,15 +39,15 @@ public abstract class AbstractEntityStage extends AbstractStage implements Locat protected final @NotNull EntityType entity; protected final int amount; - protected AbstractEntityStage(@NotNull QuestBranch branch, @NotNull EntityType entity, int amount) { - super(branch); + protected AbstractEntityStage(@NotNull StageController controller, @NotNull EntityType entity, int amount) { + super(controller); this.entity = entity; this.amount = amount; } protected void event(@NotNull Player p, @NotNull EntityType type) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (branch.hasStageLaunched(acc, this) && canUpdate(p)) { + if (hasStarted(p) && canUpdate(p)) { if (entity == null || type.equals(entity)) { Integer playerAmount = getPlayerAmount(acc); if (playerAmount == null) { @@ -54,7 +55,7 @@ protected void event(@NotNull Player p, @NotNull EntityType type) { }else if (playerAmount.intValue() <= 1) { finishStage(p); }else { - updateObjective(acc, p, "amount", playerAmount.intValue() - 1); + updateObjective(p, "amount", playerAmount.intValue() - 1); } } } @@ -65,7 +66,7 @@ protected void event(@NotNull Player p, @NotNull EntityType type) { } @Override - protected void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { + public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { super.initPlayerDatas(acc, datas); datas.put("amount", amount); } @@ -84,7 +85,8 @@ protected void serialize(@NotNull ConfigurationSection section) { } @Override - protected @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull Source source) { + public @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, + @NotNull DescriptionSource source) { return new Supplier[] { () -> getMobsLeft(acc) }; } @@ -106,7 +108,7 @@ public boolean canBeFetchedAsynchronously() { }) .filter(Objects::nonNull) .sorted(Comparator.comparing(Entry::getValue)) - .<Located>map(entry -> Located.LocatedEntity.open(entry.getKey())) + .<Located>map(entry -> Located.LocatedEntity.create(entry.getKey())) .spliterator(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java index 5aa6afad..c8f330c7 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java @@ -16,24 +16,26 @@ import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.quests.branches.QuestBranch; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.ItemsGUI; import fr.skytasul.quests.gui.misc.ItemComparisonGUI; -import fr.skytasul.quests.utils.types.CountableObject; public abstract class AbstractItemStage extends AbstractCountableStage<ItemStack> { protected final @NotNull ItemComparisonMap comparisons; - protected AbstractItemStage(@NotNull QuestBranch branch, @NotNull List<@NotNull CountableObject<ItemStack>> objects, + protected AbstractItemStage(@NotNull StageController controller, + @NotNull List<@NotNull CountableObject<ItemStack>> objects, ItemComparisonMap comparisons) { - super(branch, objects); + super(controller, objects); this.comparisons = comparisons; } - protected AbstractItemStage(@NotNull QuestBranch branch, @NotNull ConfigurationSection section) { - super(branch, new ArrayList<>()); + protected AbstractItemStage(@NotNull StageController controller, @NotNull ConfigurationSection section) { + super(controller, new ArrayList<>()); if (section.contains("itemComparisons")) { comparisons = new ItemComparisonMap(section.getConfigurationSection("itemComparisons")); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java b/api/src/main/java/fr/skytasul/quests/api/utils/BQBlock.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java rename to api/src/main/java/fr/skytasul/quests/api/utils/BQBlock.java index 7cde80e9..739ea338 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/BQBlock.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/BQBlock.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.types; +package fr.skytasul.quests.api.utils; import java.util.Collection; import java.util.Iterator; @@ -14,7 +14,6 @@ import fr.skytasul.quests.api.stages.types.Locatable.Located; import fr.skytasul.quests.api.stages.types.Locatable.Located.LocatedBlock; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.utils.compatibility.Post1_13; public abstract class BQBlock { @@ -81,7 +80,7 @@ public String toString() { } public static @NotNull Spliterator<Locatable.@NotNull Located> getNearbyBlocks( - @NotNull Locatable.MultipleLocatable.NearbyFetcher fetcher, @NotNull Collection<@NotNull BQBlock> types) { + @NotNull Locatable.MultipleLocatable.NearbyFetcher fetcher, @NotNull Collection<fr.skytasul.quests.api.utils.BQBlock> types) { if (!fetcher.isTargeting(LocatedType.BLOCK)) return Spliterators.emptySpliterator(); int minY = (int) Math.max(fetcher.getCenter().getWorld().getMinHeight(), fetcher.getCenter().getY() - fetcher.getMaxDistance()); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/CountableObject.java b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/utils/types/CountableObject.java rename to api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java index a11cea5f..1ebbb177 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/CountableObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.types; +package fr.skytasul.quests.api.utils; import java.util.Objects; import java.util.UUID; @@ -30,7 +30,7 @@ public interface MutableCountableObject<T> extends CountableObject<T> { } - static <T> @NotNull CountableObject<T> create(@NotNull UUID uuid, @NotNull T object, int amount) { + static <T> fr.skytasul.quests.api.utils.CountableObject<T> create(@NotNull UUID uuid, @NotNull T object, int amount) { return new DummyCountableObject<>(uuid, object, amount); } 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 e6d19514..8ebfee63 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,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; public enum PlayerListCategory { @@ -42,10 +41,6 @@ public int getSlot() { public @NotNull String getName() { return name; } - - public boolean isEnabled() { - return QuestsConfiguration.getMenuConfig().getEnabledTabs().contains(this); - } public static @Nullable PlayerListCategory fromString(@NotNull String name) { try { diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java index 4e73b1f7..d2601eca 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java @@ -35,7 +35,7 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.scoreboard.DisplaySlot; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -112,7 +112,8 @@ public static String getStringFromNameAndAmount(String name, String amountColor, String string = name; if (remaining > 1 || showXOne) { string += "§r" + amountColor + " " - + Utils.format(QuestsConfiguration.getDescriptionAmountFormat(), remaining, done, total, percentage); + + MessageUtils.format(QuestsConfiguration.getConfig().getStageDescriptionConfig().getSplitAmountFormat(), + remaining, done, total, percentage); } return string; } diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 7e518306..b1a87d23 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -71,7 +71,7 @@ public class BeautyQuests extends JavaPlugin implements QuestsPlugin { /* --------- Storage --------- */ private String lastVersion; - private QuestsConfiguration config; + private QuestsConfigurationImplementation config; private String loadedLanguage; @@ -275,14 +275,15 @@ private void registerCommands(){ } private void launchSaveCycle(){ - if (QuestsConfiguration.saveCycle > 0 && saveTask == null) { - int cycle = QuestsConfiguration.saveCycle * 60 * 20; + if (config.saveCycle > 0 && saveTask == null) { + int cycle = config.saveCycle * 60 * 20; saveTask = new BukkitRunnable() { @Override public void run() { try { saveAllConfig(false); - if (QuestsConfiguration.saveCycleMessage) logger.info("Datas saved ~ periodic save"); + if (config.saveCycleMessage) + logger.info("Datas saved ~ periodic save"); }catch (Exception e) { logger.severe("Error when saving!", e); } @@ -293,7 +294,7 @@ public void run() { } private void stopSaveCycle(){ - if (QuestsConfiguration.saveCycle > 0 && saveTask != null){ + if (config.saveCycle > 0 && saveTask != null) { saveTask.cancel(); saveTask = null; logger.info("Periodic saves task stopped."); @@ -370,7 +371,7 @@ private void launchUpdateChecker(String pluginVersion) { private void loadConfigParameters(boolean init) throws LoadingException { try{ File configFile = new File(getDataFolder(), "config.yml"); - config = new QuestsConfiguration(this); + config = new QuestsConfigurationImplementation(this); if (config.update()) { config.getConfig().save(configFile); logger.info("Updated config."); @@ -459,7 +460,7 @@ private void loadAllDatas() throws Throwable { dependencies.lockDependencies(); // command.lockCommands(); we cannot register Brigadier after plugin initialization... - if (scoreboards == null && QuestsConfiguration.showScoreboards()) { + if (scoreboards == null && config.getQuestsConfig().scoreboards()) { File scFile = new File(getDataFolder(), "scoreboard.yml"); if (!scFile.exists()) saveResource("scoreboard.yml", true); scoreboards = new ScoreboardManager(scFile); @@ -487,9 +488,9 @@ private void loadAllDatas() throws Throwable { pools = new QuestPoolsManagerImplementation(new File(getDataFolder(), "questPools.yml")); quests = new QuestsManagerImplementation(this, data.getInt("lastID"), saveFolder); - if (QuestsConfiguration.firstQuestID != -1) { + if (config.firstQuestID != -1) { logger.warning("The config option \"firstQuest\" is present in your config.yml but is now unsupported. Please remove it."); - QuestImplementation quest = quests.getQuest(QuestsConfiguration.firstQuestID); + QuestImplementation quest = quests.getQuest(config.firstQuestID); if (quest != null) { if (quest.hasOption(OptionAutoQuest.class)) { OptionAutoQuest option = quest.getOption(OptionAutoQuest.class); @@ -563,7 +564,8 @@ private void resetDatas(){ /* ---------- Backups ---------- */ public boolean createFolderBackup(Path backup) { - if (!QuestsConfiguration.backups) return false; + if (!config.backups) + return false; logger.info("Creating quests backup..."); Path backupDir = backup.resolve("quests"); Path saveFolderPath = saveFolder.toPath(); @@ -586,7 +588,8 @@ public boolean createFolderBackup(Path backup) { } public boolean createDataBackup(Path backup) { - if (!QuestsConfiguration.backups) return false; + if (!config.backups) + return false; logger.info("Creating data backup..."); try{ Path target = backup.resolve("data.yml"); @@ -604,7 +607,8 @@ public boolean createDataBackup(Path backup) { } public boolean createPlayerDatasBackup(Path backup, PlayersManagerYAML yamlManager) { - if (!QuestsConfiguration.backups) return false; + if (!config.backups) + return false; logger.info("Creating player datas backup..."); Path backupDir = backup.resolve("players"); @@ -628,7 +632,8 @@ public boolean createPlayerDatasBackup(Path backup, PlayersManagerYAML yamlManag } public boolean createQuestBackup(Path file, String msg) { - if (!QuestsConfiguration.backups) return false; + if (!config.backups) + return false; logger.info("Creating single quest backup..."); try{ Path target = Paths.get(file.toString() + "-backup" + format.format(new Date()) + ".yml"); @@ -727,7 +732,7 @@ public boolean hasSavingFailed() { @Override public @NotNull String getPrefix() { - return QuestsConfiguration.getPrefix(); + return config.getPrefix(); } @Override @@ -736,7 +741,7 @@ public boolean hasSavingFailed() { } @Override - public @NotNull QuestsConfiguration getConfiguration() { + public @NotNull QuestsConfigurationImplementation getConfiguration() { return config; } diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index 5b9e1dc5..3baa85dc 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -102,7 +102,7 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("description", 12, OptionDescription.class, OptionDescription::new, null)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("customItem", 13, OptionQuestItem.class, - OptionQuestItem::new, QuestsConfiguration.getItemMaterial(), "customMaterial")); + OptionQuestItem::new, QuestsConfigurationImplementation.getItemMaterial(), "customMaterial")); QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("confirmMessage", 15, OptionConfirmMessage.class, OptionConfirmMessage::new, null)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramText", 17, OptionHologramText.class, @@ -118,9 +118,9 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("cancelActions", 22, OptionCancelRewards.class, OptionCancelRewards::new, new ArrayList<>())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunch", 25, OptionHologramLaunch.class, - OptionHologramLaunch::new, QuestsConfiguration.getHoloLaunchItem())); + OptionHologramLaunch::new, QuestsConfigurationImplementation.getHoloLaunchItem())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunchNo", 26, OptionHologramLaunchNo.class, - OptionHologramLaunchNo::new, QuestsConfiguration.getHoloLaunchNoItem())); + OptionHologramLaunchNo::new, QuestsConfigurationImplementation.getHoloLaunchNoItem())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("scoreboard", 27, OptionScoreboardEnabled.class, OptionScoreboardEnabled::new, true)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hideNoRequirements", 28, @@ -130,19 +130,19 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("repeatable", 30, OptionRepeatable.class, OptionRepeatable::new, false, "multiple")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("timer", 31, OptionTimer.class, OptionTimer::new, - QuestsConfiguration.getTimeBetween())); + QuestsConfigurationImplementation.getTimeBetween())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("visibility", 32, OptionVisibility.class, OptionVisibility::new, Arrays.asList(QuestVisibilityLocation.values()), "hid", "hide")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endSound", 34, OptionEndSound.class, - OptionEndSound::new, QuestsConfiguration.getFinishSound())); + OptionEndSound::new, QuestsConfigurationImplementation.getFinishSound())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("firework", 35, OptionFirework.class, - OptionFirework::new, QuestsConfiguration.getDefaultFirework())); + OptionFirework::new, QuestsConfigurationImplementation.getDefaultFirework())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("requirements", 36, OptionRequirements.class, OptionRequirements::new, new ArrayList<>())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("startRewards", 38, OptionStartRewards.class, OptionStartRewards::new, new ArrayList<>(), "startRewardsList")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("startMessage", 39, OptionStartMessage.class, - OptionStartMessage::new, QuestsConfiguration.getPrefix() + Lang.STARTED_QUEST.toString())); + OptionStartMessage::new, QuestsConfigurationImplementation.getPrefix() + Lang.STARTED_QUEST.toString())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("starterNPC", 40, OptionStarterNPC.class, OptionStarterNPC::new, null, "starterID")); QuestsAPI.getAPI().registerQuestOption( @@ -150,7 +150,7 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endRewards", 43, OptionEndRewards.class, OptionEndRewards::new, new ArrayList<>(), "rewardsList")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endMsg", 44, OptionEndMessage.class, - OptionEndMessage::new, QuestsConfiguration.getPrefix() + Lang.FINISHED_BASE.toString())); + OptionEndMessage::new, QuestsConfigurationImplementation.getPrefix() + Lang.FINISHED_BASE.toString())); } public static void registerRewards() { diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java similarity index 50% rename from core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java rename to core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 0030435d..2ad7196b 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfiguration.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -1,9 +1,8 @@ package fr.skytasul.quests; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.List; +import java.util.EnumSet; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -16,12 +15,14 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import com.google.common.collect.Sets; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; 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.npcs.NpcClickType; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescription; import fr.skytasul.quests.api.utils.MinecraftNames; @@ -33,86 +34,53 @@ import fr.skytasul.quests.utils.compatibility.Accounts; import fr.skytasul.quests.utils.compatibility.DependenciesManager; -public class QuestsConfiguration { - - private static int timer = 5; - private static String minecraftTranslationsFile = null; - private static int maxLaunchedQuests = 0; - private static boolean sounds = true; - private static boolean fireworks = true; - private static boolean gps = false; - private static boolean skillAPIoverride = true; - private static boolean scoreboard = true; - private static String finishSound = "ENTITY_PLAYER_LEVELUP"; - private static String nextStageSound = "ITEM_FIRECHARGE_USE"; - private static ItemStack item = XMaterial.BOOK.parseItem(); - private static XMaterial pageItem = XMaterial.ARROW; - private static int startParticleDistance, startParticleDistanceSquared; - private static int requirementUpdateTime; - private static boolean enablePrefix = true; - private static double hologramsHeight = 0.0; - private static boolean disableTextHologram = false; - private static boolean showCustomHologramName = true; - private static boolean mobsProgressBar = false; - private static int progressBarTimeoutSeconds = 15; - private static boolean hookAcounts = false; - private static boolean usePlayerBlockTracker = false; - private static ParticleEffect particleStart; - private static ParticleEffect particleTalk; - private static ParticleEffect particleNext; - private static boolean sendUpdate = true; - private static boolean stageStart = true; - private static boolean questConfirmGUI = false; - private static Collection<ClickType> npcClicks = Arrays.asList(ClickType.RIGHT, ClickType.SHIFT_RIGHT); - private static boolean skipNpcGuiIfOnlyOneQuest = true; - private static String dSetName = "Quests"; - private static String dIcon = "bookshelf"; - private static int dMinZoom = 0; - // stageDescription - private static String itemNameColor; - private static String itemAmountColor; - private static String stageDescriptionFormat = "§8({0}/{1}) §e{2}"; - private static String descPrefix = "{nl}§e- §6"; - private static String descAmountFormat = "x{0}"; - private static boolean descXOne = true; - private static boolean inlineAlone = true; - private static List<DescriptionSource> descSources = new ArrayList<>(); - private static boolean requirementReasonOnMultipleQuests = true; - private static boolean stageEndRewardsMessage = true; - private static QuestDescription questDescription; - - private static ItemStack holoLaunchItem = null; - private static ItemStack holoLaunchNoItem = null; - private static ItemStack holoTalkItem = null; - - private static FireworkMeta defaultFirework = null; +public class QuestsConfigurationImplementation implements QuestsConfiguration { + + public static QuestsConfigurationImplementation getConfiguration() { + return BeautyQuests.getInstance().getConfiguration(); + } + + private String minecraftTranslationsFile = null; + private boolean gps = false; + private boolean skillAPIoverride = true; + private boolean enablePrefix = true; + private double hologramsHeight = 0.0; + private boolean disableTextHologram = false; + private boolean showCustomHologramName = true; + private boolean hookAcounts = false; + private boolean usePlayerBlockTracker = false; + private ParticleEffect particleStart; + private ParticleEffect particleTalk; + private ParticleEffect particleNext; + private String dSetName = "Quests"; + private String dIcon = "bookshelf"; + private int dMinZoom = 0; + private QuestDescription questDescription; + + private ItemStack holoLaunchItem = null; + private ItemStack holoLaunchNoItem = null; + private ItemStack holoTalkItem = null; + + private FireworkMeta defaultFirework = null; - static boolean backups = true; + boolean backups = true; - static boolean saveCycleMessage = true; - static int saveCycle = 15; - static int firstQuestID = -1; // changed in 0.19, TODO + boolean saveCycleMessage = true; + int saveCycle = 15; + int firstQuestID = -1; // changed in 0.19, TODO private FileConfiguration config; + private QuestsConfig quests; private DialogsConfig dialogs; private QuestsMenuConfig menu; + private StageDescriptionConfig stageDescription; - QuestsConfiguration(BeautyQuests plugin) { + QuestsConfigurationImplementation(BeautyQuests plugin) { config = plugin.getConfig(); + quests = new QuestsConfig(); dialogs = new DialogsConfig(config.getConfigurationSection("dialogs")); menu = new QuestsMenuConfig(config.getConfigurationSection("questsMenu")); - } - - public FileConfiguration getConfig() { - return config; - } - - public DialogsConfig getDialogs() { - return dialogs; - } - - public QuestsMenuConfig getQuestsMenu() { - return menu; + stageDescription = new StageDescriptionConfig(); } boolean update() { @@ -126,56 +94,19 @@ void init() { backups = config.getBoolean("backups", true); if (!backups) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Backups are disabled due to the presence of \"backups: false\" in config.yml."); - timer = config.getInt("redoMinuts"); minecraftTranslationsFile = config.getString("minecraftTranslationsFile"); - if (isMinecraftTranslationsEnabled()) { + if (isMinecraftTranslationsEnabled()) initializeTranslations(); - } + quests.init(); dialogs.init(); menu.init(); - + stageDescription.init(); + saveCycle = config.getInt("saveCycle"); saveCycleMessage = config.getBoolean("saveCycleMessage"); firstQuestID = config.getInt("firstQuest", -1); - maxLaunchedQuests = config.getInt("maxLaunchedQuests"); - sendUpdate = config.getBoolean("playerQuestUpdateMessage"); - stageStart = config.getBoolean("playerStageStartMessage"); - questConfirmGUI = config.getBoolean("questConfirmGUI"); - sounds = config.getBoolean("sounds"); - fireworks = config.getBoolean("fireworks"); gps = DependenciesManager.gps.isEnabled() && config.getBoolean("gps"); skillAPIoverride = config.getBoolean("skillAPIoverride"); - scoreboard = config.getBoolean("scoreboards"); - if (config.isItemStack("item")) { - item = config.getItemStack("item"); - }else if (config.isString("item")) { - item = XMaterial.matchXMaterial(config.getString("item")).orElse(XMaterial.BOOK).parseItem(); - }else item = XMaterial.BOOK.parseItem(); - item = ItemUtils.clearVisibleAttributes(item); - if (config.contains("pageItem")) pageItem = XMaterial.matchXMaterial(config.getString("pageItem")).orElse(XMaterial.ARROW); - if (pageItem == null) pageItem = XMaterial.ARROW; - startParticleDistance = config.getInt("startParticleDistance"); - startParticleDistanceSquared = startParticleDistance * startParticleDistance; - requirementUpdateTime = config.getInt("requirementUpdateTime"); - requirementReasonOnMultipleQuests = config.getBoolean("requirementReasonOnMultipleQuests"); - stageEndRewardsMessage = config.getBoolean("stageEndRewardsMessage"); - mobsProgressBar = config.getBoolean("mobsProgressBar"); - progressBarTimeoutSeconds = config.getInt("progressBarTimeoutSeconds"); - try { - if (config.isString("npcClick")) { - String click = config.getString("npcClick"); - npcClicks = Arrays.asList(click.equals("ANY") ? ClickType.values() : new ClickType[] { ClickType.valueOf(click.toUpperCase()) }); - }else { - npcClicks = config.getStringList("npcClick") - .stream() - .map(String::toUpperCase) - .map(ClickType::valueOf) - .collect(Collectors.toList()); - } - }catch (IllegalArgumentException ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unknown click type " + config.get("npcClick") + " for config entry \"npcClick\""); - } - skipNpcGuiIfOnlyOneQuest = config.getBoolean("skip npc gui if only one quest"); enablePrefix = config.getBoolean("enablePrefix"); disableTextHologram = config.getBoolean("disableTextHologram"); showCustomHologramName = config.getBoolean("showCustomHologramName"); @@ -190,24 +121,6 @@ void init() { if (dSetName == null || dSetName.isEmpty()) DependenciesManager.dyn.disable(); dIcon = config.getString("dynmap.markerIcon"); dMinZoom = config.getInt("dynmap.minZoom"); - finishSound = loadSound("finishSound"); - nextStageSound = loadSound("nextStageSound"); - - // stageDescription - itemNameColor = config.getString("itemNameColor"); - itemAmountColor = config.getString("itemAmountColor"); - stageDescriptionFormat = config.getString("stageDescriptionFormat"); - descPrefix = "{nl}" + config.getString("stageDescriptionItemsSplit.prefix"); - descAmountFormat = config.getString("stageDescriptionItemsSplit.amountFormat"); - descXOne = config.getBoolean("stageDescriptionItemsSplit.showXOne"); - inlineAlone = config.getBoolean("stageDescriptionItemsSplit.inlineAlone"); - for (String s : config.getStringList("stageDescriptionItemsSplit.sources")){ - try{ - descSources.add(DescriptionSource.valueOf(s)); - }catch (IllegalArgumentException ex){ - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Loading of description splitted sources failed : source " + s + " does not exist"); - } - } questDescription = new QuestDescription(config.getConfigurationSection("questDescription")); @@ -297,237 +210,295 @@ private boolean migrateEntry(ConfigurationSection config, ConfigurationSection m return false; } - public static String getPrefix(){ - return (enablePrefix) ? Lang.Prefix.toString() : "§6"; + public FileConfiguration getConfig() { + return config; } - public static int getTimeBetween(){ - return timer; - } - - public static int getMaxLaunchedQuests() { - return maxLaunchedQuests; + @Override + public @NotNull Quests getQuestsConfig() { + return quests; } - public static boolean sendQuestUpdateMessage(){ - return sendUpdate; + @Override + public @NotNull DialogsConfig getDialogsConfig() { + return dialogs; } - public static boolean sendStageStartMessage(){ - return stageStart; + @Override + public @NotNull QuestsMenuConfig getQuestsMenuConfig() { + return menu; } - public static boolean questConfirmGUI(){ - return questConfirmGUI; - } - - public static boolean playSounds(){ - return sounds; + @Override + public @NotNull StageDescriptionConfig getStageDescriptionConfig() { + return stageDescription; } - public static boolean doFireworks(){ - return fireworks; - } - - public static boolean showMobsProgressBar() { - return mobsProgressBar && QuestsAPI.getAPI().hasBossBarManager(); - } - - public static int getProgressBarTimeout(){ - return progressBarTimeoutSeconds; - } - - public static Collection<ClickType> getNPCClicks() { - return npcClicks; - } - - public static boolean skipNpcGuiIfOnlyOneQuest() { - return skipNpcGuiIfOnlyOneQuest; + public String getPrefix() { + return (enablePrefix) ? Lang.Prefix.toString() : "§6"; } - public static boolean handleGPS(){ + public boolean handleGPS() { return gps; } - public static boolean xpOverridedSkillAPI(){ + public boolean xpOverridedSkillAPI() { return skillAPIoverride; } - - public static boolean showScoreboards(){ - return scoreboard; - } - - public static ItemStack getItemMaterial() { - return item; - } - - public static XMaterial getPageMaterial(){ - return pageItem; - } - - public static int getRequirementUpdateTime() { - return requirementUpdateTime; - } - - public static boolean isRequirementReasonSentOnMultipleQuests() { - return requirementReasonOnMultipleQuests; - } - - public static boolean hasStageEndRewardsMessage() { - return stageEndRewardsMessage; - } - - public static int getStartParticleDistance() { - return startParticleDistance; - } - - public static int getStartParticleDistanceSquared() { - return startParticleDistanceSquared; - } - public static boolean isTextHologramDisabled(){ + public boolean isTextHologramDisabled() { return disableTextHologram; } - public static String getItemAmountColor() { - return itemAmountColor; - } - - public static String getStageDescriptionFormat() { - return stageDescriptionFormat; - } - - public static String getItemNameColor() { - return itemNameColor; - } - - public static boolean showStartParticles(){ + public boolean showStartParticles() { return particleStart != null; } - public static ParticleEffect getParticleStart() { + public ParticleEffect getParticleStart() { return particleStart; } - public static boolean showTalkParticles(){ + public boolean showTalkParticles() { return particleTalk != null; } - public static ParticleEffect getParticleTalk() { + public ParticleEffect getParticleTalk() { return particleTalk; } - public static boolean showNextParticles(){ + public boolean showNextParticles() { return particleNext != null; } - public static ParticleEffect getParticleNext() { + public ParticleEffect getParticleNext() { return particleNext; } - public static double getHologramsHeight(){ + public double getHologramsHeight() { return hologramsHeight; } - public static boolean isCustomHologramNameShown(){ + public boolean isCustomHologramNameShown() { return showCustomHologramName; } - public static ItemStack getHoloLaunchItem(){ + public ItemStack getHoloLaunchItem() { return holoLaunchItem; } - public static ItemStack getHoloLaunchNoItem(){ + public ItemStack getHoloLaunchNoItem() { return holoLaunchNoItem; } - public static ItemStack getHoloTalkItem(){ + public ItemStack getHoloTalkItem() { return holoTalkItem; } - public static FireworkMeta getDefaultFirework() { + public FireworkMeta getDefaultFirework() { return defaultFirework; } - public static boolean hookAccounts(){ + public boolean hookAccounts() { return hookAcounts; } - public static boolean usePlayerBlockTracker() { + public boolean usePlayerBlockTracker() { return usePlayerBlockTracker; } - public static String dynmapSetName(){ + public String dynmapSetName() { return dSetName; } - public static String dynmapMarkerIcon(){ + public String dynmapMarkerIcon() { return dIcon; } - public static int dynmapMinimumZoom(){ + public int dynmapMinimumZoom() { return dMinZoom; } - public static boolean isMinecraftTranslationsEnabled() { + public boolean isMinecraftTranslationsEnabled() { return minecraftTranslationsFile != null && !minecraftTranslationsFile.isEmpty(); } - public static String getDescriptionItemPrefix(){ - return descPrefix; - } - - public static String getDescriptionAmountFormat() { - return descAmountFormat; - } - - public static boolean showDescriptionItemsXOne(DescriptionSource source){ - return splitDescription(source) && descXOne; - } - - public static boolean inlineAlone() { - return inlineAlone; - } - - public static boolean splitDescription(DescriptionSource source){ - if (source == DescriptionSource.FORCESPLIT) return true; - if (source == DescriptionSource.FORCELINE) return false; - return descSources.contains(source); - } - - public static QuestDescription getQuestDescription() { + public QuestDescription getQuestDescription() { return questDescription; } - public static String getFinishSound(){ - return finishSound; - } - - public static String getNextStageSound() { - return nextStageSound; - } - - public static DialogsConfig getDialogsConfig() { - return BeautyQuests.getInstance().getConfiguration().dialogs; - } - - public static QuestsMenuConfig getMenuConfig() { - return BeautyQuests.getInstance().getConfiguration().menu; - } - - public enum ClickType { - RIGHT, SHIFT_RIGHT, LEFT, SHIFT_LEFT; - - public static ClickType of(boolean left, boolean shift) { - if (left) { - return shift ? SHIFT_LEFT : LEFT; - }else { - return shift ? SHIFT_RIGHT : RIGHT; + public class QuestsConfig implements QuestsConfiguration.Quests { + + private int defaultTimer = 5; + private int maxLaunchedQuests = 0; + private boolean scoreboards = true; + private boolean sounds = true; + private boolean fireworks = true; + private String finishSound = "ENTITY_PLAYER_LEVELUP"; + private String nextStageSound = "ITEM_FIRECHARGE_USE"; + private ItemStack defaultQuestItem = XMaterial.BOOK.parseItem(); + private XMaterial pageItem = XMaterial.ARROW; + private int startParticleDistance; + private int requirementUpdateTime; + private boolean sendUpdate = true; + private boolean stageStart = true; + private boolean questConfirmGUI = false; + private Collection<NpcClickType> npcClicks = Arrays.asList(NpcClickType.RIGHT, NpcClickType.SHIFT_RIGHT); + private boolean skipNpcGuiIfOnlyOneQuest = true; + private boolean mobsProgressBar = false; + private int progressBarTimeoutSeconds = 15; + private boolean requirementReasonOnMultipleQuests = true; + private boolean stageEndRewardsMessage = true; + + private void init() { + defaultTimer = config.getInt("redoMinuts"); + maxLaunchedQuests = config.getInt("maxLaunchedQuests"); + scoreboards = config.getBoolean("scoreboards"); + sendUpdate = config.getBoolean("playerQuestUpdateMessage"); + stageStart = config.getBoolean("playerStageStartMessage"); + questConfirmGUI = config.getBoolean("questConfirmGUI"); + sounds = config.getBoolean("sounds"); + fireworks = config.getBoolean("fireworks"); + if (config.isItemStack("item")) { + defaultQuestItem = config.getItemStack("item"); + } else if (config.isString("item")) { + defaultQuestItem = XMaterial.matchXMaterial(config.getString("item")).orElse(XMaterial.BOOK).parseItem(); + } else + defaultQuestItem = XMaterial.BOOK.parseItem(); + defaultQuestItem = ItemUtils.clearVisibleAttributes(defaultQuestItem); + if (config.contains("pageItem")) + pageItem = XMaterial.matchXMaterial(config.getString("pageItem")).orElse(XMaterial.ARROW); + if (pageItem == null) + pageItem = XMaterial.ARROW; + startParticleDistance = config.getInt("startParticleDistance"); + requirementUpdateTime = config.getInt("requirementUpdateTime"); + finishSound = loadSound("finishSound"); + nextStageSound = loadSound("nextStageSound"); + try { + if (config.isString("npcClick")) { + String click = config.getString("npcClick"); + npcClicks = Arrays.asList(click.equals("ANY") ? NpcClickType.values() + : new NpcClickType[] {NpcClickType.valueOf(click.toUpperCase())}); + } else { + npcClicks = config.getStringList("npcClick") + .stream() + .map(String::toUpperCase) + .map(NpcClickType::valueOf) + .collect(Collectors.toList()); + } + } catch (IllegalArgumentException ex) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Unknown click type " + config.get("npcClick") + " for config entry \"npcClick\""); } + skipNpcGuiIfOnlyOneQuest = config.getBoolean("skip npc gui if only one quest"); + mobsProgressBar = config.getBoolean("mobsProgressBar"); + progressBarTimeoutSeconds = config.getInt("progressBarTimeoutSeconds"); + requirementReasonOnMultipleQuests = config.getBoolean("requirementReasonOnMultipleQuests"); + stageEndRewardsMessage = config.getBoolean("stageEndRewardsMessage"); + } + + @Override + public int getDefaultTimer() { + return defaultTimer; + } + + @Override + public int maxLaunchedQuests() { + return maxLaunchedQuests; + } + + @Override + public boolean scoreboards() { + return scoreboards; + } + + @Override + public boolean playerQuestUpdateMessage() { + return sendUpdate; + } + + @Override + public boolean playerStageStartMessage() { + return stageStart; + } + + @Override + public boolean questConfirmGUI() { + return questConfirmGUI; + } + + @Override + public boolean sounds() { + return sounds; + } + + @Override + public String finishSound() { + return finishSound; + } + + @Override + public String nextStageSound() { + return nextStageSound; + } + + @Override + public boolean fireworks() { + return fireworks; + } + + @Override + public boolean mobsProgressBar() { + return mobsProgressBar && QuestsAPI.getAPI().hasBossBarManager(); + } + + @Override + public int progressBarTimeoutSeconds() { + return progressBarTimeoutSeconds; + } + + @Override + public Collection<NpcClickType> getNpcClicks() { + return npcClicks; + } + + @Override + public boolean skipNpcGuiIfOnlyOneQuest() { + return skipNpcGuiIfOnlyOneQuest; + } + + @Override + public ItemStack getDefaultQuestItem() { + return defaultQuestItem; + } + + @Override + public XMaterial getPageMaterial() { + return pageItem; } + + @Override + public double startParticleDistance() { + return startParticleDistance; + } + + @Override + public int requirementUpdateTime() { + return requirementUpdateTime; + } + + @Override + public boolean requirementReasonOnMultipleQuests() { + return requirementReasonOnMultipleQuests; + } + + @Override + public boolean stageEndRewardsMessage() { + return stageEndRewardsMessage; + } + } - - public class DialogsConfig { + + public class DialogsConfig implements QuestsConfiguration.Dialogs { private boolean inActionBar = false; private int defaultTime = 100; @@ -571,49 +542,59 @@ private void init() { defaultNPCSound = config.getString("defaultNPCSound"); } + @Override public boolean sendInActionBar() { return inActionBar; } + @Override public int getDefaultTime() { return defaultTime; } + @Override public boolean isSkippableByDefault() { return defaultSkippable; } + @Override public boolean isClickDisabled() { return disableClick; } + @Override public boolean isHistoryEnabled() { return history; } + @Override public int getMaxMessagesPerHistoryPage() { return maxMessagesPerHistoryPage; } + @Override public int getMaxDistance() { return maxDistance; } + @Override public int getMaxDistanceSquared() { return maxDistanceSquared; } + @Override public String getDefaultPlayerSound() { return defaultPlayerSound; } + @Override public String getDefaultNPCSound() { return defaultNPCSound; } } - public class QuestsMenuConfig { + public class QuestsMenuConfig implements QuestsConfiguration.QuestsMenu { private Set<PlayerListCategory> tabs; private boolean openNotStartedTabWhenEmpty = true; @@ -638,24 +619,110 @@ private void init() { tabs = config.getStringList("enabledTabs").stream().map(PlayerListCategory::fromString).collect(Collectors.toSet()); if (tabs.isEmpty()) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Quests Menu must have at least one enabled tab."); - tabs = Sets.newHashSet(PlayerListCategory.values()); + tabs = EnumSet.allOf(PlayerListCategory.class); } openNotStartedTabWhenEmpty = config.getBoolean("openNotStartedTabWhenEmpty"); allowPlayerCancelQuest = config.getBoolean("allowPlayerCancelQuest"); } + @Override public boolean isNotStartedTabOpenedWhenEmpty() { return openNotStartedTabWhenEmpty; } + @Override public boolean allowPlayerCancelQuest() { return allowPlayerCancelQuest; } + @Override public Set<PlayerListCategory> getEnabledTabs() { return tabs; } } + public class StageDescriptionConfig implements QuestsConfiguration.StageDescription { + + private String itemNameColor; + private String itemAmountColor; + private String stageDescriptionFormat = "§8({0}/{1}) §e{2}"; + private String descPrefix = "{nl}§e- §6"; + private String descAmountFormat = "x{0}"; + private boolean descXOne = true; + private boolean inlineAlone = true; + private Set<DescriptionSource> descSources = EnumSet.noneOf(DescriptionSource.class); + + private void init() { + itemNameColor = config.getString("itemNameColor"); + itemAmountColor = config.getString("itemAmountColor"); + stageDescriptionFormat = config.getString("stageDescriptionFormat"); + descPrefix = "{nl}" + config.getString("stageDescriptionItemsSplit.prefix"); + descAmountFormat = config.getString("stageDescriptionItemsSplit.amountFormat"); + descXOne = config.getBoolean("stageDescriptionItemsSplit.showXOne"); + inlineAlone = config.getBoolean("stageDescriptionItemsSplit.inlineAlone"); + for (String s : config.getStringList("stageDescriptionItemsSplit.sources")) { + try { + descSources.add(DescriptionSource.valueOf(s)); + } catch (IllegalArgumentException ex) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Loading of description splitted sources failed : source " + s + " does not exist"); + } + } + } + + @Override + public String getStageDescriptionFormat() { + return stageDescriptionFormat; + } + + @Override + public String getItemNameColor() { + return itemNameColor; + } + + @Override + public String getItemAmountColor() { + return itemAmountColor; + } + + @Override + public String getSplitPrefix() { + return descPrefix; + } + + @Override + public String getSplitAmountFormat() { + return descAmountFormat; + } + + @Override + public boolean isAloneSplitAmountShown() { + return descXOne; + } + + @Override + public boolean isAloneSplitInlined() { + return inlineAlone; + } + + @Override + public Set<DescriptionSource> getSplitSources() { + return descSources; + } + + public boolean showDescriptionItemsXOne(DescriptionSource source) { + return splitDescription(source) && descXOne; + } + + public boolean splitDescription(DescriptionSource source) { + if (source == DescriptionSource.FORCESPLIT) + return true; + if (source == DescriptionSource.FORCELINE) + return false; + return descSources.contains(source); + } + + } + } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 60e9cab0..dff711b7 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -23,6 +23,7 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; @@ -49,7 +50,8 @@ public class QuestsListener implements Listener{ @EventHandler (priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onNPCClick(BQNPCClickEvent e) { if (e.isCancelled()) return; - if (!QuestsConfiguration.getNPCClicks().contains(e.getClick())) return; + if (!QuestsConfiguration.getConfig().getQuestsConfig().getNpcClicks().contains(e.getClick())) + return; Player p = e.getPlayer(); BQNPC npc = e.getNPC(); @@ -132,7 +134,7 @@ public void onJoin(PlayerJoinEvent e){ QuestsPlugin.getPlugin().getLoggerExpanded().debug(player.getName() + " (" + player.getUniqueId().toString() + ") joined the server"); // for timing purpose - if (BeautyQuests.getInstance().loaded && !QuestsConfiguration.hookAccounts()) { + if (BeautyQuests.getInstance().loaded && !QuestsConfigurationImplementation.getConfiguration().hookAccounts()) { BeautyQuests.getInstance().getPlayersManager().loadPlayer(player); } } @@ -141,7 +143,7 @@ public void onJoin(PlayerJoinEvent e){ public void onQuit(PlayerQuitEvent e) { Player player = e.getPlayer(); QuestsPlugin.getPlugin().getLoggerExpanded().debug(player.getName() + " left the server"); // for timing purpose - if (!QuestsConfiguration.hookAccounts()) { + if (!QuestsConfigurationImplementation.getConfiguration().hookAccounts()) { BeautyQuests.getInstance().getPlayersManager().unloadPlayer(player); } } 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 2faeb350..7015d6c3 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.commands.CommandsManager; @@ -36,7 +36,7 @@ public class CommandsManagerImplementation implements CommandsManager { public CommandsManagerImplementation() { handler = BukkitCommandHandler.create(BeautyQuests.getInstance()); - handler.setMessagePrefix(QuestsConfiguration.getPrefix()); + handler.setMessagePrefix(QuestsConfigurationImplementation.getPrefix()); handler.failOnTooManyArguments(); handler.registerValueResolver(Quest.class, context -> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index 83d48d7e..94d6091b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.GuiManager; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -28,11 +28,11 @@ public class GuiManagerImplementation implements GuiManager, Listener { - private Map<Player, CustomInventory> players = new HashMap<>(); + private Map<Player, Gui> players = new HashMap<>(); private boolean dismissClose = false; @Override - public void open(@NotNull Player player, @NotNull CustomInventory inventory) { + public void open(@NotNull Player player, @NotNull Gui inventory) { try { closeWithoutExit(player); QuestsPlugin.getPlugin().getLoggerExpanded() @@ -74,7 +74,7 @@ public boolean hasGuiOpened(@NotNull Player player) { } @Override - public @Nullable CustomInventory getOpenedGui(@NotNull Player player) { + public @Nullable Gui getOpenedGui(@NotNull Player player) { return players.get(player); } @@ -89,7 +89,7 @@ public void onClose(InventoryCloseEvent event) { return; Player player = (Player) event.getPlayer(); - CustomInventory gui = players.get(player); + Gui gui = players.get(player); if (gui == null) return; @@ -125,7 +125,7 @@ public void onClick(InventoryClickEvent event) { return; Player player = (Player) event.getWhoClicked(); - CustomInventory gui = players.get(player); + Gui gui = players.get(player); if (gui == null) return; @@ -151,7 +151,7 @@ public void onClick(InventoryClickEvent event) { if (event.getCursor().getType() == Material.AIR) { if (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR) return; - if (gui.onClick(player, event.getCurrentItem(), event.getSlot(), click)) + if (gui.onClick(null)) event.setCancelled(true); } else { if (gui.onClickCursor(player, event.getCurrentItem(), event.getCursor(), @@ -182,7 +182,7 @@ public void onOpen(InventoryOpenEvent event) { } } - private void ensureSameInventory(CustomInventory gui, Inventory inventory) { + private void ensureSameInventory(Gui gui, Inventory inventory) { if (gui.getInventory() != inventory) throw new IllegalStateException( "The inventory opened by the player is not the same as the one registered by the plugin"); diff --git a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java index 7c45236a..a4aef7e6 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java @@ -10,9 +10,9 @@ import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.utils.types.BQBlock; -import fr.skytasul.quests.utils.types.CountableObject; -import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; +import fr.skytasul.quests.api.utils.BQBlock; +import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; public class BlocksGUI extends ListGUI<MutableCountableObject<BQBlock>> { 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 4541dfc4..3e1feb49 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 @@ -17,15 +17,15 @@ import fr.skytasul.quests.api.editors.checkers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.gui.layout.Button; -import fr.skytasul.quests.api.gui.layout.ClickEvent; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; +import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; -import fr.skytasul.quests.utils.types.BQBlock; public class SelectBlockGUI extends LayoutedGUI.LayoutedRowsGUI { @@ -42,14 +42,14 @@ public SelectBlockGUI(boolean allowAmount, BiConsumer<BQBlock, Integer> run) { this.run = run; if (allowAmount) - buttons.put(1, Button.create(XMaterial.REDSTONE, () -> Lang.Amount.format(amount), Collections.emptyList(), + buttons.put(1, LayoutedButton.create(XMaterial.REDSTONE, () -> Lang.Amount.format(amount), Collections.emptyList(), this::amountClick)); - buttons.put(2, Button.create(XMaterial.NAME_TAG, Lang.blockName.toString(), + buttons.put(2, LayoutedButton.create(XMaterial.NAME_TAG, Lang.blockName.toString(), Arrays.asList(QuestOption.formatNullableValue(customName, customName == null)), this::nameClick)); - buttons.put(4, new Button() { + buttons.put(4, new LayoutedButton() { @Override - public void click(@NotNull ClickEvent event) { + public void click(@NotNull LayoutedClickEvent event) { typeClick(event); } @@ -67,7 +67,7 @@ public void place(@NotNull Inventory inventory, int slot) { }); if (MinecraftVersion.MAJOR >= 13) { - buttons.put(5, Button.create(() -> { + buttons.put(5, LayoutedButton.create(() -> { ItemStack item = ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.blockData.toString(), QuestOption.formatNullableValue(blockData, blockData == null)); if (blockData != null) @@ -75,7 +75,7 @@ public void place(@NotNull Inventory inventory, int slot) { return item; }, this::dataClick)); - buttons.put(6, Button.create(() -> { + buttons.put(6, LayoutedButton.create(() -> { ItemStack item = ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.blockTag.toString(), QuestOption.formatDescription(Lang.blockTagLore.toString()), "", QuestOption.formatNullableValue(tag, tag == null)); @@ -85,10 +85,10 @@ public void place(@NotNull Inventory inventory, int slot) { }, this::tagClick)); } - buttons.put(8, Button.create(ItemUtils.itemDone, this::doneClick)); + buttons.put(8, LayoutedButton.create(ItemUtils.itemDone, this::doneClick)); } - private void amountClick(ClickEvent event) { + private void amountClick(LayoutedClickEvent event) { Lang.BLOCKS_AMOUNT.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { amount = obj; @@ -96,7 +96,7 @@ private void amountClick(ClickEvent event) { }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); } - private void nameClick(ClickEvent event) { + private void nameClick(LayoutedClickEvent event) { Lang.BLOCK_NAME.send(event.getPlayer()); new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { customName = obj; @@ -104,7 +104,7 @@ private void nameClick(ClickEvent event) { }).passNullIntoEndConsumer().start(); } - private void typeClick(ClickEvent event) { + private void typeClick(LayoutedClickEvent event) { Lang.BLOCK_NAME.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopen, type -> { this.type = type; @@ -120,7 +120,7 @@ private void typeClick(ClickEvent event) { }, MaterialParser.BLOCK_PARSER).start(); } - private void dataClick(ClickEvent event) { + private void dataClick(LayoutedClickEvent event) { Lang.BLOCK_DATA.send(event.getPlayer(), String.join(", ", NMS.getNMS().getAvailableBlockProperties(type.parseMaterial()))); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { @@ -139,7 +139,7 @@ private void dataClick(ClickEvent event) { }).useStrippedMessage().start(); } - private void tagClick(ClickEvent event) { + private void tagClick(LayoutedClickEvent event) { Lang.BLOCK_TAGS.send(event.getPlayer(), String.join(", ", NMS.getNMS().getAvailableBlockTags())); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { NamespacedKey key = NamespacedKey.fromString((String) obj); @@ -154,7 +154,7 @@ private void tagClick(ClickEvent event) { }).useStrippedMessage().start(); } - private void doneClick(ClickEvent event) { + private void doneClick(LayoutedClickEvent event) { event.close(); BQBlock block; if (blockData != null) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java index 3f4592ce..a586c7f0 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java @@ -10,8 +10,8 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.CustomInventory; -import fr.skytasul.quests.api.gui.CustomInventory.CloseBehavior; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.Gui.CloseBehavior; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.Utils; @@ -19,7 +19,7 @@ import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.types.Command; -public class CommandGUI implements CustomInventory { +public class CommandGUI implements Gui { private static final int SLOT_COMMAND = 1; private static final int SLOT_CONSOLE = 3; @@ -63,8 +63,8 @@ public CommandGUI setFromExistingCommand(Command cmd) { this.console = cmd.console; this.parse = cmd.parse; this.delay = cmd.delay; - if (inv != null && console) ItemUtils.set(inv.getItem(SLOT_CONSOLE), true); - if (inv != null && parse) ItemUtils.set(inv.getItem(SLOT_PARSE), true); + if (inv != null && console) ItemUtils.setSwitch(inv.getItem(SLOT_CONSOLE), true); + if (inv != null && parse) ItemUtils.setSwitch(inv.getItem(SLOT_PARSE), true); if (inv != null) inv.getItem(SLOT_FINISH).setType(Material.DIAMOND); } return this; @@ -83,11 +83,11 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli break; case SLOT_CONSOLE: - console = ItemUtils.toggle(current); + console = ItemUtils.toggleSwitch(current); break; case SLOT_PARSE: - parse = ItemUtils.toggle(current); + parse = ItemUtils.toggleSwitch(current); break; case SLOT_DELAY: diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java index 98f78a51..d89edaa8 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java @@ -13,7 +13,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.QuestCreateEvent; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; @@ -32,7 +32,7 @@ import fr.skytasul.quests.structure.QuestBranchImplementation; import fr.skytasul.quests.structure.StageControllerImplementation; -public class FinishGUI extends UpdatableOptionSet<Updatable> implements CustomInventory { +public class FinishGUI extends UpdatableOptionSet<Updatable> implements Gui { private final QuestCreationSession session; @@ -145,7 +145,7 @@ public void click(Player p, ItemStack item, ClickType click) { return inv; } - public CustomInventory reopen(Player p){ + public Gui reopen(Player p){ Inventories.put(p, this, inv); p.openInventory(inv); return this; @@ -290,7 +290,7 @@ private void setStagesEdited() { @Override public void click(Player p, ItemStack item, ClickType click) { - keepPlayerDatas = ItemUtils.toggle(item); + keepPlayerDatas = ItemUtils.toggleSwitch(item); done.update(); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java index 980d8ffa..afd83d9e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java @@ -11,15 +11,15 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.CustomInventory; -import fr.skytasul.quests.api.gui.CustomInventory.CloseBehavior; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.Gui.CloseBehavior; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.misc.ItemCreatorGUI; -public class ItemsGUI implements CustomInventory { +public class ItemsGUI implements Gui { public static ItemStack none = ItemUtils.item(XMaterial.RED_STAINED_GLASS_PANE, "§c", Lang.itemsNone.toString()); diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java index 157e31dc..7d5eacbe 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java @@ -50,11 +50,11 @@ public int setItem(int slot, ItemStack is, StageRunnable click) { public int setItem(int slot, ItemStack is, StageRunnable click, boolean override, boolean refresh) { Pair<ItemStack, StageRunnable> en = new Pair<>(is, click); if (override){ - items.set(slot, en); + items.setSwitch(slot, en); }else { if (items.get(slot) != null){ slot = items.add(en); - }else items.set(slot, en); + }else items.setSwitch(slot, en); } if (items.getLast() <= 8) { maxPage = 1; @@ -78,7 +78,7 @@ public void editItem(int slot, ItemStack newItem){ public void editItem(int slot, ItemStack newItem, boolean refresh) { Pair<ItemStack, StageRunnable> last = items.get(slot); if (last == null) return; - items.set(slot, new Pair<>(newItem, last.getValue())); + items.setSwitch(slot, new Pair<>(newItem, last.getValue())); if (refresh) { setItems(activePage); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 726c1847..6f2edffc 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -11,7 +11,7 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; @@ -26,7 +26,7 @@ import fr.skytasul.quests.gui.creation.stages.StageRunnable.StageRunnableClick; import fr.skytasul.quests.structure.QuestBranchImplementation; -public class StagesGUI implements CustomInventory { +public class StagesGUI implements Gui { private static final int SLOT_FINISH = 52; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java index d2f28d30..d5eadb0c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java @@ -4,18 +4,18 @@ import java.util.function.Consumer; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; -public class BranchesGUI extends CustomInventory { // WIP +public class BranchesGUI extends Gui { // WIP private Branch main = new Branch(null); @@ -99,7 +99,7 @@ public void create(Consumer<IThing> thing) { } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { if (slot == 52) { if (xOffset > 0) { xOffset--; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java index 5ebe2a05..14f2d836 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java @@ -29,7 +29,7 @@ public ItemStack getItemStack(ItemComparison object) { @Override public void click(ItemComparison existing, ItemStack item, ClickType clickType) { - ItemUtils.set(item, comparisons.toggle(existing)); + ItemUtils.setSwitch(item, comparisons.toggle(existing)); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java index b2d4953e..da290935 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java @@ -6,7 +6,6 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -17,11 +16,12 @@ import fr.skytasul.quests.api.editors.TextListEditor; import fr.skytasul.quests.api.editors.checkers.MaterialParser; import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -public class ItemCreatorGUI extends CustomInventory { +public class ItemCreatorGUI extends Gui { private Player p; private Consumer<ItemStack> run; @@ -72,7 +72,7 @@ private void refresh(){ } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { switch (slot){ case 0: Lang.CHOOSE_ITEM_TYPE.send(p); @@ -92,7 +92,7 @@ public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { break; case 2: - flags = ItemUtils.toggle(current); + flags = ItemUtils.toggleSwitch(current); refresh(); break; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java index 2eb5137e..ffc98d66 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java @@ -4,19 +4,19 @@ import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.gui.creation.ItemsGUI; -public class ItemGUI extends CustomInventory { +public class ItemGUI extends Gui { private Consumer<ItemStack> end; private Runnable cancel; @@ -43,7 +43,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { if (slot != 4) return true; new ItemCreatorGUI((obj) -> { end.accept(obj); diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index e1fc3f87..fe2deb0e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -4,14 +4,14 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -20,7 +20,7 @@ import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.utils.types.Title; -public class TitleGUI extends CustomInventory { +public class TitleGUI extends Gui { private static final int SLOT_TITLE = 0; private static final int SLOT_SUBTITLE = 1; @@ -114,7 +114,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { } @Override - public boolean onClick(Player player, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { switch (slot) { case SLOT_TITLE: startStringEditor(player, Lang.TITLE_TITLE.toString(), this::setTitle); diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java index 8b38cce9..06eec832 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java @@ -15,10 +15,10 @@ import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.LeveledMobFactory; +import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.mobs.Mob; import fr.skytasul.quests.utils.QuestUtils; -import fr.skytasul.quests.utils.types.CountableObject; -import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; public class MobsListGUI extends ListGUI<MutableCountableObject<Mob<?>>> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index a5b23c64..8dc86309 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -4,7 +4,6 @@ import org.bukkit.Bukkit; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -12,7 +11,8 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -21,7 +21,7 @@ import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -public class NpcCreateGUI extends CustomInventory { +public class NpcCreateGUI extends Gui { private static final ItemStack nameItem = ItemUtils.item(XMaterial.NAME_TAG, Lang.name.toString()); private static final ItemStack move = ItemUtils.item(XMaterial.MINECART, Lang.move.toString(), Lang.moveLore.toString()); @@ -75,7 +75,7 @@ private void setSkin(String skin) { } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { switch (slot){ case 0: diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index bab96abf..382078d2 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -7,10 +7,10 @@ import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.SelectNPC; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; -import fr.skytasul.quests.api.gui.layout.Button; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.gui.layout.LayoutedGUI.Builder; import fr.skytasul.quests.api.localization.Lang; @@ -23,24 +23,24 @@ private NpcSelectGUI() {} public static ItemStack createNPC = ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.createNPC.toString()); public static ItemStack selectNPC = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); - public static @NotNull CustomInventory select(@NotNull Runnable cancel, @NotNull Consumer<@NotNull BQNPC> end) { + public static @NotNull Gui select(@NotNull Runnable cancel, @NotNull Consumer<@NotNull BQNPC> end) { return select(cancel, end, false); } - public static @NotNull CustomInventory selectNullable(@NotNull Runnable cancel, + public static @NotNull Gui selectNullable(@NotNull Runnable cancel, @NotNull Consumer<@Nullable BQNPC> end) { return select(cancel, end, true); } - private static CustomInventory select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, + private static Gui select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, boolean nullable) { - Builder builder = LayoutedGUI.newBuilder().addButton(1, Button.create(createNPC, event -> { + Builder builder = LayoutedGUI.newBuilder().addButton(1, LayoutedButton.create(createNPC, event -> { new NpcCreateGUI(end, event::reopen).open(event.getPlayer()); - })).addButton(3, Button.create(selectNPC, event -> { + })).addButton(3, LayoutedButton.create(selectNPC, event -> { new SelectNPC(event.getPlayer(), event::reopen, end).start(); })); if (nullable) - builder.addButton(2, Button.create(ItemUtils.itemNone, event -> { + builder.addButton(2, LayoutedButton.create(ItemUtils.itemNone, event -> { event.close(); end.accept(null); })); diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index a45af9d6..7c973891 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -8,14 +8,13 @@ import org.bukkit.Color; import org.bukkit.Particle; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.ColorParser; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -25,7 +24,7 @@ import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; import fr.skytasul.quests.utils.compatibility.Post1_13; -public class ParticleEffectGUI extends CustomInventory { +public class ParticleEffectGUI extends Gui { private static final int SLOT_SHAPE = 1; private static final int SLOT_PARTICLE = 3; @@ -86,7 +85,7 @@ public CloseBehavior onClose(Player p) { } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { switch (slot) { case SLOT_SHAPE: diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java index 603c74e9..68dd338b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java @@ -4,7 +4,6 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -12,14 +11,15 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.WorldParser; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.utils.types.Permission; -public class PermissionGUI extends CustomInventory { +public class PermissionGUI extends Gui { private String perm, world = null; private boolean take = false; @@ -52,7 +52,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { switch (slot) { case 0: Lang.CHOOSE_PERM_REWARD.send(p); @@ -73,7 +73,7 @@ public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { }, new WorldParser()).start(); break; case 2: - take = ItemUtils.toggle(current); + take = ItemUtils.toggleSwitch(current); break; case 4: if (current.getType() == Material.COAL) break; diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index f155e073..6a00a2d8 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -6,9 +6,7 @@ import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; @@ -17,7 +15,8 @@ import fr.skytasul.quests.api.editors.checkers.DurationParser; import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectLocation; @@ -27,7 +26,7 @@ import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.npc.NpcSelectGUI; -public class PoolEditGUI extends CustomInventory { +public class PoolEditGUI extends Gui { private static final int SLOT_NPC = 1; private static final int SLOT_HOLOGRAM = 2; @@ -122,7 +121,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inv) { } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { switch (slot) { case SLOT_NPC: NpcSelectGUI.select(() -> reopen(p), npc -> { @@ -165,10 +164,10 @@ public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { }, new DurationParser(MinecraftTimeUnit.SECOND, MinecraftTimeUnit.DAY)).start(); break; case SLOT_REDO: - redoAllowed = ItemUtils.toggle(current); + redoAllowed = ItemUtils.toggleSwitch(current); break; case SLOT_DUPLICATE: - avoidDuplicates = ItemUtils.toggle(current); + avoidDuplicates = ItemUtils.toggleSwitch(current); break; case SLOT_REQUIREMENTS: QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.POOL, requirements -> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java index 810d0668..4a8c6e9b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java @@ -11,7 +11,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -63,7 +63,7 @@ public static void choose(@NotNull Player player, @NotNull Collection<@NotNull Q if (quests.isEmpty()) { if (cancel != null) cancel.run(); - } else if (quests.size() == 1 && canSkip && QuestsConfiguration.skipNpcGuiIfOnlyOneQuest()) { + } else if (quests.size() == 1 && canSkip && QuestsConfigurationImplementation.skipNpcGuiIfOnlyOneQuest()) { run.accept(quests.iterator().next()); } else { ChooseQuestGUI gui = new ChooseQuestGUI(quests, run, cancel); 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 23bd2383..9fdb57aa 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 @@ -14,7 +14,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.gui.templates.PagedGUI; @@ -134,8 +134,8 @@ class WrappedDialogable { List<String> msg = lines.get(i); boolean last = i + 1 == lines.size(); boolean pageFull = !page.lines.isEmpty() && page.lines.size() + msg.size() > MAX_LINES; - if (QuestsConfiguration.getDialogsConfig().getMaxMessagesPerHistoryPage() > 0) - pageFull |= messagesInPage >= QuestsConfiguration.getDialogsConfig().getMaxMessagesPerHistoryPage(); + if (QuestsConfigurationImplementation.getDialogsConfig().getMaxMessagesPerHistoryPage() > 0) + pageFull |= messagesInPage >= QuestsConfigurationImplementation.getDialogsConfig().getMaxMessagesPerHistoryPage(); if (last || pageFull) { // means the page currently in writing must be flushed 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 23454786..123387e3 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 @@ -7,17 +7,17 @@ import org.bukkit.DyeColor; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; @@ -31,7 +31,7 @@ import fr.skytasul.quests.players.PlayerAccountImplementation; import fr.skytasul.quests.utils.QuestUtils; -public class PlayerListGUI extends CustomInventory { +public class PlayerListGUI extends Gui { static final String UNSELECTED_PREFIX = "§7○ "; private static final String SELECTED_PREFIX = "§b§l● "; @@ -64,14 +64,14 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { setBarItem(0, ItemUtils.itemLaterPage); setBarItem(4, ItemUtils.itemNextPage); - for (PlayerListCategory enabledCat : QuestsConfiguration.getMenuConfig().getEnabledTabs()) { + for (PlayerListCategory enabledCat : QuestsConfigurationImplementation.getMenuConfig().getEnabledTabs()) { setBarItem(enabledCat.getSlot(), ItemUtils.item(enabledCat.getMaterial(), UNSELECTED_PREFIX + enabledCat.getName())); } if (PlayerListCategory.IN_PROGRESS.isEnabled()) { setCategory(PlayerListCategory.IN_PROGRESS); - if (quests.isEmpty() && QuestsConfiguration.getMenuConfig().isNotStartedTabOpenedWhenEmpty() && PlayerListCategory.NOT_STARTED.isEnabled()) setCategory(PlayerListCategory.NOT_STARTED); + if (quests.isEmpty() && QuestsConfigurationImplementation.getMenuConfig().isNotStartedTabOpenedWhenEmpty() && PlayerListCategory.NOT_STARTED.isEnabled()) setCategory(PlayerListCategory.NOT_STARTED); }else if (PlayerListCategory.NOT_STARTED.isEnabled()) { setCategory(PlayerListCategory.NOT_STARTED); }else setCategory(PlayerListCategory.FINISHED); @@ -101,8 +101,8 @@ private void setItems(){ case FINISHED: displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); - if (QuestsConfiguration.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { + List<String> lore = new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); + if (QuestsConfigurationImplementation.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { if (!lore.isEmpty()) lore.add(null); lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); } @@ -112,10 +112,10 @@ private void setItems(){ case IN_PROGRESS: displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); + List<String> lore = new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); - boolean hasDialogs = QuestsConfiguration.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs(); - boolean cancellable = QuestsConfiguration.getMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); + boolean hasDialogs = QuestsConfigurationImplementation.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs(); + boolean cancellable = QuestsConfigurationImplementation.getMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); if (cancellable || hasDialogs) { if (!lore.isEmpty()) lore.add(null); if (cancellable) lore.add("§8" + Lang.ClickLeft + " §8> " + Lang.cancelLore); @@ -129,7 +129,7 @@ private void setItems(){ displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) .collect(Collectors.toList()), qu -> { - return createQuestItem(qu, new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription()); + return createQuestItem(qu, new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription()); }); break; @@ -188,7 +188,7 @@ private void toggleCategorySelected() { @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { switch (slot % 9){ case 8: int barSlot = (slot - 8) / 9; @@ -229,12 +229,12 @@ public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { } }else { if (click.isRightClick()) { - if (QuestsConfiguration.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { + if (QuestsConfigurationImplementation.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { QuestUtils.playPluginSound(p, "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); new DialogHistoryGUI(acc, qu, () -> reopen(p)).open(p); } }else if (click.isLeftClick()) { - if (QuestsConfiguration.getMenuConfig().allowPlayerCancelQuest() && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { + if (QuestsConfigurationImplementation.getMenuConfig().allowPlayerCancelQuest() && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { ConfirmGUI.confirm(() -> qu.cancelPlayer(acc), () -> reopen(p), Lang.INDICATION_CANCEL.format(qu.getName())).open(p); } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java b/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java index 05d690f0..3da05556 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java @@ -1,6 +1,6 @@ package fr.skytasul.quests.options; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionBoolean; @@ -9,7 +9,7 @@ public class OptionCancellable extends QuestOptionBoolean { @Override public boolean shouldDisplay(OptionSet options) { - return QuestsConfiguration.getMenuConfig().allowPlayerCancelQuest(); + return QuestsConfigurationImplementation.getMenuConfig().allowPlayerCancelQuest(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java index 4341fdcb..37420d93 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java @@ -2,7 +2,7 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; @@ -31,7 +31,7 @@ public String getItemDescription() { @Override public boolean shouldDisplay(OptionSet options) { - return QuestsConfiguration.questConfirmGUI(); + return QuestsConfigurationImplementation.questConfirmGUI(); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java index ce82a043..b784bbc3 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java @@ -9,7 +9,7 @@ import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; @@ -91,7 +91,7 @@ public boolean clickCursor(FinishGUI gui, Player p, ItemStack item, ItemStack cu @Override public boolean shouldDisplay(OptionSet options) { - return QuestsConfiguration.doFireworks(); + return QuestsConfigurationImplementation.doFireworks(); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java index ae031c85..acfe7aee 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java @@ -2,7 +2,7 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; @@ -36,7 +36,7 @@ public String getItemDescription() { @Override public boolean shouldDisplay(OptionSet options) { - return !QuestsConfiguration.isTextHologramDisabled() && QuestsAPI.getAPI().hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; + return !QuestsConfigurationImplementation.isTextHologramDisabled() && QuestsAPI.getAPI().hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java index 3247dccf..f4738c9b 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java @@ -14,7 +14,8 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -62,7 +63,7 @@ public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType c }).open(p); } - class VisibilityGUI extends CustomInventory { + class VisibilityGUI extends Gui { private EnumMap<QuestVisibilityLocation, Boolean> locations = new EnumMap<>(QuestVisibilityLocation.class); private Runnable reopen; @@ -87,9 +88,9 @@ public Inventory open(Player p) { } @Override - public boolean onClick(Player p, ItemStack current, int slot, ClickType click) { + public void onClick(GuiClickEvent event) { if (slot >= 0 && slot < 4) { - locations.put(QuestVisibilityLocation.values()[slot], ItemUtils.toggle(current)); + locations.put(QuestVisibilityLocation.values()[slot], ItemUtils.toggleSwitch(current)); }else if (slot == 4) { setValue(locations.entrySet().stream().filter(Entry::getValue).map(Entry::getKey).collect(Collectors.toList())); reopen.run(); 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 7e3c56d3..0a3ef1e8 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -21,7 +21,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.data.SavableData; @@ -96,11 +96,11 @@ public void addAccountData(@NotNull SavableData<?> data) { } protected @NotNull AbstractAccount createAbstractAccount(@NotNull Player p) { - return QuestsConfiguration.hookAccounts() ? Accounts.getPlayerAccount(p) : new UUIDAccount(p.getUniqueId()); + return QuestsConfigurationImplementation.hookAccounts() ? Accounts.getPlayerAccount(p) : new UUIDAccount(p.getUniqueId()); } protected @NotNull String getIdentifier(@NotNull OfflinePlayer p) { - if (QuestsConfiguration.hookAccounts()) { + if (QuestsConfigurationImplementation.hookAccounts()) { if (!p.isOnline()) throw new IllegalArgumentException("Cannot fetch player identifier of an offline player with AccountsHook"); return "Hooked|" + Accounts.getPlayerCurrentIdentifier(p.getPlayer()); @@ -110,7 +110,7 @@ public void addAccountData(@NotNull SavableData<?> data) { protected @Nullable AbstractAccount createAccountFromIdentifier(@NotNull String identifier) { if (identifier.startsWith("Hooked|")){ - if (!QuestsConfiguration.hookAccounts()) throw new MissingDependencyException("AccountsHook is not enabled or config parameter is disabled, but saved datas need it."); + if (!QuestsConfigurationImplementation.hookAccounts()) throw new MissingDependencyException("AccountsHook is not enabled or config parameter is disabled, but saved datas need it."); String nidentifier = identifier.substring(7); try{ return Accounts.getAccountFromIdentifier(nidentifier); @@ -120,7 +120,7 @@ public void addAccountData(@NotNull SavableData<?> data) { }else { try{ UUID uuid = UUID.fromString(identifier); - if (QuestsConfiguration.hookAccounts()){ + if (QuestsConfigurationImplementation.hookAccounts()){ try{ return Accounts.createAccountFromUUID(uuid); }catch (UnsupportedOperationException ex){ diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 037431f2..2ddc7644 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -11,8 +11,8 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.gui.layout.Button; -import fr.skytasul.quests.api.gui.layout.ClickEvent; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; +import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -95,26 +95,26 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { public void itemClick(QuestObjectClickEvent event) { LayoutedGUI.newBuilder() .addButton(0, - Button.create(XMaterial.NETHER_STAR, () -> "§b" + Lang.requirements.format(requirements.size()), + LayoutedButton.create(XMaterial.NETHER_STAR, () -> "§b" + Lang.requirements.format(requirements.size()), Collections.emptyList(), this::editRequirements)) .addButton(1, - Button.create(XMaterial.CHEST, () -> "§a" + Lang.rewards.format(rewards.size()), + LayoutedButton.create(XMaterial.CHEST, () -> "§a" + Lang.rewards.format(rewards.size()), Collections.emptyList(), this::editRewards)) - .addButton(4, Button.create(ItemUtils.itemDone, __ -> event.reopenGUI())) + .addButton(4, LayoutedButton.create(ItemUtils.itemDone, __ -> event.reopenGUI())) .setName(Lang.INVENTORY_REWARDS_WITH_REQUIREMENTS.toString()) .setCloseBehavior(StandardCloseBehavior.REOPEN) .build() .open(event.getPlayer()); } - private void editRequirements(ClickEvent event) { + private void editRequirements(LayoutedClickEvent event) { QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.OTHER, newRequirements -> { RequirementDependentReward.this.requirements = newRequirements; event.refreshItemReopen(); }, requirements).open(event.getPlayer()); } - private void editRewards(ClickEvent event) { + private void editRewards(LayoutedClickEvent event) { QuestsAPI.getAPI().getRewards().createGUI(QuestObjectLocation.OTHER, newRewards -> { RequirementDependentReward.this.rewards = newRewards; event.refreshItemReopen(); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index 6ecad0f0..db18218f 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -4,7 +4,7 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; import fr.skytasul.quests.api.localization.Lang; @@ -28,7 +28,7 @@ public XPReward(String customDescription, int exp) { @Override public List<String> give(Player p) { - if (DependenciesManager.skapi.isEnabled() && QuestsConfiguration.xpOverridedSkillAPI()) { + if (DependenciesManager.skapi.isEnabled() && QuestsConfigurationImplementation.xpOverridedSkillAPI()) { SkillAPI.giveExp(p, exp); }else p.giveExp(exp); return Arrays.asList(exp + " " + Lang.Exp.toString()); diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java index 68097bdf..1238952a 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java @@ -15,7 +15,7 @@ import org.bukkit.scheduler.BukkitRunnable; import fr.mrmicky.fastboard.FastBoard; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; @@ -360,7 +360,7 @@ private String formatQuestPlaceholders(String text) { .findFirst(); if (optionalDescription.isPresent()) { if (lazyContext == null) - lazyContext = new QuestDescriptionContext(QuestsConfiguration.getQuestDescription(), + lazyContext = new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), shown, acc, PlayerListCategory.IN_PROGRESS, DescriptionSource.SCOREBOARD); replacement = String.join("\n", optionalDescription.get().provideDescription(lazyContext)); } else { diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java index df594da3..77b56466 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java @@ -18,7 +18,7 @@ import org.bukkit.event.player.PlayerChangedWorldEvent; import fr.mrmicky.fastboard.FastBoard; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsHandler; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; @@ -92,7 +92,7 @@ public void removePlayerScoreboard(Player p){ } public void create(Player p){ - if (!QuestsConfiguration.showScoreboards()) return; + if (!QuestsConfigurationImplementation.showScoreboards()) return; removePlayerScoreboard(p); Scoreboard scoreboard = new Scoreboard(p, this); @@ -104,7 +104,7 @@ public void create(Player p){ @Override public void load() { - if (!QuestsConfiguration.showScoreboards()) return; + if (!QuestsConfigurationImplementation.showScoreboards()) return; try { new FastBoard(null); // trigger class initialization diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java index c902614c..1adf22dd 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java @@ -151,7 +151,7 @@ public static class Creator extends StageCreation<StageArea> { public Creator(Line line, boolean ending) { super(line, ending); line.setItem(7, ItemUtils.item(XMaterial.PAPER, Lang.stageRegion.toString()), (p, item) -> launchRegionEditor(p, false), true, true); - line.setItem(6, ItemUtils.itemSwitch(Lang.stageRegionExit.toString(), exit), (p, item) -> setExit(ItemUtils.toggle(item))); + line.setItem(6, ItemUtils.itemSwitch(Lang.stageRegionExit.toString(), exit), (p, item) -> setExit(ItemUtils.toggleSwitch(item))); } public void setRegion(String regionName, String worldName) { @@ -163,7 +163,7 @@ public void setRegion(String regionName, String worldName) { public void setExit(boolean exit) { if (this.exit != exit) { this.exit = exit; - line.editItem(6, ItemUtils.set(line.getItem(6), exit)); + line.editItem(6, ItemUtils.setSwitch(line.getItem(6), exit)); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 8fc00d14..2a315592 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -10,7 +10,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; @@ -46,12 +46,12 @@ public StageBringBack(StageController controller, ItemStack[] items, String cust String[] array = new String[items.length]; // create messages on beginning for (int i = 0; i < array.length; i++){ - array[i] = QuestsConfiguration.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfiguration.getItemAmountColor(), QuestsConfiguration.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)); + array[i] = QuestsConfigurationImplementation.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfigurationImplementation.getItemAmountColor(), QuestsConfigurationImplementation.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)); } splitted = Utils.descriptionLines(DescriptionSource.FORCESPLIT, array); - if (QuestsConfiguration.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)){ + if (QuestsConfigurationImplementation.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)){ for (int i = 0; i < array.length; i++){ - array[i] = QuestsConfiguration.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfiguration.getItemAmountColor(), false); + array[i] = QuestsConfigurationImplementation.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfigurationImplementation.getItemAmountColor(), false); } } line = Utils.descriptionLines(DescriptionSource.FORCELINE, array); @@ -93,12 +93,12 @@ protected String getMessage() { @Override public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Utils.format(Lang.SCOREBOARD_ITEMS.toString() + " " + (QuestsConfiguration.splitDescription(source) ? splitted : line), npcName()); + return Utils.format(Lang.SCOREBOARD_ITEMS.toString() + " " + (QuestsConfigurationImplementation.splitDescription(source) ? splitted : line), npcName()); } @Override protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source){ - return new String[]{QuestsConfiguration.splitDescription(source) ? splitted : line, npcName()}; + return new String[]{QuestsConfigurationImplementation.splitDescription(source) ? splitted : line, npcName()}; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 75434f21..056e1458 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -9,7 +9,7 @@ import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; @@ -70,12 +70,12 @@ protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { @Override protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_BUCKET.format(Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), amount, false)); + return Lang.SCOREBOARD_BUCKET.format(Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), amount, false)); } @Override protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Supplier[] { () -> Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), amount, false) }; + return new Supplier[] { () -> Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), amount, false) }; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index c713604c..bba69dee 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -110,9 +110,9 @@ public static class Creator extends StageCreation<StageChat> { public Creator(Line line, boolean ending) { super(line, ending); - line.setItem(PLACEHOLDERS_SLOT, ItemUtils.itemSwitch(Lang.placeholders.toString(), placeholders), (p, item) -> setPlaceholders(ItemUtils.toggle(item))); - line.setItem(IGNORE_CASE_SLOT, ItemUtils.itemSwitch(Lang.ignoreCase.toString(), ignoreCase), (p, item) -> setIgnoreCase(ItemUtils.toggle(item))); - line.setItem(CANCEL_EVENT_SLOT, ItemUtils.itemSwitch(Lang.cancelEvent.toString(), cancel), (p, item) -> setCancel(ItemUtils.toggle(item))); + line.setItem(PLACEHOLDERS_SLOT, ItemUtils.itemSwitch(Lang.placeholders.toString(), placeholders), (p, item) -> setPlaceholders(ItemUtils.toggleSwitch(item))); + line.setItem(IGNORE_CASE_SLOT, ItemUtils.itemSwitch(Lang.ignoreCase.toString(), ignoreCase), (p, item) -> setIgnoreCase(ItemUtils.toggleSwitch(item))); + line.setItem(CANCEL_EVENT_SLOT, ItemUtils.itemSwitch(Lang.cancelEvent.toString(), cancel), (p, item) -> setCancel(ItemUtils.toggleSwitch(item))); line.setItem(MESSAGE_SLOT, ItemUtils.item(XMaterial.PLAYER_HEAD, Lang.editMessage.toString()), (p, item) -> launchEditor(p)); } @@ -124,21 +124,21 @@ public void setText(String text) { public void setPlaceholders(boolean placeholders) { if (this.placeholders != placeholders) { this.placeholders = placeholders; - line.editItem(PLACEHOLDERS_SLOT, ItemUtils.set(line.getItem(PLACEHOLDERS_SLOT), placeholders)); + line.editItem(PLACEHOLDERS_SLOT, ItemUtils.setSwitch(line.getItem(PLACEHOLDERS_SLOT), placeholders)); } } public void setIgnoreCase(boolean ignoreCase) { if (this.ignoreCase != ignoreCase) { this.ignoreCase = ignoreCase; - line.editItem(IGNORE_CASE_SLOT, ItemUtils.set(line.getItem(IGNORE_CASE_SLOT), ignoreCase)); + line.editItem(IGNORE_CASE_SLOT, ItemUtils.setSwitch(line.getItem(IGNORE_CASE_SLOT), ignoreCase)); } } public void setCancel(boolean cancel) { if (this.cancel != cancel) { this.cancel = cancel; - line.editItem(CANCEL_EVENT_SLOT, ItemUtils.set(line.getItem(CANCEL_EVENT_SLOT), cancel)); + line.editItem(CANCEL_EVENT_SLOT, ItemUtils.setSwitch(line.getItem(CANCEL_EVENT_SLOT), cancel)); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index 0ccba14e..ccffb74c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -11,7 +11,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.events.internal.BQCraftEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -135,12 +135,12 @@ private int getPlayerAmount(PlayerAccount acc) { @Override protected String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Lang.SCOREBOARD_CRAFT.format(Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false)); + return Lang.SCOREBOARD_CRAFT.format(Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false)); } @Override protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Supplier[] { () -> Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfiguration.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false) }; + return new Supplier[] { () -> Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false) }; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java index d68d2571..667e816d 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java @@ -14,8 +14,8 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; +import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.utils.types.CountableObject; public class StageEatDrink extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java index 48059868..7132d436 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java @@ -16,8 +16,8 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; +import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.utils.types.CountableObject; public class StageEnchant extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java index 6bce7349..5dcbf653 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java @@ -18,8 +18,8 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; +import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.utils.types.CountableObject; public class StageFish extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java index 8a4ad23a..eff58d69 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java @@ -18,7 +18,7 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.WaitBlockClick; -import fr.skytasul.quests.api.gui.CustomInventory; +import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; @@ -30,10 +30,10 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.blocks.SelectBlockGUI; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.utils.types.BQBlock; import fr.skytasul.quests.utils.types.BQLocation; @LocatableType (types = { LocatedType.BLOCK, LocatedType.OTHER }) @@ -153,13 +153,13 @@ public static class Creator extends StageCreation<StageInteract> { public Creator(Line line, boolean ending) { super(line, ending); - line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), (p, item) -> setLeftClick(ItemUtils.toggle(item))); + line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), (p, item) -> setLeftClick(ItemUtils.toggleSwitch(item))); } public void setLeftClick(boolean leftClick) { if (this.leftClick != leftClick) { this.leftClick = leftClick; - line.editItem(6, ItemUtils.set(line.getItem(6), leftClick)); + line.editItem(6, ItemUtils.setSwitch(line.getItem(6), leftClick)); } } @@ -224,7 +224,7 @@ public StageInteract finishStage(StageController controller) { }else return new StageInteract(branch, leftClick, block); } - private class ChooseActionGUI implements CustomInventory { + private class ChooseActionGUI implements Gui { private Runnable cancel, location, type; 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 e7f2c5ae..1aead3c0 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -7,7 +7,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; import fr.skytasul.quests.api.editors.checkers.NumberParser; @@ -87,13 +87,13 @@ public void onPlayerMove(PlayerMoveEvent e){ @Override public void joins(PlayerAccount acc, Player p) { super.joins(acc, p); - if (QuestsConfiguration.handleGPS() && gps) GPS.launchCompass(p, lc); + if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.launchCompass(p, lc); } @Override public void leaves(PlayerAccount acc, Player p) { super.leaves(acc, p); - if (QuestsConfiguration.handleGPS() && gps) GPS.stopCompass(p); + if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.stopCompass(p); } @Override @@ -101,7 +101,7 @@ public void start(PlayerAccount acc) { super.start(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); - if (QuestsConfiguration.handleGPS() && gps) GPS.launchCompass(p, lc); + if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.launchCompass(p, lc); } } @@ -110,7 +110,7 @@ public void ended(PlayerAccount acc) { super.ended(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); - if (QuestsConfiguration.handleGPS() && gps) GPS.stopCompass(p); + if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.stopCompass(p); } } @@ -172,7 +172,7 @@ public Creator(Line line, boolean ending) { }, PatternParser.PARSER).passNullIntoEndConsumer().start(); }); - if (QuestsConfiguration.handleGPS()) line.setItem(SLOT_GPS, ItemUtils.itemSwitch(Lang.stageGPS.toString(), gps), (p, item) -> setGPS(ItemUtils.toggle(item)), true, true); + if (QuestsConfigurationImplementation.handleGPS()) line.setItem(SLOT_GPS, ItemUtils.itemSwitch(Lang.stageGPS.toString(), gps), (p, item) -> setGPS(ItemUtils.toggleSwitch(item)), true, true); } public void setLocation(Location location) { @@ -193,7 +193,7 @@ public void setPattern(Pattern pattern) { public void setGPS(boolean gps) { if (this.gps != gps) { this.gps = gps; - if (QuestsConfiguration.handleGPS()) line.editItem(SLOT_GPS, ItemUtils.set(line.getItem(SLOT_GPS), gps)); + if (QuestsConfigurationImplementation.handleGPS()) line.editItem(SLOT_GPS, ItemUtils.setSwitch(line.getItem(SLOT_GPS), gps)); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java index 208648c0..ff69c337 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java @@ -15,8 +15,8 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractItemStage; +import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.utils.types.CountableObject; public class StageMelt extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index e3b6d08c..9925cd62 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -18,7 +18,7 @@ import com.cryptomorin.xseries.XMaterial; import com.gestankbratwurst.playerblocktracker.PlayerBlockTracker; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -30,9 +30,9 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.BQBlock; +import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.utils.types.BQBlock; -import fr.skytasul.quests.utils.types.CountableObject; @LocatableType (types = LocatedType.BLOCK) public class StageMine extends AbstractCountableBlockStage implements Locatable.MultipleLocatable { @@ -63,7 +63,7 @@ public void onMine(BQBlockBreakEvent e) { if (branch.hasStageLaunched(acc, this)){ for (Block block : e.getBlocks()) { if (placeCancelled) { - if (QuestsConfiguration.usePlayerBlockTracker()) { + if (QuestsConfigurationImplementation.usePlayerBlockTracker()) { if (PlayerBlockTracker.isTracked(block)) return; } else { if (block.hasMetadata("playerInStage")) { @@ -79,7 +79,7 @@ public void onMine(BQBlockBreakEvent e) { @EventHandler (priority = EventPriority.MONITOR) public void onPlace(BlockPlaceEvent e){ - if (QuestsConfiguration.usePlayerBlockTracker()) + if (QuestsConfigurationImplementation.usePlayerBlockTracker()) return; if (e.isCancelled() || !placeCancelled) return; @@ -126,7 +126,7 @@ public static class Creator extends AbstractCountableBlockStage.AbstractCreator< public Creator(Line line, boolean ending) { super(line, ending); - line.setItem(6, ItemUtils.itemSwitch(Lang.preventBlockPlace.toString(), prevent), (p, item) -> setPrevent(ItemUtils.toggle(item))); + line.setItem(6, ItemUtils.itemSwitch(Lang.preventBlockPlace.toString(), prevent), (p, item) -> setPrevent(ItemUtils.toggleSwitch(item))); } @Override @@ -137,7 +137,7 @@ protected ItemStack getBlocksItem() { public void setPrevent(boolean prevent) { if (this.prevent != prevent) { this.prevent = prevent; - line.editItem(6, ItemUtils.set(line.getItem(6), prevent)); + line.editItem(6, ItemUtils.setSwitch(line.getItem(6), prevent)); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index 7b388fc0..b0720217 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -29,11 +29,11 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.mobs.MobsListGUI; import fr.skytasul.quests.mobs.Mob; -import fr.skytasul.quests.utils.types.CountableObject; -import fr.skytasul.quests.utils.types.CountableObject.MutableCountableObject; @LocatableType (types = LocatedType.ENTITY) public class StageMobs extends AbstractCountableStage<Mob<?>> implements Locatable.MultipleLocatable { @@ -165,7 +165,7 @@ public Creator(Line line, boolean ending) { reopenGUI(p, true); }).open(p); }); - line.setItem(6, ItemUtils.itemSwitch(Lang.mobsKillType.toString(), shoot), (p, item) -> setShoot(ItemUtils.toggle(item))); + line.setItem(6, ItemUtils.itemSwitch(Lang.mobsKillType.toString(), shoot), (p, item) -> setShoot(ItemUtils.toggleSwitch(item))); } public void setMobs(List<MutableCountableObject<Mob<?>>> mobs) { @@ -176,7 +176,7 @@ public void setMobs(List<MutableCountableObject<Mob<?>>> mobs) { public void setShoot(boolean shoot) { if (this.shoot != shoot) { this.shoot = shoot; - line.editItem(6, ItemUtils.set(line.getItem(6), shoot)); + line.editItem(6, ItemUtils.setSwitch(line.getItem(6), shoot)); } } 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 dcadf8ff..f7220616 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -14,7 +14,7 @@ import org.bukkit.scheduler.BukkitTask; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.AbstractHolograms; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; @@ -75,24 +75,24 @@ public void run() { tmp.add(p); } - if (QuestsConfiguration.getHoloTalkItem() != null && QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility()) { + if (QuestsConfigurationImplementation.getHoloTalkItem() != null && QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility()) { if (hologram == null) createHoloLaunch(); hologram.setPlayersVisible(tmp); hologram.teleport(Utils.upLocationForEntity((LivingEntity) en, 1)); } - if (QuestsConfiguration.showTalkParticles()) { + if (QuestsConfigurationImplementation.showTalkParticles()) { if (tmp.isEmpty()) return; - QuestsConfiguration.getParticleTalk().send(en, tmp); + QuestsConfigurationImplementation.getParticleTalk().send(en, tmp); } } }.runTaskTimer(BeautyQuests.getInstance(), 20L, 6L); } private void createHoloLaunch(){ - ItemStack item = QuestsConfiguration.getHoloTalkItem(); + ItemStack item = QuestsConfigurationImplementation.getHoloTalkItem(); hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(npc.getLocation(), false); - if (QuestsConfiguration.isCustomHologramNameShown() && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) + if (QuestsConfigurationImplementation.isCustomHologramNameShown() && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) hologram.appendTextLine(item.getItemMeta().getDisplayName()); hologram.appendItem(item); } @@ -178,7 +178,7 @@ protected void initDialogRunner() { public void onClick(BQNPCClickEvent e) { if (e.isCancelled()) return; if (e.getNPC() != npc) return; - if (!QuestsConfiguration.getNPCClicks().contains(e.getClick())) return; + if (!QuestsConfigurationImplementation.getNPCClicks().contains(e.getClick())) return; Player p = e.getPlayer(); e.setCancelled(dialogRunner.onClick(p).shouldCancel()); @@ -196,7 +196,7 @@ protected String npcName(){ public void joins(PlayerAccount acc, Player p) { super.joins(acc, p); cachePlayer(p); - if (QuestsConfiguration.handleGPS() && !hide) GPS.launchCompass(p, npc.getLocation()); + if (QuestsConfigurationImplementation.handleGPS() && !hide) GPS.launchCompass(p, npc.getLocation()); } private void cachePlayer(Player p) { @@ -210,7 +210,7 @@ private void uncachePlayer(Player p) { } private void uncacheAll() { - if (QuestsConfiguration.handleGPS() && !hide) cached.forEach(GPS::stopCompass); + if (QuestsConfigurationImplementation.handleGPS() && !hide) cached.forEach(GPS::stopCompass); if (npc != null) cached.forEach(p -> npc.removeHiddenForPlayer(p, this)); } @@ -218,7 +218,7 @@ private void uncacheAll() { public void leaves(PlayerAccount acc, Player p) { super.leaves(acc, p); uncachePlayer(p); - if (QuestsConfiguration.handleGPS() && !hide) GPS.stopCompass(p); + if (QuestsConfigurationImplementation.handleGPS() && !hide) GPS.stopCompass(p); if (dialogRunner != null) dialogRunner.removePlayer(p); } @@ -228,7 +228,7 @@ public void start(PlayerAccount acc) { if (acc.isCurrent()) { Player p = acc.getPlayer(); cachePlayer(p); - if (QuestsConfiguration.handleGPS() && npc != null) GPS.launchCompass(p, npc.getLocation()); + if (QuestsConfigurationImplementation.handleGPS() && npc != null) GPS.launchCompass(p, npc.getLocation()); } } @@ -239,7 +239,7 @@ public void ended(PlayerAccount acc) { Player p = acc.getPlayer(); if (dialogRunner != null) dialogRunner.removePlayer(p); uncachePlayer(p); - if (QuestsConfiguration.handleGPS() && !hide) GPS.stopCompass(p); + if (QuestsConfigurationImplementation.handleGPS() && !hide) GPS.stopCompass(p); } } @@ -255,7 +255,7 @@ public void unload() { @Override public void load(){ super.load(); - if (QuestsConfiguration.showTalkParticles() || QuestsConfiguration.getHoloTalkItem() != null){ + if (QuestsConfigurationImplementation.showTalkParticles() || QuestsConfigurationImplementation.getHoloTalkItem() != null){ if (!hide) launchRefreshTask(); } } @@ -309,7 +309,7 @@ protected AbstractCreator(Line line, boolean ending) { }, dialog == null ? dialog = new Dialog() : dialog).start(); }, true, true); - line.setItem(SLOT_HIDE, ItemUtils.itemSwitch(Lang.stageHide.toString(), hidden), (p, item) -> setHidden(ItemUtils.toggle(item)), true, true); + line.setItem(SLOT_HIDE, ItemUtils.itemSwitch(Lang.stageHide.toString(), hidden), (p, item) -> setHidden(ItemUtils.toggleSwitch(item)), true, true); } public void setNPCId(int npcID) { @@ -325,7 +325,7 @@ public void setDialog(Dialog dialog) { public void setHidden(boolean hidden) { if (this.hidden != hidden) { this.hidden = hidden; - line.editItem(SLOT_HIDE, ItemUtils.set(line.getItem(SLOT_HIDE), hidden)); + line.editItem(SLOT_HIDE, ItemUtils.setSwitch(line.getItem(SLOT_HIDE), hidden)); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index f6fdd174..98788124 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -16,9 +16,9 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; +import fr.skytasul.quests.api.utils.BQBlock; +import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.utils.types.BQBlock; -import fr.skytasul.quests.utils.types.CountableObject; public class StagePlaceBlocks extends AbstractCountableBlockStage { diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java index b04b133e..d71d17ce 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnmodifiableView; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.PlayerSetStageEvent; import fr.skytasul.quests.api.localization.Lang; @@ -138,7 +138,7 @@ public boolean isEndingStage(StageController stage) { if (datas.getStage() < 0) return "§cerror: no stage set for branch " + getId(); if (datas.getStage() >= regularStages.size()) return "§cerror: datas do not match"; - return MessageUtils.format(QuestsConfiguration.getStageDescriptionFormat(), datas.getStage() + 1, + return MessageUtils.format(QuestsConfigurationImplementation.getStageDescriptionFormat(), datas.getStage() + 1, regularStages.size(), regularStages.get(datas.getStage()).getDescriptionLine(acc, source)); } @@ -245,7 +245,7 @@ private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplem asyncReward.add(acc); try { List<String> given = QuestUtils.giveRewards(p, stage.getStage().getRewards()); - if (!given.isEmpty() && QuestsConfiguration.hasStageEndRewardsMessage()) + if (!given.isEmpty() && QuestsConfigurationImplementation.hasStageEndRewardsMessage()) Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); } catch (InterruptingBranchException ex) { QuestsPlugin.getPlugin().getLoggerExpanded().debug( @@ -264,7 +264,7 @@ private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplem }else{ try { List<String> given = QuestUtils.giveRewards(p, stage.getStage().getRewards()); - if (!given.isEmpty() && QuestsConfiguration.hasStageEndRewardsMessage()) + if (!given.isEmpty() && QuestsConfigurationImplementation.hasStageEndRewardsMessage()) Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); runAfter.run(); } catch (InterruptingBranchException ex) { @@ -287,7 +287,7 @@ public void setStage(@NotNull PlayerAccount acc, int id) { remove(acc, true); }else { PlayerQuestDatas questDatas = acc.getQuestDatas(getQuest()); - if (QuestsConfiguration.sendQuestUpdateMessage() && p != null && questDatas.getStage() != -1) + if (QuestsConfigurationImplementation.sendQuestUpdateMessage() && p != null && questDatas.getStage() != -1) Lang.QUEST_UPDATED.send(p, getQuest().getName()); questDatas.setStage(id); if (p != null) playNextStage(p); @@ -298,7 +298,7 @@ public void setStage(@NotNull PlayerAccount acc, int id) { public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { Player p = acc.getPlayer(); - if (QuestsConfiguration.sendQuestUpdateMessage() && p != null && launchStage) + if (QuestsConfigurationImplementation.sendQuestUpdateMessage() && p != null && launchStage) Lang.QUEST_UPDATED.send(p, getQuest().getName()); PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); datas.setInEndingStages(); @@ -310,8 +310,8 @@ public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { } private void playNextStage(@NotNull Player p) { - QuestUtils.playPluginSound(p.getLocation(), QuestsConfiguration.getNextStageSound(), 0.5F); - if (QuestsConfiguration.showNextParticles()) QuestsConfiguration.getParticleNext().send(p, Arrays.asList(p)); + QuestUtils.playPluginSound(p.getLocation(), QuestsConfigurationImplementation.getNextStageSound(), 0.5F); + if (QuestsConfigurationImplementation.showNextParticles()) QuestsConfigurationImplementation.getParticleNext().send(p, Arrays.asList(p)); } public void remove(){ diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index 41514534..342220cf 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.PlayerQuestResetEvent; @@ -279,7 +279,7 @@ public boolean canStart(@NotNull Player p, boolean sendMessage) { public boolean testRequirements(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { if (!p.hasPermission("beautyquests.start")) return false; if (!testQuestLimit(p, acc, sendMessage)) return false; - sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) || (QuestsConfiguration.isRequirementReasonSentOnMultipleQuests() || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); + sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) || (QuestsConfigurationImplementation.isRequirementReasonSentOnMultipleQuests() || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); return QuestUtils.testRequirements(p, getOptionValueOrDef(OptionRequirements.class), sendMessage); } @@ -296,8 +296,8 @@ public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boo if (playerMaxLaunchedQuestOpt.isPresent()) { playerMaxLaunchedQuest = playerMaxLaunchedQuestOpt.getAsInt(); }else { - if (QuestsConfiguration.getMaxLaunchedQuests() == 0) return true; - playerMaxLaunchedQuest = QuestsConfiguration.getMaxLaunchedQuests(); + if (QuestsConfigurationImplementation.getMaxLaunchedQuests() == 0) return true; + playerMaxLaunchedQuest = QuestsConfigurationImplementation.getMaxLaunchedQuests(); } if (QuestsAPI.getAPI().getQuestsManager().getStartedSize(acc) >= playerMaxLaunchedQuest) { if (sendMessage) @@ -372,7 +372,7 @@ public double getDescriptionPriority() { return CompletableFuture.completedFuture(false); String confirm; - if (QuestsConfiguration.questConfirmGUI() && !"none".equals(confirm = getOptionValueOrDef(OptionConfirmMessage.class))) { + if (QuestsConfigurationImplementation.questConfirmGUI() && !"none".equals(confirm = getOptionValueOrDef(OptionConfirmMessage.class))) { CompletableFuture<Boolean> future = new CompletableFuture<>(); ConfirmGUI.confirm(() -> { start(p); 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 d80e3e6b..0688fd7d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -12,7 +12,7 @@ import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.metadata.FixedMetadataValue; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; @@ -49,7 +49,7 @@ public static void playPluginSound(Player p, String sound, float volume) { } public static void playPluginSound(Player p, String sound, float volume, float pitch) { - if (!QuestsConfiguration.playSounds()) + if (!QuestsConfigurationImplementation.playSounds()) return; if ("none".equals(sound)) return; @@ -62,7 +62,7 @@ public static void playPluginSound(Player p, String sound, float volume, float p } public static void playPluginSound(Location lc, String sound, float volume) { - if (!QuestsConfiguration.playSounds()) + if (!QuestsConfigurationImplementation.playSounds()) return; try { lc.getWorld().playSound(lc, Sound.valueOf(sound), volume, 1); @@ -75,15 +75,15 @@ public static void playPluginSound(Location lc, String sound, float volume) { public static String descriptionLines(DescriptionSource source, String... elements) { if (elements.length == 0) return Lang.Unknown.toString(); - if (QuestsConfiguration.splitDescription(source) && (!QuestsConfiguration.inlineAlone() || elements.length > 1)) { - return QuestsConfiguration.getDescriptionItemPrefix() - + Utils.buildFromArray(elements, 0, QuestsConfiguration.getDescriptionItemPrefix()); + if (QuestsConfigurationImplementation.splitDescription(source) && (!QuestsConfigurationImplementation.inlineAlone() || elements.length > 1)) { + return QuestsConfigurationImplementation.getDescriptionItemPrefix() + + Utils.buildFromArray(elements, 0, QuestsConfigurationImplementation.getDescriptionItemPrefix()); } - return MessageUtils.itemsToFormattedString(elements, QuestsConfiguration.getItemAmountColor()); + return MessageUtils.itemsToFormattedString(elements, QuestsConfigurationImplementation.getItemAmountColor()); } public static void spawnFirework(Location lc, FireworkMeta meta) { - if (!QuestsConfiguration.doFireworks() || meta == null) + if (!QuestsConfigurationImplementation.doFireworks() || meta == null) return; runOrSync(() -> { Consumer<Firework> fwConsumer = fw -> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java index b9efaddf..ef5b0ca9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java @@ -10,7 +10,7 @@ import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.utils.types.BQBlock; +import fr.skytasul.quests.api.utils.BQBlock; public class Post1_13 { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java index c32e4597..9b335395 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java @@ -2,7 +2,7 @@ import java.util.function.Consumer; import org.bukkit.Location; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.quests.Quest; @@ -22,7 +22,7 @@ public class BQBlueMap extends AbstractMapIntegration { @Override public boolean isEnabled() { - return QuestsConfiguration.dynmapMarkerIcon() != null && !QuestsConfiguration.dynmapMarkerIcon().isEmpty(); + return QuestsConfigurationImplementation.dynmapMarkerIcon() != null && !QuestsConfigurationImplementation.dynmapMarkerIcon().isEmpty(); } @Override @@ -30,7 +30,7 @@ protected void initializeMarkers(Runnable initializeQuests) { BlueMapAPI.onEnable(enableConsumer = api -> { try { set = MarkerSet.builder() - .label(QuestsConfiguration.dynmapSetName()) + .label(QuestsConfigurationImplementation.dynmapSetName()) .defaultHidden(false) .toggleable(true) .build(); @@ -60,7 +60,7 @@ protected void addMarker(Quest quest, Location lc) { for (BlueMapMap map : maps) { POIMarker marker = POIMarker.toBuilder() .label(quest.getName()) - .icon(QuestsConfiguration.dynmapMarkerIcon(), 0, 0) + .icon(QuestsConfigurationImplementation.dynmapMarkerIcon(), 0, 0) .position(lc.getBlockX(), lc.getBlockY(), lc.getBlockZ()) .build(); set.getMarkers().put("qu_" + quest.getId() + "_" + i++, marker); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java index 16167ff0..1db90f41 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java @@ -7,7 +7,7 @@ import org.dynmap.markers.MarkerAPI; import org.dynmap.markers.MarkerIcon; import org.dynmap.markers.MarkerSet; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.quests.Quest; import net.md_5.bungee.api.ChatColor; @@ -19,21 +19,21 @@ public class BQDynmap extends AbstractMapIntegration { @Override public boolean isEnabled() { - return QuestsConfiguration.dynmapMarkerIcon() != null && !QuestsConfiguration.dynmapMarkerIcon().isEmpty(); + return QuestsConfigurationImplementation.dynmapMarkerIcon() != null && !QuestsConfigurationImplementation.dynmapMarkerIcon().isEmpty(); } @Override protected void initializeMarkers(Runnable initializeQuests) { DynmapAPI dynmap = (DynmapAPI) Bukkit.getPluginManager().getPlugin("dynmap"); MarkerAPI api = dynmap.getMarkerAPI(); - icon = api.getMarkerIcon(QuestsConfiguration.dynmapMarkerIcon()); + icon = api.getMarkerIcon(QuestsConfigurationImplementation.dynmapMarkerIcon()); markers = api.getMarkerSet("beautyquests.markerset"); if (markers == null){ - markers = api.createMarkerSet("beautyquests.markerset", QuestsConfiguration.dynmapSetName(), null, false); - }else markers.setMarkerSetLabel(QuestsConfiguration.dynmapSetName()); + markers = api.createMarkerSet("beautyquests.markerset", QuestsConfigurationImplementation.dynmapSetName(), null, false); + }else markers.setMarkerSetLabel(QuestsConfigurationImplementation.dynmapSetName()); - markers.setMinZoom(QuestsConfiguration.dynmapMinimumZoom()); + markers.setMinZoom(QuestsConfigurationImplementation.dynmapMinimumZoom()); markers.setHideByDefault(false); markers.setDefaultMarkerIcon(icon); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java index 18687839..8ff45a01 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java @@ -10,10 +10,10 @@ import org.bukkit.event.EventPriority; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.QuestsConfiguration.ClickType; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.npcs.NpcClickType; import net.citizensnpcs.Settings; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.CitizensReloadEvent; @@ -50,13 +50,13 @@ public Collection<Integer> getIDs() { @EventHandler (priority = EventPriority.HIGHEST) public void onNPCRightClick(NPCRightClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - super.clickEvent(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? ClickType.SHIFT_RIGHT : ClickType.RIGHT); + super.clickEvent(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_RIGHT : NpcClickType.RIGHT); } @EventHandler (priority = EventPriority.HIGHEST) public void onNPCLeftClick(NPCLeftClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - super.clickEvent(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? ClickType.SHIFT_LEFT : ClickType.LEFT); + super.clickEvent(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_LEFT : NpcClickType.LEFT); } @EventHandler diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java index 760a774d..8e196d84 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java @@ -11,9 +11,9 @@ import org.bukkit.event.EventHandler; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import fr.skytasul.quests.QuestsConfiguration.ClickType; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.npcs.NpcClickType; import io.github.znetworkw.znpcservers.ServersNPC; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.npc.NPC; @@ -69,7 +69,7 @@ protected BQNPC create(Location location, EntityType type, String name) { @EventHandler public void onInteract(NPCInteractEvent e) { - super.clickEvent(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), ClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); + super.clickEvent(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), NpcClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); } public static class BQServerNPC extends BQNPC { diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java index 6d27d8af..cfeb453c 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java @@ -10,7 +10,7 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.DialogSendEvent; import fr.skytasul.quests.api.events.DialogSendMessageEvent; @@ -63,8 +63,8 @@ private TestResult test(Player p) { @Override public boolean canContinue(Player p) { - if (npc == null || QuestsConfiguration.getDialogsConfig().getMaxDistance() == 0) return true; - return p.getLocation().distanceSquared(npc.getLocation()) <= QuestsConfiguration.getDialogsConfig().getMaxDistanceSquared(); + if (npc == null || QuestsConfigurationImplementation.getDialogsConfig().getMaxDistance() == 0) return true; + return p.getLocation().distanceSquared(npc.getLocation()) <= QuestsConfigurationImplementation.getDialogsConfig().getMaxDistanceSquared(); } private void end(Player p) { @@ -79,7 +79,7 @@ private void end(Player p) { @Override public TestResult onClick(Player p) { - if (QuestsConfiguration.getDialogsConfig().isClickDisabled()) { + if (QuestsConfigurationImplementation.getDialogsConfig().isClickDisabled()) { PlayerStatus status = players.get(p); if (status != null && status.task != null) return TestResult.DENY; } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 5dd23340..7950e6b6 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -1,6 +1,4 @@ # - General configuration - -# Number of minutes before the quest can be redone -redoMinuts: 5 # Chosen lang (file name) Available by default: fr_FR, en_US, zh_CN, zh_HK, de_DE, it_IT, es_ES, pt_PT, pt_BR, sv_SE, hu_HU, ru_RU, pl_PL, th_TH, lt_LT, vi_VN lang: en_US # (1.13 and above) Minecraft vanilla translations (JSON file name). Some can be found on SkytAsul's Discord server @@ -13,11 +11,6 @@ enablePrefix: true saveCycle: 15 # Enable "periodic save" message in console saveCycleMessage: true -# Maximum amount of quests that can be started at the same time by a player. -# This limit can also be set by player by giving the permission "beautyquests.start.<max launched quests>" -# to a group or a player with your permissions plugin. -# It is possible not to count some quests in this limit with the "Bypass limit" quest option. -maxLaunchedQuests: 0 # Database configuration database: enabled: false @@ -33,6 +26,13 @@ database: playerPools: "player_pools" # - Quests behaviors - +# Number of minutes before the quest can be redone +redoMinuts: 5 +# Maximum amount of quests that can be started at the same time by a player. +# This limit can also be set by player by giving the permission "beautyquests.start.<max launched quests>" +# to a group or a player with your permissions plugin. +# It is possible not to count some quests in this limit with the "Bypass limit" quest option. +maxLaunchedQuests: 0 # Enable or disable the scoreboards - more options in scoreboard.yml scoreboards: true # Enable or disable message when a quest is updated (next stage) From 8ba2a9f214844703b35f5ec6c5902697490825d9 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 2 May 2023 21:37:54 +0200 Subject: [PATCH 16/95] :bug: Fixed issue with entity spawn eggs --- core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java | 9 +++++++++ core/src/main/java/fr/skytasul/quests/utils/Utils.java | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java b/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java index 77b948d9..e627e5ed 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java +++ b/core/src/main/java/fr/skytasul/quests/gui/ItemUtils.java @@ -17,6 +17,7 @@ import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.SkullMeta; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.utils.ChatUtils; import fr.skytasul.quests.utils.Lang; @@ -37,6 +38,10 @@ public class ItemUtils { * @return the ItemStack instance */ public static ItemStack item(XMaterial type, String name, String... lore) { + if (!type.isSupported()) { + BeautyQuests.logger.warning("Trying to create an item for an unsupported material " + type.name()); + type = XMaterial.SPONGE; + } ItemStack is = type.parseItem(); ItemMeta im = is.getItemMeta(); im.addItemFlags(ItemFlag.values()); @@ -52,6 +57,10 @@ public static ItemStack item(XMaterial type, String name, String... lore) { * @return the ItemStack instance */ public static ItemStack item(XMaterial type, String name, List<String> lore) { + if (!type.isSupported()) { + BeautyQuests.logger.warning("Trying to create an item for an unsupported material " + type.name()); + type = XMaterial.SPONGE; + } ItemStack is = type.parseItem(); ItemMeta im = is.getItemMeta(); im.addItemFlags(ItemFlag.values()); diff --git a/core/src/main/java/fr/skytasul/quests/utils/Utils.java b/core/src/main/java/fr/skytasul/quests/utils/Utils.java index 65e6fe55..a8bd3145 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Utils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Utils.java @@ -583,7 +583,8 @@ public static boolean isQuestItem(ItemStack item) { public static XMaterial mobItem(EntityType type) { if (type == null) return XMaterial.SPONGE; Optional<XMaterial> material = XMaterial.matchXMaterial(type.name() + "_SPAWN_EGG"); - if (material.isPresent()) return material.get(); + if (material.isPresent() && material.get().isSupported()) + return material.get(); if (type == EntityType.WITHER) return XMaterial.WITHER_SKELETON_SKULL; if (type == EntityType.IRON_GOLEM) return XMaterial.IRON_BLOCK; if (type == EntityType.SNOWMAN) return XMaterial.SNOW_BLOCK; From cc623a1ccf9d0646d00d553effabb5eb69947530 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 7 May 2023 15:59:42 +0200 Subject: [PATCH 17/95] :construction: Still WIP --- api/pom.xml | 2 +- .../quests/api/QuestsConfiguration.java | 4 ++ .../quests/api/gui/GuiClickEvent.java | 20 +++++- .../options/description/QuestDescription.java | 40 ++---------- .../quests/api/utils/PlayerListCategory.java | 5 ++ core/pom.xml | 2 +- .../QuestsConfigurationImplementation.java | 62 ++++++++++++++++++- .../CommandsManagerImplementation.java | 3 +- .../quests/commands/CommandsPools.java | 2 +- .../quests/gui/GuiManagerImplementation.java | 19 +++--- .../quests/gui/quests/PlayerListGUI.java | 54 +++++++++------- dist/pom.xml | 2 +- pom.xml | 4 +- v1_12_R1/pom.xml | 2 +- v1_15_R1/pom.xml | 2 +- v1_16_R1/pom.xml | 2 +- v1_16_R2/pom.xml | 2 +- v1_16_R3/pom.xml | 2 +- v1_17_R1/pom.xml | 2 +- v1_18_R1/pom.xml | 2 +- v1_18_R2/pom.xml | 2 +- v1_19_R1/pom.xml | 2 +- v1_19_R2/pom.xml | 2 +- v1_19_R3/pom.xml | 2 +- v1_9_R1/pom.xml | 2 +- v1_9_R2/pom.xml | 2 +- 26 files changed, 152 insertions(+), 93 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index 3fb761a4..dde2b738 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <build> diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java index 5d93217c..7975a704 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -7,6 +7,7 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.npcs.NpcClickType; import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.options.description.QuestDescription; import fr.skytasul.quests.api.utils.PlayerListCategory; public interface QuestsConfiguration { @@ -27,6 +28,9 @@ public interface QuestsConfiguration { @NotNull StageDescription getStageDescriptionConfig(); + @NotNull + QuestDescription getQuestDescriptionConfig(); + interface Quests { int getDefaultTimer(); diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java index 082c24bf..99fbf6fe 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java @@ -9,16 +9,18 @@ public class GuiClickEvent { private final @NotNull Player player; + private final @NotNull Gui gui; private final @Nullable ItemStack clicked; private final @Nullable ItemStack cursor; private final int slot; private final @NotNull ClickType click; - private boolean cancelled; + private boolean cancelled = true; - public GuiClickEvent(@NotNull Player player, @Nullable ItemStack clicked, @Nullable ItemStack cursor, int slot, - @NotNull ClickType click) { + public GuiClickEvent(@NotNull Player player, @NotNull Gui gui, @Nullable ItemStack clicked, @Nullable ItemStack cursor, + int slot, @NotNull ClickType click) { this.player = player; + this.gui = gui; this.clicked = clicked; this.cursor = cursor; this.slot = slot; @@ -28,6 +30,10 @@ public GuiClickEvent(@NotNull Player player, @Nullable ItemStack clicked, @Nulla public @NotNull Player getPlayer() { return player; } + + public @NotNull Gui getGui() { + return gui; + } public @Nullable ItemStack getClicked() { return clicked; @@ -57,4 +63,12 @@ public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } + public void reopen() { + gui.reopen(player); + } + + public void close() { + gui.close(player); + } + } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java index 2154f23a..1dc9f4e3 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescription.java @@ -1,43 +1,15 @@ package fr.skytasul.quests.api.options.description; -import org.bukkit.configuration.ConfigurationSection; - -public class QuestDescription { - - private boolean requirements; - private String requirementsValid; - private String requirementsInvalid; - - private boolean rewards; - private String rewardsFormat; - - public QuestDescription(ConfigurationSection config) { - requirements = config.getBoolean("requirements.display"); - requirementsValid = config.getString("requirements.valid"); - requirementsInvalid = config.getString("requirements.invalid"); - - rewards = config.getBoolean("rewards.display"); - rewardsFormat = config.getString("rewards.format"); - } +public interface QuestDescription { - public boolean showRewards() { - return rewards; - } + public boolean showRewards(); - public String getRewardsFormat() { - return rewardsFormat; - } + public String getRewardsFormat(); - public boolean showRequirements() { - return requirements; - } + public boolean showRequirements(); - public String getRequirementsValid() { - return requirementsValid; - } + public String getRequirementsValid(); - public String getRequirementsInvalid() { - return requirementsInvalid; - } + public String getRequirementsInvalid(); } 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 8ebfee63..2e6c1747 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,6 +3,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; public enum PlayerListCategory { @@ -42,6 +43,10 @@ public int getSlot() { return name; } + public boolean isEnabled() { + return QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs().contains(this); + } + public static @Nullable PlayerListCategory fromString(@NotNull String name) { try { return PlayerListCategory.valueOf(name.toUpperCase()); diff --git a/core/pom.xml b/core/pom.xml index 129cb8e1..7d0a8840 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <build> diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 2ad7196b..7ef336b2 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -55,7 +55,6 @@ public static QuestsConfigurationImplementation getConfiguration() { private String dSetName = "Quests"; private String dIcon = "bookshelf"; private int dMinZoom = 0; - private QuestDescription questDescription; private ItemStack holoLaunchItem = null; private ItemStack holoLaunchNoItem = null; @@ -74,6 +73,7 @@ public static QuestsConfigurationImplementation getConfiguration() { private DialogsConfig dialogs; private QuestsMenuConfig menu; private StageDescriptionConfig stageDescription; + private QuestDescriptionConfig questDescription; QuestsConfigurationImplementation(BeautyQuests plugin) { config = plugin.getConfig(); @@ -81,6 +81,7 @@ public static QuestsConfigurationImplementation getConfiguration() { dialogs = new DialogsConfig(config.getConfigurationSection("dialogs")); menu = new QuestsMenuConfig(config.getConfigurationSection("questsMenu")); stageDescription = new StageDescriptionConfig(); + questDescription = new QuestDescriptionConfig(config.getConfigurationSection("questDescription")); } boolean update() { @@ -101,6 +102,7 @@ void init() { dialogs.init(); menu.init(); stageDescription.init(); + questDescription.init(); saveCycle = config.getInt("saveCycle"); saveCycleMessage = config.getBoolean("saveCycleMessage"); @@ -122,8 +124,6 @@ void init() { dIcon = config.getString("dynmap.markerIcon"); dMinZoom = config.getInt("dynmap.minZoom"); - questDescription = new QuestDescription(config.getConfigurationSection("questDescription")); - if (MinecraftVersion.MAJOR >= 9) { particleStart = loadParticles(config, "start", new ParticleEffect(Particle.REDSTONE, ParticleShape.POINT, Color.YELLOW)); particleTalk = loadParticles(config, "talk", new ParticleEffect(Particle.VILLAGER_HAPPY, ParticleShape.BAR, null)); @@ -234,6 +234,11 @@ public FileConfiguration getConfig() { return stageDescription; } + @Override + public @NotNull QuestDescriptionConfig getQuestDescriptionConfig() { + return questDescription; + } + public String getPrefix() { return (enablePrefix) ? Lang.Prefix.toString() : "§6"; } @@ -725,4 +730,55 @@ public boolean splitDescription(DescriptionSource source) { } + public class QuestDescriptionConfig implements QuestDescription { + + private boolean requirements; + private String requirementsValid; + private String requirementsInvalid; + + private boolean rewards; + private String rewardsFormat; + + private final ConfigurationSection config; + + public QuestDescriptionConfig(ConfigurationSection config) { + this.config = config; + } + + private void init() { + requirements = config.getBoolean("requirements.display"); + requirementsValid = config.getString("requirements.valid"); + requirementsInvalid = config.getString("requirements.invalid"); + + rewards = config.getBoolean("rewards.display"); + rewardsFormat = config.getString("rewards.format"); + } + + @Override + public boolean showRewards() { + return rewards; + } + + @Override + public String getRewardsFormat() { + return rewardsFormat; + } + + @Override + public boolean showRequirements() { + return requirements; + } + + @Override + public String getRequirementsValid() { + return requirementsValid; + } + + @Override + public String getRequirementsInvalid() { + return requirementsInvalid; + } + + } + } 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 7015d6c3..405e16ec 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -7,7 +7,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.commands.CommandsManager; @@ -36,7 +35,7 @@ public class CommandsManagerImplementation implements CommandsManager { public CommandsManagerImplementation() { handler = BukkitCommandHandler.create(BeautyQuests.getInstance()); - handler.setMessagePrefix(QuestsConfigurationImplementation.getPrefix()); + handler.setMessagePrefix(QuestsPlugin.getPlugin().getPrefix()); handler.failOnTooManyArguments(); handler.registerValueResolver(Quest.class, context -> { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index 4eb6580c..35b40835 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java @@ -3,9 +3,9 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.gui.pools.PoolsManageGUI; -import fr.skytasul.quests.players.PlayerAccount; import fr.skytasul.quests.structure.pools.QuestPoolImplementation; import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Subcommand; diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index 94d6091b..af8920dc 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -17,6 +17,7 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.GuiManager; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -148,16 +149,14 @@ public void onClick(InventoryClickEvent event) { ensureSameInventory(gui, event.getClickedInventory()); - if (event.getCursor().getType() == Material.AIR) { - if (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR) - return; - if (gui.onClick(null)) - event.setCancelled(true); - } else { - if (gui.onClickCursor(player, event.getCurrentItem(), event.getCursor(), - event.getSlot())) - event.setCancelled(true); - } + if (event.getCursor().getType() == Material.AIR + && (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR)) + return; + + GuiClickEvent guiEvent = new GuiClickEvent(player, gui, event.getCurrentItem(), event.getCursor(), + event.getSlot(), event.getClick()); + gui.onClick(guiEvent); + event.setCancelled(guiEvent.isCancelled()); } catch (Exception ex) { event.setCancelled(true); Lang.ERROR_OCCURED.send(player, ex.getMessage() + " in " + gui.getClass().getSimpleName()); 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 123387e3..5386c342 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 @@ -13,8 +13,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.GuiClickEvent; @@ -64,14 +64,16 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { setBarItem(0, ItemUtils.itemLaterPage); setBarItem(4, ItemUtils.itemNextPage); - for (PlayerListCategory enabledCat : QuestsConfigurationImplementation.getMenuConfig().getEnabledTabs()) { + for (PlayerListCategory enabledCat : QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs()) { setBarItem(enabledCat.getSlot(), ItemUtils.item(enabledCat.getMaterial(), UNSELECTED_PREFIX + enabledCat.getName())); } if (PlayerListCategory.IN_PROGRESS.isEnabled()) { setCategory(PlayerListCategory.IN_PROGRESS); - if (quests.isEmpty() && QuestsConfigurationImplementation.getMenuConfig().isNotStartedTabOpenedWhenEmpty() && PlayerListCategory.NOT_STARTED.isEnabled()) setCategory(PlayerListCategory.NOT_STARTED); + if (quests.isEmpty() && QuestsConfiguration.getConfig().getQuestsMenuConfig().isNotStartedTabOpenedWhenEmpty() + && PlayerListCategory.NOT_STARTED.isEnabled()) + setCategory(PlayerListCategory.NOT_STARTED); }else if (PlayerListCategory.NOT_STARTED.isEnabled()) { setCategory(PlayerListCategory.NOT_STARTED); }else setCategory(PlayerListCategory.FINISHED); @@ -101,8 +103,10 @@ private void setItems(){ case FINISHED: displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); - if (QuestsConfigurationImplementation.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { + List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), + qu, acc, cat, DescriptionSource.MENU).formatDescription(); + if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs()) { if (!lore.isEmpty()) lore.add(null); lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); } @@ -112,10 +116,13 @@ private void setItems(){ case IN_PROGRESS: displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); + List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), + qu, acc, cat, DescriptionSource.MENU).formatDescription(); - boolean hasDialogs = QuestsConfigurationImplementation.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs(); - boolean cancellable = QuestsConfigurationImplementation.getMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); + boolean hasDialogs = QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs(); + boolean cancellable = + QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); if (cancellable || hasDialogs) { if (!lore.isEmpty()) lore.add(null); if (cancellable) lore.add("§8" + Lang.ClickLeft + " §8> " + Lang.cancelLore); @@ -129,7 +136,9 @@ private void setItems(){ displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) .collect(Collectors.toList()), qu -> { - return createQuestItem(qu, new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), qu, acc, cat, DescriptionSource.MENU).formatDescription()); + return createQuestItem(qu, + new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), qu, + acc, cat, DescriptionSource.MENU).formatDescription()); }); break; @@ -189,9 +198,9 @@ private void toggleCategorySelected() { @Override public void onClick(GuiClickEvent event) { - switch (slot % 9){ + switch (event.getSlot() % 9) { case 8: - int barSlot = (slot - 8) / 9; + int barSlot = (event.getSlot() - 8) / 9; switch (barSlot){ case 0: if (page == 0) break; @@ -217,33 +226,34 @@ public void onClick(GuiClickEvent event) { break; default: - int id = (int) (slot - (Math.floor(slot * 1D / 9D) * 2) + page * 35); + int id = (int) (event.getSlot() - (Math.floor(event.getSlot() * 1D / 9D) * 2) + page * 35); Quest qu = quests.get(id); if (cat == PlayerListCategory.NOT_STARTED) { if (!qu.getOptionValueOrDef(OptionStartable.class)) break; if (!acc.isCurrent()) break; Player target = acc.getPlayer(); if (qu.canStart(target, true)) { - p.closeInventory(); + event.close(); qu.attemptStart(target); } }else { - if (click.isRightClick()) { - if (QuestsConfigurationImplementation.getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs()) { - QuestUtils.playPluginSound(p, "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); - new DialogHistoryGUI(acc, qu, () -> reopen(p)).open(p); + if (event.getClick().isRightClick()) { + if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs()) { + QuestUtils.playPluginSound(event.getPlayer(), "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); + new DialogHistoryGUI(acc, qu, event::reopen).open(event.getPlayer()); } - }else if (click.isLeftClick()) { - if (QuestsConfigurationImplementation.getMenuConfig().allowPlayerCancelQuest() && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { - ConfirmGUI.confirm(() -> qu.cancelPlayer(acc), () -> reopen(p), - Lang.INDICATION_CANCEL.format(qu.getName())).open(p); + } else if (event.getClick().isLeftClick()) { + if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() + && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { + ConfirmGUI.confirm(() -> qu.cancelPlayer(acc), event::reopen, + Lang.INDICATION_CANCEL.format(qu.getName())).open(event.getPlayer()); } } } break; } - return true; } @Override diff --git a/dist/pom.xml b/dist/pom.xml index 3c2874ea..2d23b703 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <build> diff --git a/pom.xml b/pom.xml index b8bc0aa6..c5ac71c7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>beautyquests</name> @@ -18,7 +18,7 @@ <maven.compiler.target>1.8</maven.compiler.target> <maven.javadoc.skip>true</maven.javadoc.skip> <build.number>unknown</build.number> - <human.version>0.21</human.version> + <human.version>1.0</human.version> </properties> <repositories> diff --git a/v1_12_R1/pom.xml b/v1_12_R1/pom.xml index d1836a69..ff9bd2e9 100644 --- a/v1_12_R1/pom.xml +++ b/v1_12_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_15_R1/pom.xml b/v1_15_R1/pom.xml index e47b78c5..a546f759 100644 --- a/v1_15_R1/pom.xml +++ b/v1_15_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R1/pom.xml b/v1_16_R1/pom.xml index 535d1457..9fc470b9 100644 --- a/v1_16_R1/pom.xml +++ b/v1_16_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R2/pom.xml b/v1_16_R2/pom.xml index 2b1dceaa..165aff1a 100644 --- a/v1_16_R2/pom.xml +++ b/v1_16_R2/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R3/pom.xml b/v1_16_R3/pom.xml index 8fa9439e..3a8e768d 100644 --- a/v1_16_R3/pom.xml +++ b/v1_16_R3/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml index d7fe83a0..da20e321 100644 --- a/v1_17_R1/pom.xml +++ b/v1_17_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties> diff --git a/v1_18_R1/pom.xml b/v1_18_R1/pom.xml index 577cadce..5aba4ecf 100644 --- a/v1_18_R1/pom.xml +++ b/v1_18_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties> diff --git a/v1_18_R2/pom.xml b/v1_18_R2/pom.xml index 3fc0c2ac..74fc899e 100644 --- a/v1_18_R2/pom.xml +++ b/v1_18_R2/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties> diff --git a/v1_19_R1/pom.xml b/v1_19_R1/pom.xml index 4926c528..e480a5c5 100644 --- a/v1_19_R1/pom.xml +++ b/v1_19_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties> diff --git a/v1_19_R2/pom.xml b/v1_19_R2/pom.xml index fe850f75..4465a1fd 100644 --- a/v1_19_R2/pom.xml +++ b/v1_19_R2/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties> diff --git a/v1_19_R3/pom.xml b/v1_19_R3/pom.xml index 44db70d1..1e46d5ff 100644 --- a/v1_19_R3/pom.xml +++ b/v1_19_R3/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties> diff --git a/v1_9_R1/pom.xml b/v1_9_R1/pom.xml index 4262b438..f2e6a56f 100644 --- a/v1_9_R1/pom.xml +++ b/v1_9_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_9_R2/pom.xml b/v1_9_R2/pom.xml index 9d616afa..7d3fa0ff 100644 --- a/v1_9_R2/pom.xml +++ b/v1_9_R2/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>0.21-SNAPSHOT</version> + <version>1.0-SNAPSHOT</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> From c5ece16bba142aba6640c687c15b46b3bd266abc Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 12 Jun 2023 10:30:36 +0200 Subject: [PATCH 18/95] :construction: Still WIP (almost done!) --- .../quests/api/QuestsConfiguration.java | 4 + .../skytasul/quests/api/gui/AbstractGui.java | 56 +++ .../java/fr/skytasul/quests/api/gui/Gui.java | 156 ++++---- .../fr/skytasul/quests/api/gui/ItemUtils.java | 4 +- .../quests/api/gui/layout/LayoutedButton.java | 31 ++ .../api/gui/layout/LayoutedClickEvent.java | 45 +-- .../quests/api/gui/layout/LayoutedGUI.java | 30 +- .../quests/api/gui/templates/ChooseGUI.java | 4 +- .../quests/api/gui/templates/ConfirmGUI.java | 6 +- .../quests/api/gui/templates/PagedGUI.java | 4 +- .../quests/api/options/QuestOption.java | 14 +- .../api/options/QuestOptionBoolean.java | 8 +- .../api/options/QuestOptionCreator.java | 4 + .../quests/api/options/QuestOptionItem.java | 13 +- .../quests/api/options/QuestOptionObject.java | 36 +- .../api/options/QuestOptionRewards.java | 19 +- .../quests/api/options/QuestOptionString.java | 30 +- .../api/options/UpdatableOptionSet.java | 28 +- .../description/QuestDescriptionProvider.java | 2 +- .../skytasul/quests/api/pools/QuestPool.java | 4 +- .../quests/api/pools/QuestPoolsManager.java | 6 +- .../api/quests/creation/QuestCreationGui.java | 15 + .../creation/QuestCreationGuiClickEvent.java | 27 ++ .../api/requirements/RequirementList.java | 57 +++ .../quests/api/rewards/RewardList.java | 69 ++++ .../quests/api/stages/AbstractStage.java | 60 ++- .../quests/api/stages/StageController.java | 5 - .../skytasul/quests/api/stages/StageType.java | 5 +- .../stages/{ => creation}/StageCreation.java | 147 ++++---- .../stages/creation/StageCreationContext.java | 26 ++ .../stages/creation/StageGuiClickEvent.java | 47 +++ .../stages/creation/StageGuiClickHandler.java | 10 + .../api/stages/creation/StageGuiLine.java | 44 +++ .../api/stages/options/StageOption.java | 2 +- .../types/AbstractCountableBlockStage.java | 25 +- .../stages/types/AbstractCountableStage.java | 38 +- .../api/stages/types/AbstractEntityStage.java | 41 +- .../api/stages/types/AbstractItemStage.java | 38 +- .../quests/api/stages/types/Locatable.java | 5 +- .../skytasul/quests/DefaultQuestFeatures.java | 33 +- .../quests/gui/GuiManagerImplementation.java | 2 +- .../quests/gui/creation/CommandGUI.java | 118 ------ .../quests/gui/creation/FinishGUI.java | 321 ---------------- .../quests/gui/creation/ItemsGUI.java | 109 ------ .../gui/creation/QuestCreationSession.java | 63 ++-- .../quest/QuestCreationGuiImplementation.java | 292 +++++++++++++++ .../stages/{Line.java => LineOld.java} | 6 +- .../StageCreationContextImplementation.java | 67 ++++ .../stages/StageLineImplementation.java | 191 ++++++++++ .../quests/gui/creation/stages/StagesGUI.java | 353 ++++++++++-------- .../{misc => items}/ItemComparisonGUI.java | 2 +- .../gui/{misc => items}/ItemCreatorGUI.java | 174 +++++---- .../quests/gui/{misc => items}/ItemGUI.java | 30 +- .../skytasul/quests/gui/items/ItemsGUI.java | 112 ++++++ .../skytasul/quests/gui/misc/BranchesGUI.java | 4 +- .../gui/{creation => misc}/BucketTypeGUI.java | 11 +- .../skytasul/quests/gui/misc/CommandGUI.java | 94 +++++ .../fr/skytasul/quests/gui/misc/TitleGUI.java | 104 +++--- .../skytasul/quests/gui/npc/NpcCreateGUI.java | 33 +- .../skytasul/quests/gui/npc/NpcSelectGUI.java | 8 +- .../gui/particles/ParticleEffectGUI.java | 145 +++---- .../quests/gui/permissions/PermissionGUI.java | 28 +- .../quests/gui/pools/PoolEditGUI.java | 70 ++-- .../quests/gui/quests/ChooseQuestGUI.java | 5 +- .../quests/gui/quests/DialogHistoryGUI.java | 7 +- .../quests/gui/quests/PlayerListGUI.java | 4 +- .../quests/options/OptionCancelRewards.java | 33 +- .../quests/options/OptionCancellable.java | 4 +- .../quests/options/OptionConfirmMessage.java | 4 +- .../quests/options/OptionDescription.java | 5 +- .../quests/options/OptionEndRewards.java | 10 +- .../quests/options/OptionFailOnDeath.java | 4 +- .../quests/options/OptionFirework.java | 49 ++- .../quests/options/OptionHologramText.java | 3 +- .../quests/options/OptionQuestItem.java | 57 ++- .../quests/options/OptionQuestPool.java | 41 +- .../quests/options/OptionRepeatable.java | 6 +- .../quests/options/OptionRequirements.java | 17 +- .../quests/options/OptionStartDialog.java | 24 +- .../quests/options/OptionStartRewards.java | 7 - .../quests/options/OptionStartable.java | 2 +- .../quests/options/OptionStarterNPC.java | 23 +- .../skytasul/quests/options/OptionTimer.java | 25 +- .../quests/options/OptionVisibility.java | 38 +- .../players/AbstractPlayersManager.java | 11 +- .../requirements/EquipmentRequirement.java | 4 +- .../logical/LogicalOrRequirement.java | 22 +- .../quests/rewards/CheckpointReward.java | 24 +- .../quests/rewards/CommandReward.java | 2 +- .../skytasul/quests/rewards/ItemReward.java | 2 +- .../skytasul/quests/rewards/RandomReward.java | 34 +- .../quests/rewards/RemoveItemsReward.java | 4 +- .../rewards/RequirementDependentReward.java | 37 +- .../fr/skytasul/quests/rewards/XPReward.java | 3 +- .../quests/scoreboards/Scoreboard.java | 5 +- .../quests/scoreboards/ScoreboardManager.java | 8 +- .../fr/skytasul/quests/stages/StageArea.java | 46 ++- .../fr/skytasul/quests/stages/StageBreed.java | 17 +- .../quests/stages/StageBringBack.java | 94 +++-- .../skytasul/quests/stages/StageBucket.java | 74 ++-- .../fr/skytasul/quests/stages/StageChat.java | 53 ++- .../fr/skytasul/quests/stages/StageCraft.java | 76 ++-- .../quests/stages/StageDealDamage.java | 56 +-- .../fr/skytasul/quests/stages/StageDeath.java | 30 +- .../skytasul/quests/stages/StageEatDrink.java | 20 +- .../skytasul/quests/stages/StageEnchant.java | 26 +- .../fr/skytasul/quests/stages/StageFish.java | 28 +- .../skytasul/quests/stages/StageInteract.java | 125 +++---- .../skytasul/quests/stages/StageLocation.java | 95 +++-- .../fr/skytasul/quests/stages/StageMelt.java | 24 +- .../fr/skytasul/quests/stages/StageMine.java | 60 +-- .../fr/skytasul/quests/stages/StageMobs.java | 49 +-- .../fr/skytasul/quests/stages/StageNPC.java | 124 +++--- .../quests/stages/StagePlaceBlocks.java | 20 +- .../skytasul/quests/stages/StagePlayTime.java | 99 ++--- .../fr/skytasul/quests/stages/StageTame.java | 15 +- .../structure/QuestBranchImplementation.java | 23 +- .../quests/structure/QuestImplementation.java | 57 +-- .../pools/QuestPoolImplementation.java | 19 +- .../QuestPoolsManagerImplementation.java | 5 +- .../fr/skytasul/quests/utils/QuestUtils.java | 49 --- 121 files changed, 3017 insertions(+), 2326 deletions(-) create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGui.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGuiClickEvent.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java rename api/src/main/java/fr/skytasul/quests/api/stages/{ => creation}/StageCreation.java (51%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreationContext.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickEvent.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickHandler.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java create mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/quest/QuestCreationGuiImplementation.java rename core/src/main/java/fr/skytasul/quests/gui/creation/stages/{Line.java => LineOld.java} (94%) create mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java create mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java rename core/src/main/java/fr/skytasul/quests/gui/{misc => items}/ItemComparisonGUI.java (96%) rename core/src/main/java/fr/skytasul/quests/gui/{misc => items}/ItemCreatorGUI.java (51%) rename core/src/main/java/fr/skytasul/quests/gui/{misc => items}/ItemGUI.java (71%) create mode 100644 core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java rename core/src/main/java/fr/skytasul/quests/gui/{creation => misc}/BucketTypeGUI.java (76%) create mode 100644 core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java index 7975a704..b66a0af9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -127,6 +127,10 @@ interface StageDescription { Set<DescriptionSource> getSplitSources(); + default boolean isAloneSplitAmountShown(DescriptionSource source) { + return getSplitSources().contains(source) && isAloneSplitAmountShown(); + } + } } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java b/api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java new file mode 100644 index 00000000..3e437a77 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java @@ -0,0 +1,56 @@ +package fr.skytasul.quests.api.gui; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; + +public abstract class AbstractGui implements Gui { + + private @Nullable Inventory inventory; + + @Override + public @Nullable Inventory getInventory() { + return inventory; + } + + @Override + public final void showInternal(Player player) { + if (inventory == null) { + inventory = instanciate(player); + populate(player, inventory); + } else { + refresh(player, inventory); + } + inventory = player.openInventory(inventory).getTopInventory(); + } + + @Override + public final void reopen(@NotNull Player player, boolean refresh) { + if (refresh) + inventory = null; + open(player); + } + + public final void repopulate(@NotNull Player player) { + if (inventory == null) + return; + + inventory.clear(); + populate(player, inventory); + } + + protected abstract Inventory instanciate(@NotNull Player player); + + protected abstract void populate(@NotNull Player player, @NotNull Inventory inventory); + + protected void refresh(@NotNull Player player, @NotNull Inventory inventory) {} + + @Override + public @NotNull CloseBehavior onClose(@NotNull Player player) { + return StandardCloseBehavior.CONFIRM; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/Gui.java b/api/src/main/java/fr/skytasul/quests/api/gui/Gui.java index 66da1756..d43795a9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/Gui.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/Gui.java @@ -1,91 +1,65 @@ -package fr.skytasul.quests.api.gui; - -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.close.CloseBehavior; -import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; - -public abstract class Gui { - - private @Nullable Inventory inventory; - - public @Nullable Inventory getInventory() { - return inventory; - } - - /** - * Called internally when opening inventory - * - * @param p Player to open - * @return inventory opened - */ - public final void show(Player player) { - if (inventory == null) { - inventory = instanciate(player); - populate(player, inventory); - } else { - refresh(player, inventory); - } - inventory = player.openInventory(inventory).getTopInventory(); - } - - /** - * Opens the inventory to the player. Direct reference to - * {@link GuiManager#open(Player, CustomInventory)} - * - * @param player Player - * @see Inventories#create(Player, CustomInventory) - */ - public final void open(@NotNull Player player) { - QuestsPlugin.getPlugin().getGuiManager().open(player, this); - } - - public final void reopen(@NotNull Player player) { - reopen(player, false); - } - - public final void reopen(@NotNull Player player, boolean refresh) { - if (refresh) - inventory = null; - open(player); - } - - public final void repopulate(@NotNull Player player) { - if (inventory == null) - return; - - inventory.clear(); - populate(player, inventory); - } - - public final void close(@NotNull Player player) { - QuestsPlugin.getPlugin().getGuiManager().closeAndExit(player); - } - - protected abstract Inventory instanciate(@NotNull Player player); - - protected abstract void populate(@NotNull Player player, @NotNull Inventory inventory); - - protected void refresh(@NotNull Player player, @NotNull Inventory inventory) {} - - /** - * Called when clicking on an item - * - * @param event object containing informations about click action - */ - public abstract void onClick(@NotNull GuiClickEvent event); - - /** - * Called when closing the inventory - * - * @param player Player who has the inventory opened - * @return Remove player from inventories system - */ - public @NotNull CloseBehavior onClose(@NotNull Player player) { - return StandardCloseBehavior.CONFIRM; - } - -} +package fr.skytasul.quests.api.gui; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.close.CloseBehavior; + +public interface Gui { + + /** + * Gets the inventory for this Gui. + * + * @return the Bukkit inventory of this Gui, or <code>null</code> if it has not yet been built. + */ + @Nullable + Inventory getInventory(); + + /** + * Called internally when opening inventory + * + * @param p Player to open + * @return inventory opened + */ + void showInternal(@NotNull Player player); + + /** + * Opens the inventory to the player. Direct reference to + * {@link GuiManager#open(Player, CustomInventory)} + * + * @param player Player + * @see Inventories#create(Player, CustomInventory) + */ + default void open(@NotNull Player player) { + QuestsPlugin.getPlugin().getGuiManager().open(player, this); + } + + default void reopen(@NotNull Player player) { + reopen(player, false); + } + + void reopen(@NotNull Player player, boolean refresh); + + default void close(@NotNull Player player) { + QuestsPlugin.getPlugin().getGuiManager().closeAndExit(player); + } + + /** + * Called when clicking on an item + * + * @param event object containing informations about click action + */ + void onClick(@NotNull GuiClickEvent event); + + /** + * Called when closing the inventory + * + * @param player Player who has the inventory opened + * @return behavior to have for this closing + */ + @NotNull + CloseBehavior onClose(@NotNull Player player); + +} 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 75a79f26..12befd14 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 @@ -312,14 +312,14 @@ public static ItemStack removeEnchant(ItemStack is, Enchantment en){ * @see #itemNextPage */ public static final ImmutableItemStack itemLaterPage = new ImmutableItemStack( - item(QuestsConfiguration.getConfig().getQuestsConfig().pageItem(), Lang.laterPage.toString())); + item(QuestsConfiguration.getConfig().getQuestsConfig().getPageMaterial(), Lang.laterPage.toString())); /** * Immutable ItemStack instance with lore : <i>inv.stages.nextPage</i> and material : <i>pageItem</i> * @see #itemLaterPage */ public static final ImmutableItemStack itemNextPage = new ImmutableItemStack( - item(QuestsConfiguration.getConfig().getQuestsConfig().pageItem(), Lang.nextPage.toString())); + item(QuestsConfiguration.getConfig().getQuestsConfig().getPageMaterial(), Lang.nextPage.toString())); /** * Immutable ItemStack instance with name : <i>inv.cancel</i> and material : barrier diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedButton.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedButton.java index 4eedac24..6cf6d96d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedButton.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedButton.java @@ -1,6 +1,7 @@ package fr.skytasul.quests.api.gui.layout; import java.util.List; +import java.util.function.BooleanSupplier; import java.util.function.Supplier; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -8,11 +9,16 @@ import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.options.QuestOption; public interface LayoutedButton extends LayoutedClickHandler { public void place(@NotNull Inventory inventory, int slot); + public default boolean isValid() { + return true; + } + interface ItemButton extends LayoutedButton { public @Nullable ItemStack getItem(); @@ -58,6 +64,26 @@ public void click(@NotNull LayoutedClickEvent event) { }; } + public static @NotNull LayoutedButton createLoreValue(@NotNull XMaterial material, @Nullable String name, + @NotNull Supplier<@Nullable Object> loreValue, @NotNull LayoutedClickHandler click) { + return new ItemButton() { + + @Override + public void click(@NotNull LayoutedClickEvent event) { + click.click(event); + } + + @Override + public @Nullable ItemStack getItem() { + @Nullable + Object value = loreValue.get(); + return ItemUtils.item(material, name, + QuestOption.formatNullableValue(value == null ? null : value.toString())); + } + + }; + } + public static @NotNull LayoutedButton create(@NotNull XMaterial material, @NotNull Supplier<@Nullable String> name, @NotNull Supplier<@Nullable List<String>> lore, @NotNull LayoutedClickHandler click) { return new ItemButton() { @@ -142,4 +168,9 @@ public void click(@NotNull LayoutedClickEvent event) { }; } + public static @NotNull LayoutedButton createSwitch(@NotNull BooleanSupplier stateSupplier, @NotNull String name, + @Nullable List<@Nullable String> lore, @NotNull LayoutedClickHandler click) { + return create(() -> ItemUtils.itemSwitch(name, stateSupplier.getAsBoolean(), lore.toArray(new String[0])), click); + } + } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickEvent.java index 45415f73..e4658366 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedClickEvent.java @@ -2,53 +2,42 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.gui.GuiClickEvent; -public class LayoutedClickEvent { +public class LayoutedClickEvent extends GuiClickEvent { - private final @NotNull Player player; - private final @NotNull LayoutedGUI gui; - private final int slot; - private final @NotNull ClickType click; + private @NotNull LayoutedGUI gui; - public LayoutedClickEvent(@NotNull Player player, @NotNull LayoutedGUI gui, int slot, @NotNull ClickType click) { - this.player = player; + public LayoutedClickEvent(@NotNull Player player, @NotNull LayoutedGUI gui, @Nullable ItemStack clicked, + @Nullable ItemStack cursor, int slot, @NotNull ClickType click) { + super(player, gui, clicked, cursor, slot, click); this.gui = gui; - this.slot = slot; - this.click = click; } - public @NotNull Player getPlayer() { - return player; + @Override + public void setCancelled(boolean cancelled) { + throw new UnsupportedOperationException(); } + @Override public @NotNull LayoutedGUI getGui() { return gui; } - public int getSlot() { - return slot; - } - - public @NotNull ClickType getClick() { - return click; - } - - public void reopen() { - gui.reopen(player); + public void refreshItem() { + gui.refresh(getSlot()); } public void refreshItemReopen() { - gui.refresh(slot); - gui.reopen(player); + gui.refresh(getSlot()); + gui.reopen(getPlayer()); } public void refreshGuiReopen() { - gui.reopen(player, true); - } - - public void close() { - gui.close(player); + gui.reopen(getPlayer(), true); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java index bfa98554..c1392461 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java @@ -10,12 +10,12 @@ import org.bukkit.inventory.Inventory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -public abstract class LayoutedGUI extends Gui { +public abstract class LayoutedGUI extends AbstractGui { protected final @Nullable String name; protected final @NotNull Map<Integer, LayoutedButton> buttons; @@ -34,12 +34,13 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { } @Override - public void onClick(GuiClickEvent event) { + public final void onClick(GuiClickEvent event) { LayoutedButton button = buttons.get(event.getSlot()); - if (button == null) + if (button == null || !button.isValid()) return; - button.click(new LayoutedClickEvent(event.getPlayer(), this, event.getSlot(), event.getClick())); + button.click(new LayoutedClickEvent(event.getPlayer(), this, event.getClicked(), event.getCursor(), event.getSlot(), + event.getClick())); } public void refresh(int slot) { @@ -47,10 +48,21 @@ public void refresh(int slot) { return; LayoutedButton button = buttons.get(slot); - if (button == null) + if (button == null || !button.isValid()) { + getInventory().setItem(slot, null); + } else { + button.place(getInventory(), slot); + } + } + + public void refresh(@NotNull LayoutedButton button) { + if (getInventory() == null) return; - button.place(getInventory(), slot); + buttons.forEach((slot, otherButton) -> { + if (otherButton.equals(button)) + refresh(slot); + }); } @Override @@ -74,7 +86,7 @@ protected LayoutedRowsGUI(@Nullable String name, @NotNull Map<Integer, LayoutedB } @Override - protected Inventory instanciate(@NotNull Player player) { + protected final Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, rows, name); } @@ -91,7 +103,7 @@ protected LayoutedTypeGUI(@Nullable String name, @NotNull Map<Integer, LayoutedB } @Override - protected Inventory instanciate(@NotNull Player player) { + protected final Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, type, name); } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java index 225939a6..1ed0998e 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ChooseGUI.java @@ -6,12 +6,12 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -public abstract class ChooseGUI<T> extends Gui { +public abstract class ChooseGUI<T> extends AbstractGui { private List<T> available; diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java index 64ab55d2..19f4dc1f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.gui.layout.LayoutedButton; import fr.skytasul.quests.api.gui.layout.LayoutedClickHandler; @@ -18,12 +18,12 @@ public final class ConfirmGUI { private ConfirmGUI() {} - public static Gui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + public static AbstractGui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, @Nullable String @Nullable... lore) { return confirm(yes, no, indication, lore == null ? null : Arrays.asList(lore)); } - public static Gui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + public static AbstractGui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, @Nullable List<@Nullable String> lore) { return LayoutedGUI.newBuilder() .addButton(1, diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java index a8af1068..4c69ddb8 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -28,7 +28,7 @@ * * @param <T> type of objects stocked in the inventory */ -public abstract class PagedGUI<T> extends Gui { +public abstract class PagedGUI<T> extends AbstractGui { private static ItemStack itemSearch = ItemUtils.item(XMaterial.COMPASS, Lang.search.toString()); diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index aada029e..2f925c7a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -4,10 +4,8 @@ import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,7 +13,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; public abstract class QuestOption<T> implements Cloneable { @@ -118,17 +116,11 @@ public boolean shouldDisplay(@NotNull OptionSet options) { return true; } - public void updatedDependencies(@NotNull OptionSet options, @NotNull ItemStack item) {} + public void onDependenciesUpdated(@NotNull OptionSet options/* , @NotNull ItemStack item TODO wtf */) {} public abstract @NotNull ItemStack getItemStack(@NotNull OptionSet options); - public abstract void click(@NotNull FinishGUI gui, @NotNull Player p, @NotNull ItemStack item, int slot, - @NotNull ClickType click); - - public boolean clickCursor(@NotNull FinishGUI gui, @NotNull Player p, @NotNull ItemStack item, @NotNull ItemStack cursor, - int slot) { - return true; - } + public abstract void click(@NotNull QuestCreationGuiClickEvent event); public @NotNull String formatValue(@Nullable String valueString) { return formatNullableValue(valueString, !hasCustomValue()); diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java index 8e74d7fd..373bfee9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionBoolean.java @@ -1,11 +1,9 @@ package fr.skytasul.quests.api.options; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; public abstract class QuestOptionBoolean extends QuestOption<Boolean> { @@ -40,9 +38,9 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { + public void click(QuestCreationGuiClickEvent event) { setValue(!getValue()); - ItemUtils.setSwitch(item, getValue()); + ItemUtils.setSwitch(event.getClicked(), getValue()); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java index 184220f1..155f7fca 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionCreator.java @@ -42,6 +42,10 @@ public static int calculateSlot(int preferedSlot) { return prevSlot == preferedSlot ? prevSlot + 1 : preferedSlot; } + public static int getLastSlot() { + return creators.values().stream().mapToInt(creator -> creator.slot).max().getAsInt(); + } + public boolean applies(@NotNull String key) { return id.equals(key) || Arrays.stream(oldNames).anyMatch(key::equals); } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java index d302b230..cd88f3f5 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java @@ -4,14 +4,13 @@ import java.util.Arrays; import java.util.List; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.FinishGUI; import fr.skytasul.quests.gui.misc.ItemGUI; public abstract class QuestOptionItem extends QuestOption<ItemStack> { @@ -56,7 +55,7 @@ private List<String> getLore() { lore.add(Lang.defaultValue.toString()); } lore.add(""); - lore.add(Lang.RemoveMid.toString()); + lore.add("§8" + Lang.ClickShiftRight.toString() + " > §7" + Lang.Remove.toString()); } return lore; @@ -72,16 +71,16 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - if (click == ClickType.MIDDLE) { + public void click(QuestCreationGuiClickEvent event) { + if (event.getClick() == ClickType.SHIFT_RIGHT) { setValue(null); - gui.inv.setItem(slot, getItemStack(null)); + event.getGui().updateOptionItem(this); }else { new ItemGUI(is -> { setValue(is); gui.inv.setItem(slot, getItemStack(null)); gui.reopen(player); - }, () -> gui.reopen(player)).open(p); + }, event::reopen).open(event.getPlayer()); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java index 674b74c4..9de857c2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java @@ -1,12 +1,11 @@ package fr.skytasul.quests.api.options; -import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.objects.QuestObject; @@ -14,10 +13,11 @@ import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.gui.creation.FinishGUI; -public abstract class QuestOptionObject<T extends QuestObject, C extends QuestObjectCreator<T>> extends QuestOption<List<T>> { +public abstract class QuestOptionObject<T extends QuestObject, C extends QuestObjectCreator<T>, L extends List<T>> + extends QuestOption<L> { @Override public void attach(Quest quest) { @@ -32,7 +32,7 @@ public void detach() { } @Override - public void setValue(List<T> value) { + public void setValue(L value) { if (getValue() != null && getAttachedQuest() != null) detachObjects(); super.setValue(value); if (getValue() != null && getAttachedQuest() != null) attachObjects(); @@ -57,12 +57,7 @@ public Object save() { @Override public void load(ConfigurationSection config, String key) { - getValue().addAll(QuestObject.deserializeList(config.getMapList(key), this::deserialize)); - } - - @Override - public List<T> cloneValue(List<T> value) { - return new ArrayList<>(value); + getValue().addAll(SerializableObject.deserializeList(config.getMapList(key), this::deserialize)); } protected abstract T deserialize(Map<String, Object> map); @@ -71,6 +66,13 @@ public List<T> cloneValue(List<T> value) { protected abstract QuestObjectsRegistry<T, C> getObjectsRegistry(); + protected abstract L instanciate(Collection<T> objects); + + @Override + public @Nullable L cloneValue(@Nullable L value) { + return instanciate(value); + } + protected String[] getLore() { String count = "§7" + getSizeString(getValue().size()); if (getItemDescription() == null) return new String[] { count }; @@ -83,12 +85,12 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { + public void click(QuestCreationGuiClickEvent event) { getObjectsRegistry().createGUI(QuestObjectLocation.QUEST, objects -> { - setValue(objects); - ItemUtils.lore(item, getLore()); - gui.reopen(p); - }, getValue()).open(p); + setValue(instanciate(objects)); + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); + }, getValue()).open(event.getPlayer()); } public abstract XMaterial getItemMaterial(); diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java index dc21ca69..3e6f727a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java @@ -1,21 +1,15 @@ package fr.skytasul.quests.api.options; +import java.util.Collection; import java.util.Map; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.RewardCreator; +import fr.skytasul.quests.api.rewards.RewardList; -public abstract class QuestOptionRewards extends QuestOptionObject<AbstractReward, RewardCreator> { - - @Override - protected void attachObject(AbstractReward object) { - super.attachObject(object); - if (object.isAsync()) attachedAsyncReward(object); - } - - protected abstract void attachedAsyncReward(AbstractReward reward); +public abstract class QuestOptionRewards extends QuestOptionObject<AbstractReward, RewardCreator, RewardList> { @Override protected AbstractReward deserialize(Map<String, Object> map) { @@ -29,7 +23,12 @@ protected String getSizeString(int size) { @Override protected QuestObjectsRegistry<AbstractReward, RewardCreator> getObjectsRegistry() { - return QuestsAPI.getRewards(); + return QuestsAPI.getAPI().getRewards(); } + @Override + protected RewardList instanciate(Collection<AbstractReward> objects) { + return new RewardList(objects); + } + } \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java index 341280b6..b05558f1 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java @@ -6,13 +6,12 @@ import java.util.stream.Collectors; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.TextListEditor; import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; public abstract class QuestOptionString extends QuestOption<String> { @@ -48,25 +47,24 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - sendIndication(p); + public void click(QuestCreationGuiClickEvent event) { + sendIndication(event.getPlayer()); if (isMultiline()) { List<String> splitText = getValue() == null ? new ArrayList<>() : new ArrayList<>(Arrays.asList(getValue().split("\\{nl\\}"))); - new TextListEditor(p, list -> { + new TextListEditor(event.getPlayer(), list -> { setValue(list.stream().collect(Collectors.joining("{nl}"))); - ItemUtils.lore(item, getLore()); - gui.reopen(p); + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); }, splitText).start(); }else { - new TextEditor<String>(p, () -> gui.reopen(p), obj -> { - setValue(obj); - ItemUtils.lore(item, getLore()); - gui.reopen(p); - }, () -> { - resetValue(); - ItemUtils.lore(item, getLore()); - gui.reopen(p); - }).start(); + new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { + if (obj == null) + resetValue(); + else + setValue(obj); + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); + }).passNullIntoEndConsumer().start(); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java b/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java index ac9799ee..f56e6f99 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java @@ -5,10 +5,9 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import fr.skytasul.quests.api.options.UpdatableOptionSet.Updatable; @SuppressWarnings ("rawtypes") -public abstract class UpdatableOptionSet<U extends Updatable> implements OptionSet { +public class UpdatableOptionSet implements OptionSet { private Map<Class<? extends QuestOption<?>>, OptionWrapper> options = new HashMap<>(); @@ -17,8 +16,8 @@ public Iterator<QuestOption> iterator() { return options.values().stream().map(wrapper -> wrapper.option).iterator(); } - protected void addOption(QuestOption option, U updatable) { - options.put((Class<? extends QuestOption<?>>) option.getClass(), new OptionWrapper(option, updatable)); + public void addOption(QuestOption option, Runnable update) { + options.put((Class<? extends QuestOption<?>>) option.getClass(), new OptionWrapper(option, update)); } @Override @@ -31,32 +30,29 @@ public boolean hasOption(Class<? extends QuestOption<?>> clazz) { return options.containsKey(clazz); } - protected OptionWrapper getWrapper(Class<? extends QuestOption<?>> optionClass) { + public OptionWrapper getWrapper(Class<? extends QuestOption<?>> optionClass) { return options.get(optionClass); } - protected void calculateDependencies() { + public void calculateDependencies() { + options.values().forEach(wrapper -> wrapper.dependent.clear()); for (OptionWrapper wrapper : options.values()) { for (Class<? extends QuestOption<?>> requiredOptionClass : wrapper.option.getRequiredQuestOptions()) { - options.get(requiredOptionClass).dependent.add(wrapper.updatable); + options.get(requiredOptionClass).dependent.add(wrapper.update); } } } public class OptionWrapper { public final QuestOption option; - public final U updatable; - public final List<U> dependent = new ArrayList<>(); + public final Runnable update; + public final List<Runnable> dependent = new ArrayList<>(); - public OptionWrapper(QuestOption option, U updatable) { + public OptionWrapper(QuestOption option, Runnable update) { this.option = option; - this.updatable = updatable; - option.setValueUpdaterListener(() -> dependent.forEach(U::update)); + this.update = update; + option.setValueUpdaterListener(() -> dependent.forEach(Runnable::run)); } } - public interface Updatable { - void update(); - } - } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java index 0cab02be..59d36b21 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/description/QuestDescriptionProvider.java @@ -9,7 +9,7 @@ public interface QuestDescriptionProvider { public static final Comparator<QuestDescriptionProvider> COMPARATOR = Comparator.comparingDouble(QuestDescriptionProvider::getDescriptionPriority); - @NotNull + @Nullable List<@Nullable String> provideDescription(@NotNull QuestDescriptionContext context); @NotNull 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 0f6b52b0..82721a5d 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 @@ -7,7 +7,7 @@ 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.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementList; public interface QuestPool { @@ -27,7 +27,7 @@ public interface QuestPool { boolean doAvoidDuplicates(); - List<AbstractRequirement> getRequirements(); + RequirementList getRequirements(); List<Quest> getQuests(); diff --git a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java index c313d4a4..5fc3b23a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java @@ -1,17 +1,15 @@ package fr.skytasul.quests.api.pools; import java.util.Collection; -import java.util.List; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnmodifiableView; -import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementList; public interface QuestPoolsManager { public @NotNull QuestPool createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, int maxQuests, - int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, - @NotNull List<AbstractRequirement> requirements); + int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements); public void removePool(int id); diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGui.java b/api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGui.java new file mode 100644 index 00000000..f097a1c8 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGui.java @@ -0,0 +1,15 @@ +package fr.skytasul.quests.api.quests.creation; + +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.options.OptionSet; +import fr.skytasul.quests.api.options.QuestOption; + +public interface QuestCreationGui extends Gui { + + void updateOptionItem(@NotNull QuestOption<?> option); + + @NotNull + OptionSet getOptionSet(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGuiClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGuiClickEvent.java new file mode 100644 index 00000000..9ff2f7a6 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/quests/creation/QuestCreationGuiClickEvent.java @@ -0,0 +1,27 @@ +package fr.skytasul.quests.api.quests.creation; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.gui.GuiClickEvent; + +public class QuestCreationGuiClickEvent extends GuiClickEvent { + + public QuestCreationGuiClickEvent(@NotNull Player player, @NotNull QuestCreationGui gui, @Nullable ItemStack clicked, + @Nullable ItemStack cursor, int slot, @NotNull ClickType click) { + super(player, gui, clicked, cursor, slot, click); + } + + @Override + public void setCancelled(boolean cancelled) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull QuestCreationGui getGui() { + return (@NotNull QuestCreationGui) super.getGui(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java b/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java new file mode 100644 index 00000000..224f3cd0 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java @@ -0,0 +1,57 @@ +package fr.skytasul.quests.api.requirements; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.serializable.SerializableObject; + +public class RequirementList extends ArrayList<@NotNull AbstractRequirement> { + + private static final long serialVersionUID = 5568034962195448395L; + + public RequirementList() {} + + public RequirementList(@NotNull Collection<@NotNull AbstractRequirement> requirements) { + super(requirements); + } + + public boolean testPlayer(@NotNull Player p, boolean message) { + for (AbstractRequirement requirement : this) { + try { + if (!requirement.test(p)) { + if (message && !requirement.sendReason(p)) + continue; // means a reason has not yet been sent + return false; + } + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "Cannot test requirement " + requirement.getClass().getSimpleName() + " for player " + p.getName(), + ex); + return false; + } + } + return true; + } + + public void attachQuest(@NotNull Quest quest) { + forEach(requirement -> requirement.attach(quest)); + } + + public void detachQuest() { + forEach(requirement -> requirement.detach()); + } + + public @NotNull List<Map<String, Object>> serialize() { + return SerializableObject.serializeList(this); + } + + public static RequirementList deserialize(@NotNull List<Map<?, ?>> mapList) { + return new RequirementList(SerializableObject.deserializeList(mapList, AbstractRequirement::deserialize)); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java b/api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java new file mode 100644 index 00000000..340d46f5 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java @@ -0,0 +1,69 @@ +package fr.skytasul.quests.api.rewards; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.serializable.SerializableObject; + +public class RewardList extends ArrayList<@NotNull AbstractReward> { + + private static final long serialVersionUID = 1238520030299575535L; + + public RewardList() {} + + public RewardList(@NotNull Collection<@NotNull AbstractReward> rewards) { + super(rewards); + } + + public List<String> giveRewards(@NotNull Player p) throws InterruptingBranchException { + InterruptingBranchException interrupting = null; + + List<String> msg = new ArrayList<>(); + for (AbstractReward rew : this) { + try { + List<String> messages = rew.give(p); + if (messages != null) + msg.addAll(messages); + } catch (InterruptingBranchException ex) { + if (interrupting != null) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Interrupting the same branch via rewards twice!"); + } else { + interrupting = ex; + } + } catch (Throwable e) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("Error when giving reward " + rew.getName() + " to " + p.getName(), e); + } + } + + if (interrupting != null) + throw interrupting; + return msg; + } + + public void attachQuest(@NotNull Quest quest) { + forEach(reward -> reward.attach(quest)); + } + + public void detachQuest() { + forEach(reward -> reward.detach()); + } + + public boolean hasAsync() { + return stream().anyMatch(AbstractReward::isAsync); + } + + public @NotNull List<Map<String, Object>> serialize() { + return SerializableObject.serializeList(this); + } + + public static RewardList deserialize(@NotNull List<Map<?, ?>> mapList) { + return new RewardList(SerializableObject.deserializeList(mapList, AbstractReward::deserialize)); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index eed576f4..2c64e262 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -1,6 +1,5 @@ package fr.skytasul.quests.api.stages; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -11,14 +10,13 @@ import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.quests.branches.QuestBranch; -import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.requirements.RequirementList; +import fr.skytasul.quests.api.rewards.RewardList; import fr.skytasul.quests.api.serializable.SerializableCreator; -import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.api.stages.options.StageOption; -import fr.skytasul.quests.api.utils.Utils; public abstract class AbstractStage { @@ -26,11 +24,10 @@ public abstract class AbstractStage { private @Nullable String startMessage = null; private @Nullable String customText = null; - private @NotNull List<@NotNull AbstractReward> rewards = new ArrayList<>(); - private @NotNull List<@NotNull AbstractRequirement> validationRequirements = new ArrayList<>(); + private @NotNull RewardList rewards = new RewardList(); + private @NotNull RequirementList validationRequirements = new RequirementList(); private @NotNull List<@NotNull StageOption> options; - protected boolean asyncEnd = false; protected AbstractStage(@NotNull StageController controller) { this.controller = controller; @@ -55,23 +52,22 @@ public void setStartMessage(@Nullable String text) { return startMessage; } - public @NotNull List<@NotNull AbstractReward> getRewards() { + public @NotNull RewardList getRewards() { return rewards; } - public void setRewards(@NotNull List<@NotNull AbstractReward> rewards) { + public void setRewards(@NotNull RewardList rewards) { this.rewards = rewards; - rewards.forEach(reward -> reward.attach(getQuest())); - checkAsync(); + rewards.attachQuest(getQuest()); } - public @NotNull List<@NotNull AbstractRequirement> getValidationRequirements() { + public @NotNull RequirementList getValidationRequirements() { return validationRequirements; } - public void setValidationRequirements(@NotNull List<@NotNull AbstractRequirement> validationRequirements) { + public void setValidationRequirements(@NotNull RequirementList validationRequirements) { this.validationRequirements = validationRequirements; - validationRequirements.forEach(requirement -> requirement.attach(getQuest())); + validationRequirements.attachQuest(getQuest()); } public @NotNull List<@NotNull StageOption> getOptions() { @@ -95,16 +91,7 @@ public boolean sendStartMessage(){ } public boolean hasAsyncEnd() { - return asyncEnd; - } - - private void checkAsync() { - for (AbstractReward rew : rewards) { - if (rew.isAsync()) { - asyncEnd = true; - break; - } - } + return rewards.hasAsync(); } protected boolean canUpdate(@NotNull Player player) { @@ -112,7 +99,7 @@ protected boolean canUpdate(@NotNull Player player) { } protected boolean canUpdate(@NotNull Player player, boolean msg) { - return Utils.testRequirements(player, validationRequirements, msg); + return validationRequirements.testPlayer(player, msg); } /** @@ -131,7 +118,7 @@ protected final void finishStage(@NotNull Player player) { * @see QuestBranch#hasStageLaunched(PlayerAccount, AbstractStage) */ protected final boolean hasStarted(@NotNull Player player) { - return controller.hasStarted(player); + return controller.hasStarted(PlayersManager.getPlayerAccount(player)); } /** @@ -179,6 +166,10 @@ public void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullabl controller.updateObjective(p, dataKey, dataValue); } + protected <T> @Nullable T getData(@NotNull Player p, @NotNull String dataKey) { + return getData(PlayersManager.getPlayerAccount(p), dataKey); + } + protected <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { return controller.getData(acc, dataKey); } @@ -187,8 +178,8 @@ public void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullabl * Called when the stage has to be unloaded */ public void unload(){ - rewards.forEach(AbstractReward::detach); - validationRequirements.forEach(AbstractRequirement::detach); + rewards.detachQuest(); + validationRequirements.detachQuest(); } /** @@ -205,8 +196,10 @@ public final void save(@NotNull ConfigurationSection section) { section.set("customText", customText); if (startMessage != null) section.set("text", startMessage); - if (!rewards.isEmpty()) section.set("rewards", SerializableObject.serializeList(rewards)); - if (!validationRequirements.isEmpty()) section.set("requirements", SerializableObject.serializeList(validationRequirements)); + if (!rewards.isEmpty()) + section.set("rewards", rewards.serialize()); + if (!validationRequirements.isEmpty()) + section.set("requirements", validationRequirements.serialize()); options.stream().filter(StageOption::shouldSave).forEach(option -> option.save(section.createSection("options." + option.getCreator().getID()))); } @@ -217,10 +210,9 @@ public final void load(@NotNull ConfigurationSection section) { if (section.contains("customText")) customText = section.getString("customText"); if (section.contains("rewards")) - setRewards(SerializableObject.deserializeList(section.getMapList("rewards"), AbstractReward::deserialize)); + setRewards(RewardList.deserialize(section.getMapList("rewards"))); if (section.contains("requirements")) - setValidationRequirements(SerializableObject.deserializeList(section.getMapList("requirements"), - AbstractRequirement::deserialize)); + setValidationRequirements(RequirementList.deserialize(section.getMapList("requirements"))); if (section.contains("options")) { ConfigurationSection optionsSection = section.getConfigurationSection("options"); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java index 86d4230d..c38e3738 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java @@ -5,7 +5,6 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.branches.QuestBranch; public interface StageController { @@ -20,10 +19,6 @@ public interface StageController { public boolean hasStarted(@NotNull PlayerAccount acc); - public default boolean hasStarted(@NotNull Player player) { - return hasStarted(PlayersManager.getPlayerAccount(player)); - } - public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nullable Object dataValue); public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java index 3a504f6e..9f0b438c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java @@ -1,11 +1,12 @@ package fr.skytasul.quests.api.stages; -import javax.sound.sampled.Line; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.serializable.SerializableRegistry; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.options.StageOption; public class StageType<T extends AbstractStage> { @@ -73,7 +74,7 @@ public StageType(@NotNull String id, @NotNull Class<T> clazz, @NotNull String na public static interface StageCreationSupplier<T extends AbstractStage> { @NotNull - StageCreation<T> supply(@NotNull Line line, boolean endingStage); + StageCreation<T> supply(@NotNull StageCreationContext<T> context); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java similarity index 51% rename from api/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java rename to api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java index 87b40f19..d945f86f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageCreation.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java @@ -1,11 +1,12 @@ -package fr.skytasul.quests.api.stages; +package fr.skytasul.quests.api.stages.creation; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import javax.sound.sampled.Line; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; @@ -13,16 +14,25 @@ import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.rewards.RewardList; import fr.skytasul.quests.api.serializable.SerializableCreator; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.options.StageOption; -import fr.skytasul.quests.gui.creation.stages.StagesGUI; public abstract class StageCreation<T extends AbstractStage> { - - protected final Line line; - private final boolean ending; - private StageType<T> type; + + private static final ItemStack ENDING_ITEM = ItemUtils.item(XMaterial.BAKED_POTATO, Lang.ending.toString()); + private static final ItemStack DESCRITPION_MESSAGE_ITEM = + ItemUtils.item(XMaterial.OAK_SIGN, Lang.descMessage.toString()); + private static final ItemStack START_MESSAGE_ITEM = ItemUtils.item(XMaterial.FEATHER, Lang.startMsg.toString()); + private static final ItemStack VALIDATION_REQUIREMENTS_ITEM = + ItemUtils.item(XMaterial.NETHER_STAR, Lang.validationRequirements.toString(), + QuestOption.formatDescription(Lang.validationRequirementsLore.toString())); + + protected final @NotNull StageCreationContext<T> context; private List<AbstractReward> rewards; private List<AbstractRequirement> requirements; @@ -31,66 +41,16 @@ public abstract class StageCreation<T extends AbstractStage> { private String customDescription, startMessage; - private StagesGUI leadingBranch; - - protected StageCreation(Line line, boolean ending) { - this.line = line; - this.ending = ending; - - line.setItem(1, StagesGUI.ending.clone(), (p, item) -> QuestsAPI.getRewards().createGUI(QuestObjectLocation.STAGE, rewards -> { - setRewards(rewards); - reopenGUI(player, true); - }, rewards).open(player)); - - line.setItem(2, StagesGUI.descMessage.clone(), (p, item) -> { - Lang.DESC_MESSAGE.send(player); - new TextEditor<String>(player, () -> reopenGUI(player, false), obj -> { - setCustomDescription(obj); - reopenGUI(player, false); - }).passNullIntoEndConsumer().start(); - }); - - line.setItem(3, StagesGUI.startMessage.clone(), (p, item) -> { - Lang.START_TEXT.send(player); - new TextEditor<String>(player, () -> reopenGUI(player, false), obj -> { - setStartMessage(obj); - reopenGUI(player, false); - }).passNullIntoEndConsumer().start(); - }); - - line.setItem(4, StagesGUI.validationRequirements.clone(), (p, item) -> { - QuestsAPI.getRequirements().createGUI(QuestObjectLocation.STAGE, requirements -> { - setRequirements(requirements); - reopenGUI(player, true); - }, requirements).open(player); - }); - } - - public StageType<T> getType() { - return type; - } - - public Line getLine() { - return line; - } - - public void reopenGUI(Player p, boolean reImplement) { - line.gui.reopen(p, reImplement); - } - - public void remove() { - line.gui.deleteStageLine(line); + protected StageCreation(@NotNull StageCreationContext<T> context) { + this.context = context; } - - protected Runnable removeAndReopen(Player p, boolean reImplement) { - return () -> { - remove(); - reopenGUI(p, reImplement); - }; + + public @NotNull StageCreationContext<T> getCreationContext() { + return context; } - public boolean isEndingStage() { - return ending; + public @NotNull StageGuiLine getLine() { + return context.getLine(); } public List<AbstractReward> getRewards() { @@ -99,7 +59,7 @@ public List<AbstractReward> getRewards() { public void setRewards(List<AbstractReward> rewards) { this.rewards = rewards; - line.editItem(1, ItemUtils.lore(line.getItem(1), QuestOption.formatDescription(Lang.rewards.format(rewards.size())))); + getLine().refreshItemLore(1, QuestOption.formatDescription(Lang.rewards.format(rewards.size()))); } public List<AbstractRequirement> getRequirements() { @@ -107,7 +67,7 @@ public List<AbstractRequirement> getRequirements() { } public void setRequirements(List<AbstractRequirement> requirements) { - line.editItem(4, ItemUtils.lore(line.getItem(4), QuestOption.formatDescription(Lang.requirements.format(requirements.size())))); + getLine().refreshItemLore(4, QuestOption.formatDescription(Lang.requirements.format(requirements.size()))); this.requirements = requirements; } @@ -117,7 +77,7 @@ public String getCustomDescription() { public void setCustomDescription(String customDescription) { this.customDescription = customDescription; - line.editItem(2, ItemUtils.lore(line.getItem(2), QuestOption.formatNullableValue(customDescription))); + getLine().refreshItemLore(2, QuestOption.formatNullableValue(customDescription)); } public String getStartMessage() { @@ -126,21 +86,40 @@ public String getStartMessage() { public void setStartMessage(String startMessage) { this.startMessage = startMessage; - line.editItem(3, ItemUtils.lore(line.getItem(3), QuestOption.formatNullableValue(startMessage))); - } - - public StagesGUI getLeadingBranch() { - return leadingBranch; - } - - public void setLeadingBranch(StagesGUI leadingBranch) { - this.leadingBranch = leadingBranch; + getLine().refreshItemLore(3, QuestOption.formatNullableValue(startMessage)); } - public final void setup(@NotNull StageType<T> type) { - this.type = type; + public void setupLine(@NotNull StageGuiLine line) { + line.setItem(1, ENDING_ITEM.clone(), + event -> QuestsAPI.getAPI().getRewards().createGUI(QuestObjectLocation.STAGE, rewards -> { + setRewards(rewards); + event.reopen(); + }, rewards).open(event.getPlayer())); + + line.setItem(2, DESCRITPION_MESSAGE_ITEM.clone(), event -> { + Lang.DESC_MESSAGE.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { + setCustomDescription(obj); + event.reopen(); + }).passNullIntoEndConsumer().start(); + }); + + line.setItem(3, START_MESSAGE_ITEM.clone(), event -> { + Lang.START_TEXT.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { + setStartMessage(obj); + event.reopen(); + }).passNullIntoEndConsumer().start(); + }); + + line.setItem(4, VALIDATION_REQUIREMENTS_ITEM.clone(), event -> { + QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.STAGE, requirements -> { + setRequirements(requirements); + event.reopen(); + }, requirements).open(event.getPlayer()); + }); } - + /** * Called when stage item clicked * @param p player who click on the item @@ -151,7 +130,8 @@ public void start(@NotNull Player p) { setCustomDescription(null); setStartMessage(null); - options = type.getOptionsRegistry().getCreators().stream().map(SerializableCreator::newObject).collect(Collectors.toList()); + options = context.getType().getOptionsRegistry().getCreators().stream().map(SerializableCreator::newObject) + .collect(Collectors.toList()); options.forEach(option -> option.startEdition(this)); } @@ -169,16 +149,17 @@ public void edit(@NotNull T stage) { options.forEach(option -> option.startEdition(this)); } + public final @NotNull T finish(@NotNull StageController branch) { T stage = finishStage(branch); - stage.setRewards(rewards); - stage.setValidationRequirements(requirements); + stage.setRewards(new RewardList(rewards)); + stage.setValidationRequirements(new RequirementList(requirements)); stage.setCustomText(customDescription); stage.setStartMessage(startMessage); stage.setOptions((List) options); return stage; } - + /** * Called when quest creation finished * @param branch quest created diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreationContext.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreationContext.java new file mode 100644 index 00000000..c866d036 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreationContext.java @@ -0,0 +1,26 @@ +package fr.skytasul.quests.api.stages.creation; + +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageType; + +public interface StageCreationContext<T extends AbstractStage> { + + @NotNull + StageGuiLine getLine(); + + @NotNull + StageType<T> getType(); + + boolean isEndingStage(); + + @NotNull + StageCreation<T> getCreation(); + + void remove(); + + void reopenGui(); + + void removeAndReopenGui(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickEvent.java new file mode 100644 index 00000000..a289fe13 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickEvent.java @@ -0,0 +1,47 @@ +package fr.skytasul.quests.api.stages.creation; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class StageGuiClickEvent { + + private final @NotNull Player player; + private final @NotNull ItemStack clicked; + private final @NotNull ClickType click; + private final @NotNull StageCreationContext<?> context; + + public StageGuiClickEvent(@NotNull Player player, @NotNull ItemStack clicked, @NotNull ClickType click, + @NotNull StageCreationContext<?> context) { + this.player = player; + this.clicked = clicked; + this.click = click; + this.context = context; + } + + public @NotNull Player getPlayer() { + return player; + } + + public @NotNull ItemStack getClicked() { + return clicked; + } + + public @NotNull ClickType getClick() { + return click; + } + + public void reopen() { + context.reopenGui(); + } + + public void remove() { + context.remove(); + } + + public void removeAndReopen() { + context.removeAndReopenGui(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickHandler.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickHandler.java new file mode 100644 index 00000000..95be3fe1 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiClickHandler.java @@ -0,0 +1,10 @@ +package fr.skytasul.quests.api.stages.creation; + +import org.jetbrains.annotations.NotNull; + +@FunctionalInterface +public interface StageGuiClickHandler { + + void onClick(@NotNull StageGuiClickEvent event); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java new file mode 100644 index 00000000..fcbf6556 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java @@ -0,0 +1,44 @@ +package fr.skytasul.quests.api.stages.creation; + +import java.util.List; +import java.util.function.UnaryOperator; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.gui.ItemUtils; + +public interface StageGuiLine { + + @Nullable + ItemStack getItem(int slot); + + void setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHandler click); + + void refreshItem(int slot, @NotNull ItemStack item); + + default void refreshItem(int slot, UnaryOperator<ItemStack> consumer) { + refreshItem(slot, consumer.apply(getItem(slot))); + } + + default void refreshItemLore(int slot, String... lore) { + refreshItem(slot, ItemUtils.lore(getItem(slot), lore)); + } + + default void refreshItemLore(int slot, List<String> lore) { + refreshItem(slot, ItemUtils.lore(getItem(slot), lore)); + } + + default void refreshItemName(int slot, String name) { + refreshItem(slot, ItemUtils.name(getItem(slot), name)); + } + + void removeItem(int slot); + + int getPage(); + + void setPage(int page); + + @Nullable + StageGuiClickHandler click(int rawSlot); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java index a412bea8..e0f5a7e1 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOption.java @@ -4,8 +4,8 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.StageHandler; +import fr.skytasul.quests.api.stages.creation.StageCreation; public abstract class StageOption<T extends AbstractStage> extends SerializableObject implements StageHandler { diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java index f27a28b2..b1ed48a9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java @@ -3,15 +3,15 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import javax.sound.sampled.Line; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; @@ -49,14 +49,19 @@ public abstract static class AbstractCreator<T extends AbstractCountableBlockSta protected List<MutableCountableObject<BQBlock>> blocks; - protected AbstractCreator(Line line, boolean ending) { - super(line, ending); + protected AbstractCreator(@NotNull StageCreationContext<T> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(getBlocksSlot(), getBlocksItem(), (p, item) -> { + line.setItem(getBlocksSlot(), getBlocksItem(), event -> { new BlocksGUI(blocks, obj -> { setBlocks(obj); - reopenGUI(player, true); - }).open(player); + event.reopen(); + }).open(event.getPlayer()); }); } @@ -72,7 +77,7 @@ protected int getBlocksSlot() { public void setBlocks(List<MutableCountableObject<BQBlock>> blocks) { this.blocks = blocks; - line.editItem(getBlocksSlot(), ItemUtils.lore(line.getItem(getBlocksSlot()), Lang.optionValue.format(blocks.size() + " blocks"))); + getLine().refreshItemLore(getBlocksSlot(), Lang.optionValue.format(blocks.size() + " blocks")); } @Override @@ -80,7 +85,7 @@ public void start(Player p) { super.start(p); new BlocksGUI(Collections.emptyList(), obj -> { setBlocks(obj); - reopenGUI(player, true); + context.reopenGui(); }).open(p); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index 0407c441..42b622ce 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -18,11 +18,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; -import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.BossBarManager.BQBossBar; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; @@ -92,7 +93,8 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { newRemaining.put(uuid, amount); dataMap.put(uuid.toString(), amount); }); - updateObjective(acc, acc.getPlayer(), "remaining", dataMap); + if (acc.isCurrent()) + updateObjective(acc.getPlayer(), "remaining", dataMap); return newRemaining; } else if (object instanceof String) { // datas stored as string @@ -102,28 +104,28 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { throw new UnsupportedOperationException(object.getClass().getName()); } - protected void updatePlayerRemaining(@NotNull PlayerAccount acc, @NotNull Player player, - @NotNull Map<@NotNull UUID, @NotNull Integer> remaining) { - updateObjective(acc, player, "remaining", remaining.entrySet().stream() + protected void updatePlayerRemaining(@NotNull Player player, @NotNull Map<@NotNull UUID, @NotNull Integer> remaining) { + updateObjective(player, "remaining", remaining.entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toString(), Entry::getValue))); } protected void calculateSize() { cachedSize = objects.stream().mapToInt(CountableObject::getAmount).sum(); - barsEnabled = QuestsConfiguration.showMobsProgressBar() && cachedSize > 0; + barsEnabled = QuestsConfiguration.getConfig().getQuestsConfig().mobsProgressBar() && cachedSize > 0; } @Override - protected @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull Source source) { + public @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { return Utils.descriptionLines(source, buildRemainingArray(acc, source)); } @Override - protected @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull Source source) { - return new Supplier[] { () -> Utils.descriptionLines(source, buildRemainingArray(acc, source)) }; + public @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, + @NotNull DescriptionSource source) { + return new Supplier[] {() -> Utils.descriptionLines(source, buildRemainingArray(acc, source))}; } - private @NotNull String @NotNull [] buildRemainingArray(@NotNull PlayerAccount acc, @NotNull Source source) { + private @NotNull String @NotNull [] buildRemainingArray(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { Map<UUID, Integer> playerAmounts = getPlayerRemainings(acc, true); if (playerAmounts == null) return new String[] { "§4§lerror" }; String[] elements = new String[playerAmounts.size()]; @@ -156,10 +158,11 @@ public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull St * @param amount amount completed * @return <code>true</code> if there is no need to call this method again in the same game tick. */ - public boolean event(@NotNull PlayerAccount acc, @NotNull Player p, @UnknownNullability Object object, int amount) { + public boolean event(@NotNull Player p, @UnknownNullability Object object, int amount) { if (amount < 0) throw new IllegalArgumentException("Event amount must be positive (" + amount + ")"); if (!canUpdate(p)) return true; + PlayerAccount acc = PlayersManager.getPlayerAccount(p); for (CountableObject<T> countableObject : objects) { if (objectApplies(countableObject.getObject(), object)) { Map<UUID, Integer> playerAmounts = getPlayerRemainings(acc, true); @@ -185,7 +188,7 @@ public boolean event(@NotNull PlayerAccount acc, @NotNull Player p, @UnknownNull }else bar.update(playerAmounts.values().stream().mapToInt(Integer::intValue).sum()); } - updatePlayerRemaining(acc, p, playerAmounts); + updatePlayerRemaining(p, playerAmounts); return false; } } @@ -329,12 +332,15 @@ public void update(int amount) { } private void timer() { - if (QuestsConfiguration.getProgressBarTimeout() <= 0) return; - if (timer != null) timer.cancel(); + if (QuestsConfiguration.getConfig().getQuestsConfig().progressBarTimeoutSeconds() <= 0) + return; + if (timer != null) + timer.cancel(); + timer = Bukkit.getScheduler().runTaskLater(QuestsPlugin.getPlugin(), () -> { - bar.removePlayer(player); + bar.removePlayer(p); timer = null; - }, QuestsConfiguration.getProgressBarTimeout() * 20L); + }, QuestsConfiguration.getConfig().getQuestsConfig().progressBarTimeoutSeconds() * 20L); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index 344a9713..3e29c7fd 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -8,14 +8,13 @@ import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Supplier; -import javax.sound.sampled.Line; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; @@ -26,12 +25,13 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.mobs.EntityTypeGUI; @LocatableType (types = LocatedType.ENTITY) public abstract class AbstractEntityStage extends AbstractStage implements Locatable.MultipleLocatable { @@ -81,7 +81,10 @@ protected void serialize(@NotNull ConfigurationSection section) { Integer playerAmount = getPlayerAmount(acc); if (playerAmount == null) return "§cerror: no datas"; - return Utils.getStringFromNameAndAmount(entity == null ? Lang.EntityTypeAny.toString() : MinecraftNames.getEntityName(entity), QuestsConfiguration.getItemAmountColor(), playerAmount, amount, false); + return Utils.getStringFromNameAndAmount( + entity == null ? Lang.EntityTypeAny.toString() : MinecraftNames.getEntityName(entity), + QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), playerAmount, amount, + false); } @Override @@ -117,34 +120,38 @@ public abstract static class AbstractCreator<T extends AbstractEntityStage> exte protected EntityType entity = null; protected int amount = 1; - protected AbstractCreator(Line line, boolean ending) { - super(line, ending); + protected AbstractCreator(@NotNull StageCreationContext<T> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(6, ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, Lang.changeEntityType.toString()), (p, item) -> { + line.setItem(6, ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, Lang.changeEntityType.toString()), event -> { new EntityTypeGUI(x -> { setEntity(x); - reopenGUI(player, true); - }, x -> x == null ? canBeAnyEntity() : canUseEntity(x)).open(player); + event.reopen(); + }, x -> x == null ? canBeAnyEntity() : canUseEntity(x)).open(event.getPlayer()); }); - line.setItem(7, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1)), (p, item) -> { - new TextEditor<>(player, () -> { - reopenGUI(player, false); - }, x -> { + line.setItem(7, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1)), event -> { + new TextEditor<>(event.getPlayer(), event::reopen, x -> { setAmount(x); - reopenGUI(player, false); + event.reopen(); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); }); } public void setEntity(EntityType entity) { this.entity = entity; - line.editItem(6, ItemUtils.lore(line.getItem(6), Lang.optionValue.format(entity == null ? Lang.EntityTypeAny.toString() : entity.name()))); + getLine().refreshItemLore(6, + Lang.optionValue.format(entity == null ? Lang.EntityTypeAny.toString() : entity.name())); } public void setAmount(int amount) { this.amount = amount; - line.editItem(7, ItemUtils.name(line.getItem(7), Lang.Amount.format(amount))); + getLine().refreshItemName(7, Lang.Amount.format(amount)); } @Override diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java index c8f330c7..c3943565 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; -import javax.sound.sampled.Line; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -15,9 +14,10 @@ import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.creation.ItemsGUI; @@ -82,20 +82,25 @@ public abstract static class Creator<T extends AbstractItemStage> extends StageC private @NotNull List<ItemStack> items; private @NotNull ItemComparisonMap comparisons = new ItemComparisonMap(); - protected Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<T> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(6, getEditItem().clone(), (p, item) -> { + line.setItem(6, getEditItem().clone(), event -> { new ItemsGUI(items -> { setItems(items); reopenGUI(player, true); - }, items).open(player); + }, items).open(event.getPlayer()); }); - line.setItem(7, stageComparison.clone(), (p, item) -> { + line.setItem(7, stageComparison.clone(), event -> { new ItemComparisonGUI(comparisons, () -> { setComparisons(comparisons); reopenGUI(player, true); - }).open(player); + }).open(event.getPlayer()); }); } @@ -103,12 +108,13 @@ protected Creator(Line line, boolean ending) { public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); - line.editItem(6, ItemUtils.lore(line.getItem(6), Lang.optionValue.format(Lang.AmountItems.format(this.items.size())))); + getLine().refreshItemLore(6, Lang.optionValue.format(Lang.AmountItems.format(this.items.size()))); } public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; - line.editItem(7, ItemUtils.lore(line.getItem(7), Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size())))); + getLine().refreshItemLore(7, + Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size()))); } @Override @@ -116,7 +122,7 @@ public void start(Player p) { super.start(p); new ItemsGUI(items -> { setItems(items); - reopenGUI(player, true); + context.reopenGui(); }, Collections.emptyList()).open(p); } @@ -132,18 +138,18 @@ public void edit(T stage) { } @Override - public final T finishStage(QuestBranch branch) { + public final T finishStage(StageController controller) { List<CountableObject<ItemStack>> itemsMap = new ArrayList<>(); for (int i = 0; i < items.size(); i++) { ItemStack item = items.get(i); int amount = item.getAmount(); item.setAmount(1); - itemsMap.add(CountableObject.open(new UUID(item.hashCode(), 2478), item, amount)); + itemsMap.add(CountableObject.create(new UUID(item.hashCode(), 2478), item, amount)); } - return finishStage(branch, itemsMap, comparisons); + return finishStage(controller, itemsMap, comparisons); } - protected abstract T finishStage(@NotNull QuestBranch branch, + protected abstract T finishStage(@NotNull StageController controller, @NotNull List<@NotNull CountableObject<ItemStack>> items, @NotNull ItemComparisonMap comparisons); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java index 33ddf0dd..a76d5a31 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java @@ -15,7 +15,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.stages.types.Locatable.MultipleLocatable; /** * This interface indicates that an object can provide some locations on demand. @@ -67,7 +66,7 @@ interface PreciseLocatable extends Locatable { * having something else changed in the game state would return the same value. * @return the located object */ - @NotNull + @Nullable Located getLocated(); } @@ -84,7 +83,7 @@ interface MultipleLocatable extends Locatable { * @param fetcher describes the region from where the targets must be found * @return a Spliterator which allows iterating through the targets */ - @NotNull + @Nullable Spliterator<@NotNull Located> getNearbyLocated(@NotNull NearbyFetcher fetcher); /** diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index 3baa85dc..2c65d6a7 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -1,6 +1,5 @@ package fr.skytasul.quests; -import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; import org.bukkit.inventory.ItemStack; @@ -8,17 +7,20 @@ import org.bukkit.inventory.meta.Repairable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOptionCreator; import fr.skytasul.quests.api.requirements.RequirementCreator; +import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.rewards.RewardCreator; +import fr.skytasul.quests.api.rewards.RewardList; import fr.skytasul.quests.api.stages.StageType; import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.options.*; import fr.skytasul.quests.requirements.EquipmentRequirement; import fr.skytasul.quests.requirements.LevelRequirement; @@ -102,7 +104,8 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("description", 12, OptionDescription.class, OptionDescription::new, null)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("customItem", 13, OptionQuestItem.class, - OptionQuestItem::new, QuestsConfigurationImplementation.getItemMaterial(), "customMaterial")); + OptionQuestItem::new, QuestsConfiguration.getConfig().getQuestsConfig().getDefaultQuestItem(), + "customMaterial")); QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("confirmMessage", 15, OptionConfirmMessage.class, OptionConfirmMessage::new, null)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramText", 17, OptionHologramText.class, @@ -116,11 +119,11 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("cancellable", 21, OptionCancellable.class, OptionCancellable::new, true)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("cancelActions", 22, OptionCancelRewards.class, - OptionCancelRewards::new, new ArrayList<>())); + OptionCancelRewards::new, new RewardList())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunch", 25, OptionHologramLaunch.class, - OptionHologramLaunch::new, QuestsConfigurationImplementation.getHoloLaunchItem())); + OptionHologramLaunch::new, QuestsConfigurationImplementation.getConfiguration().getHoloLaunchItem())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunchNo", 26, OptionHologramLaunchNo.class, - OptionHologramLaunchNo::new, QuestsConfigurationImplementation.getHoloLaunchNoItem())); + OptionHologramLaunchNo::new, QuestsConfigurationImplementation.getConfiguration().getHoloLaunchNoItem())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("scoreboard", 27, OptionScoreboardEnabled.class, OptionScoreboardEnabled::new, true)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hideNoRequirements", 28, @@ -130,27 +133,29 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("repeatable", 30, OptionRepeatable.class, OptionRepeatable::new, false, "multiple")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("timer", 31, OptionTimer.class, OptionTimer::new, - QuestsConfigurationImplementation.getTimeBetween())); + QuestsConfiguration.getConfig().getQuestsConfig().getDefaultTimer())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("visibility", 32, OptionVisibility.class, OptionVisibility::new, Arrays.asList(QuestVisibilityLocation.values()), "hid", "hide")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endSound", 34, OptionEndSound.class, - OptionEndSound::new, QuestsConfigurationImplementation.getFinishSound())); + OptionEndSound::new, QuestsConfiguration.getConfig().getQuestsConfig().finishSound())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("firework", 35, OptionFirework.class, - OptionFirework::new, QuestsConfigurationImplementation.getDefaultFirework())); + OptionFirework::new, QuestsConfigurationImplementation.getConfiguration().getDefaultFirework())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("requirements", 36, OptionRequirements.class, - OptionRequirements::new, new ArrayList<>())); + OptionRequirements::new, new RequirementList())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("startRewards", 38, OptionStartRewards.class, - OptionStartRewards::new, new ArrayList<>(), "startRewardsList")); + OptionStartRewards::new, new RewardList(), "startRewardsList")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("startMessage", 39, OptionStartMessage.class, - OptionStartMessage::new, QuestsConfigurationImplementation.getPrefix() + Lang.STARTED_QUEST.toString())); + OptionStartMessage::new, + QuestsConfigurationImplementation.getConfiguration().getPrefix() + Lang.STARTED_QUEST.toString())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("starterNPC", 40, OptionStarterNPC.class, OptionStarterNPC::new, null, "starterID")); QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("startDialog", 41, OptionStartDialog.class, OptionStartDialog::new, null)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endRewards", 43, OptionEndRewards.class, - OptionEndRewards::new, new ArrayList<>(), "rewardsList")); + OptionEndRewards::new, new RewardList(), "rewardsList")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endMsg", 44, OptionEndMessage.class, - OptionEndMessage::new, QuestsConfigurationImplementation.getPrefix() + Lang.FINISHED_BASE.toString())); + OptionEndMessage::new, + QuestsConfigurationImplementation.getConfiguration().getPrefix() + Lang.FINISHED_BASE.toString())); } public static void registerRewards() { diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index af8920dc..3d5ae2c1 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -38,7 +38,7 @@ public void open(@NotNull Player player, @NotNull Gui inventory) { closeWithoutExit(player); QuestsPlugin.getPlugin().getLoggerExpanded() .debug(player.getName() + " has opened inventory " + inventory.getClass().getName() + "."); - inventory.open(player); + inventory.showInternal(player); players.put(player, inventory); } catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded().severe( diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java deleted file mode 100644 index a586c7f0..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/CommandGUI.java +++ /dev/null @@ -1,118 +0,0 @@ -package fr.skytasul.quests.gui.creation; - -import java.util.function.Consumer; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.Gui; -import fr.skytasul.quests.api.gui.Gui.CloseBehavior; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.utils.compatibility.DependenciesManager; -import fr.skytasul.quests.utils.types.Command; - -public class CommandGUI implements Gui { - - private static final int SLOT_COMMAND = 1; - private static final int SLOT_CONSOLE = 3; - private static final int SLOT_PARSE = 4; - private static final int SLOT_DELAY = 5; - private static final int SLOT_FINISH = 8; - - private Consumer<Command> end; - private Runnable cancel; - private Inventory inv; - - private String cmd; - private boolean console = false; - private boolean parse = false; - private int delay = 0; - - public CommandGUI(Consumer<Command> end, Runnable cancel) { - this.end = end; - this.cancel = cancel; - } - - @Override - public Inventory open(Player p) { - inv = Bukkit.createInventory(null, 9, Lang.INVENTORY_COMMAND.toString()); - - inv.setItem(SLOT_COMMAND, ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.commandValue.toString())); - inv.setItem(SLOT_CONSOLE, ItemUtils.itemSwitch(Lang.commandConsole.toString(), console)); - if (DependenciesManager.papi.isEnabled()) inv.setItem(SLOT_PARSE, ItemUtils.itemSwitch(Lang.commandParse.toString(), parse)); - inv.setItem(SLOT_DELAY, ItemUtils.item(XMaterial.CLOCK, Lang.commandDelay.toString())); - - inv.setItem(SLOT_FINISH, ItemUtils.itemDone); - inv.getItem(SLOT_FINISH).setType(cmd == null ? Material.COAL : Material.DIAMOND); - - inv = p.openInventory(inv).getTopInventory(); - return inv; - } - - public CommandGUI setFromExistingCommand(Command cmd) { - if (cmd != null) { - this.cmd = cmd.label; - this.console = cmd.console; - this.parse = cmd.parse; - this.delay = cmd.delay; - if (inv != null && console) ItemUtils.setSwitch(inv.getItem(SLOT_CONSOLE), true); - if (inv != null && parse) ItemUtils.setSwitch(inv.getItem(SLOT_PARSE), true); - if (inv != null) inv.getItem(SLOT_FINISH).setType(Material.DIAMOND); - } - return this; - } - - @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { - switch (slot){ - case SLOT_COMMAND: - Lang.COMMAND.send(p); - new TextEditor<String>(p, () -> p.openInventory(inv), cmd -> { - this.cmd = cmd; - inv.getItem(SLOT_FINISH).setType(Material.DIAMOND); - p.openInventory(inv); - }, () -> p.openInventory(inv), null).useStrippedMessage().start(); - break; - - case SLOT_CONSOLE: - console = ItemUtils.toggleSwitch(current); - break; - - case SLOT_PARSE: - parse = ItemUtils.toggleSwitch(current); - break; - - case SLOT_DELAY: - Lang.COMMAND_DELAY.send(p); - new TextEditor<>(p, () -> p.openInventory(inv), x -> { - delay = x; - p.openInventory(inv); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); - break; - - case SLOT_FINISH: - if (current.getType() == Material.DIAMOND){ - Inventories.closeAndExit(p); - end.accept(new Command(cmd, console, parse, delay)); - } - break; - - } - return true; - } - - @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(cancel); - return StandardCloseBehavior.NOTHING; - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java deleted file mode 100644 index d89edaa8..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/FinishGUI.java +++ /dev/null @@ -1,321 +0,0 @@ -package fr.skytasul.quests.gui.creation; - -import java.util.HashMap; -import java.util.Map; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.events.QuestCreateEvent; -import fr.skytasul.quests.api.gui.Gui; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.options.QuestOptionCreator; -import fr.skytasul.quests.api.options.UpdatableOptionSet; -import fr.skytasul.quests.api.options.UpdatableOptionSet.Updatable; -import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.creation.stages.StagesGUI; -import fr.skytasul.quests.options.OptionName; -import fr.skytasul.quests.players.PlayerQuestDatasImplementation; -import fr.skytasul.quests.structure.QuestBranchImplementation; -import fr.skytasul.quests.structure.StageControllerImplementation; - -public class FinishGUI extends UpdatableOptionSet<Updatable> implements Gui { - - private final QuestCreationSession session; - - /* Temporary quest datas */ - private Map<Integer, Item> clicks = new HashMap<>(); - - /* GUI variables */ - public Inventory inv; - private Player p; - - private Boolean keepPlayerDatas = null; - - private UpdatableItem done; - - public FinishGUI(QuestCreationSession session) { - this.session = session; - } - - @Override - public Inventory open(Player p){ - this.p = p; - if (inv == null){ - String invName = Lang.INVENTORY_DETAILS.toString(); - if (session.isEdition()) { - invName = invName + " #" + session.getQuestEdited().getID(); - if (MinecraftVersion.MAJOR <= 8 && invName.length() > 32) invName = Lang.INVENTORY_DETAILS.toString(); // 32 characters limit in 1.8 - } - inv = Bukkit.createInventory(null, (int) Math.ceil((QuestOptionCreator.creators.values().stream().mapToInt(creator -> creator.slot).max().getAsInt() + 1) / 9D) * 9, invName); - - for (QuestOptionCreator<?, ?> creator : QuestOptionCreator.creators.values()) { - QuestOption<?> option; - if (session.isEdition() && session.getQuestEdited().hasOption(creator.optionClass)) { - option = session.getQuestEdited().getOption(creator.optionClass).clone(); - }else { - option = creator.optionSupplier.get(); - } - UpdatableItem item = new UpdatableItem(creator.slot) { - - @Override - public void click(Player p, ItemStack item, ClickType click) { - option.click(FinishGUI.this, p, item, slot, click); - } - - @Override - public boolean clickCursor(Player p, ItemStack item, ItemStack cursor) { - return option.clickCursor(FinishGUI.this, p, item, cursor, slot); - } - - @Override - public void update() { - if (option.shouldDisplay(FinishGUI.this)) { - inv.setItem(slot, option.getItemStack(FinishGUI.this)); - }else inv.setItem(slot, null); - option.updatedDependencies(FinishGUI.this, inv.getItem(slot)); - } - }; - addOption(option, item); - clicks.put(creator.slot, item); - } - super.calculateDependencies(); - - for (QuestOption<?> option : this) { - if (option.shouldDisplay(this)) inv.setItem(option.getOptionCreator().slot, option.getItemStack(this)); - } - - int pageSlot = QuestOptionCreator.calculateSlot(3); - clicks.put(pageSlot, new Item(pageSlot) { - @Override - public void click(Player p, ItemStack item, ClickType click) { - session.openMainGUI(p); - } - }); - inv.setItem(pageSlot, ItemUtils.itemLaterPage); - - done = new UpdatableItem(QuestOptionCreator.calculateSlot(5)) { - @Override - public void update() { - boolean enabled = getOption(OptionName.class).getValue() != null; - XMaterial type = enabled ? XMaterial.GOLD_INGOT : XMaterial.NETHER_BRICK; - String itemName = (enabled ? ChatColor.GOLD : ChatColor.DARK_PURPLE).toString() + (session.isEdition() ? Lang.edit : Lang.create).toString(); - String itemLore = QuestOption.formatDescription(Lang.createLore.toString()) + (enabled ? " §a✔" : " §c✖"); - String[] lore = keepPlayerDatas == null || keepPlayerDatas.booleanValue() ? new String[] { itemLore } : new String[] { itemLore, "", Lang.resetLore.toString() }; - - ItemStack item = inv.getItem(slot); - - if (item == null) { - inv.setItem(slot, ItemUtils.item(type, itemName, lore)); - return; - }else if (!type.isSimilar(item)) { - type.setType(item); - ItemUtils.name(item, itemName); - } - ItemUtils.lore(item, lore); - } - - @Override - public void click(Player p, ItemStack item, ClickType click) { - if (getOption(OptionName.class).getValue() != null) finish(); - } - }; - - done.update(); - clicks.put(done.slot, done); - getWrapper(OptionName.class).dependent.add(done); - - } - if (session.areStagesEdited() && keepPlayerDatas == null) setStagesEdited(); - - inv = p.openInventory(inv).getTopInventory(); - return inv; - } - - public Gui reopen(Player p){ - Inventories.put(p, this, inv); - p.openInventory(inv); - return this; - } - - @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click){ - clicks.get(slot).click(p, current, click); - return true; - } - - @Override - public boolean onClickCursor(Player p, Inventory inv, ItemStack current, ItemStack cursor, int slot) { - return clicks.get(slot).clickCursor(p, current, cursor); - } - - private void finish(){ - boolean keepPlayerDatas = Boolean.TRUE.equals(this.keepPlayerDatas); - Quest qu; - if (session.isEdition()) { - QuestsPlugin.getPlugin().getLoggerExpanded().debug( - "Editing quest " + session.getQuestEdited().getID() + " with keep datas: " + keepPlayerDatas); - session.getQuestEdited().remove(false, false); - qu = new Quest(session.getQuestEdited().getID(), session.getQuestEdited().getFile()); - }else { - int id = -1; - if (session.hasCustomID()) { - if (QuestsAPI.getAPI().getQuestsManager().getQuests().stream().anyMatch(x -> x.getID() == session.getCustomID())) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot create quest with custom ID " + session.getCustomID() + " because another quest with this ID already exists."); - }else { - id = session.getCustomID(); - QuestsPlugin.getPlugin().getLoggerExpanded().warning("A quest will be created with custom ID " + id + "."); - } - } - if (id == -1) - id = QuestsAPI.getAPI().getQuestsManager().getFreeQuestID(); - qu = new Quest(id); - } - - for (QuestOption<?> option : this) { - if (option.hasCustomValue()) qu.addOption(option); - } - - QuestBranchImplementation mainBranch = new QuestBranchImplementation(qu.getBranchesManager()); - qu.getBranchesManager().addBranch(mainBranch); - boolean failure = loadBranch(mainBranch, session.getMainGUI()); - - QuestCreateEvent event = new QuestCreateEvent(p, qu, session.isEdition()); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()){ - qu.remove(false, true); - Utils.sendMessage(p, Lang.CANCELLED.toString()); - }else { - - if (session.areStagesEdited()) { - if (keepPlayerDatas) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Players quests datas will be kept for quest #" + qu.getId() - + " - this may cause datas issues."); - } else - BeautyQuests.getInstance().getPlayersManager().removeQuestDatas(session.getQuestEdited()) - .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded() - .logError("An error occurred while removing player datas after quest edition", p)); - } - - QuestsAPI.getAPI().getQuestsManager().addQuest(qu); - Utils.sendMessage(p, ((!session.isEdition()) ? Lang.SUCCESFULLY_CREATED : Lang.SUCCESFULLY_EDITED).toString(), qu.getName(), qu.getBranchesManager().getBranchesAmount()); - Utils.playPluginSound(p, "ENTITY_VILLAGER_YES", 1); - QuestsPlugin.getPlugin().getLoggerExpanded().info("New quest created: " + qu.getName() + ", ID " + qu.getId() + ", by " + p.getName()); - if (session.isEdition()) { - QuestsPlugin.getPlugin().getLoggerExpanded().info("Quest " + qu.getName() + " has been edited"); - if (failure) BeautyQuests.getInstance().createQuestBackup(qu.getFile().toPath(), "Error occurred while editing"); - } - try { - qu.saveToFile(); - }catch (Exception e) { - Lang.ERROR_OCCURED.send(p, "initial quest save"); - QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when trying to save newly created quest.", e); - } - - if (keepPlayerDatas) { - for (Player p : Bukkit.getOnlinePlayers()) { - PlayerAccount account = PlayersManager.getPlayerAccount(p); - if (account == null) continue; - if (account.hasQuestDatas(qu)) { - PlayerQuestDatasImplementation datas = account.getQuestDatas(qu); - datas.questEdited(); - if (datas.getBranch() == -1) continue; - QuestBranchImplementation branch = qu.getBranchesManager().getBranch(datas.getBranch()); - if (datas.isInEndingStages()) { - branch.getEndingStages().keySet().forEach(stage -> stage.joins(account, player)); - }else branch.getRegularStage(datas.getStage()).joins(account, p); - } - } - } - - QuestsAPI.getAPI().propagateQuestsHandlers(handler -> { - if (session.isEdition()) - handler.questEdit(qu, session.getQuestEdited(), keepPlayerDatas); - else handler.questCreate(qu); - }); - } - - Inventories.closeAndExit(p); - } - - private boolean loadBranch(QuestBranchImplementation branch, StagesGUI gui) { - boolean failure = false; - for (StageCreation<?> creation : gui.getStageCreations()) { - try{ - AbstractStage stage = createStage(creation, branch); - if (creation.isEndingStage()) { - StagesGUI newGUI = creation.getLeadingBranch(); - QuestBranchImplementation newBranch = null; - if (!newGUI.isEmpty()){ - newBranch = new QuestBranchImplementation(branch.getBranchesManager()); - branch.getBranchesManager().addBranch(newBranch); - failure |= loadBranch(newBranch, newGUI); - } - branch.addEndStage(stage, newBranch); - }else branch.addRegularStage(stage); - }catch (Exception ex) { - failure = true; - Lang.ERROR_OCCURED.send(p, " lineToStage"); - QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred wheh creating branch from GUI.", ex); - } - } - return failure; - } - - public <T extends AbstractStage> T createStage(StageCreation<T> creation, QuestBranchImplementation branch) { - StageControllerImplementation<T> controller = new StageControllerImplementation<>(branch, creation.getType()); - T stage = creation.finish(controller); - controller.setStage(stage); - return stage; - } - - private void setStagesEdited() { - keepPlayerDatas = false; - int resetSlot = QuestOptionCreator.calculateSlot(6); - inv.setItem(resetSlot, ItemUtils.itemSwitch(Lang.keepDatas.toString(), false, QuestOption.formatDescription(Lang.keepDatasLore.toString()))); - clicks.put(resetSlot, new Item(resetSlot) { - - @Override - public void click(Player p, ItemStack item, ClickType click) { - keepPlayerDatas = ItemUtils.toggleSwitch(item); - done.update(); - } - - }); - done.update(); - } - - abstract class Item { - protected final int slot; - - protected Item(int slot) { - this.slot = slot; - } - - public abstract void click(Player p, ItemStack item, ClickType click); - - public boolean clickCursor(Player p, ItemStack item, ItemStack cursor) { - return true; - } - } - - abstract class UpdatableItem extends Item implements Updatable { - protected UpdatableItem(int slot) { - super(slot); - } - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java deleted file mode 100644 index afd83d9e..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/ItemsGUI.java +++ /dev/null @@ -1,109 +0,0 @@ -package fr.skytasul.quests.gui.creation; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.Gui; -import fr.skytasul.quests.api.gui.Gui.CloseBehavior; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.Inventories; -import fr.skytasul.quests.gui.misc.ItemCreatorGUI; - -public class ItemsGUI implements Gui { - - public static ItemStack none = ItemUtils.item(XMaterial.RED_STAINED_GLASS_PANE, "§c", Lang.itemsNone.toString()); - - private Consumer<List<ItemStack>> end; - private Map<Integer, ItemStack> items = new HashMap<>(); - private int size; - - public Inventory inv; - - public ItemsGUI(Consumer<List<ItemStack>> end, List<ItemStack> itemsList) { - this.end = end; - Utils.extractItems(itemsList).forEach(item -> items.put(items.size(), item)); - this.size = (int) (Math.ceil((items.size() + 1D) / 9D) * 9); - } - - public Inventory open(Player p){ - inv = Bukkit.createInventory(null, size, Lang.INVENTORY_ITEMS.toString()); - - inv.setItem(size - 1, ItemUtils.itemDone); - - for (int i = 0; i < size - 1; i++) { - if (i < items.size()) { - inv.setItem(i, items.get(i)); - }else inv.setItem(i, none); - } - - inv = p.openInventory(inv).getTopInventory(); - return inv; - } - - private boolean addItem(Player p, ItemStack item, int slot) { - items.put(slot, item); - for (int i = 0; i < size - 1; i++) { - ItemStack is = inv.getItem(i); - if (is.equals(none)) return false; - } - size += 9; - Inventories.closeWithoutExit(p); - Inventories.put(p, this, open(p)); - return true; - } - - public boolean onClickCursor(Player p, Inventory inv, ItemStack current, ItemStack cursor, int slot){ - if (slot == size - 1) return true; - if (none.equals(current)){ - inv.setItem(slot, cursor); - Utils.runSync(() -> { - player.setItemOnCursor(null); - addItem(player, cursor, slot); - }); - return true; - }else Utils.runSync(() -> items.put(slot, inv.getItem(slot))); - return false; - } - - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click){ - if (slot == size - 1) { - Inventories.closeAndExit(p); - end.accept(items.values().stream().filter(x -> x != null).collect(Collectors.toList())); - }else { - if (current.equals(none)){ - new ItemCreatorGUI(item -> { - if (item != null) inv.setItem(slot, item); - if (!addItem(p, item, slot)) { - Inventories.put(p, this, inv); - p.openInventory(inv); - } - }, true).open(p); - }else { - if (click.isLeftClick() || (click.isRightClick() && current.getAmount() == 1)) { - Utils.runSync(() -> { - inv.setItem(slot, none); - items.remove(slot); - }); - }else Utils.runSync(() -> items.put(slot, inv.getItem(slot))); - return false; - } - } - return true; - } - - @Override - public CloseBehavior onClose(Player p, Inventory inv) { - return StandardCloseBehavior.REOPEN; - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java index 0d0ed75c..4eb420e3 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java @@ -1,67 +1,70 @@ package fr.skytasul.quests.gui.creation; import org.bukkit.entity.Player; -import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.gui.creation.quest.QuestCreationGuiImplementation; import fr.skytasul.quests.gui.creation.stages.StagesGUI; +import fr.skytasul.quests.structure.QuestImplementation; public class QuestCreationSession { - - private StagesGUI mainGUI; - private FinishGUI finishGUI; - - private final Quest questEdited; + + private StagesGUI stagesGUI; + private QuestCreationGuiImplementation creationGUI; + + private final QuestImplementation questEdited; private boolean stagesEdited = false; - + private int customID = -1; - + public QuestCreationSession() { this(null); } - - public QuestCreationSession(Quest questEdited) { + + public QuestCreationSession(QuestImplementation questEdited) { this.questEdited = questEdited; } - + public boolean hasCustomID() { return customID != -1; } - + public int getCustomID() { return customID; } - + public void setCustomID(int customID) { this.customID = customID; } - + public boolean isEdition() { return questEdited != null; } - - public Quest getQuestEdited() { + + public QuestImplementation getQuestEdited() { return questEdited; } - + public void setStagesEdited() { stagesEdited = true; } - + public boolean areStagesEdited() { return isEdition() && stagesEdited; } - - public StagesGUI getMainGUI() { - return mainGUI; + + public StagesGUI getStagesGUI() { + return stagesGUI; } - - public void openMainGUI(Player p) { - if (mainGUI == null) mainGUI = new StagesGUI(this); - mainGUI.open(p); + + public void openStagesGUI(Player p) { + if (stagesGUI == null) + stagesGUI = new StagesGUI(this); + stagesGUI.open(p); } - - public void openFinishGUI(Player p) { - if (finishGUI == null) finishGUI = new FinishGUI(this); - finishGUI.open(p); + + public void openCreationGUI(Player p) { + if (creationGUI == null) + creationGUI = new QuestCreationGuiImplementation(this); + creationGUI.open(p); } - + } 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 new file mode 100644 index 00000000..20b0f9ee --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/quest/QuestCreationGuiImplementation.java @@ -0,0 +1,292 @@ +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 com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.events.QuestCreateEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; +import fr.skytasul.quests.api.gui.layout.LayoutedButton.ItemButton; +import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.OptionSet; +import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.options.QuestOptionCreator; +import fr.skytasul.quests.api.options.UpdatableOptionSet; +import fr.skytasul.quests.api.quests.creation.QuestCreationGui; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.gui.creation.QuestCreationSession; +import fr.skytasul.quests.gui.creation.stages.StagesGUI; +import fr.skytasul.quests.options.OptionName; +import fr.skytasul.quests.players.PlayerAccountImplementation; +import fr.skytasul.quests.players.PlayerQuestDatasImplementation; +import fr.skytasul.quests.structure.QuestBranchImplementation; +import fr.skytasul.quests.structure.QuestImplementation; +import fr.skytasul.quests.structure.StageControllerImplementation; +import fr.skytasul.quests.utils.QuestUtils; +import net.md_5.bungee.api.ChatColor; + +public class QuestCreationGuiImplementation extends LayoutedGUI implements QuestCreationGui { + + private final QuestCreationSession session; + private final UpdatableOptionSet options; + + private final int doneButtonSlot; + + private Boolean keepPlayerDatas = null; + + public QuestCreationGuiImplementation(QuestCreationSession session) { + super(null, new HashMap<>(), StandardCloseBehavior.CONFIRM); + // null name because it is computed in #instanciate + this.session = session; + this.options = new UpdatableOptionSet(); + + for (QuestOptionCreator<?, ?> creator : QuestOptionCreator.creators.values()) { + QuestOption<?> option; + if (session.isEdition() && session.getQuestEdited().hasOption(creator.optionClass)) { + option = session.getQuestEdited().getOption(creator.optionClass).clone(); + } else { + option = creator.optionSupplier.get(); + } + + ItemButton optionButton = new LayoutedButton.ItemButton() { + + @Override + public void click(@NotNull LayoutedClickEvent event) { + option.click(new QuestCreationGuiClickEvent(event.getPlayer(), QuestCreationGuiImplementation.this, event.getClicked(), + event.getCursor(), event.getSlot(), event.getClick())); + } + + @Override + public @Nullable ItemStack getItem() { + return option.getItemStack(options); + } + + @Override + public boolean isValid() { + return option.shouldDisplay(options); + } + + }; + buttons.put(creator.slot, optionButton); + options.addOption(option, () -> { + option.onDependenciesUpdated(options); + refresh(optionButton); + }); + } + + options.calculateDependencies(); + + buttons.put(QuestOptionCreator.calculateSlot(3), + LayoutedButton.create(ItemUtils.itemLaterPage, event -> session.openStagesGUI(event.getPlayer()))); + + doneButtonSlot = QuestOptionCreator.calculateSlot(5); + buttons.put(doneButtonSlot, LayoutedButton.create(() -> { + boolean finishable = isFinishable(); + XMaterial type = finishable ? XMaterial.GOLD_INGOT : XMaterial.NETHER_BRICK; + String itemName = (finishable ? ChatColor.GOLD : ChatColor.DARK_PURPLE).toString() + + (session.isEdition() ? Lang.edit : Lang.create).toString(); + List<String> lore = new ArrayList<>(3); + lore.add(QuestOption.formatDescription(Lang.createLore.toString()) + (finishable ? " §a✔" : " §c✖")); + if (Boolean.FALSE.equals(keepPlayerDatas)) { + lore.add(""); + lore.add(Lang.resetLore.toString()); + } + return ItemUtils.item(type, itemName, lore); + }, event -> { + if (isFinishable()) + finish(event.getPlayer()); + })); + options.getWrapper(OptionName.class).dependent.add(() -> super.refresh(doneButtonSlot)); + } + + @Override + protected Inventory instanciate(@NotNull Player player) { + String invName = Lang.INVENTORY_DETAILS.toString(); + if (session.isEdition()) { + invName = invName + " #" + session.getQuestEdited().getId(); + if (MinecraftVersion.MAJOR <= 8 && invName.length() > 32) + invName = Lang.INVENTORY_DETAILS.toString(); // 32 characters limit in 1.8 + } + + 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; + } + + @Override + public @NotNull OptionSet getOptionSet() { + return options; + } + + @Override + public void updateOptionItem(@NotNull QuestOption<?> option) { + refresh(option.getOptionCreator().slot); + } + + private void finish(Player p) { + boolean keepPlayerDatas = Boolean.TRUE.equals(this.keepPlayerDatas); + QuestImplementation qu; + if (session.isEdition()) { + QuestsPlugin.getPlugin().getLoggerExpanded().debug( + "Editing quest " + session.getQuestEdited().getId() + " with keep datas: " + keepPlayerDatas); + session.getQuestEdited().delete(true, true); + qu = new QuestImplementation(session.getQuestEdited().getId(), session.getQuestEdited().getFile()); + }else { + int id = -1; + if (session.hasCustomID()) { + if (QuestsAPI.getAPI().getQuestsManager().getQuests().stream() + .anyMatch(x -> x.getId() == session.getCustomID())) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot create quest with custom ID " + session.getCustomID() + " because another quest with this ID already exists."); + }else { + id = session.getCustomID(); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("A quest will be created with custom ID " + id + "."); + } + } + if (id == -1) + id = BeautyQuests.getInstance().getQuestsManager().getFreeQuestID(); + qu = new QuestImplementation(id); + } + + for (QuestOption<?> option : options) { + if (option.hasCustomValue()) qu.addOption(option); + } + + QuestBranchImplementation mainBranch = new QuestBranchImplementation(qu.getBranchesManager()); + qu.getBranchesManager().addBranch(mainBranch); + boolean failure = loadBranch(mainBranch, session.getStagesGUI()); + + QuestCreateEvent event = new QuestCreateEvent(p, qu, session.isEdition()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()){ + qu.delete(true, false); + Lang.CANCELLED.send(p); + }else { + if (session.areStagesEdited()) { + if (keepPlayerDatas) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Players quests datas will be kept for quest #" + qu.getId() + + " - this may cause datas issues."); + } else + BeautyQuests.getInstance().getPlayersManager().removeQuestDatas(session.getQuestEdited()) + .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded() + .logError("An error occurred while removing player datas after quest edition", p)); + } + + QuestsAPI.getAPI().getQuestsManager().addQuest(qu); + MessageUtils.sendPrefixedMessage(p, + ((!session.isEdition()) ? Lang.SUCCESFULLY_CREATED : Lang.SUCCESFULLY_EDITED).toString(), qu.getName(), + qu.getBranchesManager().getBranches().size()); + QuestUtils.playPluginSound(p, "ENTITY_VILLAGER_YES", 1); + QuestsPlugin.getPlugin().getLoggerExpanded().info("New quest created: " + qu.getName() + ", ID " + qu.getId() + ", by " + p.getName()); + if (session.isEdition()) { + QuestsPlugin.getPlugin().getLoggerExpanded().info("Quest " + qu.getName() + " has been edited"); + if (failure) BeautyQuests.getInstance().createQuestBackup(qu.getFile().toPath(), "Error occurred while editing"); + } + try { + qu.saveToFile(); + }catch (Exception e) { + Lang.ERROR_OCCURED.send(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); + } + + private void keepDatas(QuestImplementation qu) { + for (Player p : Bukkit.getOnlinePlayers()) { + PlayerAccountImplementation account = BeautyQuests.getInstance().getPlayersManager().getAccount(p); + if (account != null && account.hasQuestDatas(qu)) { + PlayerQuestDatasImplementation datas = account.getQuestDatas(qu); + datas.questEdited(); + if (datas.getBranch() == -1) continue; + QuestBranchImplementation branch = qu.getBranchesManager().getBranch(datas.getBranch()); + if (datas.isInEndingStages()) { + branch.getEndingStages().forEach(stage -> stage.getStage().getStage().joined(p)); + } else + branch.getRegularStage(datas.getStage()).getStage().joined(p); + } + } + } + + private boolean loadBranch(QuestBranchImplementation branch, StagesGUI stagesGui) { + boolean failure = false; + for (StageCreation<?> creation : stagesGui.getStageCreations()) { + try{ + AbstractStage stage = createStage(creation, branch); + if (creation.getCreationContext().isEndingStage()) { + StagesGUI newGUI = creation.getCreationContext().getEndingBranch(); + QuestBranchImplementation newBranch = null; + if (!newGUI.isEmpty()){ + newBranch = new QuestBranchImplementation(branch.getBranchesManager()); + branch.getBranchesManager().addBranch(newBranch); + failure |= loadBranch(newBranch, newGUI); + } + branch.addEndStage(stage, newBranch); + }else branch.addRegularStage(stage); + }catch (Exception ex) { + failure = true; + Lang.ERROR_OCCURED.send(p, " lineToStage"); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred wheh creating branch from GUI.", ex); + } + } + return failure; + } + + public <T extends AbstractStage> T createStage(StageCreation<T> creation, QuestBranchImplementation branch) { + StageControllerImplementation<T> controller = + new StageControllerImplementation<>(branch, creation.getCreationContext().getType()); + T stage = creation.finish(controller); + controller.setStage(stage); + return stage; + } + + 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/creation/stages/Line.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/LineOld.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java rename to core/src/main/java/fr/skytasul/quests/gui/creation/stages/LineOld.java index 7d5eacbe..060c2ca4 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/Line.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/LineOld.java @@ -4,11 +4,11 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.gui.creation.stages.StageRunnable.StageRunnableClick; import fr.skytasul.quests.utils.types.NumberedList; -public class Line { +public class LineOld { public final StagesGUI gui; protected int line = 0; @@ -20,7 +20,7 @@ public class Line { public StageCreation<?> creation = null; - protected Line(int line, StagesGUI gui) { + protected LineOld(int line, StagesGUI gui) { this.gui = gui; this.line = line; } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java new file mode 100644 index 00000000..a31e7d06 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java @@ -0,0 +1,67 @@ +package fr.skytasul.quests.gui.creation.stages; + +import java.util.Objects; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; + +public class StageCreationContextImplementation<T extends AbstractStage> implements StageCreationContext<T> { + + private final @NotNull StageGuiLine line; + private final @NotNull StageType<T> type; + private final boolean ending; + private @Nullable StagesGUI endingBranch; + private @Nullable StageCreation<T> creation; + + public StageCreationContextImplementation(@NotNull StageGuiLine line, @NotNull StageType<T> type, boolean ending) { + this.line = line; + this.type = type; + this.ending = ending; + } + + @Override + public @NotNull StageGuiLine getLine() { + return line; + } + + @Override + public @NotNull StageType<T> getType() { + return type; + } + + @Override + public boolean isEndingStage() { + return ending; + } + + public @Nullable StagesGUI getEndingBranch() { + return endingBranch; + } + + public void setEndingBranch(StagesGUI endingBranch) { + this.endingBranch = endingBranch; + } + + @Override + public @NotNull StageCreation<T> getCreation() { + return Objects.requireNonNull(creation); + } + + void setCreation(StageCreation<T> creation) { + this.creation = creation; + } + + @Override + public void remove() {} + + @Override + public void reopenGui() {} + + @Override + public void removeAndReopenGui() {} + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java new file mode 100644 index 00000000..9dc55c67 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java @@ -0,0 +1,191 @@ +package fr.skytasul.quests.gui.creation.stages; + +import java.util.HashMap; +import java.util.Map; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.stages.creation.StageGuiClickHandler; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; + +public class StageLineImplementation implements StageGuiLine { + + private final @NotNull StagesGUI.Line line; + private final @NotNull Map<Integer, LineItem> items = new HashMap<>(); + + private int page, maxPage; + + public StageLineImplementation(StagesGUI.Line line) { + this.line = line; + } + + public boolean isEmpty() { + return items.isEmpty(); + } + + @Override + public @Nullable ItemStack getItem(int slot) { + if (!isSlotShown(slot)) + return items.get(slot).item; + + return getRawItem(getRawLineSlot(slot)); + } + + @Override + public void setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHandler click) { + if (items.containsKey(slot)) + throw new IllegalArgumentException("Slot " + slot + " already taken"); + + items.put(slot, new LineItem(item, click)); + + computeMaxPage(); + + if (isSlotShown(slot)) + refresh(); + } + + @Override + public void refreshItem(int slot, @NotNull ItemStack item) { + items.get(slot).item = item; + + if (isSlotShown(slot)) + refresh(); + } + + @Override + public void removeItem(int slot) { + items.remove(slot); + + computeMaxPage(); + + if (isSlotShown(slot)) + refresh(); + } + + public void clearItems() { + items.clear(); + maxPage = 1; + page = 0; + clearLine(); + } + + @Override + public int getPage() { + return page; + } + + @Override + public void setPage(int page) { + if (!isShown()) + return; + + clearLine(); + this.page = page; + + int pageFirst = page == 0 ? 0 : 8 + page * 7; + int pageCapacity = page == 0 ? 8 : 7; + int rawSlot = page == 0 ? 0 : 1; + for (int slot = pageFirst; slot < pageFirst + pageCapacity; slot++) { + LineItem item = items.get(slot); + if (item != null) { + setRawItem(rawSlot, item.item); + item.item = getRawItem(rawSlot); + rawSlot++; + } + } + } + + @Override + public StageGuiClickHandler click(int rawSlot) { + if (rawSlot == 0 && page > 0) { + setPage(page - 1); + return null; + } else if (rawSlot == 8 && page < maxPage - 1) { + setPage(page + 1); + return null; + } else { + int slot = (page == 0 ? 0 : page * 7) + rawSlot; + LineItem item = items.get(slot); + + return item == null ? null : item.handler; + } + } + + private void computeMaxPage() { + // first line: 8 slots (0 to 7, 8 is 2nd page button) + // next lines: 7 slots (1 to 7, 0 is prev page and 8 is next page) + + int last = items.keySet().stream().mapToInt(Integer::intValue).max().orElse(0); + if (last < 8) { + maxPage = 1; + } else { + maxPage = (int) (1 + Math.ceil((last - 8D + 1D) / 7D)); + } + + if (page >= maxPage) { + page = maxPage - 1; + } + } + + private boolean isShown() { + return line.isShown(); + } + + private boolean isSlotShown(int slot) { + int pageFirst = page == 0 ? 0 : 8 + page * 7; + int pageCapacity = page == 0 ? 8 : 7; + + return isShown() && slot >= pageFirst && slot < pageFirst + pageCapacity; + } + + public void refresh() { + setPage(page); + } + + private int getRawLineSlot(int slot) { + if (slot < 8) { + if (page != 0) + return -1; + + return slot; + } else { + int slotPage = (int) (1 + Math.ceil((slot - 8D + 1D) / 7D)); + if (slotPage != page) + return -1; + + return slot - 8 - (slotPage - 1) * 7; + } + } + + private void clearLine() { + if (!isShown()) + return; + for (int i = 0; i < 9; i++) + setRawItem(i, null); + } + + private void setRawItem(int rawSlot, ItemStack item) { + if (!isShown()) + throw new IllegalStateException(); + line.setItem(rawSlot, item); + } + + private ItemStack getRawItem(int rawSlot) { + if (!isShown()) + throw new IllegalStateException(); + return line.getItem(rawSlot); + } + + class LineItem { + + ItemStack item; + StageGuiClickHandler handler; + + public LineItem(ItemStack item, StageGuiClickHandler handler) { + this.item = item; + this.handler = handler; + } + + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 6f2edffc..e407955c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -9,35 +9,29 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageCreation; import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.Inventories; import fr.skytasul.quests.gui.creation.QuestCreationSession; -import fr.skytasul.quests.gui.creation.stages.StageRunnable.StageRunnableClick; import fr.skytasul.quests.structure.QuestBranchImplementation; -public class StagesGUI implements Gui { +public class StagesGUI extends AbstractGui { private static final int SLOT_FINISH = 52; private static final ItemStack stageCreate = ItemUtils.item(XMaterial.SLIME_BALL, Lang.stageCreate.toString()); private static final ItemStack notDone = ItemUtils.lore(ItemUtils.itemNotDone.clone(), Lang.cantFinish.toString()); - public static final ItemStack ending = ItemUtils.item(XMaterial.BAKED_POTATO, Lang.ending.toString()); - public static final ItemStack descMessage = ItemUtils.item(XMaterial.OAK_SIGN, Lang.descMessage.toString()); - public static final ItemStack startMessage = ItemUtils.item(XMaterial.FEATHER, Lang.startMsg.toString()); - public static final ItemStack validationRequirements = ItemUtils.item(XMaterial.NETHER_STAR, Lang.validationRequirements.toString(), QuestOption.formatDescription(Lang.validationRequirementsLore.toString())); - private List<Line> lines = new ArrayList<>(); private final QuestCreationSession session; @@ -57,161 +51,57 @@ public StagesGUI(QuestCreationSession session, StagesGUI previousBranch) { } @Override - public Inventory open(Player p) { - if (inv == null){ - inv = Bukkit.createInventory(null, 54, Lang.INVENTORY_STAGES.toString()); - - page = 0; - for (int i = 0; i < 20; i++) lines.add(new Line(i, this)); - setStageCreate(lines.get(0), false); - setStageCreate(lines.get(15), true); - - inv.setItem(45, ItemUtils.itemLaterPage); - inv.setItem(50, ItemUtils.itemNextPage); - - inv.setItem(SLOT_FINISH, isEmpty() ? notDone : ItemUtils.itemDone); - inv.setItem(53, previousBranch == null ? ItemUtils.itemCancel : ItemUtils.item(XMaterial.FILLED_MAP, Lang.previousBranch.toString())); - refresh(); - - if (session.isEdition() && this == session.getMainGUI()) { - editBranch(session.getQuestEdited().getBranchesManager().getBranch(0)); - inv.setItem(SLOT_FINISH, ItemUtils.itemDone); - } - } - - if (p != null) inv = p.openInventory(inv).getTopInventory(); - return inv; + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 54, Lang.INVENTORY_STAGES.toString()); } - /** - * Get the StagesGUI, open it for player if specified, and re implement the player in the inventories system if on true - * @param p player to open (can be null) - * @param reImplement re implement the player in the inventories system - * @return this StagesGUI - */ - public StagesGUI reopen(Player p, boolean reImplement){ - if (p != null){ - if (reImplement) Inventories.put(p, this, inv); - p.openInventory(inv); - } - return this; - } + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + page = 0; + for (int i = 0; i < 20; i++) + lines.add(new Line(i, i >= 15)); + lines.get(0).setCreationState(); + lines.get(15).setCreationState(); - private void setStageCreate(Line line, boolean branches){ - line.removeItems(); - line.setItem(0, stageCreate.clone(), (p, item) -> { - line.setItem(0, null, null, true, false); - int i = 0; - for (StageType<?> type : QuestsAPI.getAPI().getStages()) { - if (type.isValid()) { - line.setItem(++i, type.getItem(), (p1, item1) -> { - runClick(line, type, branches).start(p1); - }, true, false); - } - } - line.setItems(0); - }); - line.setItems(0); + inv.setItem(45, ItemUtils.itemLaterPage); + inv.setItem(50, ItemUtils.itemNextPage); + + inv.setItem(SLOT_FINISH, isEmpty() ? notDone : ItemUtils.itemDone); + inv.setItem(53, previousBranch == null ? ItemUtils.itemCancel + : ItemUtils.item(XMaterial.FILLED_MAP, Lang.previousBranch.toString())); + refresh(); + + if (session.isEdition() && this == session.getStagesGUI()) { + editBranch(session.getQuestEdited().getBranchesManager().getBranch(0)); + inv.setItem(SLOT_FINISH, ItemUtils.itemDone); + } } private String[] getLineManageLore(int line) { return new String[] { "§7" + Lang.ClickRight + "/" + Lang.ClickLeft + " > §c" + Lang.stageRemove.toString(), line == 0 || line == 15 ? ("§8" + Lang.ClickShiftRight + " > " + Lang.stageUp) : "§7" + Lang.ClickShiftRight + " > §e" + Lang.stageUp, - line == 14 || line == 19 || !isActiveLine(getLine(line + 1)) ? ("§8" + Lang.ClickShiftLeft + " > " + Lang.stageDown) : "§7" + Lang.ClickShiftLeft + " > §e" + Lang.stageDown }; + line == 14 || line == 19 || !getLine(line + 1).isActive() + ? ("§8" + Lang.ClickShiftLeft + " > " + Lang.stageDown) + : "§7" + Lang.ClickShiftLeft + " > §e" + Lang.stageDown}; } - - private void updateLineManageLore(Line line) { - line.editItem(0, ItemUtils.lore(line.getItem(0), getLineManageLore(line.getLine()))); - } - - private StageCreation<?> runClick(Line line, StageType<?> type, boolean branches) { - line.removeItems(); - StageCreation<?> creation = type.getCreationSupplier().supply(line, branches); - line.creation = creation; - creation.setup((StageType) type); - - inv.setItem(SLOT_FINISH, ItemUtils.itemDone); - - int maxStages = branches ? 20 : 15; - ItemStack manageItem = ItemUtils.item(XMaterial.BARRIER, Lang.stageType.format(type.getName()), getLineManageLore(line.getLine())); - line.setItem(0, manageItem, new StageRunnableClick() { - @Override - public void run(Player p, ItemStack item, ClickType click) { - if (click == ClickType.LEFT || click == ClickType.RIGHT) { - line.creation = null; - int lineID = line.getLine(); - if (lineID != maxStages - 1) { - line.removeItems(); - for (int i = line.getLine() + 1; i < maxStages; i++) { - Line exLine = getLine(i); - exLine.changeLine(i - 1); - if (!isActiveLine(exLine)) { - if (exLine.isEmpty()) { - setStageCreate(exLine, branches); - }else { - line.line = exLine.getLine() + 1; - } - break; - } - } - if (lineID == 0 || lineID == 15) updateLineManageLore(getLine(lineID)); - }else setStageCreate(line, branches); - if (lineID != 0 && lineID != 15) updateLineManageLore(getLine(lineID - 1)); - if (isEmpty()) inv.setItem(SLOT_FINISH, notDone); - }else if (click == ClickType.SHIFT_LEFT) { - if (line.getLine() != 14 && line.getLine() != 19) { - Line down = getLine(line.getLine() + 1); - if (isActiveLine(down)) { - down.exchangeLines(line); - updateLineManageLore(line); - updateLineManageLore(down); - } - } - }else if (click == ClickType.SHIFT_RIGHT) { - if (line.getLine() != 0 && line.getLine() != 15) { - Line up = getLine(line.getLine() - 1); - up.exchangeLines(line); - updateLineManageLore(line); - updateLineManageLore(up); - } - } - } - }); - if (line.getLine() != maxStages - 1) { - Line next = getLine(line.getLine() + 1); - if (!isActiveLine(next)) setStageCreate(next, branches); - } - - if (branches){ - if (creation.getLeadingBranch() == null) creation.setLeadingBranch(new StagesGUI(session, this)); - line.setItem(14, ItemUtils.item(XMaterial.FILLED_MAP, Lang.newBranch.toString()), (p, item) -> Inventories.open(p, creation.getLeadingBranch())); - } - - if (line.getLine() != 0 && line.getLine() != 15) updateLineManageLore(getLine(line.getLine() - 1)); - - return creation; - } - - private boolean isActiveLine(Line line) { - return line.creation != null; - } - - public Line getLine(int id){ - for (Line l : lines){ - if (l.getLine() == id) return l; + public Line getLine(int id) { + for (Line l : lines) { + if (l.lineId == id) + return l; } return null; } public boolean isEmpty(){ if (lines.isEmpty()) return true; // if this StagesGUI has never been opened - return !isActiveLine(getLine(0)) && !isActiveLine(getLine(15)); + return !getLine(0).isActive() && !getLine(15).isActive(); } public void deleteStageLine(Line line) { - if (isActiveLine(line)) line.execute(0, null, null, ClickType.RIGHT); // item and player not used for deletion item + if (line.isActive()) + line.remove(); } @Override @@ -251,7 +141,7 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli } }else { session.setStagesEdited(); - Line line = getLine((slot - slot % 9)/9 +5*page); + Line line = getLine((slot - slot % 9) / 9 + 5 * page); line.click(slot - (line.getLine() - page * 5) * 9, p, current, click); } return true; @@ -306,4 +196,173 @@ private void editBranch(QuestBranchImplementation branch){ } } + class Line { + + StageLineImplementation lineObj; + int lineId; + StageCreationContextImplementation<?> context; + boolean ending; + + Line(int lineId, boolean ending) { + this.lineId = lineId; + this.lineObj = new StageLineImplementation(this); + } + + boolean isActive() { + return context != null; + } + + void setCreationState() { + lineObj.clearItems(); + lineObj.setItem(0, stageCreate.clone(), event -> setSelectionState()); + } + + void setSelectionState() { + lineObj.clearItems(); + int i = 0; + for (StageType<?> type : QuestsAPI.getAPI().getStages()) { + lineObj.setItem(++i, type.getItem(), event -> { + setStageCreation(event.getPlayer(), type); + }); + } + } + + <T extends AbstractStage> void setStageCreation(Player p, StageType<T> type) { + lineObj.clearItems(); + + context = new StageCreationContextImplementation<>(lineObj, type, ending); + context.setCreation( + (StageCreation) type.getCreationSupplier().supply((@NotNull StageCreationContext<T>) context)); + + inv.setItem(SLOT_FINISH, ItemUtils.itemDone); + + int maxStages = ending ? 20 : 15; + ItemStack manageItem = + ItemUtils.item(XMaterial.BARRIER, Lang.stageType.format(type.getName()), getLineManageLore(lineId)); + lineObj.setItem(0, manageItem, event -> { + switch (event.getClick()) { + case LEFT: + case RIGHT: + remove(); + break; + case SHIFT_LEFT: + descend(); + break; + case SHIFT_RIGHT: + ascend(); + break; + default: + break; + } + }); + + if (lineId != maxStages - 1) { + Line next = getLine(lineId + 1); + if (!next.isActive()) + next.setCreationState(); + } + + if (ending) { + if (context.getEndingBranch() == null) + context.setEndingBranch(new StagesGUI(session, StagesGUI.this)); + lineObj.setItem(14, ItemUtils.item(XMaterial.FILLED_MAP, Lang.newBranch.toString()), + event -> context.getEndingBranch().open(event.getPlayer())); + } + + if (lineId != 0 && lineId != 15) + getLine(lineId - 1).updateLineManageLore(); + + context.getCreation().start(p); + } + + void updateLineManageLore() { + lineObj.refreshItemLore(0, getLineManageLore(lineId)); + } + + boolean isFirst() { + return lineId == 0 || lineId == 15; + } + + boolean isLast() { + return lineId == 14 || lineId == 19; + } + + void remove() { + context = null; + int maxStages = ending ? 20 : 15; + if (lineId != maxStages - 1) { + lineObj.clearItems(); + + int oldId = lineId; + Line lastLine = this; + for (int i = lineId + 1; i < maxStages; i++) { + Line nextLine = getLine(i); + nextLine.exchangeLines(lastLine); + lastLine = nextLine; + if (!nextLine.isActive()) { + if (nextLine.lineObj.isEmpty()) + nextLine.setCreationState(); + break; + } + } + if (oldId == 0 || oldId == 15) + getLine(oldId).updateLineManageLore(); + } else + setCreationState(); + if (!isFirst()) + getLine(lineId - 1).updateLineManageLore(); + if (isEmpty()) + inv.setItem(SLOT_FINISH, notDone); + } + + void descend() { + if (!isLast()) { + Line down = getLine(lineId + 1); + if (down.isActive()) { + down.exchangeLines(this); + updateLineManageLore(); + down.updateLineManageLore(); + } + } + } + + void ascend() { + if (!isFirst()) { + Line up = getLine(lineId - 1); + up.exchangeLines(this); + updateLineManageLore(); + up.updateLineManageLore(); + } + } + + void exchangeLines(Line other) { + if (other == null || other == this) + return; + int newLine = other.lineId; + + other.lineId = lineId; + other.lineObj.refresh(); + + lineId = newLine; + lineObj.refresh(); + } + + int getRawSlot(int lineSlot) { + return lineId * 9 - page * 5 + lineSlot; + } + + public boolean isShown() { + return lineId >= page * 5 && lineId < (page + 1) * 5; + } + + public void setItem(int lineSlot, ItemStack item) { + getInventory().setItem(getRawSlot(lineSlot), item); + } + + public ItemStack getItem(int lineSlot) { + return getInventory().getItem(getRawSlot(lineSlot)); + } + + } + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemComparisonGUI.java similarity index 96% rename from core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java rename to core/src/main/java/fr/skytasul/quests/gui/items/ItemComparisonGUI.java index 14f2d836..a1c89112 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemComparisonGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemComparisonGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.misc; +package fr.skytasul.quests.gui.items; import org.bukkit.DyeColor; import org.bukkit.event.inventory.ClickType; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java similarity index 51% rename from core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java rename to core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java index da290935..9320d2fa 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.misc; +package fr.skytasul.quests.gui.items; import java.util.ArrayList; import java.util.List; @@ -16,21 +16,15 @@ import fr.skytasul.quests.api.editors.TextListEditor; import fr.skytasul.quests.api.editors.checkers.MaterialParser; import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -public class ItemCreatorGUI extends Gui { +public class ItemCreatorGUI extends AbstractGui { - private Player p; private Consumer<ItemStack> run; private boolean allowCancel; - - public ItemCreatorGUI(Consumer<ItemStack> end, boolean allowCancel){ - run = end; - this.allowCancel = allowCancel; - } private XMaterial type; private int amount = 1; @@ -38,10 +32,14 @@ public ItemCreatorGUI(Consumer<ItemStack> end, boolean allowCancel){ private List<String> lore = new ArrayList<>(); private boolean quest = false; private boolean flags = false; - + + public ItemCreatorGUI(Consumer<ItemStack> end, boolean allowCancel) { + run = end; + this.allowCancel = allowCancel; + } + @Override protected Inventory instanciate(@NotNull Player player) { - this.p = player; return Bukkit.createInventory(null, 18, Lang.INVENTORY_CREATOR.toString()); } @@ -59,12 +57,8 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { inventory.getItem(17).setType(Material.COAL); } - private void reopen() { - reopen(p); - } - - private void refresh(){ - if (type != null){ + private void refresh() { + if (type != null) { getInventory().setItem(13, build()); if (getInventory().getItem(17).getType() != Material.DIAMOND) getInventory().getItem(17).setType(Material.DIAMOND); @@ -73,87 +67,91 @@ private void refresh(){ @Override public void onClick(GuiClickEvent event) { - switch (slot){ - case 0: - Lang.CHOOSE_ITEM_TYPE.send(p); - new TextEditor<>(p, this::reopen, obj -> { - type = obj; - reopen(); - }, MaterialParser.ITEM_PARSER).start(); - break; - - case 1: - Lang.CHOOSE_ITEM_AMOUNT.send(p); - new TextEditor<>(p, this::reopen, obj -> { - amount = /*Math.min(obj, 64)*/ obj; - ItemUtils.name(current, Lang.Amount.format(amount)); - reopen(); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); - break; - - case 2: - flags = ItemUtils.toggleSwitch(current); - refresh(); - break; - - case 3: - Lang.CHOOSE_ITEM_NAME.send(p); - new TextEditor<String>(p, this::reopen, obj -> { - name = obj; - reopen(); - }).start(); - break; - - case 4: - Lang.CHOOSE_ITEM_LORE.send(p); - new TextListEditor(p, list -> { - lore = list; - reopen(); - }, lore).start(); - break; - - case 6: - if (!quest){ - ItemUtils.name(current, Lang.itemQuest.toString() + " §a" + Lang.Yes.toString()); - quest = true; - }else { - ItemUtils.name(current, Lang.itemQuest.toString() + " §c" + Lang.No.toString()); - quest = false; - } - refresh(); - break; - - case 8: - close(p); - run.accept(null); - break; - - case 17: //VALIDATE - if (current.getType() == Material.DIAMOND){ - close(p); - run.accept(build()); - } - break; - - case 13: //GIVE - if (type != null) p.getOpenInventory().setCursor(build()); - break; + switch (event.getSlot()) { + case 0: + Lang.CHOOSE_ITEM_TYPE.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { + type = obj; + event.reopen(); + }, MaterialParser.ITEM_PARSER).start(); + break; + + case 1: + Lang.CHOOSE_ITEM_AMOUNT.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { + amount = /* Math.min(obj, 64) */ obj; + ItemUtils.name(event.getClicked(), Lang.Amount.format(amount)); + event.reopen(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); + break; + + case 2: + flags = ItemUtils.toggleSwitch(event.getClicked()); + refresh(); + break; + + case 3: + Lang.CHOOSE_ITEM_NAME.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { + name = obj; + event.reopen(); + }).start(); + break; + + case 4: + Lang.CHOOSE_ITEM_LORE.send(event.getPlayer()); + new TextListEditor(event.getPlayer(), list -> { + lore = list; + event.reopen(); + }, lore).start(); + break; + + case 6: + if (!quest) { + ItemUtils.name(event.getClicked(), Lang.itemQuest.toString() + " §a" + Lang.Yes.toString()); + quest = true; + } else { + ItemUtils.name(event.getClicked(), Lang.itemQuest.toString() + " §c" + Lang.No.toString()); + quest = false; + } + refresh(); + break; + + case 8: + close(event.getPlayer()); + run.accept(null); + break; + + case 17: // VALIDATE + if (event.getClicked().getType() == Material.DIAMOND) { + close(event.getPlayer()); + run.accept(build()); + } + break; + + case 13: // GIVE + if (type != null) + event.getPlayer().getOpenInventory().setCursor(build()); + break; } - return true; } - private ItemStack build(){ + private ItemStack build() { ItemStack is = type.parseItem(); ItemMeta im = is.getItemMeta(); - if (name != null) im.setDisplayName(name); - if (flags) im.addItemFlags(ItemFlag.values()); + if (name != null) + im.setDisplayName(name); + if (flags) + im.addItemFlags(ItemFlag.values()); is.setItemMeta(im); is.setAmount(amount); - if (lore != null) ItemUtils.lore(is, lore); + if (lore != null) + ItemUtils.lore(is, lore); - if (quest) ItemUtils.loreAdd(is, " ", Lang.QuestItemLore.toString()); + if (quest) + ItemUtils.loreAdd(is, " ", Lang.QuestItemLore.toString()); return is; } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemGUI.java similarity index 71% rename from core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java rename to core/src/main/java/fr/skytasul/quests/gui/items/ItemGUI.java index ffc98d66..5cd55c1e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ItemGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.misc; +package fr.skytasul.quests.gui.items; import java.util.function.Consumer; import org.bukkit.Bukkit; @@ -8,15 +8,15 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.gui.creation.ItemsGUI; +import fr.skytasul.quests.utils.QuestUtils; -public class ItemGUI extends Gui { +public class ItemGUI extends AbstractGui { private Consumer<ItemStack> end; private Runnable cancel; @@ -44,19 +44,15 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { @Override public void onClick(GuiClickEvent event) { - if (slot != 4) return true; - new ItemCreatorGUI((obj) -> { - end.accept(obj); - }, false).open(p); - return true; - } - - @Override - public boolean onClickCursor(Player p, ItemStack current, ItemStack cursor, int slot) { - if (slot != 4) return true; - p.setItemOnCursor(null); - end.accept(cursor); - return false; + if (event.getSlot() == 4) { + if (event.hasCursor()) { + event.getPlayer().setItemOnCursor(null); + event.setCancelled(false); + QuestUtils.runSync(() -> end.accept(event.getCursor())); + } else { + new ItemCreatorGUI(end, false).open(event.getPlayer()); + } + } } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java new file mode 100644 index 00000000..b69db00d --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java @@ -0,0 +1,112 @@ +package fr.skytasul.quests.gui.items; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; +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 com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.AbstractGui; +import fr.skytasul.quests.api.gui.GuiClickEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.utils.QuestUtils; + +public class ItemsGUI extends AbstractGui { + + public static ItemStack none = ItemUtils.item(XMaterial.RED_STAINED_GLASS_PANE, "§c", Lang.itemsNone.toString()); + + private Consumer<List<ItemStack>> end; + private Map<Integer, ItemStack> items = new HashMap<>(); + private int size; + + public ItemsGUI(Consumer<List<ItemStack>> end, List<ItemStack> itemsList) { + this.end = end; + Utils.extractItems(itemsList).forEach(item -> items.put(items.size(), item)); + this.size = (int) (Math.ceil((items.size() + 1D) / 9D) * 9); + } + + @Override + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, size, Lang.INVENTORY_ITEMS.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inv) { + inv.setItem(size - 1, ItemUtils.itemDone); + + for (int i = 0; i < size - 1; i++) { + if (i < items.size()) { + inv.setItem(i, items.get(i)); + }else inv.setItem(i, none); + } + } + + private boolean addItem(Player p, ItemStack item, int slot) { + items.put(slot, item); + for (int i = 0; i < size - 1; i++) { + ItemStack is = getInventory().getItem(i); + if (is.equals(none)) return false; + } + size += 9; + reopen(p, true); + return true; + } + + @Override + public void onClick(@NotNull GuiClickEvent event) { + if (event.hasCursor()) { + if (event.getSlot() == size - 1) + return; // means player wants to drop an item on the validation button + + if (none.equals(event.getClicked())) { + getInventory().setItem(event.getSlot(), event.getCursor()); + QuestUtils.runSync(() -> { + event.getPlayer().setItemOnCursor(null); + addItem(event.getPlayer(), event.getCursor(), event.getSlot()); + }); + } else { + QuestUtils.runSync(() -> items.put(event.getSlot(), event.getCursor())); + event.setCancelled(false); + } + } else { + // nothing in cursor + if (event.getSlot() == size - 1) { + event.close(); + end.accept(items.values().stream().filter(x -> x != null).collect(Collectors.toList())); + }else { + if (event.getClicked().equals(none)) { + new ItemCreatorGUI(item -> { + if (item != null) + getInventory().setItem(event.getSlot(), item); + if (!addItem(event.getPlayer(), item, event.getSlot())) + event.reopen(); + }, true).open(event.getPlayer()); + } else { + if (event.getClick().isLeftClick() || (event.getClick().isRightClick() && event.getClicked().getAmount() == 1)) { + QuestUtils.runSync(() -> { + getInventory().setItem(event.getSlot(), none); + items.remove(event.getSlot()); + }); + } else + QuestUtils.runSync(() -> items.put(event.getSlot(), getInventory().getItem(event.getSlot()))); + event.setCancelled(false); + } + } + } + } + + @Override + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REOPEN; + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java index d5eadb0c..622baa34 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java @@ -8,14 +8,14 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; -public class BranchesGUI extends Gui { // WIP +public class BranchesGUI extends AbstractGui { // WIP private Branch main = new Branch(null); diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/BucketTypeGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/BucketTypeGUI.java similarity index 76% rename from core/src/main/java/fr/skytasul/quests/gui/creation/BucketTypeGUI.java rename to core/src/main/java/fr/skytasul/quests/gui/misc/BucketTypeGUI.java index c4b58532..fad86fa7 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/BucketTypeGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/BucketTypeGUI.java @@ -1,14 +1,14 @@ -package fr.skytasul.quests.gui.creation; +package fr.skytasul.quests.gui.misc; import java.util.Arrays; import java.util.function.Consumer; import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.gui.templates.ChooseGUI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.stages.StageBucket.BucketType; public class BucketTypeGUI extends ChooseGUI<BucketType>{ @@ -38,9 +38,8 @@ public void finish(BucketType object){ } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Utils.runSync(cancel); - return StandardCloseBehavior.NOTHING; + public CloseBehavior onClose(Player p) { + return new DelayCloseBehavior(cancel); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java new file mode 100644 index 00000000..54dc228b --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java @@ -0,0 +1,94 @@ +package fr.skytasul.quests.gui.misc; + +import java.util.HashMap; +import java.util.function.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; +import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.utils.compatibility.DependenciesManager; +import fr.skytasul.quests.utils.types.Command; + +public class CommandGUI extends LayoutedGUI.LayoutedRowsGUI { + + private Consumer<Command> end; + + private String cmd; + private boolean console = false; + private boolean parse = false; + private int delay = 0; + + private final @NotNull LayoutedButton doneButton; + + public CommandGUI(Consumer<Command> end, Runnable cancel) { + super(Lang.INVENTORY_COMMAND.toString(), new HashMap<>(), new DelayCloseBehavior(cancel), 1); + this.end = end; + + buttons.put(1, + doneButton = LayoutedButton.createLoreValue(XMaterial.COMMAND_BLOCK, Lang.commandValue.toString(), () -> cmd, + this::commandClick)); + buttons.put(3, LayoutedButton.create(() -> ItemUtils.itemSwitch(Lang.commandConsole.toString(), console), + this::consoleClick)); + if (DependenciesManager.papi.isEnabled()) + buttons.put(4, LayoutedButton.create(() -> ItemUtils.itemSwitch(Lang.commandParse.toString(), parse), + this::parseClick)); + buttons.put(5, LayoutedButton.createLoreValue(XMaterial.CLOCK, Lang.commandDelay.toString(), () -> delay, + this::delayClick)); + buttons.put(8, + LayoutedButton.create(() -> cmd == null ? ItemUtils.itemNotDone : ItemUtils.itemDone, this::doneClick)); + } + + public CommandGUI setFromExistingCommand(@Nullable Command cmd) { + if (getInventory() != null) + throw new IllegalStateException("GUI has already been built"); + if (cmd != null) { + this.cmd = cmd.label; + this.console = cmd.console; + this.parse = cmd.parse; + this.delay = cmd.delay; + } + return this; + } + + private void commandClick(LayoutedClickEvent event) { + Lang.COMMAND.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, cmd -> { + this.cmd = cmd; + refresh(doneButton); + event.refreshItemReopen(); + }).passNullIntoEndConsumer().useStrippedMessage().start(); + } + + private void consoleClick(LayoutedClickEvent event) { + console = !console; + event.refreshItem(); + } + + private void parseClick(LayoutedClickEvent event) { + parse = !parse; + event.refreshItem(); + } + + private void delayClick(LayoutedClickEvent event) { + Lang.COMMAND_DELAY.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, x -> { + delay = x; + event.refreshItemReopen(); + }, NumberParser.INTEGER_PARSER_POSITIVE).start(); + } + + private void doneClick(LayoutedClickEvent event) { + if (cmd != null) { + event.close(); + end.accept(new Command(cmd, console, parse, delay)); + } + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index fe2deb0e..96a1cb1e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -10,7 +10,7 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -20,29 +20,29 @@ import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.utils.types.Title; -public class TitleGUI extends Gui { - +public class TitleGUI extends AbstractGui { + private static final int SLOT_TITLE = 0; private static final int SLOT_SUBTITLE = 1; private static final int SLOT_FADE_IN = 3; private static final int SLOT_STAY = 4; private static final int SLOT_FADE_OUT = 5; - + private Consumer<Title> end; private String title; private String subtitle; private int fadeIn = Title.FADE_IN; private int stay = Title.STAY; private int fadeOut = Title.FADE_OUT; - + private boolean canFinish = false; - + private Inventory inv; - + public TitleGUI(Consumer<Title> end) { this.end = end; } - + public TitleGUI edit(Title edit) { if (edit != null) { title = edit.title; @@ -53,41 +53,44 @@ public TitleGUI edit(Title edit) { } return this; } - + private void updateFinishState() { canFinish = title != null || subtitle != null; if (inv != null) { Material material = canFinish ? Material.DIAMOND : Material.COAL; ItemStack item = inv.getItem(8); - if (item.getType() != material) item.setType(material); + if (item.getType() != material) + item.setType(material); } } - + public void setTitle(String title) { this.title = title; ItemUtils.lore(inv.getItem(SLOT_TITLE), QuestOption.formatNullableValue(title)); } - + public void setSubtitle(String subtitle) { this.subtitle = subtitle; ItemUtils.lore(inv.getItem(SLOT_SUBTITLE), QuestOption.formatNullableValue(subtitle)); } - + public void setFadeIn(int fadeIn) { this.fadeIn = fadeIn; - ItemUtils.lore(inv.getItem(SLOT_FADE_IN), QuestOption.formatNullableValue(Lang.Ticks.format(fadeIn), fadeIn == Title.FADE_IN)); + ItemUtils.lore(inv.getItem(SLOT_FADE_IN), + QuestOption.formatNullableValue(Lang.Ticks.format(fadeIn), fadeIn == Title.FADE_IN)); } - + public void setStay(int stay) { this.stay = stay; ItemUtils.lore(inv.getItem(SLOT_STAY), QuestOption.formatNullableValue(Lang.Ticks.format(stay), stay == Title.STAY)); } - + public void setFadeOut(int fadeOut) { this.fadeOut = fadeOut; - ItemUtils.lore(inv.getItem(SLOT_FADE_OUT), QuestOption.formatNullableValue(Lang.Ticks.format(fadeOut), fadeOut == Title.FADE_OUT)); + ItemUtils.lore(inv.getItem(SLOT_FADE_OUT), + QuestOption.formatNullableValue(Lang.Ticks.format(fadeOut), fadeOut == Title.FADE_OUT)); } - + @Override protected Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, 9, Lang.INVENTORY_EDIT_TITLE.toString()); @@ -100,10 +103,10 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { inventory.setItem(SLOT_FADE_IN, ItemUtils.item(XMaterial.CLOCK, Lang.title_fadeIn.toString())); inventory.setItem(SLOT_STAY, ItemUtils.item(XMaterial.CLOCK, Lang.title_stay.toString())); inventory.setItem(SLOT_FADE_OUT, ItemUtils.item(XMaterial.CLOCK, Lang.title_fadeOut.toString())); - + inventory.setItem(7, ItemUtils.itemCancel); inventory.setItem(8, ItemUtils.itemDone.toMutableStack()); - + // updating lores setTitle(title); setSubtitle(subtitle); @@ -112,39 +115,38 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { setFadeOut(fadeOut); updateFinishState(); } - + @Override public void onClick(GuiClickEvent event) { - switch (slot) { - case SLOT_TITLE: - startStringEditor(player, Lang.TITLE_TITLE.toString(), this::setTitle); - break; - case SLOT_SUBTITLE: - startStringEditor(player, Lang.TITLE_SUBTITLE.toString(), this::setSubtitle); - break; - case SLOT_FADE_IN: - startIntEditor(player, Lang.TITLE_FADEIN.toString(), this::setFadeIn); - break; - case SLOT_STAY: - startIntEditor(player, Lang.TITLE_STAY.toString(), this::setStay); - break; - case SLOT_FADE_OUT: - startIntEditor(player, Lang.TITLE_FADEOUT.toString(), this::setFadeOut); - break; - case 7: - close(player); - end.accept(null); - break; - case 8: - close(player); - end.accept(new Title(title, subtitle, fadeIn, stay, fadeOut)); - break; - default: - break; + switch (event.getSlot()) { + case SLOT_TITLE: + startStringEditor(event.getPlayer(), Lang.TITLE_TITLE.toString(), this::setTitle); + break; + case SLOT_SUBTITLE: + startStringEditor(event.getPlayer(), Lang.TITLE_SUBTITLE.toString(), this::setSubtitle); + break; + case SLOT_FADE_IN: + startIntEditor(event.getPlayer(), Lang.TITLE_FADEIN.toString(), this::setFadeIn); + break; + case SLOT_STAY: + startIntEditor(event.getPlayer(), Lang.TITLE_STAY.toString(), this::setStay); + break; + case SLOT_FADE_OUT: + startIntEditor(event.getPlayer(), Lang.TITLE_FADEOUT.toString(), this::setFadeOut); + break; + case 7: + close(event.getPlayer()); + end.accept(null); + break; + case 8: + close(event.getPlayer()); + end.accept(new Title(title, subtitle, fadeIn, stay, fadeOut)); + break; + default: + break; } - return true; } - + @Override public CloseBehavior onClose(Player p) { return new DelayCloseBehavior(() -> end.accept(null)); @@ -160,7 +162,7 @@ private void startStringEditor(Player p, String helpMsg, Consumer<String> setter p.openInventory(inv); }).passNullIntoEndConsumer().start(); } - + private void startIntEditor(Player p, String helpMsg, Consumer<Integer> setter) { MessageUtils.sendPrefixedMessage(p, helpMsg); new TextEditor<>(p, () -> { @@ -170,5 +172,5 @@ private void startIntEditor(Player p, String helpMsg, Consumer<Integer> setter) p.openInventory(inv); }, NumberParser.INTEGER_PARSER_POSITIVE).start(); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index 8dc86309..89638e1e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -11,7 +11,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -21,7 +21,7 @@ import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -public class NpcCreateGUI extends Gui { +public class NpcCreateGUI extends AbstractGui { private static final ItemStack nameItem = ItemUtils.item(XMaterial.NAME_TAG, Lang.name.toString()); private static final ItemStack move = ItemUtils.item(XMaterial.MINECART, Lang.move.toString(), Lang.moveLore.toString()); @@ -76,53 +76,52 @@ private void setSkin(String skin) { @Override public void onClick(GuiClickEvent event) { - switch (slot){ + switch (event.getSlot()) { case 0: - new WaitClick(p, () -> reopen(p), validMove.clone(), () -> reopen(p)).start(); + new WaitClick(event.getPlayer(), event::reopen, validMove.clone(), event::reopen).start(); break; case 1: - Lang.NPC_NAME.send(p); - new TextEditor<String>(p, () -> reopen(p), obj -> { + Lang.NPC_NAME.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { setName(obj); - reopen(p); + event.reopen(); }).start(); break; case 3: - Lang.NPC_SKIN.send(p); - new TextEditor<String>(p, () -> reopen(p), obj -> { + Lang.NPC_SKIN.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { if (obj != null) setSkin(obj); - reopen(p); + event.reopen(); }).useStrippedMessage().start(); break; case 5: new EntityTypeGUI(en -> { setType(en); - reopen(p); - }, x -> x != null && QuestsAPI.getAPI().getNPCsManager().isValidEntityType(x)).open(p); + event.reopen(); + }, x -> x != null && QuestsAPI.getAPI().getNPCsManager().isValidEntityType(x)).open(event.getPlayer()); break; case 7: - close(p); + event.close(); cancel.run(); break; case 8: - close(p); + event.close(); try { - end.accept(QuestsAPI.getAPI().getNPCsManager().createNPC(p.getLocation(), en, name, skin)); + end.accept(QuestsAPI.getAPI().getNPCsManager().createNPC(event.getPlayer().getLocation(), en, name, skin)); }catch (Exception ex) { ex.printStackTrace(); - Lang.ERROR_OCCURED.send(p, "npc creation " + ex.getMessage()); + Lang.ERROR_OCCURED.send(event.getPlayer(), "npc creation " + ex.getMessage()); cancel.run(); } break; } - return true; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index 382078d2..c78a47ef 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.SelectNPC; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.gui.layout.LayoutedButton; @@ -23,16 +23,16 @@ private NpcSelectGUI() {} public static ItemStack createNPC = ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.createNPC.toString()); public static ItemStack selectNPC = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); - public static @NotNull Gui select(@NotNull Runnable cancel, @NotNull Consumer<@NotNull BQNPC> end) { + public static @NotNull AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<@NotNull BQNPC> end) { return select(cancel, end, false); } - public static @NotNull Gui selectNullable(@NotNull Runnable cancel, + public static @NotNull AbstractGui selectNullable(@NotNull Runnable cancel, @NotNull Consumer<@Nullable BQNPC> end) { return select(cancel, end, true); } - private static Gui select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, + private static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, boolean nullable) { Builder builder = LayoutedGUI.newBuilder().addButton(1, LayoutedButton.create(createNPC, event -> { new NpcCreateGUI(end, event::reopen).open(event.getPlayer()); diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index 7c973891..fa645a19 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -1,36 +1,30 @@ package fr.skytasul.quests.gui.particles; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.function.Consumer; import java.util.stream.Collectors; -import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Particle; -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 com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.ColorParser; -import fr.skytasul.quests.api.gui.Gui; -import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; +import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; import fr.skytasul.quests.utils.compatibility.Post1_13; -public class ParticleEffectGUI extends Gui { - - private static final int SLOT_SHAPE = 1; - private static final int SLOT_PARTICLE = 3; - private static final int SLOT_COLOR = 4; - private static final int SLOT_CANCEL = 7; - private static final int SLOT_FINISH = 8; +public class ParticleEffectGUI extends LayoutedGUI.LayoutedRowsGUI { static final List<Particle> PARTICLES = Arrays.stream(Particle.values()).filter(particle -> { if (particle.getDataType() == Void.class) return true; @@ -44,8 +38,6 @@ public class ParticleEffectGUI extends Gui { private ParticleShape shape; private Color color; - private Inventory inv; - public ParticleEffectGUI(Consumer<ParticleEffect> end) { this(end, Particle.FLAME, ParticleShape.POINT, Color.AQUA); } @@ -55,91 +47,66 @@ public ParticleEffectGUI(Consumer<ParticleEffect> end, ParticleEffect effect) { } public ParticleEffectGUI(Consumer<ParticleEffect> end, Particle particle, ParticleShape shape, Color color) { + super(Lang.INVENTORY_PARTICLE_EFFECT.toString(), new HashMap<>(), new DelayCloseBehavior(() -> end.accept(null)), 1); this.end = end; this.particle = particle; this.shape = shape; this.color = color; - } - - @Override - protected Inventory instanciate(@NotNull Player player) { - return Bukkit.createInventory(null, 9, Lang.INVENTORY_PARTICLE_EFFECT.toString()); - } - @Override - protected void populate(@NotNull Player player, @NotNull Inventory inventory) { - inventory.setItem(SLOT_SHAPE, - ItemUtils.item(XMaterial.FIREWORK_STAR, Lang.particle_shape.toString(), Lang.optionValue.format(shape))); - inventory.setItem(SLOT_PARTICLE, - ItemUtils.item(XMaterial.PAPER, Lang.particle_type.toString(), Lang.optionValue.format(particle))); - if (ParticleEffect.canHaveColor(particle)) - setColorItem(); + buttons.put(1, LayoutedButton.create(XMaterial.FIREWORK_STAR, Lang.particle_shape.toString(), + () -> Arrays.asList(Lang.optionValue.format(shape)), this::shapeClick)); + buttons.put(3, LayoutedButton.create(XMaterial.PAPER, Lang.particle_type.toString(), + () -> Arrays.asList(Lang.optionValue.format(particle)), this::particleClick)); + buttons.put(4, new LayoutedButton.ItemButton() { + @Override + public void click(@NotNull LayoutedClickEvent event) { + colorClick(event); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemUtils.item(XMaterial.MAGENTA_DYE, Lang.particle_color.toString(), + Lang.optionValue.format("RGB: " + color.getRed() + " " + color.getGreen() + " " + color.getBlue())); + } + + @Override + public boolean isValid() { + return ParticleEffect.canHaveColor(particle); + } + }); + buttons.put(7, LayoutedButton.create(ItemUtils.itemCancel, this::cancelClick)); + buttons.put(8, LayoutedButton.create(ItemUtils.itemDone, this::doneClick)); + } - inventory.setItem(SLOT_CANCEL, ItemUtils.itemCancel); - inventory.setItem(SLOT_FINISH, ItemUtils.itemDone); + private void shapeClick(LayoutedClickEvent event) { + List<ParticleShape> shapes = Arrays.asList(ParticleShape.values()); + int index = shapes.indexOf(shape); + shape = shapes.get(index == shapes.size() - 1 ? 0 : (index + 1)); + event.refreshItem(); } - - @Override - public CloseBehavior onClose(Player p) { - return new DelayCloseBehavior(() -> end.accept(null)); + + private void particleClick(LayoutedClickEvent event) { + new ParticleListGUI(existing -> { + if (existing != null) + particle = existing; + event.refreshGuiReopen(); // refresh gui to refresh color button + }).allowCancel().open(event.getPlayer()); } - - @Override - public void onClick(GuiClickEvent event) { - switch (slot) { - - case SLOT_SHAPE: - List<ParticleShape> shapes = Arrays.asList(ParticleShape.values()); - int index = shapes.indexOf(shape); - shape = shapes.get(index == shapes.size() - 1 ? 0 : (index + 1)); - ItemUtils.lore(current, Lang.optionValue.format(shape)); - break; - - case SLOT_PARTICLE: - new ParticleListGUI(existing -> { - if (existing != null) { - particle = existing; - ItemUtils.lore(current, Lang.optionValue.format(particle)); - if (ParticleEffect.canHaveColor(existing)) { - setColorItem(); - }else { - inv.setItem(SLOT_COLOR, null); - } - } - ParticleEffectGUI.this.open(p); - }).allowCancel().open(p); - break; - - case SLOT_COLOR: - if (ParticleEffect.canHaveColor(particle)) { - Runnable reopen = () -> open(p); - Lang.COLOR_EDITOR.send(p); - new TextEditor<>(p, reopen, newColor -> { - color = newColor; - ItemUtils.lore(current, getColorLore()); - reopen.run(); - }, ColorParser.PARSER).start(); - } - break; - - case SLOT_CANCEL: - end.accept(null); - break; - - case SLOT_FINISH: - end.accept(new ParticleEffect(particle, shape, color)); - break; - } - return true; + + private void colorClick(LayoutedClickEvent event) { + Lang.COLOR_EDITOR.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, newColor -> { + color = newColor; + event.refreshItemReopen(); + }, ColorParser.PARSER).start(); } - - private void setColorItem() { - if (color == null) color = Color.RED; - inv.setItem(SLOT_COLOR, ItemUtils.item(XMaterial.MAGENTA_DYE, Lang.particle_color.toString(), getColorLore())); + + private void cancelClick(LayoutedClickEvent event) { + end.accept(null); } - private String[] getColorLore() { - return new String[] { Lang.optionValue.format("RGB: " + color.getRed() + " " + color.getGreen() + " " + color.getBlue()) }; + private void doneClick(LayoutedClickEvent event) { + end.accept(new ParticleEffect(particle, shape, color)); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java index 68dd338b..e0cfb3e0 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java @@ -11,7 +11,7 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.WorldParser; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -19,7 +19,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.utils.types.Permission; -public class PermissionGUI extends Gui { +public class PermissionGUI extends AbstractGui { private String perm, world = null; private boolean take = false; @@ -53,34 +53,34 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { @Override public void onClick(GuiClickEvent event) { - switch (slot) { + switch (event.getSlot()) { case 0: - Lang.CHOOSE_PERM_REWARD.send(p); - new TextEditor<String>(p, () -> reopen(p), x -> { + Lang.CHOOSE_PERM_REWARD.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, x -> { getInventory().getItem(4).setType(Material.DIAMOND); - updatePerm(p, x); + updatePerm(event.getPlayer(), x); }, () -> { getInventory().getItem(4).setType(Material.COAL); - updatePerm(p, null); + updatePerm(event.getPlayer(), null); }).useStrippedMessage().start(); break; case 1: - Lang.CHOOSE_PERM_WORLD.send(p); - new TextEditor<>(p, () -> reopen(p), worldS -> { - updateWorld(p, worldS.getName()); + Lang.CHOOSE_PERM_WORLD.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, worldS -> { + updateWorld(event.getPlayer(), worldS.getName()); }, () -> { - updateWorld(p, null); + updateWorld(event.getPlayer(), null); }, new WorldParser()).start(); break; case 2: - take = ItemUtils.toggleSwitch(current); + take = ItemUtils.toggleSwitch(event.getClicked()); break; case 4: - if (current.getType() == Material.COAL) break; + if (event.getClicked().getType() == Material.COAL) + break; end.accept(new Permission(perm, take, world)); break; } - return true; } private void updatePerm(Player p, String perm) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index 6a00a2d8..ed3d07a0 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -1,7 +1,5 @@ package fr.skytasul.quests.gui.pools; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.TimeUnit; import org.bukkit.Bukkit; import org.bukkit.Sound; @@ -15,18 +13,18 @@ import fr.skytasul.quests.api.editors.checkers.DurationParser; import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.pools.QuestPool; -import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.npc.NpcSelectGUI; -public class PoolEditGUI extends Gui { +public class PoolEditGUI extends AbstractGui { private static final int SLOT_NPC = 1; private static final int SLOT_HOLOGRAM = 2; @@ -48,7 +46,7 @@ public class PoolEditGUI extends Gui { private long timeDiff = TimeUnit.DAYS.toMillis(1); private int npcID = -1; private boolean avoidDuplicates = true; - private List<AbstractRequirement> requirements = new ArrayList<>(); + private RequirementList requirements = new RequirementList(); private boolean canFinish = false; private QuestPool editing; @@ -122,59 +120,59 @@ protected void populate(@NotNull Player player, @NotNull Inventory inv) { @Override public void onClick(GuiClickEvent event) { - switch (slot) { + switch (event.getSlot()) { case SLOT_NPC: - NpcSelectGUI.select(() -> reopen(p), npc -> { + NpcSelectGUI.select(event::reopen, npc -> { npcID = npc.getId(); - ItemUtils.lore(current, getNPCLore()); + ItemUtils.lore(event.getClicked(), getNPCLore()); handleDoneButton(getInventory()); - reopen(p); - }).open(p); + reopen(event.getPlayer()); + }).open(event.getPlayer()); break; case SLOT_HOLOGRAM: - Lang.POOL_HOLOGRAM_TEXT.send(p); - new TextEditor<String>(p, () -> reopen(p), msg -> { + Lang.POOL_HOLOGRAM_TEXT.send(event.getPlayer()); + new TextEditor<String>(event.getPlayer(), event::reopen, msg -> { hologram = msg; - ItemUtils.lore(current, getHologramLore()); - reopen(p); + ItemUtils.lore(event.getClicked(), getHologramLore()); + reopen(event.getPlayer()); }).passNullIntoEndConsumer().start(); break; case SLOT_MAX_QUESTS: - Lang.POOL_MAXQUESTS.send(p); - new TextEditor<>(p, () -> reopen(p), msg -> { + Lang.POOL_MAXQUESTS.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, msg -> { maxQuests = msg; - ItemUtils.lore(current, getMaxQuestsLore()); - reopen(p); + ItemUtils.lore(event.getClicked(), getMaxQuestsLore()); + reopen(event.getPlayer()); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; case SLOT_QUESTS_PER_LAUNCH: - Lang.POOL_QUESTS_PER_LAUNCH.send(p); - new TextEditor<>(p, () -> reopen(p), msg -> { + Lang.POOL_QUESTS_PER_LAUNCH.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, msg -> { questsPerLaunch = msg; - ItemUtils.lore(current, getQuestsPerLaunchLore()); - reopen(p); + ItemUtils.lore(event.getClicked(), getQuestsPerLaunchLore()); + reopen(event.getPlayer()); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; case SLOT_TIME: - Lang.POOL_TIME.send(p); - new TextEditor<>(p, () -> reopen(p), msg -> { + Lang.POOL_TIME.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, msg -> { timeDiff = msg * 1000; - ItemUtils.lore(current, getTimeLore()); - reopen(p); + ItemUtils.lore(event.getClicked(), getTimeLore()); + reopen(event.getPlayer()); }, new DurationParser(MinecraftTimeUnit.SECOND, MinecraftTimeUnit.DAY)).start(); break; case SLOT_REDO: - redoAllowed = ItemUtils.toggleSwitch(current); + redoAllowed = ItemUtils.toggleSwitch(event.getClicked()); break; case SLOT_DUPLICATE: - avoidDuplicates = ItemUtils.toggleSwitch(current); + avoidDuplicates = ItemUtils.toggleSwitch(event.getClicked()); break; case SLOT_REQUIREMENTS: - QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.POOL, requirements -> { - PoolEditGUI.this.requirements = requirements; - ItemUtils.lore(current, getRequirementsLore()); - reopen(p); - }, requirements).open(p); + QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.POOL, newRequirements -> { + requirements = new RequirementList(newRequirements); + ItemUtils.lore(event.getClicked(), getRequirementsLore()); + reopen(event.getPlayer()); + }, requirements).open(event.getPlayer()); break; case SLOT_CANCEL: @@ -184,10 +182,10 @@ public void onClick(GuiClickEvent event) { if (canFinish) { BeautyQuests.getInstance().getPoolsManager().createPool(editing, npcID, hologram, maxQuests, questsPerLaunch, redoAllowed, timeDiff, avoidDuplicates, requirements); end.run(); - }else p.playSound(p.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); + } else + event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); break; } - return true; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java index 4a8c6e9b..0dec444b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java @@ -11,7 +11,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -63,7 +63,8 @@ public static void choose(@NotNull Player player, @NotNull Collection<@NotNull Q if (quests.isEmpty()) { if (cancel != null) cancel.run(); - } else if (quests.size() == 1 && canSkip && QuestsConfigurationImplementation.skipNpcGuiIfOnlyOneQuest()) { + } else if (quests.size() == 1 && canSkip + && QuestsConfiguration.getConfig().getQuestsConfig().skipNpcGuiIfOnlyOneQuest()) { run.accept(quests.iterator().next()); } else { ChooseQuestGUI gui = new ChooseQuestGUI(quests, run, cancel); 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 9fdb57aa..a6f2575d 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 @@ -14,7 +14,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.gui.templates.PagedGUI; @@ -134,8 +134,9 @@ class WrappedDialogable { List<String> msg = lines.get(i); boolean last = i + 1 == lines.size(); boolean pageFull = !page.lines.isEmpty() && page.lines.size() + msg.size() > MAX_LINES; - if (QuestsConfigurationImplementation.getDialogsConfig().getMaxMessagesPerHistoryPage() > 0) - pageFull |= messagesInPage >= QuestsConfigurationImplementation.getDialogsConfig().getMaxMessagesPerHistoryPage(); + if (QuestsConfiguration.getConfig().getDialogsConfig().getMaxMessagesPerHistoryPage() > 0) + pageFull |= messagesInPage >= QuestsConfiguration.getConfig().getDialogsConfig() + .getMaxMessagesPerHistoryPage(); if (last || pageFull) { // means the page currently in writing must be flushed 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 5386c342..9a45f8fb 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 @@ -16,7 +16,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -31,7 +31,7 @@ import fr.skytasul.quests.players.PlayerAccountImplementation; import fr.skytasul.quests.utils.QuestUtils; -public class PlayerListGUI extends Gui { +public class PlayerListGUI extends AbstractGui { static final String UNSELECTED_PREFIX = "§7○ "; private static final String SELECTED_PREFIX = "§b§l● "; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java index 5f059c48..bea95d69 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java @@ -1,9 +1,6 @@ package fr.skytasul.quests.options; import java.util.stream.Collectors; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.gui.ItemUtils; @@ -11,36 +8,34 @@ import fr.skytasul.quests.api.objects.QuestObjectGUI; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOptionRewards; -import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.api.rewards.RewardList; public class OptionCancelRewards extends QuestOptionRewards { - - @Override - protected void attachedAsyncReward(AbstractReward reward) {} - + @Override public XMaterial getItemMaterial() { return XMaterial.TNT_MINECART; } - + @Override public String getItemName() { return Lang.cancelRewards.toString(); } - + @Override public String getItemDescription() { return Lang.cancelRewardsLore.toString(); } - + @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - new QuestObjectGUI<>(Lang.INVENTORY_CANCEL_ACTIONS.toString(), QuestObjectLocation.CANCELLING, QuestsAPI.getAPI().getRewards().getCreators().stream().filter(x -> !x.canBeAsync()).collect(Collectors.toList()), objects -> { - setValue(objects); - ItemUtils.lore(item, getLore()); - gui.reopen(p); - }, getValue()).open(p); + public void click(QuestCreationGuiClickEvent event) { + new QuestObjectGUI<>(Lang.INVENTORY_CANCEL_ACTIONS.toString(), QuestObjectLocation.CANCELLING, QuestsAPI.getAPI() + .getRewards().getCreators().stream().filter(x -> !x.canBeAsync()).collect(Collectors.toList()), objects -> { + setValue(new RewardList(objects)); + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); + }, getValue()).open(event.getPlayer()); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java b/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java index 3da05556..c0aab2a3 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionCancellable.java @@ -1,6 +1,6 @@ package fr.skytasul.quests.options; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionBoolean; @@ -9,7 +9,7 @@ public class OptionCancellable extends QuestOptionBoolean { @Override public boolean shouldDisplay(OptionSet options) { - return QuestsConfigurationImplementation.getMenuConfig().allowPlayerCancelQuest(); + return QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java index 37420d93..f1cb427a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java @@ -2,7 +2,7 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; @@ -31,7 +31,7 @@ public String getItemDescription() { @Override public boolean shouldDisplay(OptionSet options) { - return QuestsConfigurationImplementation.questConfirmGUI(); + return QuestsConfiguration.getConfig().getQuestsConfig().questConfirmGUI(); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java index b1ff6dfd..df12533a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java @@ -11,7 +11,7 @@ import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.MessageUtils; public class OptionDescription extends QuestOptionString implements QuestDescriptionProvider { @@ -55,7 +55,8 @@ public boolean isMultiline() { public List<String> provideDescription(QuestDescriptionContext context) { List<String> description = cachedDescription.getIfPresent(context); if (description == null) { - description = Arrays.asList("§7" + Utils.finalFormat(context.getPlayerAccount().getPlayer(), getValue(), true)); + description = + Arrays.asList("§7" + MessageUtils.finalFormat(context.getPlayerAccount().getPlayer(), getValue(), true)); cachedDescription.put(context, description); } return description; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java index 2febe195..d62f3b74 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java @@ -9,19 +9,13 @@ import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.PlayerListCategory; -import fr.skytasul.quests.api.utils.Utils; public class OptionEndRewards extends QuestOptionRewards implements QuestDescriptionProvider { private static final Pattern SPLIT_PATTERN = Pattern.compile("\\{JOIN\\}"); - @Override - protected void attachedAsyncReward(AbstractReward reward) { - getAttachedQuest().asyncEnd = true; - } - @Override public XMaterial getItemMaterial() { return XMaterial.CHEST; @@ -48,7 +42,7 @@ public List<String> provideDescription(QuestDescriptionContext context) { .filter(Objects::nonNull) .flatMap(SPLIT_PATTERN::splitAsStream) .filter(x -> !x.isEmpty()) - .map(x -> Utils.format(context.getDescriptionOptions().getRewardsFormat(), x)) + .map(x -> MessageUtils.format(context.getDescriptionOptions().getRewardsFormat(), x)) .collect(Collectors.toList()); if (rewards.isEmpty()) return null; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java index 74d335d6..95d3f2be 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java @@ -5,8 +5,8 @@ import org.bukkit.event.entity.PlayerDeathEvent; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionBoolean; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.players.PlayerAccountImplementation; public class OptionFailOnDeath extends QuestOptionBoolean implements Listener { @@ -22,7 +22,7 @@ public String getDescription() { @EventHandler public void onDeath(PlayerDeathEvent e) { - PlayerAccountImplementation acc = PlayersManager.getPlayerAccount(e.getEntity()); + PlayerAccount acc = PlayersManager.getPlayerAccount(e.getEntity()); if (acc == null) return; if (getAttachedQuest().hasStarted(acc)) { getAttachedQuest().cancelPlayer(acc); diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java index b784bbc3..6f51efcf 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java @@ -3,19 +3,18 @@ import java.util.ArrayList; import java.util.List; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.utils.QuestUtils; public class OptionFirework extends QuestOption<FireworkMeta> { @@ -64,34 +63,32 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - if (click == ClickType.SHIFT_RIGHT) { - resetValue(); - ItemUtils.lore(item, getLore()); - }else if (click == ClickType.RIGHT) { - setValue(null); - Lang.FIREWORK_REMOVED.send(p); - ItemUtils.lore(item, getLore()); - } - } - - @Override - public boolean clickCursor(FinishGUI gui, Player p, ItemStack item, ItemStack cursor, int slot) { - ItemMeta cursorMeta = cursor.getItemMeta(); - if (cursorMeta instanceof FireworkMeta) { - setValue((FireworkMeta) cursorMeta); - ItemUtils.lore(item, getLore()); - Utils.runSync(() -> player.setItemOnCursor(null)); - Lang.FIREWORK_EDITED.send(p); + public void click(QuestCreationGuiClickEvent event) { + if (event.hasCursor()) { + ItemMeta cursorMeta = event.getCursor().getItemMeta(); + if (cursorMeta instanceof FireworkMeta) { + setValue((FireworkMeta) cursorMeta); + ItemUtils.lore(event.getClicked(), getLore()); + QuestUtils.runSync(() -> event.getPlayer().setItemOnCursor(null)); + Lang.FIREWORK_EDITED.send(event.getPlayer()); + } else { + Lang.FIREWORK_INVALID.send(event.getPlayer()); + } }else { - Lang.FIREWORK_INVALID.send(p); + if (event.getClick() == ClickType.SHIFT_RIGHT) { + resetValue(); + ItemUtils.lore(event.getClicked(), getLore()); + } else if (event.getClick() == ClickType.RIGHT) { + setValue(null); + Lang.FIREWORK_REMOVED.send(event.getPlayer()); + ItemUtils.lore(event.getClicked(), getLore()); + } } - return true; } @Override public boolean shouldDisplay(OptionSet options) { - return QuestsConfigurationImplementation.doFireworks(); + return QuestsConfiguration.getConfig().getQuestsConfig().fireworks(); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java index acfe7aee..38f4ac06 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java @@ -36,7 +36,8 @@ public String getItemDescription() { @Override public boolean shouldDisplay(OptionSet options) { - return !QuestsConfigurationImplementation.isTextHologramDisabled() && QuestsAPI.getAPI().hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; + return !QuestsConfigurationImplementation.getConfiguration().isTextHologramDisabled() + && QuestsAPI.getAPI().hasHologramsManager() && options.getOption(OptionStarterNPC.class).getValue() != null; } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java index 6ce3a889..d724ad85 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java @@ -2,8 +2,6 @@ import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; @@ -12,8 +10,8 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.utils.QuestUtils; public class OptionQuestItem extends QuestOption<ItemStack> { @@ -54,32 +52,31 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - Lang.QUEST_MATERIAL.send(p); - new TextEditor<>(p, () -> gui.reopen(p), obj -> { - if (obj == null) { - resetValue(); - }else { - setValue(obj.parseItem()); - } - gui.inv.setItem(slot, ItemUtils.nameAndLore(getValue().clone(), Lang.customMaterial.toString(), getLore())); - ItemStack setItem = gui.inv.getItem(slot); - if (setItem == null || setItem.getType() == Material.AIR) { - // means that the material cannot be treated as an inventory item (ex: fire) - resetValue(); - Lang.INVALID_ITEM_TYPE.send(p); - gui.inv.setItem(slot, ItemUtils.nameAndLore(getValue().clone(), Lang.customMaterial.toString(), getLore())); - } - gui.reopen(p); - }, MaterialParser.ANY_PARSER).passNullIntoEndConsumer().start(); - } - - @Override - public boolean clickCursor(FinishGUI gui, Player p, ItemStack item, ItemStack cursor, int slot) { - Utils.runSync(() -> player.setItemOnCursor(null)); - setValue(cursor); - ItemUtils.nameAndLore(cursor, Lang.customMaterial.toString(), getLore()); - return false; + public void click(QuestCreationGuiClickEvent event) { + if (event.hasCursor()) { + QuestUtils.runSync(() -> event.getPlayer().setItemOnCursor(null)); + setValue(event.getCursor()); + ItemUtils.nameAndLore(event.getCursor(), Lang.customMaterial.toString(), getLore()); + event.setCancelled(false); + } else { + Lang.QUEST_MATERIAL.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { + if (obj == null) { + resetValue(); + } else { + setValue(obj.parseItem()); + } + event.getGui().updateOptionItem(this); + ItemStack setItem = event.getGui().getInventory().getItem(event.getSlot()); + if (setItem == null || setItem.getType() == Material.AIR) { + // means that the material cannot be treated as an inventory item (ex: fire) + resetValue(); + Lang.INVALID_ITEM_TYPE.send(event.getPlayer()); + event.getGui().updateOptionItem(this); + } + event.reopen(); + }, MaterialParser.ANY_PARSER).passNullIntoEndConsumer().start(); + } } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java index 56c3cbeb..af14717d 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java @@ -2,28 +2,28 @@ import java.util.ArrayList; import java.util.List; -import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.OpenCloseBehavior; import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.creation.FinishGUI; -import fr.skytasul.quests.structure.QuestImplementation; -import fr.skytasul.quests.structure.pools.QuestPoolImplementation; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; -public class OptionQuestPool extends QuestOption<QuestPoolImplementation> { +public class OptionQuestPool extends QuestOption<QuestPool> { @Override - public void attach(QuestImplementation quest) { + public void attach(Quest quest) { super.attach(quest); if (getValue() != null) getValue().addQuest(quest); } @@ -45,7 +45,7 @@ public void load(ConfigurationSection config, String key) { } @Override - public QuestPoolImplementation cloneValue(QuestPoolImplementation value) { + public QuestPool cloneValue(QuestPool value) { return value; } @@ -67,32 +67,31 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - if (click == ClickType.SHIFT_RIGHT) { + public void click(QuestCreationGuiClickEvent event) { + if (event.getClick() == ClickType.SHIFT_RIGHT) { setValue(null); - ItemUtils.lore(item, getLore()); - gui.reopen(p); + ItemUtils.lore(event.getClicked(), getLore()); }else { - new PagedGUI<QuestPoolImplementation>(Lang.INVENTORY_POOLS_LIST.toString(), DyeColor.CYAN, BeautyQuests.getInstance().getPoolsManager().getPools(), list -> gui.reopen(p), null) { + new PagedGUI<QuestPool>(Lang.INVENTORY_POOLS_LIST.toString(), DyeColor.CYAN, + BeautyQuests.getInstance().getPoolsManager().getPools(), list -> event.reopen(), null) { @Override - public ItemStack getItemStack(QuestPoolImplementation object) { + public ItemStack getItemStack(QuestPool object) { return object.getItemStack(Lang.poolChoose.toString()); } @Override - public void click(QuestPoolImplementation existing, ItemStack poolItem, ClickType click) { + public void click(QuestPool existing, ItemStack poolItem, ClickType click) { setValue(existing); - ItemUtils.lore(item, getLore()); - gui.reopen(player); + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); } @Override - public CloseBehavior onClose(Player p, Inventory inv) { - Bukkit.getScheduler().runTask(BeautyQuests.getInstance(), () -> gui.reopen(p)); - return StandardCloseBehavior.NOTHING; + public CloseBehavior onClose(Player p) { + return new OpenCloseBehavior(event.getGui()); } - }.open(p); + }.open(event.getPlayer()); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java b/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java index a14400e6..99a3e7c7 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java @@ -7,6 +7,7 @@ import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.structure.QuestImplementation; public class OptionRepeatable extends QuestOptionBoolean implements QuestDescriptionProvider { @@ -25,10 +26,11 @@ public List<String> provideDescription(QuestDescriptionContext context) { if (context.getCategory() != PlayerListCategory.FINISHED) return null; List<String> lore = new ArrayList<>(4); - if (context.getQuest().testTimer(context.getPlayerAccount(), false)) { + QuestImplementation quest = (QuestImplementation) context.getQuest(); + if (quest.testTimer(context.getPlayerAccount(), false)) { lore.add(Lang.canRedo.toString()); }else { - lore.add(Lang.timeWait.format(context.getQuest().getTimeLeft(context.getPlayerAccount()))); + lore.add(Lang.timeWait.format(quest.getTimeLeft(context.getPlayerAccount()))); } lore.add(null); lore.add(Lang.timesFinished.format(context.getQuestDatas().getTimesFinished())); diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java index 922eed8a..eb49622c 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.options; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; @@ -13,10 +14,12 @@ import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementCreator; +import fr.skytasul.quests.api.requirements.RequirementList; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.PlayerListCategory; -import fr.skytasul.quests.api.utils.Utils; -public class OptionRequirements extends QuestOptionObject<AbstractRequirement, RequirementCreator> implements QuestDescriptionProvider { +public class OptionRequirements extends QuestOptionObject<AbstractRequirement, RequirementCreator, RequirementList> + implements QuestDescriptionProvider { @Override protected AbstractRequirement deserialize(Map<String, Object> map) { @@ -33,6 +36,11 @@ protected QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getObjec return QuestsAPI.getAPI().getRequirements(); } + @Override + protected RequirementList instanciate(Collection<AbstractRequirement> objects) { + return new RequirementList(objects); + } + @Override public XMaterial getItemMaterial() { return XMaterial.NETHER_STAR; @@ -57,7 +65,10 @@ public List<String> provideDescription(QuestDescriptionContext context) { List<String> requirements = getValue().stream() .map(x -> { String description = x.getDescription(context.getPlayerAccount().getPlayer()); - if (description != null) description = Utils.format(x.test(context.getPlayerAccount().getPlayer()) ? context.getDescriptionOptions().getRequirementsValid() : context.getDescriptionOptions().getRequirementsInvalid(), description); + if (description != null) + description = MessageUtils.format(x.test(context.getPlayerAccount().getPlayer()) + ? context.getDescriptionOptions().getRequirementsValid() + : context.getDescriptionOptions().getRequirementsInvalid(), description); return description; }) .filter(Objects::nonNull) diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java index 40b61c58..463fb063 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java @@ -2,8 +2,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemoryConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.DialogEditor; @@ -14,13 +12,13 @@ import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.stages.types.Dialogable; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.utils.types.DialogRunnerImplementation; public class OptionStartDialog extends QuestOption<Dialog> implements Dialogable { - private DialogRunner runner; + private DialogRunnerImplementation runner; public OptionStartDialog() { super(OptionStarterNPC.class); @@ -49,7 +47,9 @@ public boolean shouldDisplay(OptionSet options) { } private String[] getLore() { - return new String[] { formatDescription(Lang.startDialogLore.toString()), "", getValue() == null ? Lang.NotSet.toString() : "§7" + Lang.AmountDialogLines.format(getValue().messages.size()) }; + return new String[] {formatDescription(Lang.startDialogLore.toString()), "", + getValue() == null ? Lang.NotSet.toString() + : "§7" + Lang.AmountDialogLines.format(getValue().getMessages().size())}; } @Override @@ -58,12 +58,12 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - Utils.sendMessage(p, Lang.NPC_TEXT.toString()); + public void click(QuestCreationGuiClickEvent event) { + Lang.NPC_TEXT.send(event.getPlayer()); if (getValue() == null) setValue(new Dialog()); - new DialogEditor(p, () -> { - ItemUtils.lore(item, getLore()); - gui.reopen(p); + new DialogEditor(event.getPlayer(), () -> { + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); }, getValue()).start(); } @@ -89,7 +89,7 @@ public void detach() { @Override public DialogRunner getDialogRunner() { if (runner == null) { - runner = new DialogRunner(getValue(), getNPC()); + runner = new DialogRunnerImplementation(getValue(), getNPC()); runner.addEndAction(p -> getAttachedQuest().attemptStart(p)); } return runner; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java index b3cbd3fa..8a8ea663 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java @@ -1,18 +1,11 @@ package fr.skytasul.quests.options; -import java.util.ArrayList; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionRewards; -import fr.skytasul.quests.api.rewards.AbstractReward; public class OptionStartRewards extends QuestOptionRewards { - @Override - protected void attachedAsyncReward(AbstractReward reward) { - if (getAttachedQuest().asyncStart == null) getAttachedQuest().asyncStart = new ArrayList<>(); - } - @Override public XMaterial getItemMaterial() { return XMaterial.CARROT_ON_A_STICK; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java index 175ed6cf..1cdd2e5b 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartable.java @@ -26,7 +26,7 @@ public String getDescription() { @Override public List<String> provideDescription(QuestDescriptionContext context) { if (context.getCategory() != PlayerListCategory.NOT_STARTED || !context.getPlayerAccount().isCurrent()) return null; - return context.getQuest().isLauncheable(context.getPlayerAccount().getPlayer(), context.getPlayerAccount(), false) ? STARTABLE : NOT_STARTABLE; + return context.getQuest().canStart(context.getPlayerAccount().getPlayer(), false) ? STARTABLE : NOT_STARTABLE; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 069ded68..ddbb5470 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -3,8 +3,6 @@ import java.util.ArrayList; import java.util.List; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; @@ -13,7 +11,7 @@ import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.gui.creation.FinishGUI; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.gui.npc.NpcSelectGUI; public class OptionStarterNPC extends QuestOption<BQNPC> { @@ -52,18 +50,19 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - new NpcSelectGUI(() -> gui.reopen(p), npc -> { + public void click(QuestCreationGuiClickEvent event) { + NpcSelectGUI.selectNullable(event::reopen, npc -> { setValue(npc); - ItemUtils.lore(item, getLore(gui)); - gui.reopen(p); - }).setNullable().open(p); + ItemUtils.lore(event.getClicked(), getLore(event.getGui().getOptionSet())); + event.reopen(); + }).open(event.getPlayer()); } @Override - public void updatedDependencies(OptionSet options, ItemStack item) { - super.updatedDependencies(options, item); - ItemUtils.lore(item, getLore(options)); + public void onDependenciesUpdated(OptionSet options) { + super.onDependenciesUpdated(options); + // ItemUtils.lore(item, getLore(options)); + // TODO wtf ? } - + } 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 8b4c2023..a51e2ad8 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java @@ -1,8 +1,6 @@ package fr.skytasul.quests.options; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; @@ -11,8 +9,8 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.FinishGUI; public class OptionTimer extends QuestOption<Integer> { @@ -50,17 +48,16 @@ private String[] getLore() { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { - Lang.TIMER.send(p); - new TextEditor<>(p, () -> gui.reopen(p), obj -> { - setValue(obj.intValue()); - ItemUtils.lore(item, getLore()); - gui.reopen(p); - }, () -> { - resetValue(); - ItemUtils.lore(item, getLore()); - gui.reopen(p); - }, MinecraftTimeUnit.MINUTE.getParser()).start(); + public void click(QuestCreationGuiClickEvent event) { + Lang.TIMER.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { + if (obj == null) + resetValue(); + else + setValue(obj.intValue()); + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); + }, MinecraftTimeUnit.MINUTE.getParser()).passNullIntoEndConsumer().start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java index f4738c9b..ca6a8f2f 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java @@ -9,12 +9,12 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -22,8 +22,8 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; -import fr.skytasul.quests.gui.creation.FinishGUI; public class OptionVisibility extends QuestOption<List<QuestVisibilityLocation>> { @@ -56,14 +56,14 @@ public ItemStack getItemStack(OptionSet options) { } @Override - public void click(FinishGUI gui, Player p, ItemStack item, int slot, ClickType click) { + public void click(QuestCreationGuiClickEvent event) { new VisibilityGUI(() -> { - ItemUtils.lore(item, getLore()); - gui.reopen(p); - }).open(p); + ItemUtils.lore(event.getClicked(), getLore()); + event.reopen(); + }).open(event.getPlayer()); } - class VisibilityGUI extends Gui { + class VisibilityGUI extends AbstractGui { private EnumMap<QuestVisibilityLocation, Boolean> locations = new EnumMap<>(QuestVisibilityLocation.class); private Runnable reopen; @@ -73,29 +73,29 @@ public VisibilityGUI(Runnable reopen) { } @Override - public Inventory open(Player p) { - Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_VISIBILITY.toString()); - + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_VISIBILITY.toString()); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { for (int i = 0; i < 4; i++) { QuestVisibilityLocation loc = QuestVisibilityLocation.values()[i]; boolean visible = getValue().contains(loc); locations.put(loc, visible); - inv.setItem(i, ItemUtils.itemSwitch(loc.getName(), visible)); + inventory.setItem(i, ItemUtils.itemSwitch(loc.getName(), visible)); } - inv.setItem(4, ItemUtils.itemDone); - - return p.openInventory(inv).getTopInventory(); + inventory.setItem(4, ItemUtils.itemDone); } @Override public void onClick(GuiClickEvent event) { - if (slot >= 0 && slot < 4) { - locations.put(QuestVisibilityLocation.values()[slot], ItemUtils.toggleSwitch(current)); - }else if (slot == 4) { + if (event.getSlot() >= 0 && event.getSlot() < 4) { + locations.put(QuestVisibilityLocation.values()[event.getSlot()], ItemUtils.toggleSwitch(event.getClicked())); + } else if (event.getSlot() == 4) { setValue(locations.entrySet().stream().filter(Entry::getValue).map(Entry::getKey).collect(Collectors.toList())); reopen.run(); } - return true; } @Override 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 0a3ef1e8..7451e4f6 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -96,11 +96,12 @@ public void addAccountData(@NotNull SavableData<?> data) { } protected @NotNull AbstractAccount createAbstractAccount(@NotNull Player p) { - return QuestsConfigurationImplementation.hookAccounts() ? Accounts.getPlayerAccount(p) : new UUIDAccount(p.getUniqueId()); + return QuestsConfigurationImplementation.getConfiguration().hookAccounts() ? Accounts.getPlayerAccount(p) + : new UUIDAccount(p.getUniqueId()); } protected @NotNull String getIdentifier(@NotNull OfflinePlayer p) { - if (QuestsConfigurationImplementation.hookAccounts()) { + if (QuestsConfigurationImplementation.getConfiguration().hookAccounts()) { if (!p.isOnline()) throw new IllegalArgumentException("Cannot fetch player identifier of an offline player with AccountsHook"); return "Hooked|" + Accounts.getPlayerCurrentIdentifier(p.getPlayer()); @@ -110,7 +111,9 @@ public void addAccountData(@NotNull SavableData<?> data) { protected @Nullable AbstractAccount createAccountFromIdentifier(@NotNull String identifier) { if (identifier.startsWith("Hooked|")){ - if (!QuestsConfigurationImplementation.hookAccounts()) throw new MissingDependencyException("AccountsHook is not enabled or config parameter is disabled, but saved datas need it."); + if (!QuestsConfigurationImplementation.getConfiguration().hookAccounts()) + throw new MissingDependencyException( + "AccountsHook is not enabled or config parameter is disabled, but saved datas need it."); String nidentifier = identifier.substring(7); try{ return Accounts.getAccountFromIdentifier(nidentifier); @@ -120,7 +123,7 @@ public void addAccountData(@NotNull SavableData<?> data) { }else { try{ UUID uuid = UUID.fromString(identifier); - if (QuestsConfigurationImplementation.hookAccounts()){ + if (QuestsConfigurationImplementation.getConfiguration().hookAccounts()) { try{ return Accounts.createAccountFromUUID(uuid); }catch (UnsupportedOperationException ex){ diff --git a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java index 0dd86fc9..5ecfeb6f 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java @@ -16,8 +16,8 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.gui.misc.ItemComparisonGUI; -import fr.skytasul.quests.gui.misc.ItemGUI; +import fr.skytasul.quests.gui.items.ItemComparisonGUI; +import fr.skytasul.quests.gui.items.ItemGUI; public class EquipmentRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java index 7e7e530c..85b32183 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java @@ -1,7 +1,5 @@ package fr.skytasul.quests.requirements.logical; -import java.util.ArrayList; -import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsAPI; @@ -11,17 +9,17 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.api.serializable.SerializableObject; +import fr.skytasul.quests.api.requirements.RequirementList; public class LogicalOrRequirement extends AbstractRequirement { - private List<AbstractRequirement> requirements; + private RequirementList requirements; public LogicalOrRequirement() { - this(null, null, new ArrayList<>()); + this(null, null, new RequirementList()); } - public LogicalOrRequirement(String customDescription, String customReason, List<AbstractRequirement> requirements) { + public LogicalOrRequirement(String customDescription, String customReason, RequirementList requirements) { super(customDescription, customReason); this.requirements = requirements; } @@ -29,13 +27,13 @@ public LogicalOrRequirement(String customDescription, String customReason, List< @Override public void attach(Quest quest) { super.attach(quest); - requirements.forEach(req -> req.attach(quest)); + requirements.attachQuest(quest); } @Override public void detach() { super.detach(); - requirements.forEach(AbstractRequirement::detach); + requirements.detachQuest(); } @Override @@ -47,7 +45,7 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.OTHER, requirements -> { - this.requirements = requirements; + this.requirements = new RequirementList(requirements); event.reopenGUI(); }, requirements).open(event.getPlayer()); } @@ -59,19 +57,19 @@ public boolean test(Player p) { @Override public AbstractRequirement clone() { - return new LogicalOrRequirement(getCustomDescription(), getCustomReason(), new ArrayList<>(requirements)); + return new LogicalOrRequirement(getCustomDescription(), getCustomReason(), new RequirementList(requirements)); } @Override public void save(ConfigurationSection section) { super.save(section); - section.set("requirements", SerializableObject.serializeList(requirements)); + section.set("requirements", requirements.serialize()); } @Override public void load(ConfigurationSection section) { super.load(section); - requirements = SerializableObject.deserializeList(section.getMapList("requirements"), AbstractRequirement::deserialize); + requirements = RequirementList.deserialize(section.getMapList("requirements")); } } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java index 6da48436..c49bfc1e 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java @@ -1,6 +1,5 @@ package fr.skytasul.quests.rewards; -import java.util.ArrayList; import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -13,18 +12,17 @@ import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; -import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.utils.QuestUtils; +import fr.skytasul.quests.api.rewards.RewardList; public class CheckpointReward extends AbstractReward { - private List<AbstractReward> actions; + private RewardList actions; public CheckpointReward() { - this(null, new ArrayList<>()); + this(null, new RewardList()); } - public CheckpointReward(String customDescription, List<AbstractReward> actions) { + public CheckpointReward(String customDescription, RewardList actions) { super(customDescription); this.actions = actions; } @@ -32,13 +30,13 @@ public CheckpointReward(String customDescription, List<AbstractReward> actions) @Override public void attach(Quest quest) { super.attach(quest); - actions.forEach(rew -> rew.attach(quest)); + actions.attachQuest(quest); } @Override public void detach() { super.detach(); - actions.forEach(AbstractReward::detach); + actions.detachQuest(); } @Override @@ -49,7 +47,7 @@ public List<String> give(Player p) { public void applies(Player p) { try { - QuestUtils.giveRewards(p, actions); + actions.giveRewards(p); } catch (InterruptingBranchException e) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to interrupt branching in a checkpoint reward (useless). " + toString()); } @@ -57,7 +55,7 @@ public void applies(Player p) { @Override public AbstractReward clone() { - return new CheckpointReward(getCustomDescription(), new ArrayList<>(actions)); + return new CheckpointReward(getCustomDescription(), new RewardList(actions)); } @Override @@ -69,7 +67,7 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { QuestsAPI.getAPI().getRewards().createGUI(Lang.INVENTORY_CHECKPOINT_ACTIONS.toString(), QuestObjectLocation.CHECKPOINT, rewards -> { - actions = rewards; + actions = new RewardList(rewards); event.reopenGUI(); }, actions, null).open(event.getPlayer()); } @@ -77,13 +75,13 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { super.save(section); - section.set("actions", SerializableObject.serializeList(actions)); + section.set("actions", actions.serialize()); } @Override public void load(ConfigurationSection section) { super.load(section); - actions = SerializableObject.deserializeList(section.getMapList("actions"), AbstractReward::deserialize); + actions = RewardList.deserialize(section.getMapList("actions")); } } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index 90f565ff..93742529 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -16,7 +16,7 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.CommandGUI; +import fr.skytasul.quests.gui.misc.CommandGUI; import fr.skytasul.quests.utils.types.Command; public class CommandReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java index 587d77f4..279c9b5d 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java @@ -11,7 +11,7 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.ItemsGUI; +import fr.skytasul.quests.gui.items.ItemsGUI; public class ItemReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java index 0e5b9ad5..346308d8 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java @@ -16,19 +16,21 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.serializable.SerializableObject; +import fr.skytasul.quests.api.rewards.InterruptingBranchException; +import fr.skytasul.quests.api.rewards.RewardList; public class RandomReward extends AbstractReward { - private List<AbstractReward> rewards; + private RewardList rewards; private int min, max; public RandomReward() { - this(null, new ArrayList<>(), 1, 1); + this(null, new RewardList(), 1, 1); } - public RandomReward(String customDescription, List<AbstractReward> rewards, int min, int max) { + public RandomReward(String customDescription, RewardList rewards, int min, int max) { super(customDescription); this.rewards = rewards; this.min = min; @@ -44,7 +46,19 @@ public void setMinMax(int min, int max) { } @Override - public List<String> give(Player p) { + public void attach(Quest quest) { + super.attach(quest); + rewards.attachQuest(quest); + } + + @Override + public void detach() { + super.detach(); + rewards.forEach(AbstractReward::detach); + } + + @Override + public List<String> give(Player p) throws InterruptingBranchException { ThreadLocalRandom random = ThreadLocalRandom.current(); int amount = min == max ? min : random.nextInt(min, max + 1); @@ -57,6 +71,8 @@ public List<String> give(Player p) { try { List<String> messages = reward.give(p); if (messages != null) msg.addAll(messages); + } catch (InterruptingBranchException ex) { + throw ex; }catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when giving random reward " + reward.getName() + " to " + p.getName(), ex); } @@ -72,7 +88,7 @@ public boolean isAsync() { @Override public AbstractReward clone() { - return new RandomReward(getCustomDescription(), new ArrayList<>(rewards), min, max); + return new RandomReward(getCustomDescription(), new RewardList(rewards), min, max); } @Override @@ -97,7 +113,7 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { public void itemClick(QuestObjectClickEvent event) { if (event.isInCreation() || event.getClick().isLeftClick()) { QuestsAPI.getAPI().getRewards().createGUI(QuestObjectLocation.OTHER, rewards -> { - this.rewards = rewards; + this.rewards = new RewardList(rewards); event.reopenGUI(); }, rewards).open(event.getPlayer()); }else if (event.getClick().isRightClick()) { @@ -115,7 +131,7 @@ public void itemClick(QuestObjectClickEvent event) { @Override public void save(ConfigurationSection section) { super.save(section); - section.set("rewards", SerializableObject.serializeList(rewards)); + section.set("rewards", rewards.serialize()); section.set("min", min); section.set("max", max); } @@ -123,7 +139,7 @@ public void save(ConfigurationSection section) { @Override public void load(ConfigurationSection section) { super.load(section); - rewards = SerializableObject.deserializeList(section.getMapList("rewards"), AbstractReward::deserialize); + rewards = RewardList.deserialize(section.getMapList("rewards")); setMinMax(section.getInt("min"), section.getInt("max")); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java index e4b594be..3cefbf11 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java @@ -14,8 +14,8 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.ItemsGUI; -import fr.skytasul.quests.gui.misc.ItemComparisonGUI; +import fr.skytasul.quests.gui.items.ItemComparisonGUI; +import fr.skytasul.quests.gui.items.ItemsGUI; public class RemoveItemsReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 2ddc7644..86944b39 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -1,6 +1,5 @@ package fr.skytasul.quests.rewards; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -20,22 +19,22 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; -import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.utils.QuestUtils; +import fr.skytasul.quests.api.rewards.RewardList; public class RequirementDependentReward extends AbstractReward { - private List<AbstractRequirement> requirements; - private List<AbstractReward> rewards; + private RequirementList requirements; + private RewardList rewards; public RequirementDependentReward() { - this(null, new ArrayList<>(), new ArrayList<>()); + this(null, new RequirementList(), new RewardList()); } - public RequirementDependentReward(String customDescription, List<AbstractRequirement> requirements, - List<AbstractReward> rewards) { + public RequirementDependentReward(String customDescription, RequirementList requirements, + RewardList rewards) { super(customDescription); this.requirements = requirements; this.rewards = rewards; @@ -44,8 +43,8 @@ public RequirementDependentReward(String customDescription, List<AbstractRequire @Override public void attach(Quest quest) { super.attach(quest); - requirements.forEach(req -> req.attach(quest)); - rewards.forEach(rew -> rew.attach(quest)); + requirements.attachQuest(quest); + rewards.attachQuest(quest); } @Override @@ -58,7 +57,7 @@ public void detach() { @Override public List<String> give(Player p) throws InterruptingBranchException { if (requirements.stream().allMatch(requirement -> requirement.test(p))) - return QuestUtils.giveRewards(p, rewards); + return rewards.giveRewards(p); return null; } @@ -69,8 +68,8 @@ public boolean isAsync() { @Override public AbstractReward clone() { - return new RequirementDependentReward(getCustomDescription(), new ArrayList<>(requirements), - new ArrayList<>(rewards)); + return new RequirementDependentReward(getCustomDescription(), new RequirementList(requirements), + new RewardList(rewards)); } @Override @@ -109,14 +108,14 @@ public void itemClick(QuestObjectClickEvent event) { private void editRequirements(LayoutedClickEvent event) { QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.OTHER, newRequirements -> { - RequirementDependentReward.this.requirements = newRequirements; + requirements = new RequirementList(newRequirements); event.refreshItemReopen(); }, requirements).open(event.getPlayer()); } private void editRewards(LayoutedClickEvent event) { QuestsAPI.getAPI().getRewards().createGUI(QuestObjectLocation.OTHER, newRewards -> { - RequirementDependentReward.this.rewards = newRewards; + rewards = new RewardList(newRewards); event.refreshItemReopen(); }, rewards).open(event.getPlayer()); } @@ -124,15 +123,15 @@ private void editRewards(LayoutedClickEvent event) { @Override public void save(ConfigurationSection section) { super.save(section); - section.set("requirements", SerializableObject.serializeList(requirements)); - section.set("rewards", SerializableObject.serializeList(rewards)); + section.set("requirements", requirements.serialize()); + section.set("rewards", rewards.serialize()); } @Override public void load(ConfigurationSection section) { super.load(section); - requirements = SerializableObject.deserializeList(section.getMapList("requirements"), AbstractRequirement::deserialize); - rewards = SerializableObject.deserializeList(section.getMapList("rewards"), AbstractReward::deserialize); + requirements = RequirementList.deserialize(section.getMapList("requirements")); + rewards = RewardList.deserialize(section.getMapList("rewards")); } } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index db18218f..caff6b0a 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -28,7 +28,8 @@ public XPReward(String customDescription, int exp) { @Override public List<String> give(Player p) { - if (DependenciesManager.skapi.isEnabled() && QuestsConfigurationImplementation.xpOverridedSkillAPI()) { + if (DependenciesManager.skapi.isEnabled() + && QuestsConfigurationImplementation.getConfiguration().xpOverridedSkillAPI()) { SkillAPI.giveExp(p, exp); }else p.giveExp(exp); return Arrays.asList(exp + " " + Lang.Exp.toString()); diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java index 1238952a..c629833f 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java @@ -15,8 +15,8 @@ import org.bukkit.scheduler.BukkitRunnable; import fr.mrmicky.fastboard.FastBoard; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; @@ -360,7 +360,8 @@ private String formatQuestPlaceholders(String text) { .findFirst(); if (optionalDescription.isPresent()) { if (lazyContext == null) - lazyContext = new QuestDescriptionContext(QuestsConfigurationImplementation.getQuestDescription(), + lazyContext = new QuestDescriptionContext( + QuestsConfiguration.getConfig().getQuestDescriptionConfig(), shown, acc, PlayerListCategory.IN_PROGRESS, DescriptionSource.SCOREBOARD); replacement = String.join("\n", optionalDescription.get().provideDescription(lazyContext)); } else { diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java index 77b56466..2125b6bb 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java @@ -18,7 +18,7 @@ import org.bukkit.event.player.PlayerChangedWorldEvent; import fr.mrmicky.fastboard.FastBoard; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsHandler; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; @@ -92,7 +92,8 @@ public void removePlayerScoreboard(Player p){ } public void create(Player p){ - if (!QuestsConfigurationImplementation.showScoreboards()) return; + if (!QuestsConfiguration.getConfig().getQuestsConfig().scoreboards()) + return; removePlayerScoreboard(p); Scoreboard scoreboard = new Scoreboard(p, this); @@ -104,7 +105,8 @@ public void create(Player p){ @Override public void load() { - if (!QuestsConfigurationImplementation.showScoreboards()) return; + if (!QuestsConfiguration.getConfig().getQuestsConfig().scoreboards()) + return; try { new FastBoard(null); // trigger class initialization diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java index 1adf22dd..ad634be8 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; @@ -19,13 +20,13 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.MessageUtils; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardEntryEvent; @@ -117,7 +118,7 @@ public Located getLocated() { .add(region.getMinimumPoint())) // midpoint .add(0.5, 0.5, 0.5); - center = Locatable.Located.open(centerLoc); + center = Locatable.Located.create(centerLoc); lastCenter = System.currentTimeMillis(); } return center; @@ -139,7 +140,7 @@ public void serialize(ConfigurationSection section) { } public static StageArea deserialize(ConfigurationSection section, StageController controller) { - return new StageArea(branch, section.getString("region"), section.getString("world"), section.getBoolean("exit", false)); + return new StageArea(controller, section.getString("region"), section.getString("world"), section.getBoolean("exit", false)); } public static class Creator extends StageCreation<StageArea> { @@ -148,38 +149,47 @@ public static class Creator extends StageCreation<StageArea> { private String regionName; private String worldName; - public Creator(Line line, boolean ending) { - super(line, ending); - line.setItem(7, ItemUtils.item(XMaterial.PAPER, Lang.stageRegion.toString()), (p, item) -> launchRegionEditor(p, false), true, true); - line.setItem(6, ItemUtils.itemSwitch(Lang.stageRegionExit.toString(), exit), (p, item) -> setExit(ItemUtils.toggleSwitch(item))); + public Creator(@NotNull StageCreationContext<StageArea> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); + line.setItem(7, ItemUtils.item(XMaterial.PAPER, Lang.stageRegion.toString()), + event -> launchRegionEditor(event.getPlayer(), false)); + line.setItem(6, ItemUtils.itemSwitch(Lang.stageRegionExit.toString(), exit), event -> setExit(!exit)); } public void setRegion(String regionName, String worldName) { this.regionName = regionName; this.worldName = worldName; - line.editItem(7, ItemUtils.lore(line.getItem(7), Lang.optionValue.format(regionName + " (" + worldName + ")"))); + getLine().refreshItemLore(7, Lang.optionValue.format(regionName + " (" + worldName + ")")); } public void setExit(boolean exit) { if (this.exit != exit) { this.exit = exit; - line.editItem(6, ItemUtils.setSwitch(line.getItem(6), exit)); + getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, exit)); } } private void launchRegionEditor(Player p, boolean first) { - Utils.sendMessage(p, Lang.REGION_NAME.toString() + (first ? "" : "\n" + Lang.TYPE_CANCEL.toString())); + MessageUtils.sendPrefixedMessage(p, + Lang.REGION_NAME.toString() + (first ? "" : "\n" + Lang.TYPE_CANCEL.toString())); new TextEditor<String>(p, () -> { - if (first) remove(); - reopenGUI(p, false); + if (first) + context.remove(); + context.reopenGui(); }, obj -> { if (BQWorldGuard.getInstance().regionExists(obj, p.getWorld())) { setRegion(obj, p.getWorld().getName()); }else { - Utils.sendMessage(p, Lang.REGION_DOESNT_EXIST.toString()); - if (first) remove(); + MessageUtils.sendPrefixedMessage(p, Lang.REGION_DOESNT_EXIST.toString()); + if (first) + context.remove(); } - reopenGUI(p, false); + context.reopenGui(); }).useStrippedMessage().start(); } @@ -198,7 +208,7 @@ public void edit(StageArea stage) { @Override public StageArea finishStage(StageController controller) { - return new StageArea(branch, regionName, worldName, exit); + return new StageArea(controller, regionName, worldName, exit); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java index e7bd2b61..0f208e98 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java @@ -6,17 +6,18 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityBreedEvent; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractEntityStage; -import fr.skytasul.quests.gui.creation.stages.Line; public class StageBreed extends AbstractEntityStage { public StageBreed(StageController controller, EntityType entity, int amount) { - super(branch, entity, amount); + super(controller, entity, amount); } @EventHandler @@ -28,21 +29,21 @@ public void onBreed(EntityBreedEvent e) { } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_BREED.format(getMobsLeft(acc)); } public static StageBreed deserialize(ConfigurationSection section, StageController controller) { String type = section.getString("entityType"); - return new StageBreed(branch, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); + return new StageBreed(controller, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); } public static class Creator extends AbstractEntityStage.AbstractCreator<StageBreed> { - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageBreed> context) { + super(context); } - + @Override protected boolean canUseEntity(EntityType type) { return Breedable.class.isAssignableFrom(type.getEntityClass()); @@ -50,7 +51,7 @@ protected boolean canUseEntity(EntityType type) { @Override protected StageBreed finishStage(StageController controller) { - return new StageBreed(branch, entity, amount); + return new StageBreed(controller, entity, amount); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 2a315592..9b63a632 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -9,8 +9,9 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; @@ -18,10 +19,13 @@ import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.ItemsGUI; -import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.gui.misc.ItemComparisonGUI; +import fr.skytasul.quests.gui.items.ItemComparisonGUI; +import fr.skytasul.quests.gui.items.ItemsGUI; +import fr.skytasul.quests.utils.QuestUtils; public class StageBringBack extends StageNPC{ @@ -46,15 +50,22 @@ public StageBringBack(StageController controller, ItemStack[] items, String cust String[] array = new String[items.length]; // create messages on beginning for (int i = 0; i < array.length; i++){ - array[i] = QuestsConfigurationImplementation.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfigurationImplementation.getItemAmountColor(), QuestsConfigurationImplementation.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)); + array[i] = QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemNameColor() + + Utils.getStringFromItemStack(items[i], + QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), + QuestsConfiguration.getConfig().getStageDescriptionConfig() + .isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)); } - splitted = Utils.descriptionLines(DescriptionSource.FORCESPLIT, array); - if (QuestsConfigurationImplementation.showDescriptionItemsXOne(DescriptionSource.FORCESPLIT)){ + splitted = QuestUtils.descriptionLines(DescriptionSource.FORCESPLIT, array); + if (QuestsConfiguration.getConfig().getStageDescriptionConfig() + .isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)) { for (int i = 0; i < array.length; i++){ - array[i] = QuestsConfigurationImplementation.getItemNameColor() + Utils.getStringFromItemStack(items[i], QuestsConfigurationImplementation.getItemAmountColor(), false); + array[i] = QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemNameColor() + Utils + .getStringFromItemStack(items[i], + QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), false); } } - line = Utils.descriptionLines(DescriptionSource.FORCELINE, array); + line = QuestUtils.descriptionLines(DescriptionSource.FORCELINE, array); } public boolean checkItems(Player p, boolean msg){ @@ -73,7 +84,7 @@ public boolean checkItems(Player p, boolean msg){ public void sendNeedMessage(Player p) { String message = getMessage(); if (message != null && !message.isEmpty() && !message.equals("none")) - Lang.NpcText.sendWP(p, npcName(), Utils.format(message, line), 1, 1); + Lang.NpcText.sendWP(p, npcName(), MessageUtils.format(message, line), 1, 1); } public void removeItems(Player p){ @@ -93,17 +104,23 @@ protected String getMessage() { @Override public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Utils.format(Lang.SCOREBOARD_ITEMS.toString() + " " + (QuestsConfigurationImplementation.splitDescription(source) ? splitted : line), npcName()); + return MessageUtils.format(Lang.SCOREBOARD_ITEMS.toString() + " " + + (QuestsConfiguration.getConfig().getStageDescriptionConfig().getSplitSources().contains(source) ? splitted + : line), + npcName()); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source){ - return new String[]{QuestsConfigurationImplementation.splitDescription(source) ? splitted : line, npcName()}; + public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { + return new String[] { + QuestsConfiguration.getConfig().getStageDescriptionConfig().getSplitSources().contains(source) ? splitted + : line, + npcName()}; } @Override - public void start(PlayerAccount acc) { - super.start(acc); + public void started(PlayerAccount acc) { + super.started(acc); if (acc.isCurrent() && sendStartMessage()) sendNeedMessage(acc.getPlayer()); } @@ -153,7 +170,7 @@ public static StageBringBack deserialize(ConfigurationSection section, StageCont if (section.contains("itemComparisons")) { comparisons = new ItemComparisonMap(section.getConfigurationSection("itemComparisons")); }else comparisons = new ItemComparisonMap(); - StageBringBack st = new StageBringBack(branch, items, customMessage, comparisons); + StageBringBack st = new StageBringBack(controller, items, customMessage, comparisons); st.loadDatas(section); return st; } @@ -168,42 +185,51 @@ public abstract static class AbstractCreator<T extends StageBringBack> extends S protected String message = null; protected ItemComparisonMap comparisons = new ItemComparisonMap(); - public AbstractCreator(Line line, boolean ending) { - super(line, ending); + protected AbstractCreator(@NotNull StageCreationContext<T> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(5, stageItems, (p, item) -> { + line.setItem(5, stageItems, event -> { new ItemsGUI(items -> { setItems(items); - reopenGUI(p, true); - }, items).open(p); + event.reopen(); + }, items).open(event.getPlayer()); }); - line.setItem(9, stageMessage, (p, item) -> { - new TextEditor<String>(p, () -> reopenGUI(p, false), x -> { + line.setItem(9, stageMessage, event -> { + new TextEditor<String>(event.getPlayer(), event::reopen, x -> { setMessage(x); - reopenGUI(p, false); + event.reopen(); }).passNullIntoEndConsumer().start(); }); - line.setItem(10, stageComparison, (p, item) -> { + line.setItem(10, stageComparison, event -> { new ItemComparisonGUI(comparisons, () -> { setComparisons(comparisons); - reopenGUI(p, true); - }).open(p); + event.reopen(); + }).open(event.getPlayer()); }); } public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); - line.editItem(5, ItemUtils.lore(line.getItem(5), Lang.optionValue.format(Lang.AmountItems.format(this.items.size())))); + getLine().refreshItemLore(5, Lang.optionValue.format(Lang.AmountItems.format(this.items.size()))); } public void setMessage(String message) { this.message = message; - line.editItem(9, ItemUtils.lore(line.getItem(9), message == null ? Lang.optionValue.format(Lang.NEED_OBJECTS.toString()) + " " + Lang.defaultValue.toString() : Lang.optionValue.format(message))); + getLine().refreshItemLore(9, + message == null + ? Lang.optionValue.format(Lang.NEED_OBJECTS.toString()) + " " + Lang.defaultValue.toString() + : Lang.optionValue.format(message)); } public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; - line.editItem(10, ItemUtils.lore(line.getItem(10), Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size())))); + getLine().refreshItemLore(10, + Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size()))); } @Override @@ -226,13 +252,13 @@ public void edit(T stage) { public static class Creator extends AbstractCreator<StageBringBack> { - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageBringBack> context) { + super(context); } - + @Override protected StageBringBack createStage(StageController controller) { - return new StageBringBack(branch, items.toArray(new ItemStack[0]), message, comparisons); + return new StageBringBack(controller, items.toArray(new ItemStack[0]), message, comparisons); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 056e1458..90943c1e 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -8,8 +8,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; @@ -19,10 +20,12 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.BucketTypeGUI; -import fr.skytasul.quests.gui.creation.stages.Line; +import fr.skytasul.quests.gui.misc.BucketTypeGUI; public class StageBucket extends AbstractStage { @@ -46,14 +49,13 @@ public int getBucketAmount() { @EventHandler (priority = EventPriority.MONITOR) public void onBucketFill(PlayerBucketFillEvent e) { Player p = e.getPlayer(); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (branch.hasStageLaunched(acc, this) && canUpdate(p)) { + if (hasStarted(p) && canUpdate(p)) { if (BucketType.fromMaterial(XMaterial.matchXMaterial(e.getItemStack())) == bucket) { - int amount = getPlayerAmount(acc); + int amount = getPlayerAmount(PlayersManager.getPlayerAccount(p)); if (amount <= 1) { finishStage(p); }else { - updateObjective(acc, p, "amount", --amount); + updateObjective(p, "amount", --amount); } } } @@ -64,18 +66,22 @@ private int getPlayerAmount(PlayerAccount acc) { } @Override - protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { + public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { datas.put("amount", amount); } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_BUCKET.format(Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), amount, false)); + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { + return Lang.SCOREBOARD_BUCKET.format(Utils.getStringFromNameAndAmount(bucket.getName(), + QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), + amount, false)); } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Supplier[] { () -> Utils.getStringFromNameAndAmount(bucket.getName(), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), amount, false) }; + public Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { + return new Supplier[] {() -> Utils.getStringFromNameAndAmount(bucket.getName(), + QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), + amount, false)}; } @Override @@ -85,7 +91,7 @@ protected void serialize(ConfigurationSection section) { } public static StageBucket deserialize(ConfigurationSection section, StageController controller) { - return new StageBucket(branch, BucketType.valueOf(section.getString("bucket")), section.getInt("amount")); + return new StageBucket(controller, BucketType.valueOf(section.getString("bucket")), section.getInt("amount")); } public enum BucketType { @@ -135,46 +141,50 @@ public static class Creator extends StageCreation<StageBucket> { private BucketType bucket; private int amount; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageBucket> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(6, ItemUtils.item(XMaterial.REDSTONE, Lang.editBucketAmount.toString()), (p, item) -> { - Lang.BUCKET_AMOUNT.send(p); - new TextEditor<>(p, () -> reopenGUI(p, true), obj -> { + line.setItem(6, ItemUtils.item(XMaterial.REDSTONE, Lang.editBucketAmount.toString()), event -> { + Lang.BUCKET_AMOUNT.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { setAmount(obj); - reopenGUI(p, true); + event.reopen(); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); }); - line.setItem(7, ItemUtils.item(XMaterial.BUCKET, Lang.editBucketType.toString()), (p, item) -> { - new BucketTypeGUI(() -> reopenGUI(p, true), bucket -> { + line.setItem(7, ItemUtils.item(XMaterial.BUCKET, Lang.editBucketType.toString()), event -> { + new BucketTypeGUI(event::reopen, bucket -> { setBucket(bucket); - reopenGUI(p, true); - }).open(p); + event.reopen(); + }).open(event.getPlayer()); }); } public void setBucket(BucketType bucket) { this.bucket = bucket; - ItemStack newItem = ItemUtils.lore(line.getItem(7), Lang.optionValue.format(bucket.getName())); + ItemStack newItem = ItemUtils.lore(getLine().getItem(7), Lang.optionValue.format(bucket.getName())); newItem.setType(bucket.type.parseMaterial()); - line.editItem(7, newItem); + getLine().refreshItem(7, newItem); } public void setAmount(int amount) { this.amount = amount; - line.editItem(6, ItemUtils.lore(line.getItem(6), Lang.Amount.format(amount))); + getLine().refreshItemLore(6, Lang.Amount.format(amount)); } @Override public void start(Player p) { super.start(p); - Runnable cancel = removeAndReopen(p, true); - new BucketTypeGUI(cancel, bucket -> { + new BucketTypeGUI(context::removeAndReopenGui, bucket -> { setBucket(bucket); Lang.BUCKET_AMOUNT.send(p); - new TextEditor<>(p, cancel, obj -> { + new TextEditor<>(p, context::removeAndReopenGui, obj -> { setAmount(obj); - reopenGUI(p, true); + context.reopenGui(); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); }).open(p); } @@ -188,7 +198,7 @@ public void edit(StageBucket stage) { @Override public StageBucket finishStage(StageController controller) { - return new StageBucket(branch, bucket, amount); + return new StageBucket(controller, bucket, amount); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index bba69dee..d0bed7f5 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -6,6 +6,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; @@ -14,9 +15,10 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.stages.Line; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.MessageUtils; public class StageChat extends AbstractStage{ @@ -45,7 +47,7 @@ public String descriptionLine(PlayerAccount acc, DescriptionSource source){ } @Override - protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source){ + public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new String[]{text}; } @@ -74,7 +76,8 @@ public void onCommand(PlayerCommandPreprocessEvent e) { } private boolean check(String message, Player p) { - if (placeholders) message = Utils.finalFormat(p, message, true); + if (placeholders) + message = MessageUtils.finalFormat(p, message, true); if (!(ignoreCase ? message.equalsIgnoreCase(text) : message.equals(text))) return false; if (!hasStarted(p)) return false; if (canUpdate(p)) finishStage(p); @@ -92,7 +95,7 @@ public void serialize(ConfigurationSection section) { } public static StageChat deserialize(ConfigurationSection section, StageController controller) { - return new StageChat(branch, section.getString("writeText"), section.getBoolean("cancel", true), section.getBoolean("ignoreCase", false), section.getBoolean("placeholders", true)); + return new StageChat(controller, section.getString("writeText"), section.getBoolean("cancel", true), section.getBoolean("ignoreCase", false), section.getBoolean("placeholders", true)); } public static class Creator extends StageCreation<StageChat> { @@ -107,38 +110,47 @@ public static class Creator extends StageCreation<StageChat> { private boolean cancel = true; private boolean ignoreCase = false; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageChat> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(PLACEHOLDERS_SLOT, ItemUtils.itemSwitch(Lang.placeholders.toString(), placeholders), (p, item) -> setPlaceholders(ItemUtils.toggleSwitch(item))); - line.setItem(IGNORE_CASE_SLOT, ItemUtils.itemSwitch(Lang.ignoreCase.toString(), ignoreCase), (p, item) -> setIgnoreCase(ItemUtils.toggleSwitch(item))); - line.setItem(CANCEL_EVENT_SLOT, ItemUtils.itemSwitch(Lang.cancelEvent.toString(), cancel), (p, item) -> setCancel(ItemUtils.toggleSwitch(item))); - line.setItem(MESSAGE_SLOT, ItemUtils.item(XMaterial.PLAYER_HEAD, Lang.editMessage.toString()), (p, item) -> launchEditor(p)); + line.setItem(PLACEHOLDERS_SLOT, ItemUtils.itemSwitch(Lang.placeholders.toString(), placeholders), + event -> setPlaceholders(!placeholders)); + line.setItem(IGNORE_CASE_SLOT, ItemUtils.itemSwitch(Lang.ignoreCase.toString(), ignoreCase), + event -> setIgnoreCase(!ignoreCase)); + line.setItem(CANCEL_EVENT_SLOT, ItemUtils.itemSwitch(Lang.cancelEvent.toString(), cancel), + event -> setCancel(!cancel)); + line.setItem(MESSAGE_SLOT, ItemUtils.item(XMaterial.PLAYER_HEAD, Lang.editMessage.toString()), + event -> launchEditor(event.getPlayer())); } public void setText(String text) { this.text = text; - line.editItem(MESSAGE_SLOT, ItemUtils.lore(line.getItem(MESSAGE_SLOT), Lang.optionValue.format(text))); + getLine().refreshItem(MESSAGE_SLOT, item -> ItemUtils.lore(item, Lang.optionValue.format(text))); } public void setPlaceholders(boolean placeholders) { if (this.placeholders != placeholders) { this.placeholders = placeholders; - line.editItem(PLACEHOLDERS_SLOT, ItemUtils.setSwitch(line.getItem(PLACEHOLDERS_SLOT), placeholders)); + getLine().refreshItem(PLACEHOLDERS_SLOT, item -> ItemUtils.setSwitch(item, placeholders)); } } public void setIgnoreCase(boolean ignoreCase) { if (this.ignoreCase != ignoreCase) { this.ignoreCase = ignoreCase; - line.editItem(IGNORE_CASE_SLOT, ItemUtils.setSwitch(line.getItem(IGNORE_CASE_SLOT), ignoreCase)); + getLine().refreshItem(IGNORE_CASE_SLOT, item -> ItemUtils.setSwitch(item, ignoreCase)); } } public void setCancel(boolean cancel) { if (this.cancel != cancel) { this.cancel = cancel; - line.editItem(CANCEL_EVENT_SLOT, ItemUtils.setSwitch(line.getItem(CANCEL_EVENT_SLOT), cancel)); + getLine().refreshItem(CANCEL_EVENT_SLOT, item -> ItemUtils.setSwitch(item, cancel)); } } @@ -159,18 +171,19 @@ public void edit(StageChat stage) { @Override public StageChat finishStage(StageController controller) { - return new StageChat(branch, text, cancel, ignoreCase, placeholders); + return new StageChat(controller, text, cancel, ignoreCase, placeholders); } private void launchEditor(Player p) { Lang.CHAT_MESSAGE.send(p); new TextEditor<String>(p, () -> { - if (text == null) remove(); - reopenGUI(p, true); + if (text == null) + context.remove(); + context.reopenGui(); }, obj -> { obj = obj.replace("{SLASH}", "/"); setText(obj); - reopenGUI(p, false); + context.reopenGui(); }).start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index ccffb74c..0d556e3a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -10,8 +10,9 @@ import org.bukkit.event.inventory.FurnaceExtractEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.events.internal.BQCraftEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -21,11 +22,12 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.stages.Line; -import fr.skytasul.quests.gui.misc.ItemComparisonGUI; -import fr.skytasul.quests.gui.misc.ItemGUI; +import fr.skytasul.quests.gui.items.ItemComparisonGUI; +import fr.skytasul.quests.gui.items.ItemGUI; /** * @author SkytAsul, ezeiger92, TheBusyBiscuit @@ -49,14 +51,12 @@ public ItemStack getItem(){ @EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = true) public void onFurnaceExtract(FurnaceExtractEvent event) { Player p = event.getPlayer(); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - - if (comparisons.isSimilar(result, new ItemStack(event.getItemType())) && branch.hasStageLaunched(acc, this) && canUpdate(p, true)) { - int amount = getPlayerAmount(acc) - event.getItemAmount(); + if (comparisons.isSimilar(result, new ItemStack(event.getItemType())) && hasStarted(p) && canUpdate(p, true)) { + int amount = getPlayerAmount(PlayersManager.getPlayerAccount(p)) - event.getItemAmount(); if (amount <= 0) { finishStage(p); }else { - updateObjective(acc, p, "amount", amount); + updateObjective(p, "amount", amount); } } } @@ -64,8 +64,7 @@ public void onFurnaceExtract(FurnaceExtractEvent event) { @EventHandler public void onCraft(BQCraftEvent event) { Player p = event.getPlayer(); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (branch.hasStageLaunched(acc, this) && canUpdate(p)) { + if (hasStarted(p) && canUpdate(p)) { ItemStack item = event.getResult(); if (comparisons.isSimilar(result, item)) { @@ -112,18 +111,18 @@ public void onCraft(BQCraftEvent event) { // No use continuing if we haven't actually crafted a thing if (recipeAmount == 0) return; - int amount = getPlayerAmount(acc) - recipeAmount; + int amount = getPlayerAmount(PlayersManager.getPlayerAccount(p)) - recipeAmount; if (amount <= 0) { finishStage(p); }else { - updateObjective(acc, p, "amount", amount); + updateObjective(p, "amount", amount); } } } } @Override - protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { + public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { super.initPlayerDatas(acc, datas); datas.put("amount", result.getAmount()); } @@ -134,13 +133,17 @@ private int getPlayerAmount(PlayerAccount acc) { } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Lang.SCOREBOARD_CRAFT.format(Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false)); + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { + return Lang.SCOREBOARD_CRAFT.format(Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), + QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), + result.getAmount(), false)); } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Supplier[] { () -> Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), QuestsConfigurationImplementation.getItemAmountColor(), getPlayerAmount(acc), result.getAmount(), false) }; + public Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { + return new Supplier[] {() -> Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), + QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), + result.getAmount(), false)}; } @Override @@ -151,7 +154,7 @@ protected void serialize(ConfigurationSection section) { } public static StageCraft deserialize(ConfigurationSection section, StageController controller) { - return new StageCraft(branch, ItemStack.deserialize(section.getConfigurationSection("result").getValues(false)), section.contains("itemComparisons") ? new ItemComparisonMap(section.getConfigurationSection("itemComparisons")) : new ItemComparisonMap()); + return new StageCraft(controller, ItemStack.deserialize(section.getConfigurationSection("result").getValues(false)), section.contains("itemComparisons") ? new ItemComparisonMap(section.getConfigurationSection("itemComparisons")) : new ItemComparisonMap()); } public static int fits(ItemStack stack, Inventory inv) { @@ -173,31 +176,38 @@ public static class Creator extends StageCreation<StageCraft> { private ItemStack item; private ItemComparisonMap comparisons = new ItemComparisonMap(); - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageCraft> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(ITEM_SLOT, ItemUtils.item(XMaterial.CHEST, Lang.editItem.toString()), (p, item) -> { + line.setItem(ITEM_SLOT, ItemUtils.item(XMaterial.CHEST, Lang.editItem.toString()), event -> { new ItemGUI((is) -> { setItem(is); - reopenGUI(p, true); - }, () -> reopenGUI(p, true)).open(p); + event.reopen(); + }, event::reopen).open(event.getPlayer()); }); - line.setItem(COMPARISONS_SLOT, ItemUtils.item(XMaterial.PRISMARINE_SHARD, Lang.stageItemsComparison.toString()), (p, item) -> { + line.setItem(COMPARISONS_SLOT, ItemUtils.item(XMaterial.PRISMARINE_SHARD, Lang.stageItemsComparison.toString()), event -> { new ItemComparisonGUI(comparisons, () -> { setComparisons(comparisons); - reopenGUI(p, true); - }).open(p); + event.reopen(); + }).open(event.getPlayer()); }); } public void setItem(ItemStack item) { this.item = item; - line.editItem(ITEM_SLOT, ItemUtils.lore(line.getItem(ITEM_SLOT), Lang.optionValue.format(Utils.getStringFromItemStack(item, "§8", true)))); + getLine().refreshItem(ITEM_SLOT, + item2 -> ItemUtils.lore(item2, Lang.optionValue.format(Utils.getStringFromItemStack(item, "§8", true)))); } public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; - line.editItem(COMPARISONS_SLOT, ItemUtils.lore(line.getItem(COMPARISONS_SLOT), Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size())))); + getLine().refreshItem(COMPARISONS_SLOT, item -> ItemUtils.lore(item, + Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size())))); } @Override @@ -205,8 +215,8 @@ public void start(Player p) { super.start(p); new ItemGUI(is -> { setItem(is); - reopenGUI(p, true); - }, removeAndReopen(p, true)).open(p); + context.reopenGui(); + }, context::removeAndReopenGui).open(p); } @Override @@ -218,7 +228,7 @@ public void edit(StageCraft stage) { @Override public StageCraft finishStage(StageController controller) { - return new StageCraft(branch, item, comparisons); + return new StageCraft(controller, item, comparisons); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index 62d7694d..b6c2b61a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -15,6 +15,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.projectiles.ProjectileSource; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.checkers.NumberParser; @@ -27,8 +28,9 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.creation.stages.Line; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.gui.mobs.MobSelectionGUI; import fr.skytasul.quests.mobs.Mob; @@ -54,7 +56,8 @@ private static String getTargetMobsString(List<Mob> targetMobs) { } @Override - protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { + public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { + super.initPlayerDatas(acc, datas); datas.put("amount", damage); } @@ -74,25 +77,25 @@ public void onDamage(EntityDamageByEntityEvent event) { PlayerAccount account = PlayersManager.getPlayerAccount(player); - if (!branch.hasStageLaunched(account, this)) return; - if (!canUpdate(player)) return; + if (!hasStarted(player) || !canUpdate(player)) + return; double amount = getData(account, "amount"); amount -= event.getFinalDamage(); if (amount <= 0) { finishStage(player); }else { - updateObjective(account, player, "amount", amount); + updateObjective(player, "amount", amount); } } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return (targetMobs == null || targetMobs.isEmpty() ? Lang.SCOREBOARD_DEAL_DAMAGE_ANY : Lang.SCOREBOARD_DEAL_DAMAGE_MOBS).format(descriptionFormat(acc, source)); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { + public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Object[] { (Supplier<String>) () -> Integer.toString(super.<Double>getData(acc, "amount").intValue()), targetMobsString }; } @@ -104,7 +107,7 @@ protected void serialize(ConfigurationSection section) { } public static StageDealDamage deserialize(ConfigurationSection section, StageController controller) { - return new StageDealDamage(branch, + return new StageDealDamage(controller, section.getDouble("damage"), section.contains("targetMobs") ? section.getMapList("targetMobs").stream().map(map -> Mob.deserialize((Map) map)).collect(Collectors.toList()) : null); } @@ -117,24 +120,29 @@ public static class Creator extends StageCreation<StageDealDamage> { private double damage; private List<Mob> targetMobs; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageDealDamage> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(SLOT_DAMAGE, ItemUtils.item(XMaterial.REDSTONE, Lang.stageDealDamageValue.toString()), (p, item) -> { - Lang.DAMAGE_AMOUNT.send(p); - new TextEditor<>(p, () -> reopenGUI(p, false), newDamage -> { + line.setItem(SLOT_DAMAGE, ItemUtils.item(XMaterial.REDSTONE, Lang.stageDealDamageValue.toString()), event -> { + Lang.DAMAGE_AMOUNT.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, newDamage -> { setDamage(newDamage); - reopenGUI(p, false); + event.reopen(); }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).start(); }); - line.setItem(SLOT_MOBS, ItemUtils.item(XMaterial.BLAZE_SPAWN_EGG, Lang.stageDealDamageMobs.toString(), QuestOption.formatNullableValue(Lang.EntityTypeAny.toString(), true)), (p, item) -> { + line.setItem(SLOT_MOBS, ItemUtils.item(XMaterial.BLAZE_SPAWN_EGG, Lang.stageDealDamageMobs.toString(), QuestOption.formatNullableValue(Lang.EntityTypeAny.toString(), true)), event -> { new ListGUI<Mob>(Lang.stageDealDamageMobs.toString(), DyeColor.RED, targetMobs == null ? Collections.emptyList() : targetMobs) { @Override public void finish(List<Mob> objects) { setTargetMobs(objects.isEmpty() ? null : objects); - reopenGUI(player, true); + event.reopen(); } @Override @@ -147,19 +155,21 @@ public void createObject(Function<Mob, ItemStack> callback) { new MobSelectionGUI(callback::apply).open(player); } - }.open(p); + }.open(event.getPlayer()); }); } public void setDamage(double damage) { this.damage = damage; - line.editItem(SLOT_DAMAGE, ItemUtils.lore(line.getItem(SLOT_DAMAGE), QuestOption.formatNullableValue(Double.toString(damage)))); + getLine().refreshItem(SLOT_DAMAGE, + item -> ItemUtils.lore(item, QuestOption.formatNullableValue(Double.toString(damage)))); } public void setTargetMobs(List<Mob> targetMobs) { this.targetMobs = targetMobs; boolean noMobs = targetMobs == null || targetMobs.isEmpty(); - line.editItem(SLOT_MOBS, ItemUtils.lore(line.getItem(SLOT_MOBS), QuestOption.formatNullableValue(getTargetMobsString(targetMobs), noMobs))); + getLine().refreshItem(SLOT_MOBS, + item -> ItemUtils.lore(item, QuestOption.formatNullableValue(getTargetMobsString(targetMobs), noMobs))); } @Override @@ -173,15 +183,15 @@ public void edit(StageDealDamage stage) { public void start(Player p) { super.start(p); Lang.DAMAGE_AMOUNT.send(p); - new TextEditor<>(p, removeAndReopen(p, false), newDamage -> { + new TextEditor<>(p, context::removeAndReopenGui, newDamage -> { setDamage(newDamage); - reopenGUI(p, false); + context.reopenGui(); }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).start(); } @Override protected StageDealDamage finishStage(StageController controller) { - return new StageDealDamage(branch, damage, targetMobs); + return new StageDealDamage(controller, damage, targetMobs); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java index 5365a7c4..30128a24 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java @@ -9,6 +9,7 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.PlayerDeathEvent; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -16,8 +17,9 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; -import fr.skytasul.quests.gui.creation.stages.Line; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.gui.misc.DamageCausesGUI; public class StageDeath extends AbstractStage { @@ -44,7 +46,7 @@ public void onPlayerDeath(PlayerDeathEvent event) { } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_DIE.toString(); } @@ -60,7 +62,7 @@ public static StageDeath deserialize(ConfigurationSection section, StageControll }else { causes = Collections.emptyList(); } - return new StageDeath(branch, causes); + return new StageDeath(controller, causes); } public static class Creator extends StageCreation<StageDeath> { @@ -69,20 +71,26 @@ public static class Creator extends StageCreation<StageDeath> { private List<DamageCause> causes; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageDeath> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(CAUSES_SLOT, ItemUtils.item(XMaterial.SKELETON_SKULL, Lang.stageDeathCauses.toString()), (p, item) -> { + line.setItem(CAUSES_SLOT, ItemUtils.item(XMaterial.SKELETON_SKULL, Lang.stageDeathCauses.toString()), event -> { new DamageCausesGUI(causes, newCauses -> { setCauses(newCauses); - reopenGUI(p, true); - }).open(p); + event.reopen(); + }).open(event.getPlayer()); }); } public void setCauses(List<DamageCause> causes) { this.causes = causes; - line.editItem(CAUSES_SLOT, ItemUtils.lore(line.getItem(CAUSES_SLOT), Lang.optionValue.format(causes.isEmpty() ? Lang.stageDeathCauseAny : Lang.stageDeathCausesSet.format(causes.size())))); + getLine().refreshItem(CAUSES_SLOT, item -> ItemUtils.lore(item, Lang.optionValue + .format(causes.isEmpty() ? Lang.stageDeathCauseAny : Lang.stageDeathCausesSet.format(causes.size())))); } @Override @@ -99,7 +107,7 @@ public void edit(StageDeath stage) { @Override protected StageDeath finishStage(StageController controller) { - return new StageDeath(branch, causes); + return new StageDeath(controller, causes); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java index 667e816d..954bd5e5 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java @@ -5,46 +5,46 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; -import fr.skytasul.quests.gui.creation.stages.Line; public class StageEatDrink extends AbstractItemStage { public StageEatDrink(StageController controller, List<CountableObject<ItemStack>> objects, ItemComparisonMap comparisons) { - super(branch, objects, comparisons); + super(controller, objects, comparisons); } public StageEatDrink(ConfigurationSection section, StageController controller) { - super(branch, section); + super(controller, section); } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_EAT_DRINK.format(super.descriptionLine(acc, source)); } @EventHandler public void onItemConsume(PlayerItemConsumeEvent event) { - event(PlayersManager.getPlayerAccount(event.getPlayer()), event.getPlayer(), event.getItem(), 1); + event(event.getPlayer(), event.getItem(), 1); } public static class Creator extends AbstractItemStage.Creator<StageEatDrink> { private static final ItemStack editItems = ItemUtils.item(XMaterial.COOKED_PORKCHOP, Lang.stageEatDrinkItems.toString()); - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageEatDrink> context) { + super(context); } - + @Override protected ItemStack getEditItem() { return editItems; @@ -52,7 +52,7 @@ protected ItemStack getEditItem() { @Override protected StageEatDrink finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { - return new StageEatDrink(branch, items, comparisons); + return new StageEatDrink(controller, items, comparisons); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java index 7132d436..1fd17e54 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java @@ -7,58 +7,58 @@ import org.bukkit.event.enchantment.EnchantItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; -import fr.skytasul.quests.gui.creation.stages.Line; public class StageEnchant extends AbstractItemStage { public StageEnchant(StageController controller, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { - super(branch, fishes, comparisons); + super(controller, fishes, comparisons); } public StageEnchant(StageController controller, ConfigurationSection section) { - super(branch, section); + super(controller, section); } @EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = true) public void onEnchant(EnchantItemEvent e) { - PlayerAccount acc = PlayersManager.getPlayerAccount(e.getEnchanter()); - if (!branch.hasStageLaunched(acc, this)) return; + if (!hasStarted(e.getEnchanter())) + return; ItemStack finalItem = e.getItem().clone(); ItemMeta meta = finalItem.getItemMeta(); e.getEnchantsToAdd().forEach((enchant, level) -> meta.addEnchant(enchant, level, false)); finalItem.setItemMeta(meta); - event(acc, e.getEnchanter(), finalItem, e.getItem().getAmount()); + event(e.getEnchanter(), finalItem, e.getItem().getAmount()); } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_ENCHANT.format(super.descriptionLine(acc, source)); } public static StageEnchant deserialize(ConfigurationSection section, StageController controller) { - return new StageEnchant(branch, section); + return new StageEnchant(controller, section); } public static class Creator extends AbstractItemStage.Creator<StageEnchant> { private static final ItemStack editItems = ItemUtils.item(XMaterial.ENCHANTING_TABLE, Lang.editItemsToEnchant.toString()); - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageEnchant> context) { + super(context); } - + @Override protected ItemStack getEditItem() { return editItems; @@ -66,7 +66,7 @@ protected ItemStack getEditItem() { @Override protected StageEnchant finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { - return new StageEnchant(branch, items, comparisons); + return new StageEnchant(controller, items, comparisons); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java index 5dcbf653..722d62e1 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java @@ -9,57 +9,57 @@ import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerFishEvent.State; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; -import fr.skytasul.quests.gui.creation.stages.Line; public class StageFish extends AbstractItemStage { public StageFish(StageController controller, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { - super(branch, fishes, comparisons); + super(controller, fishes, comparisons); } public StageFish(StageController controller, ConfigurationSection section) { - super(branch, section); + super(controller, section); } @EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = true) public void onFish(PlayerFishEvent e){ if (e.getState() == State.CAUGHT_FISH && e.getCaught() instanceof Item){ Player p = e.getPlayer(); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); Item item = (Item) e.getCaught(); - if (item.isDead() || !branch.hasStageLaunched(acc, this)) return; + if (item.isDead() || !hasStarted(p)) + return; ItemStack fish = item.getItemStack(); - event(acc, p, fish, fish.getAmount()); + event(p, fish, fish.getAmount()); } } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_FISH.format(super.descriptionLine(acc, source)); } public static StageFish deserialize(ConfigurationSection section, StageController controller) { - return new StageFish(branch, section); + return new StageFish(controller, section); } public static class Creator extends AbstractItemStage.Creator<StageFish> { private static final ItemStack editFishesItem = ItemUtils.item(XMaterial.FISHING_ROD, Lang.editFishes.toString()); - - public Creator(Line line, boolean ending) { - super(line, ending); + + public Creator(@NotNull StageCreationContext<StageFish> context) { + super(context); } - + @Override protected ItemStack getEditItem() { return editFishesItem; @@ -67,7 +67,7 @@ protected ItemStack getEditItem() { @Override protected StageFish finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { - return new StageFish(branch, items, comparisons); + return new StageFish(controller, items, comparisons); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java index eff58d69..1f22ceb0 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java @@ -2,38 +2,39 @@ import java.util.Collections; import java.util.Spliterator; -import org.bukkit.Bukkit; 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.block.Action; -import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.WaitBlockClick; -import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.layout.LayoutedButton; +import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.BQBlock; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.blocks.SelectBlockGUI; -import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.utils.types.BQLocation; @LocatableType (types = { LocatedType.BLOCK, LocatedType.OTHER }) @@ -80,7 +81,7 @@ public Located getLocated() { if (locatedBlock == null) { Block realBlock = lc.getMatchingBlock(); if (realBlock != null) - locatedBlock = Located.LocatedBlock.open(realBlock); + locatedBlock = Located.LocatedBlock.create(realBlock); } return locatedBlock; } @@ -118,7 +119,7 @@ public void onInteract(PlayerInteractEvent e){ } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return lc == null ? Lang.SCOREBOARD_INTERACT_MATERIAL.format(block.getName()) : Lang.SCOREBOARD_INTERACT.format(lc.getBlockX() + " " + lc.getBlockY() + " " + lc.getBlockZ()); } @@ -132,7 +133,7 @@ protected void serialize(ConfigurationSection section) { public static StageInteract deserialize(ConfigurationSection section, StageController controller) { if (section.contains("location")) { - return new StageInteract(branch, section.getBoolean("leftClick"), BQLocation.deserialize(section.getConfigurationSection("location").getValues(false))); + return new StageInteract(controller, section.getBoolean("leftClick"), BQLocation.deserialize(section.getConfigurationSection("location").getValues(false))); }else { BQBlock block; if (section.contains("material")) { @@ -140,7 +141,7 @@ public static StageInteract deserialize(ConfigurationSection section, StageContr }else { block = BQBlock.fromString(section.getString("block")); } - return new StageInteract(branch, section.getBoolean("leftClick"), block); + return new StageInteract(controller, section.getBoolean("leftClick"), block); } } @@ -150,62 +151,76 @@ public static class Creator extends StageCreation<StageInteract> { private Location location; private BQBlock block; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageInteract> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), (p, item) -> setLeftClick(ItemUtils.toggleSwitch(item))); + line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); } public void setLeftClick(boolean leftClick) { if (this.leftClick != leftClick) { this.leftClick = leftClick; - line.editItem(6, ItemUtils.setSwitch(line.getItem(6), leftClick)); + getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, leftClick)); } } public void setLocation(Location location) { if (this.location == null) { - line.setItem(7, ItemUtils.item(XMaterial.COMPASS, Lang.blockLocation.toString()), (p, item) -> { - Lang.CLICK_BLOCK.send(player); - new WaitBlockClick(player, () -> reopenGUI(player, false), obj -> { + getLine().setItem(7, ItemUtils.item(XMaterial.COMPASS, Lang.blockLocation.toString()), event -> { + Lang.CLICK_BLOCK.send(event.getPlayer()); + new WaitBlockClick(event.getPlayer(), event::reopen, obj -> { setLocation(obj); - reopenGUI(player, false); + event.reopen(); }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); }); } - line.editItem(7, ItemUtils.lore(line.getItem(7), QuestOption.formatDescription(Utils.locationToString(location)))); + getLine().refreshItem(7, + item -> ItemUtils.lore(item, QuestOption.formatDescription(Utils.locationToString(location)))); this.location = location; } public void setMaterial(BQBlock block) { if (this.block == null) { - line.setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), (p, item) -> { + getLine().setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), event -> { new SelectBlockGUI(false, (newBlock, __) -> { setMaterial(newBlock); - reopenGUI(player, true); - }).open(player); + event.reopen(); + }).open(event.getPlayer()); }); } - line.editItem(7, ItemUtils.lore(line.getItem(7), Lang.optionValue.format(block.getName()))); + getLine().refreshItem(7, item -> ItemUtils.lore(item, Lang.optionValue.format(block.getName()))); this.block = block; } @Override public void start(Player p) { super.start(p); - Runnable cancel = removeAndReopen(p, true); - new ChooseActionGUI(cancel, () -> { - Lang.CLICK_BLOCK.send(p); - new WaitBlockClick(p, cancel, obj -> { - setLocation(obj); - reopenGUI(p, true); - }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); - }, () -> { - new SelectBlockGUI(false, (newBlock, __) -> { - setMaterial(newBlock); - reopenGUI(p, true); - }).open(p); - }).open(p); + LayoutedGUI.newBuilder() + .setInventoryType(InventoryType.HOPPER) + .addButton(0, LayoutedButton.create(ItemUtils.item(XMaterial.COMPASS, Lang.clickLocation.toString()), + event -> { + Lang.CLICK_BLOCK.send(p); + new WaitBlockClick(p, context::removeAndReopenGui, obj -> { + setLocation(obj); + context.reopenGui(); + }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); + })) + .addButton(1, + LayoutedButton.create(ItemUtils.item(XMaterial.STICK, Lang.clickMaterial.toString()), event -> { + new SelectBlockGUI(false, (newBlock, __) -> { + setMaterial(newBlock); + context.reopenGui(); + }).open(p); + })) + .addButton(4, LayoutedButton.create(ItemUtils.itemCancel, __ -> context.removeAndReopenGui())) + .setCloseBehavior(StandardCloseBehavior.REOPEN) + .setName(Lang.INVENTORY_BLOCK_ACTION.toString()) + .build().open(p); } @Override @@ -220,42 +235,10 @@ public void edit(StageInteract stage) { @Override public StageInteract finishStage(StageController controller) { if (location != null) { - return new StageInteract(branch, leftClick, new BQLocation(location)); - }else return new StageInteract(branch, leftClick, block); + return new StageInteract(controller, leftClick, new BQLocation(location)); + }else return new StageInteract(controller, leftClick, block); } - private class ChooseActionGUI implements Gui { - - private Runnable cancel, location, type; - - public ChooseActionGUI(Runnable cancel, Runnable location, Runnable type) { - this.cancel = cancel; - this.location = location; - this.type = type; - } - - @Override - public Inventory open(Player p) { - Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, Lang.INVENTORY_BLOCK_ACTION.toString()); - inv.setItem(0, ItemUtils.item(XMaterial.COMPASS, Lang.clickLocation.toString())); - inv.setItem(1, ItemUtils.item(XMaterial.STICK, Lang.clickMaterial.toString())); - inv.setItem(4, ItemUtils.itemCancel); - return p.openInventory(inv).getTopInventory(); - } - - @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { - if (slot == 0) { - location.run(); - }else if (slot == 1) { - type.run(); - }else if (slot == 4) { - cancel.run(); - } - return true; - } - }; - } } 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 1aead3c0..ce756ff7 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -6,6 +6,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; @@ -19,12 +20,13 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.BQLocation; @@ -85,23 +87,26 @@ public void onPlayerMove(PlayerMoveEvent e){ } @Override - public void joins(PlayerAccount acc, Player p) { - super.joins(acc, p); - if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.launchCompass(p, lc); + public void joined(Player p) { + super.joined(p); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) + GPS.launchCompass(p, lc); } @Override - public void leaves(PlayerAccount acc, Player p) { - super.leaves(acc, p); - if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.stopCompass(p); + public void left(Player p) { + super.left(p); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) + GPS.stopCompass(p); } @Override - public void start(PlayerAccount acc) { - super.start(acc); + public void started(PlayerAccount acc) { + super.started(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); - if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.launchCompass(p, lc); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) + GPS.launchCompass(p, lc); } } @@ -110,17 +115,18 @@ public void ended(PlayerAccount acc) { super.ended(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); - if (QuestsConfigurationImplementation.handleGPS() && gps) GPS.stopCompass(p); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) + GPS.stopCompass(p); } } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source){ + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return descMessage; } @Override - protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { + public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Object[] { lc.getBlockX(), lc.getBlockY(), lc.getBlockZ(), lc.getWorldName() }; } @@ -132,7 +138,7 @@ protected void serialize(ConfigurationSection section) { } public static StageLocation deserialize(ConfigurationSection section, StageController controller) { - return new StageLocation(branch, BQLocation.deserialize(section.getConfigurationSection("location").getValues(false)), section.getInt("radius"), section.getBoolean("gps", true)); + return new StageLocation(controller, BQLocation.deserialize(section.getConfigurationSection("location").getValues(false)), section.getInt("radius"), section.getBoolean("gps", true)); } public static class Creator extends StageCreation<StageLocation> { @@ -147,53 +153,64 @@ public static class Creator extends StageCreation<StageLocation> { private int radius; private boolean gps = true; - public Creator(Line line, boolean ending) { - super(line, ending); - - line.setItem(SLOT_RADIUS, ItemUtils.item(XMaterial.REDSTONE, Lang.stageLocationRadius.toString()), (p, item) -> { - Lang.LOCATION_RADIUS.send(p); - new TextEditor<>(p, () -> reopenGUI(p, false), x -> { + public Creator(@NotNull StageCreationContext<StageLocation> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); + + line.setItem(SLOT_RADIUS, ItemUtils.item(XMaterial.REDSTONE, Lang.stageLocationRadius.toString()), event -> { + Lang.LOCATION_RADIUS.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, x -> { setRadius(x); - reopenGUI(p, false); + event.reopen(); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); }); - line.setItem(SLOT_LOCATION, ItemUtils.item(XMaterial.STICK, Lang.stageLocationLocation.toString()), (p, item) -> { - Lang.LOCATION_GO.send(p); - new WaitClick(p, () -> reopenGUI(p, false), NpcCreateGUI.validMove, () -> { - setLocation(new BQLocation(p.getLocation())); - reopenGUI(p, false); + 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())); + event.reopen(); }).start(); }); - line.setItem(SLOT_WORLD_PATTERN, ItemUtils.item(XMaterial.NAME_TAG, Lang.stageLocationWorldPattern.toString(), QuestOption.formatDescription(Lang.stageLocationWorldPatternLore.toString())), (p, item) -> { - Lang.LOCATION_WORLDPATTERN.send(p); - new TextEditor<>(p, () -> reopenGUI(p, false), pattern -> { + line.setItem(SLOT_WORLD_PATTERN, ItemUtils.item(XMaterial.NAME_TAG, Lang.stageLocationWorldPattern.toString(), QuestOption.formatDescription(Lang.stageLocationWorldPatternLore.toString())), event -> { + Lang.LOCATION_WORLDPATTERN.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, pattern -> { setPattern(pattern); - reopenGUI(p, false); + event.reopen(); }, PatternParser.PARSER).passNullIntoEndConsumer().start(); }); - if (QuestsConfigurationImplementation.handleGPS()) line.setItem(SLOT_GPS, ItemUtils.itemSwitch(Lang.stageGPS.toString(), gps), (p, item) -> setGPS(ItemUtils.toggleSwitch(item)), true, true); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS()) + line.setItem(SLOT_GPS, ItemUtils.itemSwitch(Lang.stageGPS.toString(), gps), event -> setGPS(!gps)); } public void setLocation(Location location) { this.location = location; - line.editItem(SLOT_LOCATION, ItemUtils.lore(line.getItem(SLOT_LOCATION), QuestOption.formatDescription(Utils.locationToString(location)))); + getLine().refreshItem(SLOT_LOCATION, + item -> ItemUtils.lore(item, QuestOption.formatDescription(Utils.locationToString(location)))); } public void setRadius(int radius) { this.radius = radius; - line.editItem(SLOT_RADIUS, ItemUtils.lore(line.getItem(SLOT_RADIUS), Lang.stageLocationCurrentRadius.format(radius))); + getLine().refreshItem(SLOT_RADIUS, item -> ItemUtils.lore(item, Lang.stageLocationCurrentRadius.format(radius))); } public void setPattern(Pattern pattern) { this.pattern = pattern; - line.editItem(SLOT_WORLD_PATTERN, ItemUtils.lore(line.getItem(SLOT_WORLD_PATTERN), QuestOption.formatDescription(Lang.stageLocationWorldPatternLore.format()), "", pattern == null ? Lang.NotSet.toString() : QuestOption.formatNullableValue(pattern.pattern()))); + getLine().refreshItem(SLOT_WORLD_PATTERN, + item -> ItemUtils.lore(item, QuestOption.formatDescription(Lang.stageLocationWorldPatternLore.format()), + "", + pattern == null ? Lang.NotSet.toString() : QuestOption.formatNullableValue(pattern.pattern()))); } public void setGPS(boolean gps) { if (this.gps != gps) { this.gps = gps; - if (QuestsConfigurationImplementation.handleGPS()) line.editItem(SLOT_GPS, ItemUtils.setSwitch(line.getItem(SLOT_GPS), gps)); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS()) + getLine().refreshItem(SLOT_GPS, item -> ItemUtils.setSwitch(item, gps)); } } @@ -207,10 +224,10 @@ private BQLocation getBQLocation() { public void start(Player p) { super.start(p); Lang.LOCATION_GO.send(p); - new WaitClick(p, removeAndReopen(p, false), NpcCreateGUI.validMove, () -> { + new WaitClick(p, context::removeAndReopenGui, NpcCreateGUI.validMove, () -> { setLocation(p.getLocation()); setRadius(5); - reopenGUI(p, false); + context.reopenGui(); }).start(); } @@ -225,7 +242,7 @@ public void edit(StageLocation stage) { @Override public StageLocation finishStage(StageController controller) { - return new StageLocation(branch, getBQLocation(), radius, gps); + return new StageLocation(controller, getBQLocation(), radius, gps); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java index ff69c337..4b05899d 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java @@ -6,50 +6,50 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.inventory.FurnaceExtractEvent; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; -import fr.skytasul.quests.gui.creation.stages.Line; public class StageMelt extends AbstractItemStage { public StageMelt(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { - super(branch, items, comparisons); + super(controller, items, comparisons); } public StageMelt(StageController controller, ConfigurationSection section) { - super(branch, section); + super(controller, section); } @EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = true) public void onMelt(FurnaceExtractEvent event) { - event(PlayersManager.getPlayerAccount(event.getPlayer()), event.getPlayer(), new ItemStack(event.getItemType()), event.getItemAmount()); + event(event.getPlayer(), new ItemStack(event.getItemType()), event.getItemAmount()); } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_MELT.format(super.descriptionLine(acc, source)); } public static StageMelt deserialize(ConfigurationSection section, StageController controller) { - return new StageMelt(branch, section); + return new StageMelt(controller, section); } public static class Creator extends AbstractItemStage.Creator<StageMelt> { private static final ItemStack editItems = ItemUtils.item(XMaterial.FURNACE, Lang.editItemsToMelt.toString()); - - public Creator(Line line, boolean ending) { - super(line, ending); + + public Creator(@NotNull StageCreationContext<StageMelt> context) { + super(context); } - + @Override protected ItemStack getEditItem() { return editItems; @@ -57,7 +57,7 @@ protected ItemStack getEditItem() { @Override protected StageMelt finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { - return new StageMelt(branch, items, comparisons); + return new StageMelt(controller, items, comparisons); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index 9925cd62..46f64a12 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -15,6 +15,7 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import com.gestankbratwurst.playerblocktracker.PlayerBlockTracker; import fr.skytasul.quests.BeautyQuests; @@ -26,13 +27,14 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.CountableObject; -import fr.skytasul.quests.gui.creation.stages.Line; @LocatableType (types = LocatedType.BLOCK) public class StageMine extends AbstractCountableBlockStage implements Locatable.MultipleLocatable { @@ -40,7 +42,7 @@ public class StageMine extends AbstractCountableBlockStage implements Locatable. private boolean placeCancelled; public StageMine(StageController controller, List<CountableObject<BQBlock>> blocks) { - super(branch, blocks); + super(controller, blocks); } public boolean isPlaceCancelled() { @@ -59,35 +61,38 @@ public String descriptionLine(PlayerAccount acc, DescriptionSource source){ @EventHandler (priority = EventPriority.MONITOR) public void onMine(BQBlockBreakEvent e) { Player p = e.getPlayer(); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (branch.hasStageLaunched(acc, this)){ - for (Block block : e.getBlocks()) { - if (placeCancelled) { - if (QuestsConfigurationImplementation.usePlayerBlockTracker()) { - if (PlayerBlockTracker.isTracked(block)) return; - } else { - if (block.hasMetadata("playerInStage")) { - if (block.getMetadata("playerInStage").get(0).asString().equals(p.getName())) - return; - } + if (!hasStarted(p)) + return; + + for (Block block : e.getBlocks()) { + if (placeCancelled) { + if (QuestsConfigurationImplementation.getConfiguration().usePlayerBlockTracker()) { + if (PlayerBlockTracker.isTracked(block)) + return; + } else { + if (block.hasMetadata("playerInStage") + && (block.getMetadata("playerInStage").get(0).asString().equals(p.getName()))) { + return; } } - if (event(acc, p, block, 1)) return; } + if (event(p, block, 1)) + return; } } @EventHandler (priority = EventPriority.MONITOR) public void onPlace(BlockPlaceEvent e){ - if (QuestsConfigurationImplementation.usePlayerBlockTracker()) + if (QuestsConfigurationImplementation.getConfiguration().usePlayerBlockTracker()) + return; + if (e.isCancelled() || !placeCancelled) return; - if (e.isCancelled() || !placeCancelled) return; Player p = e.getPlayer(); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (!branch.hasStageLaunched(acc, this)) return; + if (!hasStarted(p)) + return; - Map<UUID, Integer> playerBlocks = getPlayerRemainings(acc, true); + Map<UUID, Integer> playerBlocks = getPlayerRemainings(PlayersManager.getPlayerAccount(p), true); if (playerBlocks == null) return; for (UUID id : playerBlocks.keySet()) { Optional<CountableObject<BQBlock>> object = getObject(id); @@ -112,7 +117,7 @@ protected void serialize(ConfigurationSection section) { } public static StageMine deserialize(ConfigurationSection section, StageController controller) { - StageMine stage = new StageMine(branch, new ArrayList<>()); + StageMine stage = new StageMine(controller, new ArrayList<>()); stage.deserialize(section); if (section.contains("placeCancelled")) stage.placeCancelled = section.getBoolean("placeCancelled"); @@ -123,10 +128,15 @@ public static class Creator extends AbstractCountableBlockStage.AbstractCreator< private boolean prevent = false; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageMine> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(6, ItemUtils.itemSwitch(Lang.preventBlockPlace.toString(), prevent), (p, item) -> setPrevent(ItemUtils.toggleSwitch(item))); + line.setItem(6, ItemUtils.itemSwitch(Lang.preventBlockPlace.toString(), prevent), event -> setPrevent(!prevent)); } @Override @@ -137,7 +147,7 @@ protected ItemStack getBlocksItem() { public void setPrevent(boolean prevent) { if (this.prevent != prevent) { this.prevent = prevent; - line.editItem(6, ItemUtils.setSwitch(line.getItem(6), prevent)); + getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, prevent)); } } @@ -149,7 +159,7 @@ public void edit(StageMine stage) { @Override public StageMine finishStage(StageController controller) { - StageMine stage = new StageMine(branch, getImmutableBlocks()); + StageMine stage = new StageMine(controller, getImmutableBlocks()); stage.setPlaceCancelled(prevent); return stage; } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index b0720217..d011a7d2 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -16,22 +16,23 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.events.internal.BQMobDeathEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.AbstractCountableStage; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; -import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.mobs.MobsListGUI; import fr.skytasul.quests.mobs.Mob; @@ -41,7 +42,7 @@ public class StageMobs extends AbstractCountableStage<Mob<?>> implements Locatab private boolean shoot = false; public StageMobs(StageController controller, List<CountableObject<Mob<?>>> mobs) { - super(branch, mobs); + super(controller, mobs); } public boolean isShoot() { @@ -60,10 +61,8 @@ public void onMobKilled(BQMobDeathEvent e){ Player p = e.getKiller(); if (p == e.getBukkitEntity()) return; // player suicidal - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (branch.hasStageLaunched(acc, this)){ - event(acc, p, new KilledMob(e.getPluginMob(), e.getBukkitEntity()), e.getAmount()); - } + if (hasStarted(p)) + event(p, new KilledMob(e.getPluginMob(), e.getBukkitEntity()), e.getAmount()); } @Override @@ -87,8 +86,8 @@ public String descriptionLine(PlayerAccount acc, DescriptionSource source){ } @Override - public void start(PlayerAccount acc) { - super.start(acc); + public void started(PlayerAccount acc) { + super.started(acc); if (acc.isCurrent() && sendStartMessage()) { Lang.STAGE_MOBSLIST.send(acc.getPlayer(), (Object[]) super.descriptionFormat(acc, DescriptionSource.FORCELINE)); } @@ -139,12 +138,12 @@ public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { }) .filter(Objects::nonNull) .sorted(Comparator.comparing(Entry::getValue)) - .<Located>map(entry -> Located.LocatedEntity.open(entry.getKey())) + .<Located>map(entry -> Located.LocatedEntity.create(entry.getKey())) .spliterator(); } public static StageMobs deserialize(ConfigurationSection section, StageController controller) { - StageMobs stage = new StageMobs(branch, new ArrayList<>()); + StageMobs stage = new StageMobs(controller, new ArrayList<>()); stage.deserialize(section); if (section.contains("shoot")) stage.shoot = section.getBoolean("shoot"); @@ -156,27 +155,33 @@ public static class Creator extends StageCreation<StageMobs> { private List<MutableCountableObject<Mob<?>>> mobs; private boolean shoot = false; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageMobs> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(7, ItemUtils.item(XMaterial.STONE_SWORD, Lang.editMobs.toString()), (p, item) -> { + line.setItem(7, ItemUtils.item(XMaterial.STONE_SWORD, Lang.editMobs.toString()), event -> { new MobsListGUI(mobs, newMobs -> { setMobs(newMobs); - reopenGUI(p, true); - }).open(p); + event.reopen(); + }).open(event.getPlayer()); }); - line.setItem(6, ItemUtils.itemSwitch(Lang.mobsKillType.toString(), shoot), (p, item) -> setShoot(ItemUtils.toggleSwitch(item))); + line.setItem(6, ItemUtils.itemSwitch(Lang.mobsKillType.toString(), shoot), event -> setShoot(!shoot)); } public void setMobs(List<MutableCountableObject<Mob<?>>> mobs) { this.mobs = mobs; - line.editItem(7, ItemUtils.lore(line.getItem(7), Lang.optionValue.format(Lang.AmountMobs.format(mobs.size())))); + getLine().refreshItem(7, + item -> ItemUtils.lore(item, Lang.optionValue.format(Lang.AmountMobs.format(mobs.size())))); } public void setShoot(boolean shoot) { if (this.shoot != shoot) { this.shoot = shoot; - line.editItem(6, ItemUtils.setSwitch(line.getItem(6), shoot)); + getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, shoot)); } } @@ -185,13 +190,13 @@ public void start(Player p) { super.start(p); new MobsListGUI(Collections.emptyList(), newMobs -> { setMobs(newMobs); - reopenGUI(p, true); + context.reopenGui(); }).open(p); } @Override public StageMobs finishStage(StageController controller) { - StageMobs stage = new StageMobs(branch, + StageMobs stage = new StageMobs(controller, mobs.stream().map(MutableCountableObject::toImmutable).collect(Collectors.toList())); stage.setShoot(shoot); return stage; 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 f7220616..f74727e8 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -12,11 +12,13 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.AbstractHolograms; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.DialogEditor; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; @@ -30,15 +32,18 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.stages.Line; import fr.skytasul.quests.gui.npc.NpcSelectGUI; import fr.skytasul.quests.utils.compatibility.GPS; +import fr.skytasul.quests.utils.types.DialogRunnerImplementation; @LocatableType (types = LocatedType.ENTITY) public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable { @@ -46,7 +51,7 @@ public class StageNPC extends AbstractStage implements Locatable.PreciseLocatabl private BQNPC npc; private int npcID; protected Dialog dialog = null; - protected DialogRunner dialogRunner = null; + protected DialogRunnerImplementation dialogRunner = null; protected boolean hide = false; private BukkitTask task; @@ -75,24 +80,28 @@ public void run() { tmp.add(p); } - if (QuestsConfigurationImplementation.getHoloTalkItem() != null && QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility()) { + if (QuestsConfigurationImplementation.getConfiguration().getHoloTalkItem() != null + && QuestsAPI.getAPI().hasHologramsManager() + && QuestsAPI.getAPI().getHologramsManager().supportItems() + && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility()) { if (hologram == null) createHoloLaunch(); hologram.setPlayersVisible(tmp); hologram.teleport(Utils.upLocationForEntity((LivingEntity) en, 1)); } - if (QuestsConfigurationImplementation.showTalkParticles()) { + if (QuestsConfigurationImplementation.getConfiguration().showTalkParticles()) { if (tmp.isEmpty()) return; - QuestsConfigurationImplementation.getParticleTalk().send(en, tmp); + QuestsConfigurationImplementation.getConfiguration().getParticleTalk().send(en, tmp); } } }.runTaskTimer(BeautyQuests.getInstance(), 20L, 6L); } private void createHoloLaunch(){ - ItemStack item = QuestsConfigurationImplementation.getHoloTalkItem(); + ItemStack item = QuestsConfigurationImplementation.getConfiguration().getHoloTalkItem(); hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(npc.getLocation(), false); - if (QuestsConfigurationImplementation.isCustomHologramNameShown() && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) + if (QuestsConfigurationImplementation.getConfiguration().isCustomHologramNameShown() && item.hasItemMeta() + && item.getItemMeta().hasDisplayName()) hologram.appendTextLine(item.getItemMeta().getDisplayName()); hologram.appendItem(item); } @@ -156,18 +165,18 @@ public Located getLocated() { @Override public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Utils.format(Lang.SCOREBOARD_NPC.toString(), descriptionFormat(acc, source)); + return MessageUtils.format(Lang.SCOREBOARD_NPC.toString(), descriptionFormat(acc, source)); } @Override - protected Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { + public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new String[] { npcName() }; } protected void initDialogRunner() { if (dialogRunner != null) throw new IllegalStateException("Dialog runner already initialized"); - dialogRunner = new DialogRunner(dialog, npc); + dialogRunner = new DialogRunnerImplementation(dialog, npc); dialogRunner.addTest(super::hasStarted); dialogRunner.addTestCancelling(p -> canUpdate(p, true)); @@ -178,7 +187,8 @@ protected void initDialogRunner() { public void onClick(BQNPCClickEvent e) { if (e.isCancelled()) return; if (e.getNPC() != npc) return; - if (!QuestsConfigurationImplementation.getNPCClicks().contains(e.getClick())) return; + if (!QuestsConfiguration.getConfig().getQuestsConfig().getNpcClicks().contains(e.getClick())) + return; Player p = e.getPlayer(); e.setCancelled(dialogRunner.onClick(p).shouldCancel()); @@ -187,16 +197,17 @@ public void onClick(BQNPCClickEvent e) { protected String npcName(){ if (npc == null) return "§c§lunknown NPC " + npcID; - if (dialog != null && dialog.npcName != null) - return dialog.npcName; + if (dialog != null && dialog.getNpcName() != null) + return dialog.getNpcName(); return npc.getName(); } @Override - public void joins(PlayerAccount acc, Player p) { - super.joins(acc, p); + public void joined(Player p) { + super.joined(p); cachePlayer(p); - if (QuestsConfigurationImplementation.handleGPS() && !hide) GPS.launchCompass(p, npc.getLocation()); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) + GPS.launchCompass(p, npc.getLocation()); } private void cachePlayer(Player p) { @@ -210,25 +221,28 @@ private void uncachePlayer(Player p) { } private void uncacheAll() { - if (QuestsConfigurationImplementation.handleGPS() && !hide) cached.forEach(GPS::stopCompass); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) + cached.forEach(GPS::stopCompass); if (npc != null) cached.forEach(p -> npc.removeHiddenForPlayer(p, this)); } @Override - public void leaves(PlayerAccount acc, Player p) { - super.leaves(acc, p); + public void left(Player p) { + super.left(p); uncachePlayer(p); - if (QuestsConfigurationImplementation.handleGPS() && !hide) GPS.stopCompass(p); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) + GPS.stopCompass(p); if (dialogRunner != null) dialogRunner.removePlayer(p); } @Override - public void start(PlayerAccount acc) { - super.start(acc); + public void started(PlayerAccount acc) { + super.started(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); cachePlayer(p); - if (QuestsConfigurationImplementation.handleGPS() && npc != null) GPS.launchCompass(p, npc.getLocation()); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && npc != null) + GPS.launchCompass(p, npc.getLocation()); } } @@ -239,7 +253,8 @@ public void ended(PlayerAccount acc) { Player p = acc.getPlayer(); if (dialogRunner != null) dialogRunner.removePlayer(p); uncachePlayer(p); - if (QuestsConfigurationImplementation.handleGPS() && !hide) GPS.stopCompass(p); + if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) + GPS.stopCompass(p); } } @@ -255,7 +270,8 @@ public void unload() { @Override public void load(){ super.load(); - if (QuestsConfigurationImplementation.showTalkParticles() || QuestsConfigurationImplementation.getHoloTalkItem() != null){ + if (QuestsConfigurationImplementation.getConfiguration().showTalkParticles() + || QuestsConfigurationImplementation.getConfiguration().getHoloTalkItem() != null) { if (!hide) launchRefreshTask(); } } @@ -276,7 +292,7 @@ public void serialize(ConfigurationSection section) { } public static StageNPC deserialize(ConfigurationSection section, StageController controller) { - StageNPC st = new StageNPC(branch); + StageNPC st = new StageNPC(controller); st.loadDatas(section); return st; } @@ -291,50 +307,56 @@ public abstract static class AbstractCreator<T extends StageNPC> extends StageCr private Dialog dialog = null; private boolean hidden = false; - protected AbstractCreator(Line line, boolean ending) { - super(line, ending); + protected AbstractCreator(@NotNull StageCreationContext<T> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString()), (p, item) -> { - new NpcSelectGUI(() -> reopenGUI(p, true), newNPC -> { + line.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString()), event -> { + NpcSelectGUI.select(event::reopen, newNPC -> { setNPCId(newNPC.getId()); - reopenGUI(p, true); - }).open(p); + event.reopen(); + }).open(event.getPlayer()); }); - line.setItem(SLOT_DIALOG, ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.stageText.toString(), Lang.NotSet.toString()), (p, item) -> { - Utils.sendMessage(p, Lang.NPC_TEXT.toString()); - new DialogEditor(p, () -> { + line.setItem(SLOT_DIALOG, ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.stageText.toString(), Lang.NotSet.toString()), event -> { + Lang.NPC_TEXT.send(event.getPlayer()); + new DialogEditor(event.getPlayer(), () -> { setDialog(dialog); - reopenGUI(p, false); + event.reopen(); }, dialog == null ? dialog = new Dialog() : dialog).start(); - }, true, true); + }); - line.setItem(SLOT_HIDE, ItemUtils.itemSwitch(Lang.stageHide.toString(), hidden), (p, item) -> setHidden(ItemUtils.toggleSwitch(item)), true, true); + line.setItem(SLOT_HIDE, ItemUtils.itemSwitch(Lang.stageHide.toString(), hidden), event -> setHidden(!hidden)); } public void setNPCId(int npcID) { this.npcID = npcID; - line.editItem(SLOT_NPC, ItemUtils.lore(line.getItem(SLOT_NPC), QuestOption.formatDescription("ID: §l" + npcID))); + getLine().refreshItem(SLOT_NPC, item -> ItemUtils.lore(item, QuestOption.formatDescription("ID: §l" + npcID))); } public void setDialog(Dialog dialog) { this.dialog = dialog; - line.editItem(SLOT_DIALOG, ItemUtils.lore(line.getItem(SLOT_DIALOG), dialog == null ? Lang.NotSet.toString() : QuestOption.formatDescription(Lang.dialogLines.format(dialog.messages.size())))); + getLine().refreshItem(SLOT_DIALOG, item -> ItemUtils.lore(item, dialog == null ? Lang.NotSet.toString() + : QuestOption.formatDescription(Lang.dialogLines.format(dialog.getMessages().size())))); } public void setHidden(boolean hidden) { if (this.hidden != hidden) { this.hidden = hidden; - line.editItem(SLOT_HIDE, ItemUtils.setSwitch(line.getItem(SLOT_HIDE), hidden)); + getLine().refreshItem(SLOT_HIDE, item -> ItemUtils.setSwitch(item, hidden)); } } @Override public void start(Player p) { super.start(p); - new NpcSelectGUI(removeAndReopen(p, true), newNPC -> { + NpcSelectGUI.select(context::removeAndReopenGui, newNPC -> { setNPCId(newNPC.getId()); - reopenGUI(p, true); + context.reopenGui(); }).open(p); } @@ -348,7 +370,7 @@ public void edit(T stage) { @Override protected final T finishStage(StageController controller) { - T stage = createStage(branch); + T stage = createStage(controller); stage.setDialog(dialog); stage.setNPC(npcID); stage.setHid(hidden); @@ -356,18 +378,18 @@ protected final T finishStage(StageController controller) { } protected abstract T createStage(StageController controller); - + } public static class Creator extends AbstractCreator<StageNPC> { - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageNPC> context) { + super(context); } - + @Override - protected StageNPC createStage(StageController controller) { - return new StageNPC(branch); + protected @NotNull StageNPC createStage(@NotNull StageController controller) { + return new StageNPC(controller); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index 98788124..ff2480ca 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -8,22 +8,22 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.CountableObject; -import fr.skytasul.quests.gui.creation.stages.Line; public class StagePlaceBlocks extends AbstractCountableBlockStage { public StagePlaceBlocks(StageController controller, List<CountableObject<BQBlock>> blocks) { - super(branch, blocks); + super(controller, blocks); } @Override @@ -35,22 +35,20 @@ public String descriptionLine(PlayerAccount acc, DescriptionSource source){ public void onPlace(BlockPlaceEvent e) { if (e.isCancelled()) return; Player p = e.getPlayer(); - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (branch.hasStageLaunched(acc, this)){ - event(acc, p, e.getBlock(), 1); - } + if (hasStarted(p)) + event(p, e.getBlock(), 1); } public static StagePlaceBlocks deserialize(ConfigurationSection section, StageController controller) { - StagePlaceBlocks stage = new StagePlaceBlocks(branch, new ArrayList<>()); + StagePlaceBlocks stage = new StagePlaceBlocks(controller, new ArrayList<>()); stage.deserialize(section); return stage; } public static class Creator extends AbstractCountableBlockStage.AbstractCreator<StagePlaceBlocks> { - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StagePlaceBlocks> context) { + super(context); } @Override @@ -60,7 +58,7 @@ protected ItemStack getBlocksItem() { @Override public StagePlaceBlocks finishStage(StageController controller) { - return new StagePlaceBlocks(branch, getImmutableBlocks()); + return new StagePlaceBlocks(controller, getImmutableBlocks()); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index 6944771e..17a97eb7 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -1,6 +1,5 @@ package fr.skytasul.quests.stages; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; @@ -8,6 +7,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; @@ -17,17 +17,19 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.stages.Line; public class StagePlayTime extends AbstractStage { private final long playTicks; - private Map<PlayerAccount, BukkitTask> tasks = new HashMap<>(); + private Map<Player, BukkitTask> tasks = new HashMap<>(); public StagePlayTime(StageController controller, long ticks) { super(controller); @@ -39,12 +41,12 @@ public long getTicksToPlay() { } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_PLAY_TIME.format(descriptionFormat(acc, source)); } @Override - protected Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { + public Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { return new Supplier[] { () -> Utils.millisToHumanString(getRemaining(acc) * 50L) }; } @@ -55,54 +57,62 @@ private long getRemaining(PlayerAccount acc) { return remaining - playedTicks; } - private void launchTask(PlayerAccount acc, Player p, long remaining) { - tasks.put(acc, Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), () -> branch.finishStage(p, this), remaining < 0 ? 0 : remaining)); + private void launchTask(Player p, long remaining) { + tasks.put(p, Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), () -> finishStage(p), + remaining < 0 ? 0 : remaining)); } @Override - public void joins(PlayerAccount acc, Player p) { - super.joins(acc, p); - updateObjective(acc, null, "lastJoin", System.currentTimeMillis()); - launchTask(acc, p, Utils.parseLong(getData(acc, "remainingTime"))); + public void joined(Player p) { + super.joined(p); + updateObjective(p, "lastJoin", System.currentTimeMillis()); + launchTask(p, Utils.parseLong(getData(p, "remainingTime"))); } @Override - public void leaves(PlayerAccount acc, Player p) { - super.leaves(acc, p); - BukkitTask task = tasks.remove(acc); + public void left(Player p) { + super.left(p); + BukkitTask task = tasks.remove(p); if (task != null) { - task.cancel(); - updateObjective(acc, null, "remainingTime", getRemaining(acc)); + cancelTask(p, task); }else { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unavailable task in \"Play Time\" stage " + toString() + " for player " + acc.getName()); + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Unavailable task in \"Play Time\" stage " + toString() + " for player " + p.getName()); } } - - @Override - public void start(PlayerAccount acc) { - super.start(acc); - if (acc.isCurrent()) { - launchTask(acc, acc.getPlayer(), playTicks); - } + + private void cancelTask(Player p, BukkitTask task) { + task.cancel(); + updateObjective(p, "remainingTime", getRemaining(PlayersManager.getPlayerAccount(p))); } @Override - protected void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { - super.initPlayerDatas(acc, datas); - datas.put("remainingTime", playTicks); - datas.put("lastJoin", System.currentTimeMillis()); + public void started(PlayerAccount acc) { + super.started(acc); + + if (acc.isCurrent()) + launchTask(acc.getPlayer(), playTicks); } @Override public void ended(PlayerAccount acc) { super.ended(acc); - tasks.remove(acc).cancel(); + + if (acc.isCurrent()) + tasks.remove(acc.getPlayer()).cancel(); + } + + @Override + public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { + super.initPlayerDatas(acc, datas); + datas.put("remainingTime", playTicks); + datas.put("lastJoin", System.currentTimeMillis()); } @Override public void unload() { super.unload(); - new ArrayList<>(tasks.keySet()).forEach(acc -> leaves(acc, null)); // prevents ConcurrentModificationException at server shutdown + tasks.forEach(this::cancelTask); tasks.clear(); } @@ -112,37 +122,42 @@ protected void serialize(ConfigurationSection section) { } public static StagePlayTime deserialize(ConfigurationSection section, StageController controller) { - return new StagePlayTime(branch, section.getLong("playTicks")); + return new StagePlayTime(controller, section.getLong("playTicks")); } public static class Creator extends StageCreation<StagePlayTime> { private long ticks; - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StagePlayTime> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); - line.setItem(7, ItemUtils.item(XMaterial.CLOCK, Lang.changeTicksRequired.toString()), (p, item) -> { - Lang.GAME_TICKS.send(p); - new TextEditor<>(p, () -> reopenGUI(p, false), obj -> { + line.setItem(7, ItemUtils.item(XMaterial.CLOCK, Lang.changeTicksRequired.toString()), event -> { + Lang.GAME_TICKS.send(event.getPlayer()); + new TextEditor<>(event.getPlayer(), event::reopen, obj -> { setTicks(obj); - reopenGUI(p, false); + event.reopen(); }, MinecraftTimeUnit.TICK.getParser()).start(); }); } public void setTicks(long ticks) { this.ticks = ticks; - line.editItem(7, ItemUtils.lore(line.getItem(7), Lang.optionValue.format(ticks + " ticks"))); + getLine().refreshItemLore(7, Lang.optionValue.format(ticks + " ticks")); } @Override public void start(Player p) { super.start(p); Lang.GAME_TICKS.send(p); - new TextEditor<>(p, removeAndReopen(p, false), obj -> { + new TextEditor<>(p, context::removeAndReopenGui, obj -> { setTicks(obj); - reopenGUI(p, false); + context.reopenGui(); }, MinecraftTimeUnit.TICK.getParser()).start(); } @@ -154,7 +169,7 @@ public void edit(StagePlayTime stage) { @Override public StagePlayTime finishStage(StageController controller) { - return new StagePlayTime(branch, ticks); + return new StagePlayTime(controller, ticks); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java index 7ea3fbdc..f830c857 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java @@ -6,17 +6,18 @@ import org.bukkit.entity.Tameable; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityTameEvent; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractEntityStage; -import fr.skytasul.quests.gui.creation.stages.Line; public class StageTame extends AbstractEntityStage { public StageTame(StageController controller, EntityType entity, int amount) { - super(branch, entity, amount); + super(controller, entity, amount); } @EventHandler @@ -28,19 +29,19 @@ public void onTame(EntityTameEvent e) { } @Override - protected String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public String descriptionLine(PlayerAccount acc, DescriptionSource source) { return Lang.SCOREBOARD_TAME.format(getMobsLeft(acc)); } public static StageTame deserialize(ConfigurationSection section, StageController controller) { String type = section.getString("entityType"); - return new StageTame(branch, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); + return new StageTame(controller, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); } public static class Creator extends AbstractEntityStage.AbstractCreator<StageTame> { - public Creator(Line line, boolean ending) { - super(line, ending); + public Creator(@NotNull StageCreationContext<StageTame> context) { + super(context); } @Override @@ -50,7 +51,7 @@ protected boolean canUseEntity(EntityType type) { @Override protected StageTame finishStage(StageController controller) { - return new StageTame(branch, entity, amount); + return new StageTame(controller, entity, amount); } } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java index d71d17ce..64fcf43b 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -13,6 +13,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnmodifiableView; import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.PlayerSetStageEvent; import fr.skytasul.quests.api.localization.Lang; @@ -138,7 +139,8 @@ public boolean isEndingStage(StageController stage) { if (datas.getStage() < 0) return "§cerror: no stage set for branch " + getId(); if (datas.getStage() >= regularStages.size()) return "§cerror: datas do not match"; - return MessageUtils.format(QuestsConfigurationImplementation.getStageDescriptionFormat(), datas.getStage() + 1, + return MessageUtils.format(QuestsConfiguration.getConfig().getStageDescriptionConfig().getStageDescriptionFormat(), + datas.getStage() + 1, regularStages.size(), regularStages.get(datas.getStage()).getDescriptionLine(acc, source)); } @@ -244,8 +246,8 @@ private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplem QuestsPlugin.getPlugin().getLoggerExpanded().debug("Using " + Thread.currentThread().getName() + " as the thread for async rewards."); asyncReward.add(acc); try { - List<String> given = QuestUtils.giveRewards(p, stage.getStage().getRewards()); - if (!given.isEmpty() && QuestsConfigurationImplementation.hasStageEndRewardsMessage()) + List<String> given = stage.getStage().getRewards().giveRewards(p); + if (!given.isEmpty() && QuestsConfiguration.getConfig().getQuestsConfig().stageEndRewardsMessage()) Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); } catch (InterruptingBranchException ex) { QuestsPlugin.getPlugin().getLoggerExpanded().debug( @@ -263,8 +265,8 @@ private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplem }, "BQ async stage end " + p.getName()).start(); }else{ try { - List<String> given = QuestUtils.giveRewards(p, stage.getStage().getRewards()); - if (!given.isEmpty() && QuestsConfigurationImplementation.hasStageEndRewardsMessage()) + List<String> given = stage.getStage().getRewards().giveRewards(p); + if (!given.isEmpty() && QuestsConfiguration.getConfig().getQuestsConfig().stageEndRewardsMessage()) Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); runAfter.run(); } catch (InterruptingBranchException ex) { @@ -287,7 +289,8 @@ public void setStage(@NotNull PlayerAccount acc, int id) { remove(acc, true); }else { PlayerQuestDatas questDatas = acc.getQuestDatas(getQuest()); - if (QuestsConfigurationImplementation.sendQuestUpdateMessage() && p != null && questDatas.getStage() != -1) + if (QuestsConfiguration.getConfig().getQuestsConfig().playerQuestUpdateMessage() && p != null + && questDatas.getStage() != -1) Lang.QUEST_UPDATED.send(p, getQuest().getName()); questDatas.setStage(id); if (p != null) playNextStage(p); @@ -298,7 +301,7 @@ public void setStage(@NotNull PlayerAccount acc, int id) { public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { Player p = acc.getPlayer(); - if (QuestsConfigurationImplementation.sendQuestUpdateMessage() && p != null && launchStage) + if (QuestsConfiguration.getConfig().getQuestsConfig().playerQuestUpdateMessage() && p != null && launchStage) Lang.QUEST_UPDATED.send(p, getQuest().getName()); PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); datas.setInEndingStages(); @@ -310,8 +313,10 @@ public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { } private void playNextStage(@NotNull Player p) { - QuestUtils.playPluginSound(p.getLocation(), QuestsConfigurationImplementation.getNextStageSound(), 0.5F); - if (QuestsConfigurationImplementation.showNextParticles()) QuestsConfigurationImplementation.getParticleNext().send(p, Arrays.asList(p)); + QuestUtils.playPluginSound(p.getLocation(), QuestsConfiguration.getConfig().getQuestsConfig().nextStageSound(), + 0.5F); + if (QuestsConfigurationImplementation.getConfiguration().showNextParticles()) + QuestsConfigurationImplementation.getConfiguration().getParticleNext().send(p, Arrays.asList(p)); } public void remove(){ diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index 342220cf..f84b2fb2 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -22,8 +22,8 @@ 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.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.PlayerQuestResetEvent; import fr.skytasul.quests.api.events.QuestFinishEvent; @@ -45,11 +45,12 @@ import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.PlayerListCategory; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.options.*; import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.rewards.MessageReward; +import fr.skytasul.quests.structure.pools.QuestPoolImplementation; import fr.skytasul.quests.utils.QuestUtils; public class QuestImplementation implements Quest, QuestDescriptionProvider { @@ -64,8 +65,7 @@ public class QuestImplementation implements Quest, QuestDescriptionProvider { private List<QuestDescriptionProvider> descriptions = new ArrayList<>(); private boolean removed = false; - public boolean asyncEnd = false; - public List<Player> asyncStart = null; + public List<Player> inAsyncStart = new ArrayList<>(); public QuestImplementation(int id) { this(id, new File(BeautyQuests.getInstance().getQuestsManager().getSaveFolder(), id + ".yml")); @@ -196,6 +196,14 @@ public boolean canBypassLimit() { return getOptionValueOrDef(OptionBypassLimit.class); } + public boolean hasAsyncStart() { + return getOptionValueOrDef(OptionStartRewards.class).hasAsync(); + } + + public boolean hasAsyncEnd() { + return getOptionValueOrDef(OptionEndRewards.class).hasAsync(); + } + @Override public @NotNull BranchesManagerImplementation getBranchesManager() { return manager; @@ -209,7 +217,8 @@ public boolean canBypassLimit() { public boolean hasStarted(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(this)) return false; if (acc.getQuestDatas(this).hasStarted()) return true; - if (acc.isCurrent() && asyncStart != null && asyncStart.contains(acc.getPlayer())) return true; + if (acc.isCurrent() && hasAsyncStart() && inAsyncStart.contains(acc.getPlayer())) + return true; return false; } @@ -236,7 +245,7 @@ private void cancelInternal(@NotNull PlayerAccount acc) { if (acc.isCurrent()) { try { - QuestUtils.giveRewards(acc.getPlayer(), getOptionValueOrDef(OptionCancelRewards.class)); + getOptionValueOrDef(OptionCancelRewards.class).giveRewards(acc.getPlayer()); } catch (InterruptingBranchException ex) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to interrupt branching in a cancel reward (useless). " + toString()); } @@ -279,8 +288,10 @@ public boolean canStart(@NotNull Player p, boolean sendMessage) { public boolean testRequirements(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { if (!p.hasPermission("beautyquests.start")) return false; if (!testQuestLimit(p, acc, sendMessage)) return false; - sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) || (QuestsConfigurationImplementation.isRequirementReasonSentOnMultipleQuests() || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); - return QuestUtils.testRequirements(p, getOptionValueOrDef(OptionRequirements.class), sendMessage); + sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) + || (QuestsConfiguration.getConfig().getQuestsConfig().requirementReasonOnMultipleQuests() + || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); + return getOptionValueOrDef(OptionRequirements.class).testPlayer(p, sendMessage); } public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { @@ -296,8 +307,9 @@ public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boo if (playerMaxLaunchedQuestOpt.isPresent()) { playerMaxLaunchedQuest = playerMaxLaunchedQuestOpt.getAsInt(); }else { - if (QuestsConfigurationImplementation.getMaxLaunchedQuests() == 0) return true; - playerMaxLaunchedQuest = QuestsConfigurationImplementation.getMaxLaunchedQuests(); + if (QuestsConfiguration.getConfig().getQuestsConfig().maxLaunchedQuests() == 0) + return true; + playerMaxLaunchedQuest = QuestsConfiguration.getConfig().getQuestsConfig().maxLaunchedQuests(); } if (QuestsAPI.getAPI().getQuestsManager().getStartedSize(acc) >= playerMaxLaunchedQuest) { if (sendMessage) @@ -338,7 +350,8 @@ public void leave(@NotNull Player p) { @Override public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { if (!acc.hasQuestDatas(this)) throw new IllegalArgumentException("Account does not have quest datas for quest " + id); - if (asyncStart != null && acc.isCurrent() && asyncStart.contains(acc.getPlayer())) return "§7x"; + if (acc.isCurrent() && hasAsyncStart() && inAsyncStart.contains(acc.getPlayer())) + return "§7x"; PlayerQuestDatas datas = acc.getQuestDatas(this); if (datas.isInQuestEnd()) return Lang.SCOREBOARD_ASYNC_END.toString(); QuestBranchImplementation branch = manager.getBranch(datas.getBranch()); @@ -372,7 +385,8 @@ public double getDescriptionPriority() { return CompletableFuture.completedFuture(false); String confirm; - if (QuestsConfigurationImplementation.questConfirmGUI() && !"none".equals(confirm = getOptionValueOrDef(OptionConfirmMessage.class))) { + if (QuestsConfiguration.getConfig().getQuestsConfig().questConfirmGUI() + && !"none".equals(confirm = getOptionValueOrDef(OptionConfirmMessage.class))) { CompletableFuture<Boolean> future = new CompletableFuture<>(); ConfirmGUI.confirm(() -> { start(p); @@ -413,14 +427,14 @@ public void start(@NotNull Player p, boolean silently) { Runnable run = () -> { List<String> msg = Collections.emptyList(); try { - msg = QuestUtils.giveRewards(p, getOptionValueOrDef(OptionStartRewards.class)); + msg = getOptionValueOrDef(OptionStartRewards.class).giveRewards(p); } catch (InterruptingBranchException ex) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to interrupt branching in a starting reward (useless). " + toString()); } getOptionValueOrDef(OptionRequirements.class).stream().filter(Actionnable.class::isInstance).map(Actionnable.class::cast).forEach(x -> x.trigger(p)); if (!silently && !msg.isEmpty()) Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(msg.toArray(new String[0]))); - if (asyncStart != null) asyncStart.remove(p); + inAsyncStart.remove(p); QuestUtils.runOrSync(() -> { manager.startPlayer(acc); @@ -428,8 +442,8 @@ public void start(@NotNull Player p, boolean silently) { Bukkit.getPluginManager().callEvent(new QuestLaunchEvent(p, QuestImplementation.this)); }); }; - if (asyncStart != null){ - asyncStart.add(p); + if (hasAsyncStart()) { + inAsyncStart.add(p); QuestUtils.runAsync(run); }else run.run(); } @@ -438,11 +452,11 @@ public void start(@NotNull Player p, boolean silently) { public void finish(@NotNull Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); AdminMode.broadcast(p.getName() + " is completing the quest " + id); - PlayerQuestDatas questDatas = acc.getQuestDatas(QuestImplementation.this); + PlayerQuestDatas questDatas = acc.getQuestDatas(this); Runnable run = () -> { try { - List<String> msg = QuestUtils.giveRewards(p, getOptionValueOrDef(OptionEndRewards.class)); + List<String> msg = getOptionValueOrDef(OptionEndRewards.class).giveRewards(p); String obtained = MessageUtils.itemsToFormattedString(msg.toArray(new String[0])); if (hasOption(OptionEndMessage.class)) { String endMsg = getOption(OptionEndMessage.class).getValue(); @@ -461,7 +475,8 @@ public void finish(@NotNull Player p) { questDatas.setBranch(-1); questDatas.incrementFinished(); questDatas.setStartingTime(0); - if (hasOption(OptionQuestPool.class)) getOptionValueOrDef(OptionQuestPool.class).questCompleted(acc, QuestImplementation.this); + if (hasOption(OptionQuestPool.class)) + ((QuestPoolImplementation) getOptionValueOrDef(OptionQuestPool.class)).questCompleted(acc, this); if (isRepeatable()) { Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, Math.max(0, getOptionValueOrDef(OptionTimer.class))); @@ -471,11 +486,11 @@ public void finish(@NotNull Player p) { QuestUtils.playPluginSound(p, getOptionValueOrDef(OptionEndSound.class), 1); QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questFinish(acc, this)); - Bukkit.getPluginManager().callEvent(new QuestFinishEvent(p, QuestImplementation.this)); + Bukkit.getPluginManager().callEvent(new QuestFinishEvent(p, this)); }); }; - if (asyncEnd) { + if (hasAsyncEnd()) { questDatas.setInQuestEnd(); new Thread(() -> { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Using " + Thread.currentThread().getName() + " as the thread for async rewards."); 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 ab09e33a..a8c285be 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 @@ -22,7 +22,7 @@ import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.api.serializable.SerializableObject; +import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.players.PlayerPoolDatasImplementation; import fr.skytasul.quests.utils.QuestUtils; @@ -38,12 +38,12 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati private final boolean redoAllowed; private final long timeDiff; private final boolean avoidDuplicates; - private final List<AbstractRequirement> requirements; + private final RequirementList requirements; BQNPC npc; List<Quest> quests = new ArrayList<>(); - QuestPoolImplementation(int id, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, List<AbstractRequirement> requirements) { + QuestPoolImplementation(int id, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements) { this.id = id; this.npcID = npcID; this.hologram = hologram; @@ -105,7 +105,7 @@ public boolean doAvoidDuplicates() { } @Override - public List<AbstractRequirement> getRequirements() { + public RequirementList getRequirements() { return requirements; } @@ -226,7 +226,7 @@ public CompletableFuture<String> give(Player p) { private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, PlayerPoolDatas datas, boolean hadOne) { - if (!QuestUtils.testRequirements(p, requirements, !hadOne)) + if (!requirements.testPlayer(p, !hadOne)) return CompletableFuture.completedFuture(new PoolGiveResult("")); List<Quest> notCompleted = avoidDuplicates ? quests.stream() @@ -304,12 +304,15 @@ public void save(ConfigurationSection config) { config.set("timeDiff", timeDiff); config.set("npcID", npcID); config.set("avoidDuplicates", avoidDuplicates); - if (!requirements.isEmpty()) config.set("requirements", SerializableObject.serializeList(requirements)); + if (!requirements.isEmpty()) + config.set("requirements", requirements.serialize()); } public static QuestPoolImplementation deserialize(int id, ConfigurationSection config) { - List<AbstractRequirement> requirements = SerializableObject.deserializeList(config.getMapList("requirements"), AbstractRequirement::deserialize); - return new QuestPoolImplementation(id, config.getInt("npcID"), config.getString("hologram"), config.getInt("maxQuests"), config.getInt("questsPerLaunch", 1), config.getBoolean("redoAllowed"), config.getLong("timeDiff"), config.getBoolean("avoidDuplicates", true), requirements); + return new QuestPoolImplementation(id, config.getInt("npcID"), config.getString("hologram"), + config.getInt("maxQuests"), config.getInt("questsPerLaunch", 1), config.getBoolean("redoAllowed"), + config.getLong("timeDiff"), config.getBoolean("avoidDuplicates", true), + RequirementList.deserialize(config.getMapList("requirements"))); } private static class PoolGiveResult { diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java index 500fb097..a3b39950 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; @@ -15,7 +14,7 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.pools.QuestPoolsManager; -import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.options.OptionQuestPool; public class QuestPoolsManagerImplementation implements QuestPoolsManager { @@ -61,7 +60,7 @@ public void save(@NotNull QuestPoolImplementation pool) { public @NotNull QuestPoolImplementation createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, - @NotNull List<AbstractRequirement> requirements) { + @NotNull RequirementList requirements) { if (editing != null) ((QuestPoolImplementation) editing).unload(); 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 0688fd7d..dc078ac4 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -1,7 +1,5 @@ package fr.skytasul.quests.utils; -import java.util.ArrayList; -import java.util.List; import java.util.function.BiConsumer; import java.util.function.Consumer; import org.bukkit.Bukkit; @@ -13,12 +11,8 @@ import org.bukkit.metadata.FixedMetadataValue; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; -import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; @@ -100,47 +94,4 @@ public static void spawnFirework(Location lc, FireworkMeta meta) { }); } - public static List<String> giveRewards(Player p, List<AbstractReward> rewards) throws InterruptingBranchException { - InterruptingBranchException interrupting = null; - - List<String> msg = new ArrayList<>(); - for (AbstractReward rew : rewards) { - try { - List<String> messages = rew.give(p); - if (messages != null) - msg.addAll(messages); - } catch (InterruptingBranchException ex) { - if (interrupting != null) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Interrupting the same branch via rewards twice!"); - } else { - interrupting = ex; - } - } catch (Throwable e) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when giving reward " + rew.getName() + " to " + p.getName(), e); - } - } - - if (interrupting != null) - throw interrupting; - return msg; - } - - public static boolean testRequirements(Player p, List<AbstractRequirement> requirements, boolean message) { - for (AbstractRequirement requirement : requirements) { - try { - if (!requirement.test(p)) { - if (message && !requirement.sendReason(p)) - continue; // means a reason has not yet been sent - return false; - } - } catch (Exception ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe( - "Cannot test requirement " + requirement.getClass().getSimpleName() + " for player " + p.getName(), - ex); - return false; - } - } - return true; - } - } From cfa121f26b4ef9ccd17eb1053dae0fc3b3f9ae4a Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 12 Jun 2023 10:43:49 +0200 Subject: [PATCH 19/95] :arrow_up: Added support for Minecraft 1.20 --- core/pom.xml | 6 +- dist/pom.xml | 7 ++ pom.xml | 1 + v1_20_R1/pom.xml | 80 +++++++++++++++++++ .../skytasul/quests/utils/nms/v1_20_R1.java | 57 +++++++++++++ 5 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 v1_20_R1/pom.xml create mode 100644 v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java diff --git a/core/pom.xml b/core/pom.xml index 36d17a76..dca7acf1 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -180,13 +180,13 @@ <dependency> <groupId>io.papermc.paper</groupId> <artifactId>paper-api</artifactId> - <version>1.19.4-R0.1-SNAPSHOT</version> + <version>1.20-R0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> <groupId>net.citizensnpcs</groupId> <artifactId>citizens-main</artifactId> - <version>2.0.31-SNAPSHOT</version> + <version>2.0.32-SNAPSHOT</version> <type>jar</type> <scope>provided</scope> </dependency> @@ -253,7 +253,7 @@ <dependency> <groupId>fr.mrmicky</groupId> <artifactId>fastboard</artifactId> - <version>1.2.1</version> + <version>2.0.0</version> <scope>compile</scope> </dependency> <dependency> diff --git a/dist/pom.xml b/dist/pom.xml index 3c2874ea..68e23fb9 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -135,5 +135,12 @@ <type>jar</type> <scope>compile</scope> </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>beautyquests-v1_20_R1</artifactId> + <version>${project.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> </dependencies> </project> \ No newline at end of file diff --git a/pom.xml b/pom.xml index ebe06c7b..bcfa99a5 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,7 @@ <module>v1_19_R1</module> <module>v1_19_R2</module> <module>v1_19_R3</module> + <module>v1_20_R1</module> <module>dist</module> </modules> diff --git a/v1_20_R1/pom.xml b/v1_20_R1/pom.xml new file mode 100644 index 00000000..63fa8896 --- /dev/null +++ b/v1_20_R1/pom.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <packaging>jar</packaging> + <artifactId>beautyquests-v1_20_R1</artifactId> + <parent> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-parent</artifactId> + <version>0.21-SNAPSHOT</version> + </parent> + + <properties> + <maven.deploy.skip>true</maven.deploy.skip> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + </properties> + + <repositories> + <repository> + <id>jitpack.io</id> + <url>https://jitpack.io</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-core</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.spigotmc</groupId> + <artifactId>spigot</artifactId> + <version>1.20-R0.1-SNAPSHOT</version> + <classifier>remapped-mojang</classifier> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>net.md-5</groupId> + <artifactId>specialsource-maven-plugin</artifactId> + <version>1.2.4</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>remap</goal> + </goals> + <id>remap-obf</id> + <configuration> + <srgIn>org.spigotmc:minecraft-server:1.20-R0.1-SNAPSHOT:txt:maps-mojang</srgIn> + <reverse>true</reverse> + <remappedDependencies>org.spigotmc:spigot:1.20-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies> + <remappedArtifactAttached>true</remappedArtifactAttached> + <remappedClassifierName>remapped-obf</remappedClassifierName> + </configuration> + </execution> + <execution> + <phase>package</phase> + <goals> + <goal>remap</goal> + </goals> + <id>remap-spigot</id> + <configuration> + <inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile> + <srgIn>org.spigotmc:minecraft-server:1.20-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn> + <remappedDependencies>org.spigotmc:spigot:1.20-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java b/v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java new file mode 100644 index 00000000..4aa65315 --- /dev/null +++ b/v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java @@ -0,0 +1,57 @@ +package fr.skytasul.quests.utils.nms; + +import java.util.List; +import org.apache.commons.lang.Validate; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import net.minecraft.core.Holder.Reference; +import net.minecraft.core.HolderLookup.RegistryLookup; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.protocol.Packet; +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 io.netty.buffer.ByteBuf; + +public class v1_20_R1 extends NMS{ + + @Override + public Object bookPacket(ByteBuf buf){ + return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + } + + @Override + public void sendPacket(Player p, Object packet){ + Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); + ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + } + + @Override + public double entityNameplateHeight(Entity en) { + return en.getHeight(); + } + + @Override + public List<String> getAvailableBlockProperties(Material material) { + RegistryLookup<Block> blockRegistry = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK); + Reference<Block> block = blockRegistry + .getOrThrow(ResourceKey.create(Registries.BLOCK, new ResourceLocation(material.getKey().getKey()))); + StateDefinition<Block, BlockState> stateList = block.value().getStateDefinition(); + return stateList.getProperties().stream().map(Property::getName).toList(); + } + + @Override + public List<String> getAvailableBlockTags() { + return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK).listTags() + .map(x -> x.key().location().toString()).toList(); + } + +} \ No newline at end of file From 065cfc02a7c9a3222f3582f2225d5b9b913c26b4 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 18 Jun 2023 19:47:16 +0200 Subject: [PATCH 20/95] :arrow_up: Upgraded XSeries --- core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pom.xml b/core/pom.xml index dca7acf1..a3c6cb77 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -357,7 +357,7 @@ <dependency> <groupId>com.github.cryptomorin</groupId> <artifactId>XSeries</artifactId> - <version>9.3.1</version> + <version>9.4.0</version> </dependency> <!-- Local JARs --> From d7d1529c961a6186c4b1f13c807e45271ff7dcc7 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 19 Jun 2023 20:46:05 +0200 Subject: [PATCH 21/95] :arrow_up: Updated to 1.20.1 --- core/pom.xml | 2 +- v1_20_R1/pom.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index a3c6cb77..ccbd749e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -180,7 +180,7 @@ <dependency> <groupId>io.papermc.paper</groupId> <artifactId>paper-api</artifactId> - <version>1.20-R0.1-SNAPSHOT</version> + <version>1.20.1-R0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> diff --git a/v1_20_R1/pom.xml b/v1_20_R1/pom.xml index 63fa8896..d245f36d 100644 --- a/v1_20_R1/pom.xml +++ b/v1_20_R1/pom.xml @@ -34,7 +34,7 @@ <dependency> <groupId>org.spigotmc</groupId> <artifactId>spigot</artifactId> - <version>1.20-R0.1-SNAPSHOT</version> + <version>1.20.1-R0.1-SNAPSHOT</version> <classifier>remapped-mojang</classifier> <scope>provided</scope> </dependency> @@ -54,9 +54,9 @@ </goals> <id>remap-obf</id> <configuration> - <srgIn>org.spigotmc:minecraft-server:1.20-R0.1-SNAPSHOT:txt:maps-mojang</srgIn> + <srgIn>org.spigotmc:minecraft-server:1.20.1-R0.1-SNAPSHOT:txt:maps-mojang</srgIn> <reverse>true</reverse> - <remappedDependencies>org.spigotmc:spigot:1.20-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies> + <remappedDependencies>org.spigotmc:spigot:1.20.1-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies> <remappedArtifactAttached>true</remappedArtifactAttached> <remappedClassifierName>remapped-obf</remappedClassifierName> </configuration> @@ -69,8 +69,8 @@ <id>remap-spigot</id> <configuration> <inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile> - <srgIn>org.spigotmc:minecraft-server:1.20-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn> - <remappedDependencies>org.spigotmc:spigot:1.20-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies> + <srgIn>org.spigotmc:minecraft-server:1.20.1-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn> + <remappedDependencies>org.spigotmc:spigot:1.20.1-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies> </configuration> </execution> </executions> From 9ec1bc8ec322543c4a0bc9e3ae1da29b1dd5f3b1 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 2 Jul 2023 19:04:23 +0200 Subject: [PATCH 22/95] :construction: Still WIP --- .../fr/skytasul/quests/api/QuestsAPI.java | 4 + .../skytasul/quests/api/blocks/BQBlock.java | 63 +++++ .../quests/api/blocks/BQBlockOptions.java | 24 ++ .../quests/api/blocks/BQBlockType.java | 11 + .../quests/api/blocks/BQBlocksManager.java | 27 ++ .../quests/api/editors/EditorFactory.java | 11 + .../quests/api/editors/EditorManager.java | 4 + .../quests/api/editors/TextEditor.java | 2 +- .../{checkers => parsers}/AbstractParser.java | 2 +- .../CollectionParser.java | 2 +- .../{checkers => parsers}/ColorParser.java | 5 +- .../{checkers => parsers}/DurationParser.java | 2 +- .../{checkers => parsers}/EnumParser.java | 2 +- .../{checkers => parsers}/NumberParser.java | 2 +- .../{checkers => parsers}/PatternParser.java | 2 +- .../ScoreboardObjectiveParser.java | 2 +- .../{checkers => parsers}/WorldParser.java | 2 +- .../skytasul/quests/api/gui/GuiFactory.java | 41 ++++ .../skytasul/quests/api/gui/GuiManager.java | 4 + .../requirements/TargetNumberRequirement.java | 2 +- .../quests/api/stages/AbstractStage.java | 10 +- .../api/stages/creation/StageGuiLine.java | 2 +- .../types/AbstractCountableBlockStage.java | 2 +- .../api/stages/types/AbstractEntityStage.java | 2 +- .../fr/skytasul/quests/api/utils/BQBlock.java | 170 ------------- .../quests/api/utils/ComparisonMethod.java | 2 +- .../quests/api/utils/CountableObject.java | 2 +- .../java/fr/skytasul/quests/BeautyQuests.java | 2 +- .../quests/QuestsAPIImplementation.java | 7 + .../quests/blocks/BQBlockMaterial.java | 33 +++ .../blocks/BQBlocksManagerImplementation.java | 171 +++++++++++++ .../quests/commands/CommandsAdmin.java | 7 +- .../quests/commands/CommandsPlayer.java | 4 +- .../commands/CommandsPlayerManagement.java | 4 +- .../quests/editor/DefaultEditorFactory.java | 27 ++ .../editor/EditorManagerImplementation.java | 15 ++ .../editor/parsers}/MaterialParser.java | 8 +- .../quests/gui/DefaultGuiFactory.java | 50 ++++ .../quests/gui/GuiManagerImplementation.java | 16 ++ .../skytasul/quests/gui/blocks/BlocksGUI.java | 2 +- .../quests/gui/blocks/SelectBlockGUI.java | 16 +- .../quest/QuestCreationGuiImplementation.java | 31 +-- .../quests/gui/creation/stages/LineOld.java | 230 ------------------ .../stages/StageLineImplementation.java | 2 +- .../quests/gui/creation/stages/StagesGUI.java | 106 ++++---- .../quests/gui/items/ItemCreatorGUI.java | 6 +- .../fr/skytasul/quests/gui/items/ItemGUI.java | 12 +- .../skytasul/quests/gui/items/ItemsGUI.java | 3 +- .../skytasul/quests/gui/misc/BranchesGUI.java | 207 ---------------- .../skytasul/quests/gui/misc/CommandGUI.java | 2 +- .../fr/skytasul/quests/gui/misc/TitleGUI.java | 2 +- .../skytasul/quests/gui/mobs/MobsListGUI.java | 2 +- .../skytasul/quests/gui/npc/NpcSelectGUI.java | 12 +- .../gui/particles/ParticleEffectGUI.java | 2 +- .../quests/gui/permissions/PermissionGUI.java | 2 +- .../quests/gui/pools/PoolEditGUI.java | 16 +- .../quests/options/OptionQuestItem.java | 5 +- .../quests/options/OptionStarterNPC.java | 6 +- .../skytasul/quests/options/OptionTimer.java | 2 +- .../requirements/EquipmentRequirement.java | 12 +- .../quests/requirements/MoneyRequirement.java | 2 +- .../requirements/ScoreboardRequirement.java | 2 +- .../skytasul/quests/rewards/MoneyReward.java | 2 +- .../skytasul/quests/rewards/RandomReward.java | 2 +- .../skytasul/quests/rewards/WaitReward.java | 2 +- .../fr/skytasul/quests/rewards/XPReward.java | 2 +- .../skytasul/quests/stages/StageBucket.java | 2 +- .../fr/skytasul/quests/stages/StageCraft.java | 11 +- .../quests/stages/StageDealDamage.java | 2 +- .../skytasul/quests/stages/StageInteract.java | 10 +- .../skytasul/quests/stages/StageLocation.java | 4 +- .../fr/skytasul/quests/stages/StageMine.java | 5 +- .../fr/skytasul/quests/stages/StageNPC.java | 9 +- .../quests/stages/StagePlaceBlocks.java | 2 +- .../skytasul/quests/stages/StagePlayTime.java | 2 +- .../fr/skytasul/quests/utils/QuestUtils.java | 4 +- .../quests/utils/compatibility/Post1_13.java | 23 +- 77 files changed, 711 insertions(+), 801 deletions(-) create mode 100644 api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockOptions.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockType.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/blocks/BQBlocksManager.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/AbstractParser.java (77%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/CollectionParser.java (95%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/ColorParser.java (84%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/DurationParser.java (98%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/EnumParser.java (91%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/NumberParser.java (95%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/PatternParser.java (91%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/ScoreboardObjectiveParser.java (88%) rename api/src/main/java/fr/skytasul/quests/api/editors/{checkers => parsers}/WorldParser.java (84%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java delete mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/BQBlock.java create mode 100644 core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java create mode 100644 core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java create mode 100644 core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java rename {api/src/main/java/fr/skytasul/quests/api/editors/checkers => core/src/main/java/fr/skytasul/quests/editor/parsers}/MaterialParser.java (76%) create mode 100644 core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/stages/LineOld.java delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java index df02b003..27d0d365 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -5,6 +5,7 @@ import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.blocks.BQBlocksManager; import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.api.mobs.MobStacker; @@ -82,6 +83,9 @@ public interface QuestsAPI { void setBossBarManager(@NotNull BossBarManager newBossBarManager); + @NotNull + BQBlocksManager getBlocksManager(); + void registerQuestsHandler(@NotNull QuestsHandler handler); void unregisterQuestsHandler(@NotNull QuestsHandler handler); diff --git a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java new file mode 100644 index 00000000..97cbc96e --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java @@ -0,0 +1,63 @@ +package fr.skytasul.quests.api.blocks; + +import org.bukkit.block.Block; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.utils.MinecraftNames; + +public abstract class BQBlock { + + private final @NotNull BQBlockType type; + private final @Nullable String customName; + + private @Nullable XMaterial cachedMaterial; + private @Nullable String cachedName; + + protected BQBlock(@NotNull BQBlockOptions options) { + this.type = options.getType(); + this.customName = options.getCustomName(); + } + + protected abstract @NotNull String getDataString(); + + public abstract boolean applies(@NotNull Block block); + + public abstract @NotNull XMaterial retrieveMaterial(); + + public final @NotNull XMaterial getMaterial() { + if (cachedMaterial == null) cachedMaterial = retrieveMaterial(); + return cachedMaterial; + } + + public @NotNull String getDefaultName() { + return MinecraftNames.getMaterialName(getMaterial()); + } + + public final @NotNull String getName() { + if (cachedName == null) + cachedName = customName == null ? getDefaultName() : customName; + + return cachedName; + } + + public final @NotNull String getAsString() { + return getHeader() + getDataString() + getFooter(); + } + + private @NotNull String getHeader() { + String header = QuestsAPI.getAPI().getBlocksManager().getHeader(type); + return header == null ? "" : (header + BQBlocksManager.HEADER_SEPARATOR); + } + + private @NotNull String getFooter() { + return customName == null ? "" : BQBlocksManager.CUSTOM_NAME_FOOTER + customName; + } + + @Override + public String toString() { + return "BQBlock{" + getAsString() + "}"; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockOptions.java b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockOptions.java new file mode 100644 index 00000000..ed1268fb --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockOptions.java @@ -0,0 +1,24 @@ +package fr.skytasul.quests.api.blocks; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class BQBlockOptions { + + private final @NotNull BQBlockType type; + private final @Nullable String customName; + + public BQBlockOptions(BQBlockType type, String customName) { + this.type = type; + this.customName = customName; + } + + public @NotNull BQBlockType getType() { + return type; + } + + public @Nullable String getCustomName() { + return customName; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockType.java b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockType.java new file mode 100644 index 00000000..b3f3447b --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlockType.java @@ -0,0 +1,11 @@ +package fr.skytasul.quests.api.blocks; + +import org.jetbrains.annotations.NotNull; + +public interface BQBlockType { + + @NotNull + BQBlock deserialize(@NotNull String string, @NotNull BQBlockOptions serializedOptions) + throws IllegalArgumentException; + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlocksManager.java b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlocksManager.java new file mode 100644 index 00000000..39c98a44 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlocksManager.java @@ -0,0 +1,27 @@ +package fr.skytasul.quests.api.blocks; + +import java.util.Collection; +import java.util.Spliterator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.stages.types.Locatable; + +public interface BQBlocksManager { + + public static final String HEADER_SEPARATOR = ":"; + public static final String CUSTOM_NAME_FOOTER = "|customname:"; + + public @NotNull BQBlock deserialize(@NotNull String string) throws IllegalArgumentException; + + public void registerBlockType(@NotNull String header, @NotNull BQBlockType type); + + public @Nullable String getHeader(@NotNull BQBlockType type); + + public @NotNull Spliterator<Locatable.@NotNull Located> getNearbyBlocks( + @NotNull Locatable.MultipleLocatable.NearbyFetcher fetcher, + @NotNull Collection<fr.skytasul.quests.api.blocks.BQBlock> types); + + public @NotNull BQBlock createSimple(@NotNull XMaterial material, @Nullable String customName); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java b/api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java new file mode 100644 index 00000000..b108c28a --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java @@ -0,0 +1,11 @@ +package fr.skytasul.quests.api.editors; + +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.parsers.AbstractParser; + +public interface EditorFactory { + + public @NotNull AbstractParser<XMaterial> getMaterialParser(boolean item, boolean block); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java b/api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java index 8f540224..614ebc09 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/EditorManager.java @@ -17,4 +17,8 @@ public default void stop(@NotNull Editor editor) { public boolean isInEditor(@NotNull Player player); + public @NotNull EditorFactory getFactory(); + + public void setFactory(@NotNull EditorFactory factory); + } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java index 8256d197..ea756a95 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java @@ -3,7 +3,7 @@ import java.util.function.Consumer; import org.apache.commons.lang.Validate; import org.bukkit.entity.Player; -import fr.skytasul.quests.api.editors.checkers.AbstractParser; +import fr.skytasul.quests.api.editors.parsers.AbstractParser; import fr.skytasul.quests.api.localization.Lang; public class TextEditor<T> extends Editor { diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/AbstractParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/AbstractParser.java similarity index 77% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/AbstractParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/AbstractParser.java index 5a747e8a..69af6588 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/AbstractParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/AbstractParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import org.bukkit.entity.Player; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/CollectionParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/CollectionParser.java similarity index 95% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/CollectionParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/CollectionParser.java index 72aaee7b..b2b37eec 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/CollectionParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/CollectionParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import java.util.Collection; import java.util.Map; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ColorParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/ColorParser.java similarity index 84% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/ColorParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/ColorParser.java index a6850ca0..f594ac94 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ColorParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/ColorParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -12,7 +12,8 @@ public class ColorParser implements AbstractParser<Color> { public static final ColorParser PARSER = new ColorParser(); private final Pattern hexPattern = Pattern.compile("^#([a-fA-F0-9]{6})$"); - private final Pattern rgbPattern = Pattern.compile("^\\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\b,? ?\\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\b,? ?\\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\b$"); + private final Pattern rgbPattern = Pattern.compile( + "^\\b(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\b,? ?\\b(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\b,? ?\\b(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\b$"); private ColorParser() {} diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/DurationParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/DurationParser.java similarity index 98% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/DurationParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/DurationParser.java index 93f19519..5efee7db 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/DurationParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/DurationParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import java.util.HashMap; import java.util.Map; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/EnumParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/EnumParser.java similarity index 91% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/EnumParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/EnumParser.java index 0a6bc2e6..4c2df774 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/EnumParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/EnumParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import java.util.Arrays; import java.util.function.Predicate; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/NumberParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/NumberParser.java similarity index 95% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/NumberParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/NumberParser.java index 54d781b6..7e7a17f4 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/NumberParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/NumberParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import java.math.BigDecimal; import org.bukkit.entity.Player; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/PatternParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/PatternParser.java similarity index 91% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/PatternParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/PatternParser.java index c47671ae..d7d80646 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/PatternParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/PatternParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ScoreboardObjectiveParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/ScoreboardObjectiveParser.java similarity index 88% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/ScoreboardObjectiveParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/ScoreboardObjectiveParser.java index 342a7558..ab7200cf 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/ScoreboardObjectiveParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/ScoreboardObjectiveParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/WorldParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/WorldParser.java similarity index 84% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/WorldParser.java rename to api/src/main/java/fr/skytasul/quests/api/editors/parsers/WorldParser.java index a1d1e76c..0353ce4d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/WorldParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/WorldParser.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.api.editors.parsers; import org.bukkit.Bukkit; import org.bukkit.World; diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java new file mode 100644 index 00000000..fc758747 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java @@ -0,0 +1,41 @@ +package fr.skytasul.quests.api.gui; + +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; + +public interface GuiFactory { + + @NotNull + Gui createPlayerQuestsMenu(@NotNull PlayerAccount account); + + @NotNull + Gui createItemSelection(@NotNull Consumer<ItemStack> callback, boolean allowCancel); + + @NotNull + default Gui createItemSelection(@NotNull Consumer<ItemStack> callback, Runnable cancel) { + return createItemSelection(item -> { + if (item == null) + cancel.run(); + else + callback.accept(item); + }, true); + } + + @NotNull + Gui createItemCreator(@NotNull Consumer<ItemStack> callback, boolean allowCancel); + + @NotNull + Gui createBlocksSelection(@NotNull Consumer<List<MutableCountableObject<BQBlock>>> callback, + @NotNull Collection<MutableCountableObject<BQBlock>> existingBlocks); + + @NotNull + Gui createNpcSelection(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> callback, boolean nullable); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java index 8d315e7e..e6759867 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java @@ -19,4 +19,8 @@ public interface GuiManager { @Nullable Gui getOpenedGui(@NotNull Player player); + public @NotNull GuiFactory getFactory(); + + public void setFactory(@NotNull GuiFactory factory); + } diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java index ee65c1ad..4438b7c7 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 2c64e262..6a6c4b9f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -94,11 +94,11 @@ public boolean hasAsyncEnd() { return rewards.hasAsync(); } - protected boolean canUpdate(@NotNull Player player) { + protected final boolean canUpdate(@NotNull Player player) { return canUpdate(player, false); } - protected boolean canUpdate(@NotNull Player player, boolean msg) { + protected final boolean canUpdate(@NotNull Player player, boolean msg) { return validationRequirements.testPlayer(player, msg); } @@ -162,15 +162,15 @@ public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull St return null; } - public void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullable Object dataValue) { + protected final void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullable Object dataValue) { controller.updateObjective(p, dataKey, dataValue); } - protected <T> @Nullable T getData(@NotNull Player p, @NotNull String dataKey) { + protected final <T> @Nullable T getData(@NotNull Player p, @NotNull String dataKey) { return getData(PlayersManager.getPlayerAccount(p), dataKey); } - protected <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { + protected final <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { return controller.getData(acc, dataKey); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java index fcbf6556..23ad8ba2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java @@ -39,6 +39,6 @@ default void refreshItemName(int slot, String name) { void setPage(int page); @Nullable - StageGuiClickHandler click(int rawSlot); + StageGuiClickHandler getClick(int rawSlot); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java index b1ed48a9..b5cd48ed 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java @@ -7,12 +7,12 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; -import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.gui.blocks.BlocksGUI; diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index 3e29c7fd..a2ed8643 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -17,7 +17,7 @@ import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/BQBlock.java b/api/src/main/java/fr/skytasul/quests/api/utils/BQBlock.java deleted file mode 100644 index 739ea338..00000000 --- a/api/src/main/java/fr/skytasul/quests/api/utils/BQBlock.java +++ /dev/null @@ -1,170 +0,0 @@ -package fr.skytasul.quests.api.utils; - -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Spliterator; -import java.util.Spliterators; -import org.bukkit.block.Block; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XBlock; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.stages.types.Locatable; -import fr.skytasul.quests.api.stages.types.Locatable.Located; -import fr.skytasul.quests.api.stages.types.Locatable.Located.LocatedBlock; -import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.utils.compatibility.Post1_13; - -public abstract class BQBlock { - - public static final String BLOCKDATA_HEADER = "blockdata:"; - public static final String TAG_HEADER = "tag:"; - public static final String CUSTOM_NAME_FOOTER = "|customname:"; - - private final @Nullable String customName; - - private @Nullable XMaterial cachedMaterial; - private @Nullable String cachedName; - - protected BQBlock(@Nullable String customName) { - this.customName = customName; - } - - protected abstract @NotNull String getDataString(); - - public abstract boolean applies(@NotNull Block block); - - public abstract @NotNull XMaterial retrieveMaterial(); - - public final @NotNull XMaterial getMaterial() { - if (cachedMaterial == null) cachedMaterial = retrieveMaterial(); - return cachedMaterial; - } - - public @NotNull String getDefaultName() { - return MinecraftNames.getMaterialName(getMaterial()); - } - - public final @NotNull String getName() { - if (cachedName == null) - cachedName = customName == null ? getDefaultName() : customName; - - return cachedName; - } - - public final @NotNull String getAsString() { - return getDataString() + getFooter(); - } - - private @NotNull String getFooter() { - return customName == null ? "" : CUSTOM_NAME_FOOTER + customName; - } - - @Override - public String toString() { - return "BQBlock{" + getAsString() + "}"; - } - - public static @NotNull BQBlock fromString(@NotNull String string) { - int nameIndex = string.lastIndexOf(CUSTOM_NAME_FOOTER); - String customName = nameIndex == -1 ? null : string.substring(nameIndex + CUSTOM_NAME_FOOTER.length()); - - int dataEnd = nameIndex == -1 ? string.length() : nameIndex; - - if (string.startsWith(BLOCKDATA_HEADER)) - return new Post1_13.BQBlockData(customName, string.substring(BLOCKDATA_HEADER.length(), dataEnd)); - if (string.startsWith(TAG_HEADER)) - return new Post1_13.BQBlockTag(customName, string.substring(TAG_HEADER.length(), dataEnd)); - return new BQBlockMaterial(customName, XMaterial.valueOf(string.substring(0, dataEnd))); - } - - public static @NotNull Spliterator<Locatable.@NotNull Located> getNearbyBlocks( - @NotNull Locatable.MultipleLocatable.NearbyFetcher fetcher, @NotNull Collection<fr.skytasul.quests.api.utils.BQBlock> types) { - if (!fetcher.isTargeting(LocatedType.BLOCK)) return Spliterators.emptySpliterator(); - - int minY = (int) Math.max(fetcher.getCenter().getWorld().getMinHeight(), fetcher.getCenter().getY() - fetcher.getMaxDistance()); - double maxY = Math.min(fetcher.getCenter().getWorld().getMaxHeight(), fetcher.getCenter().getY() + fetcher.getMaxDistance()); - - int centerX = fetcher.getCenter().getBlockX(); - int centerZ = fetcher.getCenter().getBlockZ(); - - return Spliterators.spliteratorUnknownSize(new Iterator<Locatable.Located>() { - - int x = centerX; - int z = centerZ; - - int i = 0; - int y = minY; - - Locatable.Located.LocatedBlock found = null; - - private boolean findNext() { - for (; y <= maxY; y++) { - Block blockAt = fetcher.getCenter().getWorld().getBlockAt(x, y, z); - if (types.stream().anyMatch(type -> type.applies(blockAt))) { - found = Locatable.Located.LocatedBlock.create(blockAt); - y++; - return true; - } - } - if (Math.abs(x - centerX) <= Math.abs(z - centerZ) && ((x - centerX) != (z - centerZ) || x >= centerX)) - x += ((z >= centerZ) ? 1 : -1); - else - z += ((x >= centerX) ? -1 : 1); - - i++; - if (i >= fetcher.getMaxDistance() * fetcher.getMaxDistance()) return false; - y = minY; - return findNext(); - - // used the N spiral algorithm from here: https://stackoverflow.com/a/31864777 - } - - @Override - public boolean hasNext() { - if (found != null) return true; - return findNext(); - } - - @Override - public Located next() { - if (found == null) findNext(); - if (found != null) { - LocatedBlock tmpFound = found; - found = null; - return tmpFound; - } - throw new NoSuchElementException(); - } - - }, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.NONNULL); - } - - public static class BQBlockMaterial extends BQBlock { - - private final XMaterial material; - - public BQBlockMaterial(String customName, XMaterial material) { - super(customName); - this.material = material; - } - - @Override - public XMaterial retrieveMaterial() { - return material; - } - - @Override - public boolean applies(Block block) { - return XBlock.isSimilar(block, material); - } - - @Override - public String getDataString() { - return material.name(); - } - - } - -} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/ComparisonMethod.java b/api/src/main/java/fr/skytasul/quests/api/utils/ComparisonMethod.java index 5882fbc2..110abd41 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/ComparisonMethod.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/ComparisonMethod.java @@ -1,6 +1,6 @@ package fr.skytasul.quests.api.utils; -import fr.skytasul.quests.api.editors.checkers.EnumParser; +import fr.skytasul.quests.api.editors.parsers.EnumParser; import fr.skytasul.quests.api.localization.Lang; public enum ComparisonMethod { diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java index 1ebbb177..e94ab891 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java @@ -30,7 +30,7 @@ public interface MutableCountableObject<T> extends CountableObject<T> { } - static <T> fr.skytasul.quests.api.utils.CountableObject<T> create(@NotNull UUID uuid, @NotNull T object, int amount) { + static <T> CountableObject<T> create(@NotNull UUID uuid, @NotNull T object, int amount) { return new DummyCountableObject<>(uuid, object, amount); } diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index b1a87d23..3c19fef1 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -776,7 +776,7 @@ public boolean hasSavingFailed() { } @Override - public @NotNull QuestsAPI getAPI() { + public @NotNull QuestsAPIImplementation getAPI() { return QuestsAPIImplementation.INSTANCE; } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java index 2412dbb3..22af983f 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -31,6 +31,7 @@ import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.RewardCreator; import fr.skytasul.quests.api.stages.StageTypeRegistry; +import fr.skytasul.quests.blocks.BQBlocksManagerImplementation; public class QuestsAPIImplementation implements QuestsAPI { @@ -47,6 +48,7 @@ public class QuestsAPIImplementation implements QuestsAPI { private BQNPCsManager npcsManager = null; private AbstractHolograms<?> hologramsManager = null; private BossBarManager bossBarManager = null; + private BQBlocksManagerImplementation blocksManager = new BQBlocksManagerImplementation(); private final Set<QuestsHandler> handlers = new HashSet<>(); @@ -176,6 +178,11 @@ public void setBossBarManager(@NotNull BossBarManager newBossBarManager) { .debug("Bossbars manager has been registered: " + newBossBarManager.getClass().getName()); } + @Override + public @NotNull BQBlocksManagerImplementation getBlocksManager() { + return blocksManager; + } + @Override public void registerQuestsHandler(@NotNull QuestsHandler handler) { Validate.notNull(handler); diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java new file mode 100644 index 00000000..a1630caf --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java @@ -0,0 +1,33 @@ +package fr.skytasul.quests.blocks; + +import org.bukkit.block.Block; +import com.cryptomorin.xseries.XBlock; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.blocks.BQBlockOptions; + +public class BQBlockMaterial extends BQBlock { + + private final XMaterial material; + + public BQBlockMaterial(BQBlockOptions options, XMaterial material) { + super(options); + this.material = material; + } + + @Override + public XMaterial retrieveMaterial() { + return material; + } + + @Override + public boolean applies(Block block) { + return XBlock.isSimilar(block, material); + } + + @Override + public String getDataString() { + return material.name(); + } + +} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java new file mode 100644 index 00000000..ee24238a --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java @@ -0,0 +1,171 @@ +package fr.skytasul.quests.blocks; + +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Spliterator; +import java.util.Spliterators; +import org.bukkit.block.Block; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.blocks.BQBlockOptions; +import fr.skytasul.quests.api.blocks.BQBlockType; +import fr.skytasul.quests.api.blocks.BQBlocksManager; +import fr.skytasul.quests.api.stages.types.Locatable; +import fr.skytasul.quests.api.stages.types.Locatable.Located; +import fr.skytasul.quests.api.stages.types.Locatable.Located.LocatedBlock; +import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.utils.compatibility.Post1_13; + +public class BQBlocksManagerImplementation implements BQBlocksManager { + + public static final String BLOCKDATA_HEADER = "blockdata:"; + public static final String TAG_HEADER = "tag:"; + + private final BiMap<String, BQBlockType> types = HashBiMap.create(5); + + private BQBlockType materialType; + private BQBlockType blockdataType; + private BQBlockType tagType; + + public BQBlocksManagerImplementation() { + registerDefaultTypes(); + } + + private void registerDefaultTypes() { + materialType = (string, options) -> new BQBlockMaterial(options, XMaterial.valueOf(string)); + registerBlockType(null, materialType); + + if (MinecraftVersion.MAJOR >= 13) { + blockdataType = (string, options) -> new Post1_13.BQBlockData(options, string); + registerBlockType("blockdata:", blockdataType); + + tagType = (string, options) -> new Post1_13.BQBlockTag(options, string); + registerBlockType("tag:", tagType); + } + } + + @Override + public @NotNull BQBlock deserialize(@NotNull String string) throws IllegalArgumentException { + BQBlockType type; + + String header = ""; + int separator = string.indexOf(HEADER_SEPARATOR); + if (separator != -1) { + header = string.substring(0, separator); + string = string.substring(separator + 1); + } + type = types.get(header); + + if (type == null) + throw new IllegalArgumentException("Unknown block header: " + header); + + int nameIndex = string.lastIndexOf(CUSTOM_NAME_FOOTER); + String customName = nameIndex == -1 ? null : string.substring(nameIndex + CUSTOM_NAME_FOOTER.length()); + + int dataEnd = nameIndex == -1 ? string.length() : nameIndex; + + return type.deserialize(string.substring(0, dataEnd), new BQBlockOptions(type, customName)); + } + + @Override + public void registerBlockType(@Nullable String header, @NotNull BQBlockType type) { + if (types.containsKey(header)) + throw new IllegalArgumentException("The block type with header " + header + " was already registered"); + + types.put(header, type); + } + + @Override + public @Nullable String getHeader(@NotNull BQBlockType type) { + return types.inverse().get(type); + } + + @Override + public @NotNull Spliterator<@NotNull Located> getNearbyBlocks(@NotNull Locatable.MultipleLocatable.NearbyFetcher fetcher, + @NotNull Collection<BQBlock> types) { + if (!fetcher.isTargeting(LocatedType.BLOCK)) + return Spliterators.emptySpliterator(); + + int minY = (int) Math.max(fetcher.getCenter().getWorld().getMinHeight(), + fetcher.getCenter().getY() - fetcher.getMaxDistance()); + double maxY = Math.min(fetcher.getCenter().getWorld().getMaxHeight(), + fetcher.getCenter().getY() + fetcher.getMaxDistance()); + + int centerX = fetcher.getCenter().getBlockX(); + int centerZ = fetcher.getCenter().getBlockZ(); + + return Spliterators.spliteratorUnknownSize(new Iterator<Locatable.Located>() { + + int x = centerX; + int z = centerZ; + + int i = 0; + int y = minY; + + Locatable.Located.LocatedBlock found = null; + + private boolean findNext() { + for (; y <= maxY; y++) { + Block blockAt = fetcher.getCenter().getWorld().getBlockAt(x, y, z); + if (types.stream().anyMatch(type -> type.applies(blockAt))) { + found = Locatable.Located.LocatedBlock.create(blockAt); + y++; + return true; + } + } + if (Math.abs(x - centerX) <= Math.abs(z - centerZ) && ((x - centerX) != (z - centerZ) || x >= centerX)) + x += ((z >= centerZ) ? 1 : -1); + else + z += ((x >= centerX) ? -1 : 1); + + i++; + if (i >= fetcher.getMaxDistance() * fetcher.getMaxDistance()) + return false; + y = minY; + return findNext(); + + // used the N spiral algorithm from here: https://stackoverflow.com/a/31864777 + } + + @Override + public boolean hasNext() { + if (found != null) + return true; + return findNext(); + } + + @Override + public Located next() { + if (found == null) + findNext(); + if (found != null) { + LocatedBlock tmpFound = found; + found = null; + return tmpFound; + } + throw new NoSuchElementException(); + } + + }, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.NONNULL); + } + + @Override + public @NotNull BQBlock createSimple(@NotNull XMaterial material, @Nullable String customName) { + return new BQBlockMaterial(new BQBlockOptions(materialType, customName), material); + } + + public @NotNull BQBlock createBlockdata(@NotNull String blockData, @Nullable String customName) { + return new Post1_13.BQBlockData(new BQBlockOptions(tagType, customName), blockData); + } + + public @NotNull BQBlock createTag(@NotNull String tag, @Nullable String customName) { + return new Post1_13.BQBlockTag(new BQBlockOptions(tagType, customName), tag); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index b4d838db..6b2c29de 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -32,6 +32,7 @@ import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.players.PlayersManagerDB; import fr.skytasul.quests.players.PlayersManagerYAML; +import fr.skytasul.quests.structure.QuestImplementation; import fr.skytasul.quests.utils.Database; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.nms.NMS; @@ -59,7 +60,7 @@ public void create(Player player, @Optional @Flag Integer id) { session.setCustomID(id); } - session.openMainGUI(player); + session.openStagesGUI(player); } @Subcommand ("edit") @@ -67,14 +68,14 @@ public void create(Player player, @Optional @Flag Integer id) { @OutsideEditor public void edit(Player player, @Optional Quest quest) { if (quest != null) { - new QuestCreationSession(quest).openMainGUI(player); + new QuestCreationSession((QuestImplementation) quest).openStagesGUI(player); }else { Lang.CHOOSE_NPC_STARTER.send(player); new SelectNPC(player, () -> {}, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { ChooseQuestGUI.choose(player, npc.getQuests(), clickedQuest -> { - new QuestCreationSession(clickedQuest).openMainGUI(player); + new QuestCreationSession((QuestImplementation) clickedQuest).openStagesGUI(player); }, null, false); }else { Lang.NPC_NOT_QUEST.send(player); diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java index a06c783e..900e6454 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java @@ -10,7 +10,6 @@ import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.rewards.CheckpointReward; import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Subcommand; @@ -30,7 +29,8 @@ public void menu(BukkitCommandActor actor, ExecutableCommand command, @revxrsal. if (acc == null) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Player " + actor.getName() + " has got no account. This is a CRITICAL issue."); throw new CommandErrorException("no player datas"); - }else new PlayerListGUI(acc).open(actor.getAsPlayer()); + } else + QuestsPlugin.getPlugin().getGuiManager().getFactory().createPlayerQuestsMenu(acc).open(actor.getAsPlayer()); } @Subcommand ("checkpoint") 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 3558acdc..17b13560 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java @@ -287,7 +287,7 @@ public void resetQuest(BukkitCommandActor actor, Quest quest) { @Subcommand ("seePlayer") @CommandPermission ("beautyquests.command.seePlayer") public void seePlayer(Player actor, Player player) { - new PlayerListGUI(PlayersManager.getPlayerAccount(player), false).open(actor); + new PlayerListGUI(BeautyQuests.getInstance().getPlayersManager().getAccount(player), false).open(actor); } @Subcommand ("start") @@ -320,7 +320,7 @@ private void start(CommandSender sender, Player player, PlayerAccount acc, Quest return; } quest.start(player); - Lang.START_QUEST.send(sender, quest.getName(), acc.abstractAcc.getIdentifier()); + Lang.START_QUEST.send(sender, quest.getName(), acc.getNameAndID()); } @Subcommand ("cancel") diff --git a/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java b/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java new file mode 100644 index 00000000..deb9fdb7 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java @@ -0,0 +1,27 @@ +package fr.skytasul.quests.editor; + +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.EditorFactory; +import fr.skytasul.quests.api.editors.parsers.AbstractParser; +import fr.skytasul.quests.editor.parsers.MaterialParser; + +public class DefaultEditorFactory implements EditorFactory { + + public static final MaterialParser ITEM_PARSER = new MaterialParser(true, false); + public static final MaterialParser BLOCK_PARSER = new MaterialParser(false, true); + public static final MaterialParser ANY_PARSER = new MaterialParser(false, false); + + @Override + public @NotNull AbstractParser<XMaterial> getMaterialParser(boolean item, boolean block) { + if (item && !block) + return ITEM_PARSER; + if (block && !item) + return BLOCK_PARSER; + if (block && item) + return ANY_PARSER; + + throw new IllegalArgumentException("Material parser must be either for items, for blocks or both, not neither."); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java index a357de84..50eec768 100644 --- a/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java @@ -15,6 +15,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.Editor; +import fr.skytasul.quests.api.editors.EditorFactory; import fr.skytasul.quests.api.editors.EditorManager; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.MinecraftVersion; @@ -25,6 +26,8 @@ public class EditorManagerImplementation implements EditorManager, Listener { private final @NotNull Map<Player, Editor> players = new HashMap<>(); private final @Nullable BQBossBar bar; + private @NotNull EditorFactory factory; + public EditorManagerImplementation() { if (QuestsAPI.getAPI().hasBossBarManager()) { bar = QuestsAPI.getAPI().getBossBarManager().buildBossBar("§6Quests Editor", "YELLOW", "SOLID"); @@ -32,6 +35,8 @@ public EditorManagerImplementation() { } else { bar = null; } + + setFactory(new DefaultEditorFactory()); } @Override @@ -82,6 +87,16 @@ public boolean isInEditor(@NotNull Player player) { return players.containsKey(player); } + @Override + public @NotNull EditorFactory getFactory() { + return factory; + } + + @Override + public void setFactory(@NotNull EditorFactory factory) { + this.factory = factory; + } + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false) public void onChat(AsyncPlayerChatEvent e) { Editor editor = players.get(e.getPlayer()); diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/MaterialParser.java b/core/src/main/java/fr/skytasul/quests/editor/parsers/MaterialParser.java similarity index 76% rename from api/src/main/java/fr/skytasul/quests/api/editors/checkers/MaterialParser.java rename to core/src/main/java/fr/skytasul/quests/editor/parsers/MaterialParser.java index 42adc7c8..2664ceee 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/checkers/MaterialParser.java +++ b/core/src/main/java/fr/skytasul/quests/editor/parsers/MaterialParser.java @@ -1,21 +1,17 @@ -package fr.skytasul.quests.api.editors.checkers; +package fr.skytasul.quests.editor.parsers; import org.bukkit.Material; import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.parsers.AbstractParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.compatibility.Post1_13; public class MaterialParser implements AbstractParser<XMaterial> { - - public static final MaterialParser ITEM_PARSER = new MaterialParser(true, false); - public static final MaterialParser BLOCK_PARSER = new MaterialParser(false, true); - public static final MaterialParser ANY_PARSER = new MaterialParser(false, false); private boolean item, block; - @Deprecated public MaterialParser(boolean item, boolean block) { this.item = item; this.block = block; diff --git a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java new file mode 100644 index 00000000..9b1e53db --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java @@ -0,0 +1,50 @@ +package fr.skytasul.quests.gui; + +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.gui.Gui; +import fr.skytasul.quests.api.gui.GuiFactory; +import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; +import fr.skytasul.quests.gui.blocks.BlocksGUI; +import fr.skytasul.quests.gui.items.ItemCreatorGUI; +import fr.skytasul.quests.gui.items.ItemGUI; +import fr.skytasul.quests.gui.npc.NpcSelectGUI; +import fr.skytasul.quests.gui.quests.PlayerListGUI; +import fr.skytasul.quests.players.PlayerAccountImplementation; + +public class DefaultGuiFactory implements GuiFactory { + + @Override + public @NotNull Gui createPlayerQuestsMenu(@NotNull PlayerAccount account) { + return new PlayerListGUI((PlayerAccountImplementation) account); + } + + @Override + public @NotNull Gui createItemSelection(@NotNull Consumer<ItemStack> callback, boolean allowCancel) { + return new ItemGUI(callback, allowCancel); + } + + @Override + public @NotNull Gui createItemCreator(@NotNull Consumer<ItemStack> callback, boolean allowCancel) { + return new ItemCreatorGUI(callback, allowCancel); + } + + @Override + public @NotNull Gui createBlocksSelection(@NotNull Consumer<List<MutableCountableObject<BQBlock>>> callback, + @NotNull Collection<MutableCountableObject<BQBlock>> existingBlocks) { + return new BlocksGUI(existingBlocks, callback); + } + + @Override + public @NotNull Gui createNpcSelection(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> callback, + boolean nullable) { + return NpcSelectGUI.select(cancel, callback, nullable); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index 3d5ae2c1..613e9d59 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -18,6 +18,7 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.GuiClickEvent; +import fr.skytasul.quests.api.gui.GuiFactory; import fr.skytasul.quests.api.gui.GuiManager; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -31,6 +32,11 @@ public class GuiManagerImplementation implements GuiManager, Listener { private Map<Player, Gui> players = new HashMap<>(); private boolean dismissClose = false; + private GuiFactory factory; + + public GuiManagerImplementation() { + setFactory(new DefaultGuiFactory()); + } @Override public void open(@NotNull Player player, @NotNull Gui inventory) { @@ -79,6 +85,16 @@ public boolean hasGuiOpened(@NotNull Player player) { return players.get(player); } + @Override + public @NotNull GuiFactory getFactory() { + return factory; + } + + @Override + public void setFactory(@NotNull GuiFactory factory) { + this.factory = factory; + } + @EventHandler public void onClose(InventoryCloseEvent event) { if (dismissClose) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java index a4aef7e6..c9dff223 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java @@ -8,9 +8,9 @@ import java.util.function.Function; import org.bukkit.DyeColor; import org.bukkit.inventory.ItemStack; +import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; 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 3e1feb49..bced782a 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 @@ -12,9 +12,11 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.MaterialParser; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.gui.layout.LayoutedButton; @@ -22,9 +24,7 @@ import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.utils.compatibility.Post1_13; import fr.skytasul.quests.utils.nms.NMS; public class SelectBlockGUI extends LayoutedGUI.LayoutedRowsGUI { @@ -117,7 +117,7 @@ private void typeClick(LayoutedClickEvent event) { } } event.refreshGuiReopen(); - }, MaterialParser.BLOCK_PARSER).start(); + }, QuestsPlugin.getPlugin().getEditorManager().getFactory().getMaterialParser(false, true)).start(); } private void dataClick(LayoutedClickEvent event) { @@ -158,11 +158,11 @@ private void doneClick(LayoutedClickEvent event) { event.close(); BQBlock block; if (blockData != null) { - block = new Post1_13.BQBlockData(customName, Bukkit.createBlockData(type.parseMaterial(), blockData)); + block = BeautyQuests.getInstance().getAPI().getBlocksManager().createBlockdata(blockData, customName); } else if (tag != null) { - block = new Post1_13.BQBlockTag(customName, tag); + block = BeautyQuests.getInstance().getAPI().getBlocksManager().createTag(tag, customName); } else { - block = new BQBlock.BQBlockMaterial(customName, type); + block = BeautyQuests.getInstance().getAPI().getBlocksManager().createSimple(type, customName); } run.accept(block, amount); } 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 20b0f9ee..a8154ecb 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 @@ -29,10 +29,11 @@ import fr.skytasul.quests.api.quests.creation.QuestCreationGui; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.gui.creation.QuestCreationSession; +import fr.skytasul.quests.gui.creation.stages.StageCreationContextImplementation; import fr.skytasul.quests.gui.creation.stages.StagesGUI; import fr.skytasul.quests.options.OptionName; import fr.skytasul.quests.players.PlayerAccountImplementation; @@ -180,7 +181,7 @@ private void finish(Player p) { QuestBranchImplementation mainBranch = new QuestBranchImplementation(qu.getBranchesManager()); qu.getBranchesManager().addBranch(mainBranch); - boolean failure = loadBranch(mainBranch, session.getStagesGUI()); + boolean failure = loadBranch(p, mainBranch, session.getStagesGUI()); QuestCreateEvent event = new QuestCreateEvent(p, qu, session.isEdition()); Bukkit.getPluginManager().callEvent(event); @@ -244,18 +245,18 @@ private void keepDatas(QuestImplementation qu) { } } - private boolean loadBranch(QuestBranchImplementation branch, StagesGUI stagesGui) { + private boolean loadBranch(Player p, QuestBranchImplementation branch, StagesGUI stagesGui) { boolean failure = false; - for (StageCreation<?> creation : stagesGui.getStageCreations()) { + for (StageCreationContextImplementation context : stagesGui.getStageCreations()) { try{ - AbstractStage stage = createStage(creation, branch); - if (creation.getCreationContext().isEndingStage()) { - StagesGUI newGUI = creation.getCreationContext().getEndingBranch(); + StageControllerImplementation stage = createStage(context, branch); + if (context.isEndingStage()) { + StagesGUI newGUI = context.getEndingBranch(); QuestBranchImplementation newBranch = null; if (!newGUI.isEmpty()){ - newBranch = new QuestBranchImplementation(branch.getBranchesManager()); - branch.getBranchesManager().addBranch(newBranch); - failure |= loadBranch(newBranch, newGUI); + newBranch = new QuestBranchImplementation(branch.getManager()); + branch.getManager().addBranch(newBranch); + failure |= loadBranch(p, newBranch, newGUI); } branch.addEndStage(stage, newBranch); }else branch.addRegularStage(stage); @@ -268,12 +269,12 @@ private boolean loadBranch(QuestBranchImplementation branch, StagesGUI stagesGui return failure; } - public <T extends AbstractStage> T createStage(StageCreation<T> creation, QuestBranchImplementation branch) { - StageControllerImplementation<T> controller = - new StageControllerImplementation<>(branch, creation.getCreationContext().getType()); - T stage = creation.finish(controller); + public <T extends AbstractStage> StageControllerImplementation<T> createStage(StageCreationContext<T> context, + QuestBranchImplementation branch) { + StageControllerImplementation<T> controller = new StageControllerImplementation<>(branch, context.getType()); + T stage = context.getCreation().finish(controller); controller.setStage(stage); - return stage; + return controller; } private void setStagesEdited() { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/LineOld.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/LineOld.java deleted file mode 100644 index 060c2ca4..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/LineOld.java +++ /dev/null @@ -1,230 +0,0 @@ -package fr.skytasul.quests.gui.creation.stages; - -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.stages.creation.StageCreation; -import fr.skytasul.quests.gui.creation.stages.StageRunnable.StageRunnableClick; -import fr.skytasul.quests.utils.types.NumberedList; - -public class LineOld { - - public final StagesGUI gui; - protected int line = 0; - - private int activePage = 0; - private int maxPage = 1; - - private NumberedList<Pair<ItemStack, StageRunnable>> items = new NumberedList<>(); - - public StageCreation<?> creation = null; - - protected LineOld(int line, StagesGUI gui) { - this.gui = gui; - this.line = line; - } - - public boolean isEmpty() { - return items.isEmpty(); - } - - /** - * Set an item - * @param slot the slot of the item (override if any other item is on the selected slot) - * @param is the item - * @param click the action when a click on the item (if null nothing happens) <i>(runnable parameter is the player)</i> - */ - public int setItem(int slot, ItemStack is, StageRunnable click) { - return setItem(slot, is, click, false, true); - } - - /** - * Set an item - * @param slot the slot of the item - * @param is the item - * @param click the action when a click on the item (if null nothing happens) <i>(runnable parameter is the player)</i> - * @param override override if any other item is on the selected slot <b>deprecated</b> - * @param refresh refresh all items (display this item) - */ - public int setItem(int slot, ItemStack is, StageRunnable click, boolean override, boolean refresh) { - Pair<ItemStack, StageRunnable> en = new Pair<>(is, click); - if (override){ - items.setSwitch(slot, en); - }else { - if (items.get(slot) != null){ - slot = items.add(en); - }else items.setSwitch(slot, en); - } - if (items.getLast() <= 8) { - maxPage = 1; - }else maxPage = 1 + (int) Math.ceil((items.getLast() - 7) * 1.0D / 7.0D); - if (refresh){ - activePage = 0; - setItems(activePage); - } - return slot; - } - - /** - * Set a new instance of ItemStack in the list - * @param slot slot of the item that will be changed - * @param newItem the new item inserted - */ - public void editItem(int slot, ItemStack newItem){ - editItem(slot, newItem, false); - } - - public void editItem(int slot, ItemStack newItem, boolean refresh) { - Pair<ItemStack, StageRunnable> last = items.get(slot); - if (last == null) return; - items.setSwitch(slot, new Pair<>(newItem, last.getValue())); - if (refresh) { - setItems(activePage); - } - } - - /** - * Get item from slot - * @param slot item slot in the line - * @return ItemStack in the gui if shown, or stored ItemStack - */ - public ItemStack getItem(int slot){ - ItemStack item = items.get(slot).getKey(); - if (item == null) return null; - - boolean inLinePage = true; - if (maxPage > 1) { - int maxLineCapacity = activePage == 0 ? 8 : 7; - int firstID = activePage == 0 ? 0 : 8 + (activePage - 1) * 7; - if (slot < firstID || slot >= firstID + maxLineCapacity) inLinePage = false; - } - if (inLinePage) { - boolean inGUIPage = line >= gui.page * 5 && line < (gui.page + 1) * 5; - if (inGUIPage) { - int firstSlot = line * 9 - gui.page * 5 * 9; - return gui.inv.getItem(firstSlot + (slot - activePage * 7)); - } - } - return item; - } - - /** - * Move all items to a new line - * @param newLine the new line (where to move) - */ - public void changeLine(int newLine){ - clearLine(); - this.line = newLine; - clearLine(); - this.activePage = 0; - setItems(activePage); - } - - /** - * Exchange two lines (move all items) - * @param other the other line - */ - public void exchangeLines(Line other){ - if (other == null || other == this) return; - int ln = other.line; - other.changeLine(line); - this.line = ln; - this.activePage = 0; - setItems(activePage); - } - - /** - * Set items for selected page - * @param page the number of the page to display - */ - public void setItems(int page){ - if (!isInGUIPage()) return; - clearLine(); - this.activePage = page; - - int maxLineCapacity = page == 0 || maxPage == 1 ? 8 : 7; - int firstID = page == 0 ? 0 : 8 + (page - 1) * 7; - - int slot = page == 0 ? 0 : 1; - for (int id = firstID; id <= firstID + maxLineCapacity; id++) { - if (items.contains(id)) { - Pair<ItemStack, StageRunnable> pair = items.get(id); - int RSlot = getRSlot(slot); - gui.inv.setItem(RSlot, pair.getKey()); - pair.setKey(gui.inv.getItem(RSlot)); - } - slot++; - } - - if (maxPage > 1){ - if (page < maxPage - 1) RsetItem(8, ItemUtils.itemNextPage); - if (page > 0) RsetItem(0, ItemUtils.itemLaterPage); - } - } - - public int getActivePage() { - return activePage; - } - - /** - * Get line number (first slot) - * @return line number - */ - public int getLine(){ - return line; - } - - public boolean isInGUIPage(){ - return line >= gui.page*5 && line < (gui.page+1)*5; - } - - public void click(int slot, Player p, ItemStack is, ClickType click) { - if (slot == 0 && activePage > 0){ - activePage--; - setItems(activePage); - }else if (slot == 8 && activePage < maxPage - 1) { - activePage++; - setItems(activePage); - }else { - int item = (activePage == 0 ? 0 : activePage * 7) + slot; - if (items.get(item) == null) return; - if (items.get(item).getValue() == null) return; - execute(item, p, is, click); - } - } - - public void execute(int lineSlot, Player p, ItemStack is, ClickType click) { - StageRunnable runnable = items.get(lineSlot).getValue(); - if (runnable instanceof StageRunnableClick) { - ((StageRunnableClick) runnable).run(p, is, click); - }else if (runnable instanceof StageRunnable) { - runnable.run(p, is); - } - } - - private void clearLine(){ - if (!isInGUIPage()) return; - for (int i = 0; i < 9; i++){ - RsetItem(i, null); - } - } - - private int getRSlot(int lineSlot) { - return line * 9 - gui.page * 5 * 9 + lineSlot; - } - - /** - * Remove all items (and clear the line) - */ - public void removeItems(){ - items.clear(); - maxPage = 1; - clearLine(); - } - - private void RsetItem(int Rslot, ItemStack is){ - gui.inv.setItem(getRSlot(Rslot), is); - } - -} \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java index 9dc55c67..28ba0b6f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java @@ -96,7 +96,7 @@ public void setPage(int page) { } @Override - public StageGuiClickHandler click(int rawSlot) { + public StageGuiClickHandler getClick(int rawSlot) { if (rawSlot == 0 && page > 0) { setPage(page - 1); return null; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index e407955c..1790ebbd 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -1,29 +1,35 @@ package fr.skytasul.quests.gui.creation.stages; import java.util.ArrayList; -import java.util.LinkedList; +import java.util.Comparator; import java.util.List; -import java.util.Map.Entry; +import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.gui.AbstractGui; +import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.quests.branches.EndingStage; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageType; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; -import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.stages.creation.StageGuiClickEvent; +import fr.skytasul.quests.api.stages.creation.StageGuiClickHandler; import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.structure.QuestBranchImplementation; +import fr.skytasul.quests.utils.QuestUtils; public class StagesGUI extends AbstractGui { @@ -105,7 +111,8 @@ public void deleteStageLine(Line line) { } @Override - public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, ClickType click) { + public void onClick(@NotNull GuiClickEvent event) { + int slot = event.getSlot(); if (slot > 44) { if (slot == 45) { if (page > 0) { @@ -122,77 +129,58 @@ public boolean onClick(Player p, Inventory inv, ItemStack current, int slot, Cli } }else if (slot == 52) { if (isEmpty() && previousBranch == null) { - Utils.playPluginSound(p.getLocation(), "ENTITY_VILLAGER_NO", 0.6f); + QuestUtils.playPluginSound(event.getPlayer(), "ENTITY_VILLAGER_NO", 0.6f); }else { - session.openFinishGUI(p); + session.openCreationGUI(event.getPlayer()); } }else if (slot == 53) { if (previousBranch == null){ // main inventory = cancel button stop = true; - p.closeInventory(); + event.close(); if (!isEmpty()) { if (!session.isEdition()) { - Lang.QUEST_CANCEL.send(p); - }else Lang.QUEST_EDIT_CANCEL.send(p); + Lang.QUEST_CANCEL.send(event.getPlayer()); + } else + Lang.QUEST_EDIT_CANCEL.send(event.getPlayer()); } }else { // branch inventory = previous branch button - Inventories.open(p, previousBranch); + previousBranch.open(event.getPlayer()); } } }else { session.setStagesEdited(); Line line = getLine((slot - slot % 9) / 9 + 5 * page); - line.click(slot - (line.getLine() - page * 5) * 9, p, current, click); + StageGuiClickHandler click = line.lineObj.getClick(line.getLineSlot(slot)); + if (click != null) + click.onClick(new StageGuiClickEvent(event.getPlayer(), event.getClicked(), event.getClick(), line.context)); } - return true; } @Override - public CloseBehavior onClose(Player p, Inventory inv){ - if (isEmpty() || stop) return StandardCloseBehavior.REMOVE; - return StandardCloseBehavior.REOPEN; + public @NotNull CloseBehavior onClose(@NotNull Player player) { + return isEmpty() || stop ? StandardCloseBehavior.REMOVE : StandardCloseBehavior.REOPEN; } private void refresh() { for (int i = 0; i < 3; i++) inv.setItem(i + 46, ItemUtils.item(i == page ? XMaterial.LIME_STAINED_GLASS_PANE : XMaterial.WHITE_STAINED_GLASS_PANE, Lang.regularPage.toString())); inv.setItem(49, ItemUtils.item(page == 3 ? XMaterial.MAGENTA_STAINED_GLASS_PANE : XMaterial.PURPLE_STAINED_GLASS_PANE, Lang.branchesPage.toString())); - for (Line line : lines) { - line.setItems(line.getActivePage()); - } + lines.forEach(l -> l.lineObj.refresh()); } @SuppressWarnings ("rawtypes") - public List<StageCreation> getStageCreations() { - List<StageCreation> stages = new LinkedList<>(); - for (int i = 0; i < 20; i++) { - Line line = getLine(i); - if (isActiveLine(line)) stages.add(line.creation); - } - return stages; + public List<StageCreationContextImplementation> getStageCreations() { + return lines.stream().sorted(Comparator.comparingInt(line -> line.lineId)).filter(line -> line.isActive()) + .map(line -> line.context).collect(Collectors.toList()); } private void editBranch(QuestBranchImplementation branch){ - for (AbstractStage stage : branch.getRegularStages()){ - Line line = getLine(stage.getId()); - @SuppressWarnings ("rawtypes") - StageCreation creation = runClick(line, stage.getType(), false); - creation.edit(stage); - line.setItems(0); + for (StageController stage : branch.getRegularStages()) { + getLine(branch.getRegularStageId(stage)).setStageEdition(stage); } - - int i = 15; - for (Entry<AbstractStage, QuestBranchImplementation> en : branch.getEndingStages().entrySet()){ - Line line = getLine(i); - @SuppressWarnings ("rawtypes") - StageCreation creation = runClick(line, en.getKey().getType(), true); - StagesGUI gui = new StagesGUI(session, this); - gui.open(null); // init other GUI - creation.setLeadingBranch(gui); - if (en.getValue() != null) gui.editBranch(en.getValue()); - creation.edit(en.getKey()); - line.setItems(0); - i++; + + for (EndingStage stage : branch.getEndingStages()) { + getLine(branch.getEndingStageId(stage.getStage())).setStageEdition(stage.getStage(), stage.getBranch()); } } @@ -222,12 +210,12 @@ void setSelectionState() { int i = 0; for (StageType<?> type : QuestsAPI.getAPI().getStages()) { lineObj.setItem(++i, type.getItem(), event -> { - setStageCreation(event.getPlayer(), type); + setStageCreation(type).start(event.getPlayer()); }); } } - <T extends AbstractStage> void setStageCreation(Player p, StageType<T> type) { + <T extends AbstractStage> StageCreation<T> setStageCreation(StageType<T> type) { lineObj.clearItems(); context = new StageCreationContextImplementation<>(lineObj, type, ending); @@ -272,7 +260,23 @@ <T extends AbstractStage> void setStageCreation(Player p, StageType<T> type) { if (lineId != 0 && lineId != 15) getLine(lineId - 1).updateLineManageLore(); - context.getCreation().start(p); + return (StageCreation<T>) context.getCreation(); + } + + void setStageEdition(StageController stage) { + setStageEdition(stage, null); + } + + void setStageEdition(StageController stage, @Nullable QuestBranch branch) { + @SuppressWarnings("rawtypes") + StageCreation creation = setStageCreation(stage.getStageType()); + + if (branch != null) { + context.getEndingBranch().editBranch((QuestBranchImplementation) branch); + } + + creation.edit(stage.getStage()); + lineObj.setPage(0); } void updateLineManageLore() { @@ -348,7 +352,11 @@ void exchangeLines(Line other) { } int getRawSlot(int lineSlot) { - return lineId * 9 - page * 5 + lineSlot; + return lineId * 9 - page * 5 * 9 + lineSlot; + } + + int getLineSlot(int rawSlot) { + return rawSlot - (lineId * 9 - page * 5 * 9); } public boolean isShown() { diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java index 9320d2fa..db47ee52 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java @@ -12,10 +12,10 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.TextListEditor; -import fr.skytasul.quests.api.editors.checkers.MaterialParser; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -73,7 +73,7 @@ public void onClick(GuiClickEvent event) { new TextEditor<>(event.getPlayer(), event::reopen, obj -> { type = obj; event.reopen(); - }, MaterialParser.ITEM_PARSER).start(); + }, QuestsPlugin.getPlugin().getEditorManager().getFactory().getMaterialParser(true, false)).start(); break; case 1: diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemGUI.java index 5cd55c1e..795cc95f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemGUI.java @@ -8,22 +8,24 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.utils.QuestUtils; public class ItemGUI extends AbstractGui { private Consumer<ItemStack> end; - private Runnable cancel; + private boolean allowCancel; - public ItemGUI(Consumer<ItemStack> end, Runnable cancel) { + public ItemGUI(Consumer<ItemStack> end, boolean allowCancel) { this.end = end; - this.cancel = cancel; + this.allowCancel = allowCancel; } @Override @@ -50,14 +52,14 @@ public void onClick(GuiClickEvent event) { event.setCancelled(false); QuestUtils.runSync(() -> end.accept(event.getCursor())); } else { - new ItemCreatorGUI(end, false).open(event.getPlayer()); + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemCreator(end, false).open(event.getPlayer()); } } } @Override public CloseBehavior onClose(Player p) { - return new DelayCloseBehavior(cancel); + return allowCancel ? new DelayCloseBehavior(() -> end.accept(null)) : StandardCloseBehavior.REOPEN; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java index b69db00d..3250d006 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -84,7 +85,7 @@ public void onClick(@NotNull GuiClickEvent event) { end.accept(items.values().stream().filter(x -> x != null).collect(Collectors.toList())); }else { if (event.getClicked().equals(none)) { - new ItemCreatorGUI(item -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemCreator(item -> { if (item != null) getInventory().setItem(event.getSlot(), item); if (!addItem(event.getPlayer(), item, event.getSlot())) diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java deleted file mode 100644 index 622baa34..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/BranchesGUI.java +++ /dev/null @@ -1,207 +0,0 @@ -package fr.skytasul.quests.gui.misc; - -import java.util.LinkedList; -import java.util.function.Consumer; -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 com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.AbstractGui; -import fr.skytasul.quests.api.gui.GuiClickEvent; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.gui.close.CloseBehavior; -import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.localization.Lang; - -public class BranchesGUI extends AbstractGui { // WIP - - private Branch main = new Branch(null); - - private Branch shown; - private int xOffset = 0; - - @Override - protected Inventory instanciate(@NotNull Player player) { - return Bukkit.createInventory(null, 54, "Branches"); - } - - @Override - protected void populate(@NotNull Player player, @NotNull Inventory inventory) { - inventory.setItem(49, ItemUtils.item(XMaterial.DIAMOND_BLOCK, "§bBack one branch")); - - inventory.setItem(52, ItemUtils.item(XMaterial.ARROW, "§aScroll left")); - inventory.setItem(53, ItemUtils.item(XMaterial.ARROW, "§aScroll right")); - - main.things.add(new Thing()); - main.things.add(new Thing()); - main.things.add(new Thing()); - Branch branch = new Branch(main); - branch.things.add(new Thing()); - branch.things.add(new Thing()); - branch.things.add(new Thing()); - main.choices.add(branch); - branch = new Branch(main); - branch.things.add(new Thing()); - branch.things.add(new Thing()); - main.choices.add(branch); - - setBranch(main); - } - - public void refresh() { - setBranch(shown); - } - - private void setBranch(Branch branch) { - this.shown = branch; - for (int i = 0; i < 45; i++) { - getInventory().clear(i); - } - - int y = 2; - int start = y * 9; - displayBranch(shown, start, xOffset, true); - } - - private void displayBranch(Branch branch, int start, int xOffset, boolean showBranches) { - int to; - if (branch.things.size() >= xOffset + 9) { - to = xOffset + 9; - showBranches = false; // no space to continue - }else { - to = branch.things.size(); - } - for (int i = xOffset; i < to; i++) { - IThing thing = branch.things.get(i); - getInventory().setItem(start + i - xOffset, thing.getItem( - i == to - 1 ? branch.choices.isEmpty() ? ThingType.END : ThingType.BRANCHING : ThingType.NORMAL)); - } - if (!showBranches) return; - if (branch.choices.isEmpty()) { // no branch at the end - getInventory().setItem(start + to - xOffset, ItemUtils.item(XMaterial.SLIME_BALL, "§eCreate next thing", - "§8> LEFT CLICK : §7Create normal thing", "§8> RIGHT CLICK : §7Create choices")); - }else { - int i = 0; - for (Branch endBranch : branch.choices) { - displayBranch(endBranch, i * 9 + to - xOffset, 0, false); - i++; - } - for (; i < 5; i++) { - getInventory().setItem(i * 9 + to - xOffset, ItemUtils.item(XMaterial.SLIME_BALL, "§6Create choice")); - } - } - } - - public void create(Consumer<IThing> thing) { - thing.accept(new Thing()); - } - - @Override - public void onClick(GuiClickEvent event) { - if (slot == 52) { - if (xOffset > 0) { - xOffset--; - refresh(); - } - }else if (slot == 53) { - if (xOffset < shown.things.size()) { - xOffset++; - refresh(); - } - }else if (slot == 49) { - if (shown.parent != null) setBranch(shown.parent); - }else { - int y = (int) (slot / 9D); - int x = slot - (y * 9); - int xThing = xOffset + x; - if (xThing < shown.things.size()) { - p.sendMessage("You clicked on thing " + shown.things.get(xThing).getID()); - }else { - if (shown.choices.isEmpty()) { - p.sendMessage("You want to create thing at place " + xThing); - if (click.isLeftClick()) { - create(thing -> { - shown.things.add(thing); - refresh(); - }); - }else if (click.isRightClick()) { - p.sendMessage("You want to create branch at place " + xThing); - create(thing -> { - Branch branch = new Branch(shown); - branch.things.add(thing); - shown.choices.add(branch); - refresh(); - }); - } - }else if (y < shown.choices.size()) { - Branch branch = shown.choices.get(y); - xThing -= shown.things.size(); - p.sendMessage("You clicked on thing " + branch.things.get(xThing).getID()); - if (branch != shown) setBranch(branch); - }else { - p.sendMessage("You want to create a branch at place " + y); - create(thing -> { - Branch branch = new Branch(shown); - branch.things.add(thing); - shown.choices.add(branch); - refresh(); - }); - } - } - } - return true; - } - - @Override - public CloseBehavior onClose(Player p) { - return StandardCloseBehavior.REMOVE; - } - - static class Branch { - LinkedList<IThing> things = new LinkedList<>(); - LinkedList<Branch> choices = new LinkedList<>(); - - Branch parent; - - Branch(Branch parent) { - this.parent = parent; - } - } - - static enum ThingType { - NORMAL(XMaterial.LIGHT_BLUE_STAINED_GLASS_PANE, "§bBasic step"), BRANCHING(XMaterial.ORANGE_STAINED_GLASS_PANE, "§6Branching step"), END(XMaterial.RED_STAINED_GLASS_PANE, "§cEnding step"); - - private XMaterial material; - private String name; - - private ThingType(XMaterial material, String name) { - this.material = material; - this.name = name; - } - } - - static interface IThing { - int getID(); - - ItemStack getItem(ThingType type); - } - - static class Thing implements IThing { - private static int counter = 0; - - private int id = counter++; - - @Override - public int getID() { - return id; - } - - @Override - public ItemStack getItem(ThingType type) { - return ItemUtils.item(type.material, "§4Thing §b§l" + id, Lang.RemoveMid.toString(), type.name); - } - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java index 54dc228b..fc8091e3 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.gui.layout.LayoutedButton; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index 96a1cb1e..e4c0f5de 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java index 06eec832..f1514205 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java @@ -10,7 +10,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index c78a47ef..5b7139ee 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -4,7 +4,6 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.SelectNPC; import fr.skytasul.quests.api.gui.AbstractGui; @@ -23,16 +22,7 @@ private NpcSelectGUI() {} public static ItemStack createNPC = ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.createNPC.toString()); public static ItemStack selectNPC = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); - public static @NotNull AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<@NotNull BQNPC> end) { - return select(cancel, end, false); - } - - public static @NotNull AbstractGui selectNullable(@NotNull Runnable cancel, - @NotNull Consumer<@Nullable BQNPC> end) { - return select(cancel, end, true); - } - - private static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, + public static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, boolean nullable) { Builder builder = LayoutedGUI.newBuilder().addButton(1, LayoutedButton.create(createNPC, event -> { new NpcCreateGUI(end, event::reopen).open(event.getPlayer()); diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index fa645a19..5b5b4333 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.ColorParser; +import fr.skytasul.quests.api.editors.parsers.ColorParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.gui.layout.LayoutedButton; diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java index e0cfb3e0..ec973fca 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.WorldParser; +import fr.skytasul.quests.api.editors.parsers.WorldParser; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index ed3d07a0..774aaa4c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -9,10 +9,11 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.DurationParser; -import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.DurationParser; +import fr.skytasul.quests.api.editors.parsers.DurationParser.MinecraftTimeUnit; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -22,7 +23,6 @@ import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.npc.NpcSelectGUI; public class PoolEditGUI extends AbstractGui { @@ -122,12 +122,12 @@ protected void populate(@NotNull Player player, @NotNull Inventory inv) { public void onClick(GuiClickEvent event) { switch (event.getSlot()) { case SLOT_NPC: - NpcSelectGUI.select(event::reopen, npc -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, npc -> { npcID = npc.getId(); - ItemUtils.lore(event.getClicked(), getNPCLore()); + ItemUtils.lore(event.getClicked(), getNPCLore()); handleDoneButton(getInventory()); - reopen(event.getPlayer()); - }).open(event.getPlayer()); + reopen(event.getPlayer()); + }, false).open(event.getPlayer()); break; case SLOT_HOLOGRAM: Lang.POOL_HOLOGRAM_TEXT.send(event.getPlayer()); diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java index d724ad85..ed2fa4db 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java @@ -4,8 +4,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.MaterialParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; @@ -75,7 +75,8 @@ public void click(QuestCreationGuiClickEvent event) { event.getGui().updateOptionItem(this); } event.reopen(); - }, MaterialParser.ANY_PARSER).passNullIntoEndConsumer().start(); + }, QuestsPlugin.getPlugin().getEditorManager().getFactory().getMaterialParser(true, true)) + .passNullIntoEndConsumer().start(); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index ddbb5470..9ceff1fc 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -6,13 +6,13 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +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.npcs.BQNPC; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; -import fr.skytasul.quests.gui.npc.NpcSelectGUI; public class OptionStarterNPC extends QuestOption<BQNPC> { @@ -51,11 +51,11 @@ public ItemStack getItemStack(OptionSet options) { @Override public void click(QuestCreationGuiClickEvent event) { - NpcSelectGUI.selectNullable(event::reopen, npc -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, npc -> { setValue(npc); ItemUtils.lore(event.getClicked(), getLore(event.getGui().getOptionSet())); event.reopen(); - }).open(event.getPlayer()); + }, true).open(event.getPlayer()); } @Override 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 a51e2ad8..71b8616a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java @@ -4,7 +4,7 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; +import fr.skytasul.quests.api.editors.parsers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; diff --git a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java index 5ecfeb6f..c78ab52b 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java @@ -9,6 +9,7 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import com.google.common.collect.ImmutableMap; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.StaticPagedGUI; @@ -17,7 +18,6 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.gui.items.ItemComparisonGUI; -import fr.skytasul.quests.gui.items.ItemGUI; public class EquipmentRequirement extends AbstractRequirement { @@ -64,13 +64,17 @@ public void itemClick(QuestObjectClickEvent event) { return; } - new ItemGUI(newItem -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemSelection(newItem -> { + if (newItem == null) { + event.cancel(); + return; + } + slot = newSlot; item = newItem; new ItemComparisonGUI(comparisons, event::reopenGUI).open(event.getPlayer()); - - }, event::cancel).open(event.getPlayer()); + }, true).open(event.getPlayer()); }).allowCancel().open(event.getPlayer()); } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java index 7076b48d..841111a7 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java @@ -3,7 +3,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java index b0f7506c..65f00666 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java @@ -5,7 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.scoreboard.Objective; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.ScoreboardObjectiveParser; +import fr.skytasul.quests.api.editors.parsers.ScoreboardObjectiveParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java index 4f9d2606..51934a4a 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java @@ -5,7 +5,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java index 346308d8..eb754153 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java @@ -11,7 +11,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; diff --git a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java index 1b8ff869..1b73d4ee 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java @@ -4,7 +4,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index caff6b0a..e40f0ada 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -6,7 +6,7 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 90943c1e..0db0891f 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -12,7 +12,7 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index 0d556e3a..d4c1524a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.events.internal.BQCraftEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -27,7 +28,6 @@ import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.items.ItemComparisonGUI; -import fr.skytasul.quests.gui.items.ItemGUI; /** * @author SkytAsul, ezeiger92, TheBusyBiscuit @@ -185,10 +185,11 @@ public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); line.setItem(ITEM_SLOT, ItemUtils.item(XMaterial.CHEST, Lang.editItem.toString()), event -> { - new ItemGUI((is) -> { - setItem(is); + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemSelection(is -> { + if (is != null) + setItem(is); event.reopen(); - }, event::reopen).open(event.getPlayer()); + }, true).open(event.getPlayer()); }); line.setItem(COMPARISONS_SLOT, ItemUtils.item(XMaterial.PRISMARINE_SHARD, Lang.stageItemsComparison.toString()), event -> { new ItemComparisonGUI(comparisons, () -> { @@ -213,7 +214,7 @@ public void setComparisons(ItemComparisonMap comparisons) { @Override public void start(Player p) { super.start(p); - new ItemGUI(is -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemSelection(is -> { setItem(is); context.reopenGui(); }, context::removeAndReopenGui).open(p); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index b6c2b61a..c71e9f81 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java index 1f22ceb0..dea36c01 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java @@ -13,7 +13,9 @@ import org.bukkit.inventory.EquipmentSlot; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.editors.WaitBlockClick; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; @@ -31,7 +33,6 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.blocks.SelectBlockGUI; @@ -90,7 +91,7 @@ public Located getLocated() { public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { if (block == null) return null; - return BQBlock.getNearbyBlocks(fetcher, Collections.singleton(block)); + return QuestsAPI.getAPI().getBlocksManager().getNearbyBlocks(fetcher, Collections.singleton(block)); } @EventHandler @@ -137,9 +138,10 @@ public static StageInteract deserialize(ConfigurationSection section, StageContr }else { BQBlock block; if (section.contains("material")) { - block = new BQBlock.BQBlockMaterial(null, XMaterial.valueOf(section.getString("material"))); + block = QuestsAPI.getAPI().getBlocksManager().createSimple(XMaterial.valueOf(section.getString("material")), + null); }else { - block = BQBlock.fromString(section.getString("block")); + block = QuestsAPI.getAPI().getBlocksManager().deserialize(section.getString("block")); } return new StageInteract(controller, section.getBoolean("leftClick"), block); } 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 ce756ff7..a793a865 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -11,8 +11,8 @@ import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; -import fr.skytasul.quests.api.editors.checkers.NumberParser; -import fr.skytasul.quests.api.editors.checkers.PatternParser; +import fr.skytasul.quests.api.editors.parsers.NumberParser; +import fr.skytasul.quests.api.editors.parsers.PatternParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index 46f64a12..c41afc0b 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -20,6 +20,8 @@ import com.gestankbratwurst.playerblocktracker.PlayerBlockTracker; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -33,7 +35,6 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.CountableObject; @LocatableType (types = LocatedType.BLOCK) @@ -106,7 +107,7 @@ public void onPlace(BlockPlaceEvent e){ @Override public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { - return BQBlock.getNearbyBlocks(fetcher, + return QuestsAPI.getAPI().getBlocksManager().getNearbyBlocks(fetcher, objects.stream().map(CountableObject::getObject).collect(Collectors.toList())); } 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 f74727e8..77d66246 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -41,7 +41,6 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.npc.NpcSelectGUI; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; @@ -316,10 +315,10 @@ public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); line.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString()), event -> { - NpcSelectGUI.select(event::reopen, newNPC -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, newNPC -> { setNPCId(newNPC.getId()); event.reopen(); - }).open(event.getPlayer()); + }, false).open(event.getPlayer()); }); line.setItem(SLOT_DIALOG, ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.stageText.toString(), Lang.NotSet.toString()), event -> { @@ -354,10 +353,10 @@ public void setHidden(boolean hidden) { @Override public void start(Player p) { super.start(p); - NpcSelectGUI.select(context::removeAndReopenGui, newNPC -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(context::removeAndReopenGui, newNPC -> { setNPCId(newNPC.getId()); context.reopenGui(); - }).open(p); + }, false).open(p); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index ff2480ca..0c4e9a5b 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; @@ -17,7 +18,6 @@ import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; -import fr.skytasul.quests.api.utils.BQBlock; import fr.skytasul.quests.api.utils.CountableObject; public class StagePlaceBlocks extends AbstractCountableBlockStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index 17a97eb7..8aa9ac5c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -12,7 +12,7 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.checkers.DurationParser.MinecraftTimeUnit; +import fr.skytasul.quests.api.editors.parsers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; 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 dc078ac4..1ab2da28 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -43,7 +43,7 @@ public static void playPluginSound(Player p, String sound, float volume) { } public static void playPluginSound(Player p, String sound, float volume, float pitch) { - if (!QuestsConfigurationImplementation.playSounds()) + if (!QuestsConfigurationImplementation.getConfiguration().getQuestsConfig().sounds()) return; if ("none".equals(sound)) return; @@ -56,7 +56,7 @@ public static void playPluginSound(Player p, String sound, float volume, float p } public static void playPluginSound(Location lc, String sound, float volume) { - if (!QuestsConfigurationImplementation.playSounds()) + if (!QuestsConfigurationImplementation.getConfiguration().getQuestsConfig().sounds()) return; try { lc.getWorld().playSound(lc, Sound.valueOf(sound), volume, 1); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java index ef5b0ca9..fe263a64 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java @@ -10,7 +10,8 @@ import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.utils.BQBlock; +import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.blocks.BQBlockOptions; public class Post1_13 { @@ -38,12 +39,12 @@ public static class BQBlockData extends BQBlock { private final BlockData data; - public BQBlockData(String customName, String stringData) { - this(customName, Bukkit.createBlockData(stringData)); + public BQBlockData(BQBlockOptions options, String stringData) { + this(options, Bukkit.createBlockData(stringData)); } - public BQBlockData(String customName, BlockData data) { - super(customName); + public BQBlockData(BQBlockOptions options, BlockData data) { + super(options); this.data = data; } @@ -59,7 +60,7 @@ public XMaterial retrieveMaterial() { @Override public String getDataString() { - return BQBlock.BLOCKDATA_HEADER + data.getAsString(true); + return data.getAsString(true); } } @@ -69,12 +70,12 @@ public static class BQBlockTag extends BQBlock { private final Tag<Material> tag; private final String tagKey; - public BQBlockTag(String customName, String stringData) { - this(customName, Bukkit.getTag(Tag.REGISTRY_BLOCKS, NamespacedKey.fromString(stringData), Material.class)); + public BQBlockTag(BQBlockOptions options, String stringData) { + this(options, Bukkit.getTag(Tag.REGISTRY_BLOCKS, NamespacedKey.fromString(stringData), Material.class)); } - public BQBlockTag(String customName, Tag<Material> tag) { - super(customName); + public BQBlockTag(BQBlockOptions options, Tag<Material> tag) { + super(options); this.tagKey = tag.getKey().toString(); this.tag = tag; } @@ -100,7 +101,7 @@ public String getDefaultName() { @Override public String getDataString() { - return BQBlock.TAG_HEADER + tagKey; + return tagKey; } } From 6965f2408324e9983bd3d219a11ed98dffdf7f26 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 2 Jul 2023 19:36:51 +0200 Subject: [PATCH 23/95] :heavy_plus_sign: :arrow_up: Added ZNPCsPlus support and upgraded znpcs support to 4.2 --- core/libs.sh | 1 + core/pom.xml | 12 +- .../compatibility/DependenciesManager.java | 9 +- .../compatibility/npcs/BQServerNPCs.java | 17 +-- .../utils/compatibility/npcs/BQZNPCsPlus.java | 127 ++++++++++++++++++ core/src/main/resources/plugin.yml | 1 + 6 files changed, 154 insertions(+), 13 deletions(-) create mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQZNPCsPlus.java diff --git a/core/libs.sh b/core/libs.sh index fbff3b79..621336c1 100644 --- a/core/libs.sh +++ b/core/libs.sh @@ -25,6 +25,7 @@ echo -e "Maven path: $mavenPath\e[39m" "$mavenPath" install:install-file -Dfile=$jarsPath/CMILib.jar -DgroupId=com.zrips -DartifactId=cmilib -Dversion=1.2.3.3 -Dpackaging=jar -DgeneratePom=true "$mavenPath" install:install-file -Dfile=$jarsPath/UltimateTimber.jar -DgroupId=com.songoda -DartifactId=UltimateTimber -Dversion=2.3.5 -Dpackaging=jar -DgeneratePom=true "$mavenPath" install:install-file -Dfile=$jarsPath/AdvancedSpawners-API.jar -DgroupId=gcspawners -DartifactId=gcspawners -Dversion=3.3.0 -Dpackaging=jar -DgeneratePom=true +"$mavenPath" install:install-file -Dfile=$jarsPath/znpcs.jar -DgroupId=io.github.gonalez -DartifactId=znpcs -Dversion=4.2 -Dpackaging=jar -DgeneratePom=true #"$mavenPath" install:install-file -Dfile=$jarsPath/MythicMobs.jar -DgroupId=io.lumine.xikage -DartifactId=MythicMobs -Dversion=4.12.0 -Dpackaging=jar -DgeneratePom=true #"$mavenPath" install:install-file -Dfile=$jarsPath/TokenEnchantAPI.jar -DgroupId=com.vk2gpz.tokenenchant -DartifactId=TokenEnchantAPI -Dversion=18.15.2 -Dpackaging=jar -DgeneratePom=true diff --git a/core/pom.xml b/core/pom.xml index ccbd749e..484b10ee 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -197,9 +197,15 @@ <scope>provided</scope> </dependency> <dependency> - <groupId>io.github.znetworkw.znpcservers</groupId> - <artifactId>znpcservers</artifactId> - <version>3.6</version> + <groupId>io.github.gonalez</groupId> + <artifactId>znpcs</artifactId> + <version>4.2</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.github.Pyrbu</groupId> + <artifactId>ZNPCsPlus</artifactId> + <version>1.0.8</version> <scope>provided</scope> </dependency> <dependency> diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java index cf73369a..baaed758 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java @@ -41,12 +41,13 @@ import fr.skytasul.quests.utils.compatibility.npcs.BQCitizens; import fr.skytasul.quests.utils.compatibility.npcs.BQSentinel; import fr.skytasul.quests.utils.compatibility.npcs.BQServerNPCs; +import fr.skytasul.quests.utils.compatibility.npcs.BQZNPCsPlus; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; public class DependenciesManager implements Listener { public static final BQDependency znpcs = new BQDependency("ServersNPC", () -> QuestsAPI.setNPCsManager(new BQServerNPCs()), null, plugin -> { - if (plugin.getClass().getName().equals("io.github.znetworkw.znpcservers.ServersNPC")) // NOSONAR + if (plugin.getClass().getName().equals("io.github.gonalez.znpcs.ServersNPC")) // NOSONAR return true; BeautyQuests.logger.warning("Your version of znpcs (" + plugin.getDescription().getVersion() + ") is not supported by BeautyQuests."); @@ -58,6 +59,10 @@ public class DependenciesManager implements Listener { QuestsAPI.registerMobFactory(new CitizensFactory()); }); + public static final BQDependency ZNPCsPlus = new BQDependency("ZNPCsPlus", () -> { + QuestsAPI.setNPCsManager(new BQZNPCsPlus()); + }); + public static final BQDependency vault = new BQDependency("Vault", () -> { QuestsAPI.getRewards().register(new RewardCreator("moneyReward", MoneyReward.class, ItemUtils.item(XMaterial.EMERALD, Lang.rewardMoney.toString()), MoneyReward::new)); QuestsAPI.getRewards().register(new RewardCreator("permReward", PermissionReward.class, ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.rewardPerm.toString()), PermissionReward::new)); @@ -149,7 +154,7 @@ public class DependenciesManager implements Listener { public DependenciesManager() { dependencies = new ArrayList<>(Arrays.asList( /*par, eboss, */ - znpcs, citizens, // npcs + znpcs, citizens, ZNPCsPlus, // npcs wg, gps, tokenEnchant, ultimateTimber, sentinel, PlayerBlockTracker, // other mm, boss, advancedspawners, LevelledMobs, WildStacker, // mobs vault, papi, acc, // hooks diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java index 760a774d..37876b73 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java @@ -14,13 +14,13 @@ import fr.skytasul.quests.QuestsConfiguration.ClickType; import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.npcs.BQNPCsManager; -import io.github.znetworkw.znpcservers.ServersNPC; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.NPCModel; -import io.github.znetworkw.znpcservers.npc.NPCSkin; -import io.github.znetworkw.znpcservers.npc.NPCType; -import io.github.znetworkw.znpcservers.npc.event.NPCInteractEvent; +import io.github.gonalez.znpcs.ServersNPC; +import io.github.gonalez.znpcs.configuration.ConfigurationConstants; +import io.github.gonalez.znpcs.npc.NPC; +import io.github.gonalez.znpcs.npc.NPCModel; +import io.github.gonalez.znpcs.npc.NPCSkin; +import io.github.gonalez.znpcs.npc.NPCType; +import io.github.gonalez.znpcs.npc.event.NPCInteractEvent; public class BQServerNPCs extends BQNPCsManager { @@ -91,7 +91,8 @@ public int getId() { @Override public String getName() { - return npc.getNpcPojo().getHologramLines().isEmpty() ? npc.getGameProfile().getName() : npc.getNpcPojo().getHologramLines().get(0); + return npc.getNpcPojo().getHologramLines().isEmpty() ? "ID: " + npc.getNpcPojo().getId() + : npc.getNpcPojo().getHologramLines().get(0); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQZNPCsPlus.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQZNPCsPlus.java new file mode 100644 index 00000000..b503f3ea --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQZNPCsPlus.java @@ -0,0 +1,127 @@ +package fr.skytasul.quests.utils.compatibility.npcs; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import fr.skytasul.quests.QuestsConfiguration.ClickType; +import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BQNPCsManager; +import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; +import io.github.znetworkw.znpcservers.npc.NPC; +import io.github.znetworkw.znpcservers.npc.NPCModel; +import io.github.znetworkw.znpcservers.npc.NPCSkin; +import io.github.znetworkw.znpcservers.npc.NPCType; +import io.github.znetworkw.znpcservers.npc.interaction.NPCInteractEvent; +import lol.pyr.znpcsplus.ZNPCsPlus; + +public class BQZNPCsPlus extends BQNPCsManager { + + private Cache<Integer, Boolean> cachedNpcs = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + + @Override + public int getTimeToWaitForNPCs() { + return 45; + } + + @Override + public Collection<Integer> getIDs() { + return NPC.all().stream().map(x -> x.getNpcPojo().getId()).collect(Collectors.toList()); + } + + @Override + public boolean isNPC(Entity entity) { + Boolean result = cachedNpcs.getIfPresent(entity.getEntityId()); + if (result == null) { + result = NPC.all().stream().anyMatch(npc1 -> npc1.getEntityID() == entity.getEntityId()); + cachedNpcs.put(entity.getEntityId(), result); + } + return result; + } + + @Override + protected BQNPC fetchNPC(int id) { + NPC npc = NPC.find(id); + return npc == null ? null : new BQServerNPC(npc); + } + + @Override + public boolean isValidEntityType(EntityType type) { + return Arrays.stream(NPCType.values()).map(NPCType::name).anyMatch(name -> name.equals(type.name())); + } + + @Override + protected BQNPC create(Location location, EntityType type, String name) { + List<Integer> ids = ConfigurationConstants.NPC_LIST.stream().map(NPCModel::getId).collect(Collectors.toList()); + int id = ids.size(); + while (ids.contains(id)) + id++; + NPC npc = ZNPCsPlus.createNPC(id, NPCType.valueOf(type.name()), location, name); + npc.getNpcPojo().getFunctions().put("look", true); + return new BQServerNPC(npc); + } + + @EventHandler + public void onInteract(NPCInteractEvent e) { + super.clickEvent(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), + ClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); + } + + public static class BQServerNPC extends BQNPC { + + private final NPC npc; + + private BQServerNPC(NPC npc) { + this.npc = npc; + } + + public NPC getServerNPC() { + return npc; + } + + @Override + public int getId() { + return npc.getNpcPojo().getId(); + } + + @Override + public String getName() { + return npc.getNpcPojo().getHologramLines().isEmpty() ? "ID: " + npc.getNpcPojo().getId() + : npc.getNpcPojo().getHologramLines().get(0); + } + + @Override + public boolean isSpawned() { + return npc.getBukkitEntity() != null; + } + + @Override + public Entity getEntity() { + return (Entity) npc.getBukkitEntity(); + } + + @Override + public Location getLocation() { + return npc.getLocation(); + } + + @Override + public void setSkin(String skin) { + NPCSkin.forName(skin, (values, exception) -> npc.changeSkin(NPCSkin.forValues(values))); + } + + @Override + public boolean setNavigationPaused(boolean paused) { + return true; + } + + } + +} diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index e3653010..1e5f7f73 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -28,6 +28,7 @@ softdepend: - UltimateTimber - ServersNPC - Citizens +- ZNPCsPlus - ProSkillAPI - BlueMap - Sentinel From 538d70c75ebc328d4a41ca8c106bdeb9b1516f85 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 4 Jul 2023 21:10:59 +0200 Subject: [PATCH 24/95] :bug: Fixed NMS issue on 1.20.1 --- .../java/fr/skytasul/quests/utils/Utils.java | 9 +-------- .../fr/skytasul/quests/utils/nms/NMS.java | 5 +---- .../fr/skytasul/quests/utils/nms/NullNMS.java | 8 +------- .../skytasul/quests/utils/nms/v1_12_R1.java | 20 ++++++++----------- .../skytasul/quests/utils/nms/v1_15_R1.java | 16 +++------------ .../skytasul/quests/utils/nms/v1_16_R1.java | 16 +++------------ .../skytasul/quests/utils/nms/v1_16_R2.java | 16 +++------------ .../skytasul/quests/utils/nms/v1_16_R3.java | 16 +++------------ .../skytasul/quests/utils/nms/v1_17_R1.java | 19 ++++-------------- .../skytasul/quests/utils/nms/v1_18_R1.java | 19 ++++-------------- .../skytasul/quests/utils/nms/v1_18_R2.java | 19 ++++-------------- .../skytasul/quests/utils/nms/v1_19_R1.java | 19 ++++-------------- .../skytasul/quests/utils/nms/v1_19_R2.java | 16 ++++----------- .../skytasul/quests/utils/nms/v1_19_R3.java | 16 ++++----------- .../skytasul/quests/utils/nms/v1_20_R1.java | 16 ++++----------- .../fr/skytasul/quests/utils/nms/v1_9_R1.java | 18 +++++++---------- .../fr/skytasul/quests/utils/nms/v1_9_R2.java | 18 +++++++---------- 17 files changed, 65 insertions(+), 201 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/utils/Utils.java b/core/src/main/java/fr/skytasul/quests/utils/Utils.java index a8bd3145..1fb0bbfb 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/Utils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/Utils.java @@ -59,8 +59,6 @@ import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; import fr.skytasul.quests.utils.nms.NMS; import net.md_5.bungee.api.ChatColor; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; /** * A bunch of static methods who can be useful @@ -76,12 +74,7 @@ public static void openBook(Player p, ItemStack book){ int slot = p.getInventory().getHeldItemSlot(); ItemStack old = p.getInventory().getItem(slot); p.getInventory().setItem(slot, book); - - ByteBuf buf = Unpooled.buffer(256); - buf.setByte(0, (byte) 0); - buf.writerIndex(1); - - NMS.getNMS().sendPacket(p, NMS.getNMS().bookPacket(buf)); + NMS.getNMS().openBookInHand(p); p.getInventory().setItem(slot, old); } 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 edee7d1c..7776b944 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 @@ -11,7 +11,6 @@ import org.bukkit.inventory.meta.ItemMeta; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.utils.ReflectUtils; -import io.netty.buffer.ByteBuf; public abstract class NMS{ @@ -35,8 +34,6 @@ public NMS() { } } - public abstract Object bookPacket(ByteBuf buf); - public abstract double entityNameplateHeight(Entity en); // can be remplaced by Entity.getHeight from 1.11 public List<String> getAvailableBlockProperties(Material material){ @@ -61,7 +58,7 @@ public ReflectUtils getCraftReflect(){ return craftReflect; } - public abstract void sendPacket(Player p, Object packet); + public abstract void openBookInHand(Player p); public static NMS getNMS() { return nms; diff --git a/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java b/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java index 031d429d..a18c513a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java +++ b/core/src/main/java/fr/skytasul/quests/utils/nms/NullNMS.java @@ -5,14 +5,8 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.meta.ItemMeta; import fr.skytasul.quests.utils.ReflectUtils; -import io.netty.buffer.ByteBuf; public class NullNMS extends NMS { - - @Override - public Object bookPacket(ByteBuf buf) { - throw new UnsupportedOperationException("Your version is not compatible."); - } @Override public boolean equalsWithoutNBT(ItemMeta meta1, ItemMeta meta2) throws ReflectiveOperationException { @@ -20,7 +14,7 @@ public boolean equalsWithoutNBT(ItemMeta meta1, ItemMeta meta2) throws Reflectiv } @Override - public void sendPacket(Player p, Object packet) { + public void openBookInHand(Player p) { throw new UnsupportedOperationException("Your version is not compatible."); } diff --git a/v1_12_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_12_R1.java b/v1_12_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_12_R1.java index 4fef5f08..66d52aa5 100644 --- a/v1_12_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_12_R1.java +++ b/v1_12_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_12_R1.java @@ -1,29 +1,25 @@ package fr.skytasul.quests.utils.nms; -import org.apache.commons.lang.Validate; import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.server.v1_12_R1.EnumChatFormat; import net.minecraft.server.v1_12_R1.IChatBaseComponent; -import net.minecraft.server.v1_12_R1.Packet; import net.minecraft.server.v1_12_R1.PacketDataSerializer; import net.minecraft.server.v1_12_R1.PacketPlayOutCustomPayload; - import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; public class v1_12_R1 extends NMS{ @Override - public Object bookPacket(ByteBuf buf){ - return new PacketPlayOutCustomPayload("MC|BOpen", new PacketDataSerializer(buf)); - } - - @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().playerConnection.sendPacket((Packet<?>) packet); + public void openBookInHand(Player p) { + ByteBuf buf = Unpooled.buffer(256); + buf.setByte(0, (byte) 0); + buf.writerIndex(1); + + PacketPlayOutCustomPayload packet = new PacketPlayOutCustomPayload("MC|BOpen", new PacketDataSerializer(buf)); + ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet); } @Override diff --git a/v1_15_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_15_R1.java b/v1_15_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_15_R1.java index d6dcfd66..092a38ec 100644 --- a/v1_15_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_15_R1.java +++ b/v1_15_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_15_R1.java @@ -2,28 +2,18 @@ import java.util.List; import java.util.stream.Collectors; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.server.v1_15_R1.*; -import io.netty.buffer.ByteBuf; - public class v1_15_R1 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); - } @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().playerConnection.sendPacket((Packet<?>) packet); + public void openBookInHand(Player p) { + PacketPlayOutOpenBook packet = new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet); } @Override diff --git a/v1_16_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R1.java b/v1_16_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R1.java index b8985f5e..b1c7a7e1 100644 --- a/v1_16_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R1.java +++ b/v1_16_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R1.java @@ -2,28 +2,18 @@ import java.util.List; import java.util.stream.Collectors; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.server.v1_16_R1.*; -import io.netty.buffer.ByteBuf; - public class v1_16_R1 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); - } @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().playerConnection.sendPacket((Packet<?>) packet); + public void openBookInHand(Player p) { + PacketPlayOutOpenBook packet = new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet); } @Override diff --git a/v1_16_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R2.java b/v1_16_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R2.java index f14d7985..7e32095d 100644 --- a/v1_16_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R2.java +++ b/v1_16_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R2.java @@ -2,28 +2,18 @@ import java.util.List; import java.util.stream.Collectors; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.server.v1_16_R2.*; -import io.netty.buffer.ByteBuf; - public class v1_16_R2 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); - } @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().playerConnection.sendPacket((Packet<?>) packet); + public void openBookInHand(Player p) { + PacketPlayOutOpenBook packet = new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet); } @Override diff --git a/v1_16_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R3.java b/v1_16_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R3.java index 5a97c2bb..1a6e34f4 100644 --- a/v1_16_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R3.java +++ b/v1_16_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_16_R3.java @@ -2,28 +2,18 @@ import java.util.List; import java.util.stream.Collectors; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.server.v1_16_R3.*; -import io.netty.buffer.ByteBuf; - public class v1_16_R3 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); - } @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().playerConnection.sendPacket((Packet<?>) packet); + public void openBookInHand(Player p) { + PacketPlayOutOpenBook packet = new PacketPlayOutOpenBook(EnumHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet); } @Override diff --git a/v1_17_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_17_R1.java b/v1_17_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_17_R1.java index 821d122e..6c4f995a 100644 --- a/v1_17_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_17_R1.java +++ b/v1_17_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_17_R1.java @@ -1,15 +1,11 @@ package fr.skytasul.quests.utils.nms; import java.util.List; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.core.Registry; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; @@ -19,19 +15,12 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.Property; -import io.netty.buffer.ByteBuf; - public class v1_17_R1 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); - } - + @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); } @Override diff --git a/v1_18_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R1.java b/v1_18_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R1.java index c46b41cc..242fbf6f 100644 --- a/v1_18_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R1.java +++ b/v1_18_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R1.java @@ -1,15 +1,11 @@ package fr.skytasul.quests.utils.nms; import java.util.List; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.core.Registry; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; @@ -19,19 +15,12 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.Property; -import io.netty.buffer.ByteBuf; - public class v1_18_R1 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); - } - + @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); } @Override diff --git a/v1_18_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R2.java b/v1_18_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R2.java index 1d196111..5b22f76f 100644 --- a/v1_18_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R2.java +++ b/v1_18_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_18_R2.java @@ -1,15 +1,11 @@ package fr.skytasul.quests.utils.nms; import java.util.List; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.core.Registry; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; @@ -18,19 +14,12 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.Property; -import io.netty.buffer.ByteBuf; - public class v1_18_R2 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); - } - + @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); } @Override diff --git a/v1_19_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R1.java b/v1_19_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R1.java index 5c6aeb96..e9b9e62c 100644 --- a/v1_19_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R1.java +++ b/v1_19_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R1.java @@ -1,15 +1,11 @@ package fr.skytasul.quests.utils.nms; import java.util.List; - -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.core.Registry; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; @@ -18,19 +14,12 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.Property; -import io.netty.buffer.ByteBuf; - public class v1_19_R1 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); - } - + @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); } @Override diff --git a/v1_19_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R2.java b/v1_19_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R2.java index 6ef950ce..7519bc1b 100644 --- a/v1_19_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R2.java +++ b/v1_19_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R2.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.utils.nms; import java.util.List; -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; import org.bukkit.entity.Entity; @@ -9,7 +8,6 @@ import net.minecraft.core.Holder.Reference; import net.minecraft.core.HolderLookup.RegistryLookup; import net.minecraft.core.registries.Registries; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -19,19 +17,13 @@ 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 io.netty.buffer.ByteBuf; public class v1_19_R2 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); - } - + @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); } @Override diff --git a/v1_19_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R3.java b/v1_19_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R3.java index f138329b..464e8ceb 100644 --- a/v1_19_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R3.java +++ b/v1_19_R3/src/main/java/fr/skytasul/quests/utils/nms/v1_19_R3.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.utils.nms; import java.util.List; -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer; import org.bukkit.entity.Entity; @@ -9,7 +8,6 @@ import net.minecraft.core.Holder.Reference; import net.minecraft.core.HolderLookup.RegistryLookup; import net.minecraft.core.registries.Registries; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -19,19 +17,13 @@ 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 io.netty.buffer.ByteBuf; public class v1_19_R3 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); - } - + @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); } @Override diff --git a/v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java b/v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java index 4aa65315..ec5a02cb 100644 --- a/v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java +++ b/v1_20_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R1.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.utils.nms; import java.util.List; -import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; @@ -9,7 +8,6 @@ import net.minecraft.core.Holder.Reference; import net.minecraft.core.HolderLookup.RegistryLookup; import net.minecraft.core.registries.Registries; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -19,19 +17,13 @@ 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 io.netty.buffer.ByteBuf; public class v1_20_R1 extends NMS{ - - @Override - public Object bookPacket(ByteBuf buf){ - return new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); - } - + @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().connection.send((Packet<?>) packet); + public void openBookInHand(Player p) { + ClientboundOpenBookPacket packet = new ClientboundOpenBookPacket(InteractionHand.MAIN_HAND); + ((CraftPlayer) p).getHandle().connection.send(packet); } @Override diff --git a/v1_9_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R1.java b/v1_9_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R1.java index bdddae93..dda2e0cc 100644 --- a/v1_9_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R1.java +++ b/v1_9_R1/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R1.java @@ -1,30 +1,26 @@ package fr.skytasul.quests.utils.nms; -import org.apache.commons.lang.Validate; import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.server.v1_9_R1.EnumChatFormat; import net.minecraft.server.v1_9_R1.IChatBaseComponent; -import net.minecraft.server.v1_9_R1.Packet; import net.minecraft.server.v1_9_R1.PacketDataSerializer; import net.minecraft.server.v1_9_R1.PacketPlayOutCustomPayload; - import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; public class v1_9_R1 extends NMS{ @Override - public Object bookPacket(ByteBuf buf){ - return new PacketPlayOutCustomPayload("MC|BOpen", new PacketDataSerializer(buf)); - } + public void openBookInHand(Player p) { + ByteBuf buf = Unpooled.buffer(256); + buf.setByte(0, (byte) 0); + buf.writerIndex(1); - @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().playerConnection.sendPacket((Packet<?>) packet); + PacketPlayOutCustomPayload packet = new PacketPlayOutCustomPayload("MC|BOpen", new PacketDataSerializer(buf)); + ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet); } @Override diff --git a/v1_9_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R2.java b/v1_9_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R2.java index fe858742..c754b7d1 100644 --- a/v1_9_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R2.java +++ b/v1_9_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_9_R2.java @@ -1,30 +1,26 @@ package fr.skytasul.quests.utils.nms; -import org.apache.commons.lang.Validate; import org.bukkit.craftbukkit.v1_9_R2.entity.CraftEntity; import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; - import net.minecraft.server.v1_9_R2.EnumChatFormat; import net.minecraft.server.v1_9_R2.IChatBaseComponent; -import net.minecraft.server.v1_9_R2.Packet; import net.minecraft.server.v1_9_R2.PacketDataSerializer; import net.minecraft.server.v1_9_R2.PacketPlayOutCustomPayload; - import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; public class v1_9_R2 extends NMS{ @Override - public Object bookPacket(ByteBuf buf){ - return new PacketPlayOutCustomPayload("MC|BOpen", new PacketDataSerializer(buf)); - } + public void openBookInHand(Player p) { + ByteBuf buf = Unpooled.buffer(256); + buf.setByte(0, (byte) 0); + buf.writerIndex(1); - @Override - public void sendPacket(Player p, Object packet){ - Validate.isTrue(packet instanceof Packet, "The object specified is not a packet."); - ((CraftPlayer) p).getHandle().playerConnection.sendPacket((Packet<?>) packet); + PacketPlayOutCustomPayload packet = new PacketPlayOutCustomPayload("MC|BOpen", new PacketDataSerializer(buf)); + ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet); } @Override From 43dd3d43a9893b1b05da30d85a1a0e3a97f80479 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 11 Jul 2023 23:20:21 +0200 Subject: [PATCH 25/95] :construction: Reworked NPC manager --- .../fr/skytasul/quests/api/QuestsAPI.java | 7 +- .../quests/api/QuestsConfiguration.java | 22 +-- .../fr/skytasul/quests/api/QuestsPlugin.java | 4 + .../skytasul/quests/api/editors/Editor.java | 11 +- .../quests/api/editors/SelectNPC.java | 6 +- .../quests/api/events/DialogSendEvent.java | 8 +- .../api/events/DialogSendMessageEvent.java | 8 +- .../api/events/internal/BQNPCClickEvent.java | 8 +- .../skytasul/quests/api/gui/GuiFactory.java | 4 +- .../skytasul/quests/api/mobs/MobFactory.java | 8 +- .../quests/api/npcs/BQNPCsManager.java | 70 ---------- .../quests/api/npcs/BqInternalNpc.java | 31 +++++ .../quests/api/npcs/BqInternalNpcFactory.java | 44 ++++++ .../fr/skytasul/quests/api/npcs/BqNpc.java | 30 ++++ .../quests/api/npcs/BqNpcManager.java | 29 ++++ .../quests/api/npcs/dialogs/Dialog.java | 4 +- .../quests/api/options/QuestOption.java | 2 + .../quests/api/options/QuestOptionItem.java | 8 +- .../skytasul/quests/api/pools/QuestPool.java | 2 +- .../quests/api/stages/AbstractStage.java | 2 + .../quests/api/stages/types/Dialogable.java | 4 +- .../quests/api/utils/AutoRegistered.java | 18 +++ .../quests/api/utils/MessageUtils.java | 11 ++ .../SplittableDescriptionConfiguration.java | 26 ++++ .../java/fr/skytasul/quests/BeautyQuests.java | 15 +- .../quests/QuestsAPIImplementation.java | 23 +--- .../QuestsConfigurationImplementation.java | 44 ++++-- .../fr/skytasul/quests/QuestsListener.java | 9 +- .../quests/commands/CommandsAdmin.java | 7 +- .../CommandsManagerImplementation.java | 10 +- .../quests/commands/CommandsPools.java | 4 +- .../editor/EditorManagerImplementation.java | 4 + .../quests/gui/DefaultGuiFactory.java | 4 +- .../fr/skytasul/quests/gui/misc/ListBook.java | 3 +- .../skytasul/quests/gui/npc/NpcCreateGUI.java | 15 +- .../skytasul/quests/gui/npc/NpcSelectGUI.java | 4 +- .../quests/gui/pools/PoolEditGUI.java | 2 +- .../quests/gui/quests/DialogHistoryGUI.java | 3 +- .../quests/npcs/BqNpcImplementation.java | 129 +++++++++++------- .../npcs/BqNpcManagerImplementation.java | 108 +++++++++++++++ .../quests/options/OptionStartDialog.java | 4 +- .../quests/options/OptionStarterNPC.java | 13 +- .../players/AbstractPlayersManager.java | 4 +- .../quests/stages/StageBringBack.java | 26 ++-- .../fr/skytasul/quests/stages/StageNPC.java | 19 +-- .../quests/structure/QuestImplementation.java | 3 +- .../QuestsManagerImplementation.java | 6 +- .../StageControllerImplementation.java | 8 +- .../pools/QuestPoolImplementation.java | 13 +- .../fr/skytasul/quests/utils/QuestUtils.java | 40 ++++-- .../compatibility/DependenciesManager.java | 5 +- .../mobs/BQAdvancedSpawners.java | 3 +- .../utils/compatibility/mobs/BQBoss.java | 3 +- .../mobs/BukkitEntityFactory.java | 3 +- .../compatibility/mobs/CitizensFactory.java | 3 +- .../utils/compatibility/mobs/MythicMobs.java | 3 +- .../utils/compatibility/mobs/MythicMobs5.java | 3 +- .../utils/compatibility/npcs/BQCitizens.java | 32 ++--- .../utils/compatibility/npcs/BQSentinel.java | 10 +- .../compatibility/npcs/BQServerNPCs.java | 16 ++- .../worldguard/WorldGuardEntryHandler.java | 4 +- .../types/DialogRunnerImplementation.java | 6 +- 62 files changed, 621 insertions(+), 357 deletions(-) delete mode 100644 api/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java rename api/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java => core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java (76%) create mode 100644 core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java index 27d0d365..bf52459a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -9,7 +9,7 @@ import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.api.mobs.MobStacker; -import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.options.QuestOptionCreator; import fr.skytasul.quests.api.pools.QuestPoolsManager; @@ -64,10 +64,7 @@ public interface QuestsAPI { @NotNull QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards(); - @NotNull - BQNPCsManager getNPCsManager(); - - void setNPCsManager(@NotNull BQNPCsManager newNpcsManager); + void setNpcFactory(@NotNull BqInternalNpcFactory factory); boolean hasHologramsManager(); diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java index b66a0af9..8e7aeb31 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -6,9 +6,9 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.npcs.NpcClickType; -import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescription; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.SplittableDescriptionConfiguration; public interface QuestsConfiguration { @@ -109,28 +109,10 @@ interface QuestsMenu { } - interface StageDescription { + interface StageDescription extends SplittableDescriptionConfiguration { String getStageDescriptionFormat(); - String getItemNameColor(); - - String getItemAmountColor(); - - String getSplitPrefix(); - - String getSplitAmountFormat(); - - boolean isAloneSplitAmountShown(); - - boolean isAloneSplitInlined(); - - Set<DescriptionSource> getSplitSources(); - - default boolean isAloneSplitAmountShown(DescriptionSource source) { - return getSplitSources().contains(source) && isAloneSplitAmountShown(); - } - } } diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java index 5a04c6e4..a6accd9c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java @@ -5,6 +5,7 @@ import fr.skytasul.quests.api.commands.CommandsManager; import fr.skytasul.quests.api.editors.EditorManager; import fr.skytasul.quests.api.gui.GuiManager; +import fr.skytasul.quests.api.npcs.BqNpcManager; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.utils.logger.LoggerExpanded; @@ -30,6 +31,9 @@ public interface QuestsPlugin extends Plugin { public void noticeSavingFailure(); + @NotNull + BqNpcManager getNpcManager(); + public static @NotNull QuestsPlugin getPlugin() { return QuestsAPIProvider.getAPI().getPlugin(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/Editor.java b/api/src/main/java/fr/skytasul/quests/api/editors/Editor.java index 43808316..808f3120 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/Editor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/Editor.java @@ -1,15 +1,14 @@ package fr.skytasul.quests.api.editors; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.AutoRegistered; import fr.skytasul.quests.api.utils.ChatColorUtils; +@AutoRegistered public abstract class Editor { protected final @NotNull Player player; @@ -30,9 +29,6 @@ public void begin() { throw new IllegalStateException("Editor already started"); started = true; - - if (this instanceof Listener) - Bukkit.getPluginManager().registerEvents((@NotNull Listener) this, QuestsPlugin.getPlugin()); } public void end() { @@ -40,9 +36,6 @@ public void end() { throw new IllegalStateException("Editor did not started"); started = false; - - if (this instanceof Listener) - HandlerList.unregisterAll((Listener) this); } public final void start() { diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java b/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java index 693baa93..96aa7779 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java @@ -6,13 +6,13 @@ import org.bukkit.event.EventPriority; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; public class SelectNPC extends InventoryClear{ - private Consumer<BQNPC> run; + private Consumer<BqNpc> run; - public SelectNPC(Player p, Runnable cancel, Consumer<BQNPC> end) { + public SelectNPC(Player p, Runnable cancel, Consumer<BqNpc> end) { super(p, cancel); this.run = end; } diff --git a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java index bcd4e182..5130895c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java @@ -5,7 +5,7 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Dialog; public class DialogSendEvent extends Event implements Cancellable { @@ -13,11 +13,11 @@ public class DialogSendEvent extends Event implements Cancellable { private boolean cancelled = false; private final @NotNull Dialog dialog; - private final @NotNull BQNPC npc; + private final @NotNull BqNpc npc; private final @NotNull Player player; private final @NotNull Runnable runnable; - public DialogSendEvent(@NotNull Dialog dialog, @NotNull BQNPC npc, @NotNull Player player, @NotNull Runnable runnable) { + public DialogSendEvent(@NotNull Dialog dialog, @NotNull BqNpc npc, @NotNull Player player, @NotNull Runnable runnable) { this.dialog = dialog; this.npc = npc; this.player = player; @@ -39,7 +39,7 @@ public Dialog getDialog() { return dialog; } - public BQNPC getNPC() { + public BqNpc getNPC() { return npc; } diff --git a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java index f9cc1c79..a666fc19 100644 --- a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java @@ -5,7 +5,7 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.Message; @@ -15,10 +15,10 @@ public class DialogSendMessageEvent extends Event implements Cancellable { private final @NotNull Dialog dialog; private final @NotNull Message msg; - private final @NotNull BQNPC npc; + private final @NotNull BqNpc npc; private final @NotNull Player player; - public DialogSendMessageEvent(@NotNull Dialog dialog, @NotNull Message msg, @NotNull BQNPC npc, @NotNull Player player) { + public DialogSendMessageEvent(@NotNull Dialog dialog, @NotNull Message msg, @NotNull BqNpc npc, @NotNull Player player) { this.dialog = dialog; this.msg = msg; this.npc = npc; @@ -43,7 +43,7 @@ public void setCancelled(boolean cancelled) { return msg; } - public @NotNull BQNPC getNPC() { + public @NotNull BqNpc getNPC() { return npc; } diff --git a/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java index c6a920b6..b7aa5aea 100644 --- a/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java @@ -5,17 +5,17 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.NpcClickType; public class BQNPCClickEvent extends PlayerEvent implements Cancellable { - private final @NotNull BQNPC npc; + private final @NotNull BqNpc npc; private final @NotNull NpcClickType click; private boolean cancelled = false; - public BQNPCClickEvent(@NotNull BQNPC npc, @NotNull Player p, @NotNull NpcClickType click) { + public BQNPCClickEvent(@NotNull BqNpc npc, @NotNull Player p, @NotNull NpcClickType click) { super(p); this.npc = npc; this.click = click; @@ -31,7 +31,7 @@ public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } - public @NotNull BQNPC getNPC() { + public @NotNull BqNpc getNPC() { return npc; } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java index fc758747..1023fc49 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java @@ -6,7 +6,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.blocks.BQBlock; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; @@ -36,6 +36,6 @@ Gui createBlocksSelection(@NotNull Consumer<List<MutableCountableObject<BQBlock> @NotNull Collection<MutableCountableObject<BQBlock>> existingBlocks); @NotNull - Gui createNpcSelection(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> callback, boolean nullable); + Gui createNpcSelection(@NotNull Runnable cancel, @NotNull Consumer<BqNpc> callback, boolean nullable); } diff --git a/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java b/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java index eea4f35b..0950e5a1 100644 --- a/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java @@ -23,14 +23,16 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.internal.BQMobDeathEvent; +import fr.skytasul.quests.api.utils.AutoRegistered; /** - * This class implements {@link Listener} to permit the implementation to have at least one {@link EventHandler}. - * This event method will be used to fire the {@link #callEvent(Event, Object, Entity, Player)}. + * This class should implement {@link Listener} to have at least one {@link EventHandler}. This + * event method will be used to fire the {@link #callEvent(Event, Object, Entity, Player)}. * * @param <T> object which should represents a mob type from whatever plugin */ -public abstract interface MobFactory<T> extends Listener { +@AutoRegistered +public abstract interface MobFactory<T> { /** * @return internal ID of this Mob Factory diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java deleted file mode 100644 index 1378c692..00000000 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPCsManager.java +++ /dev/null @@ -1,70 +0,0 @@ -package fr.skytasul.quests.api.npcs; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.ClickType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; - -public abstract class BQNPCsManager implements Listener { - - protected final Map<Integer, BQNPC> npcs = new HashMap<>(); - - public abstract int getTimeToWaitForNPCs(); - - public abstract @NotNull Collection<@NotNull Integer> getIDs(); - - public abstract boolean isNPC(@NotNull Entity entity); - - public final @NotNull BQNPC createNPC(@NotNull Location location, @NotNull EntityType type, @NotNull String name, - @Nullable String skin) { - BQNPC npc = create(location, type, name); - try { - if (type == EntityType.PLAYER) npc.setSkin(skin); - }catch (Exception ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("Failed to set NPC skin", ex); - } - npcs.put(npc.getId(), npc); - return npc; - } - - public abstract boolean isValidEntityType(@NotNull EntityType type); - - protected abstract @NotNull BQNPC create(@NotNull Location location, @NotNull EntityType type, @NotNull String name); - - public final @Nullable BQNPC getById(int id) { - return npcs.computeIfAbsent(id, this::fetchNPC); - } - - protected abstract @Nullable BQNPC fetchNPC(int id); - - protected final void removeEvent(int id) { - BQNPC npc = npcs.get(id); - if (npc == null) return; - npc.delete("NPC #" + id + " removed"); - npcs.remove(id); - } - - protected final void clickEvent(@NotNull Cancellable event, int npcID, @NotNull Player p, @NotNull ClickType click) { - if (event != null && event.isCancelled()) return; - BQNPCClickEvent newEvent = new BQNPCClickEvent(getById(npcID), p, click); - Bukkit.getPluginManager().callEvent(newEvent); - if (event != null) event.setCancelled(newEvent.isCancelled()); - } - - public void unload() { - npcs.values().forEach(BQNPC::unload); - npcs.clear(); - } - -} diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java new file mode 100644 index 00000000..540037b3 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java @@ -0,0 +1,31 @@ +package fr.skytasul.quests.api.npcs; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface BqInternalNpc { + + public abstract int getId(); + + public abstract @NotNull String getName(); + + public abstract boolean isSpawned(); + + public abstract @NotNull Entity getEntity(); + + public abstract @NotNull Location getLocation(); + + public abstract void setSkin(@Nullable String skin); + + /** + * Sets the "paused" state of the NPC navigation + * + * @param paused should the navigation be paused + * @return <code>true</code> if the navigation was paused before this call, <code>false</code> + * otherwise + */ + public abstract boolean setNavigationPaused(boolean paused); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java new file mode 100644 index 00000000..0fd1d595 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java @@ -0,0 +1,44 @@ +package fr.skytasul.quests.api.npcs; + +import java.util.Collection; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.utils.AutoRegistered; + +@AutoRegistered +public interface BqInternalNpcFactory { + + int getTimeToWaitForNPCs(); + + boolean isNPC(@NotNull Entity entity); + + @NotNull + Collection<@NotNull Integer> getIDs(); + + @Nullable + BqInternalNpc fetchNPC(int id); + + @NotNull + BqInternalNpc create(@NotNull Location location, @NotNull EntityType type, @NotNull String name); + + boolean isValidEntityType(@NotNull EntityType type); + + default void npcClicked(@Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click) { + QuestsPlugin.getPlugin().getNpcManager().npcClicked(event, npcID, p, click); + } + + default void npcRemoved(int id) { + QuestsPlugin.getPlugin().getNpcManager().npcRemoved(id); + } + + default void npcsReloaded() { + QuestsPlugin.getPlugin().getNpcManager().reload(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java new file mode 100644 index 00000000..3d480d27 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java @@ -0,0 +1,30 @@ +package fr.skytasul.quests.api.npcs; + +import java.util.Set; +import java.util.function.Predicate; +import org.bukkit.entity.Player; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.types.Locatable; + +public interface BqNpc extends Locatable.Located.LocatedEntity { + + BqInternalNpc getNpc(); + + Set<Quest> getQuests(); + + boolean hasQuestStarted(Player p); + + Set<QuestPool> getPools(); + + void hideForPlayer(Player p, Object holder); + + void removeHiddenForPlayer(Player p, Object holder); + + boolean canGiveSomething(Player p); + + void addStartablePredicate(Predicate<Player> predicate, Object holder); + + void removeStartablePredicate(Object holder); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java new file mode 100644 index 00000000..016fb110 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java @@ -0,0 +1,29 @@ +package fr.skytasul.quests.api.npcs; + +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface BqNpcManager { + + boolean isEnabled(); + + void setInternalFactory(BqInternalNpcFactory internalFactory); + + @NotNull + BqNpc createNPC(@NotNull Location location, @NotNull EntityType type, @NotNull String name, + @Nullable String skin); + + @Nullable + BqNpc getById(int id); + + void npcRemoved(int id); + + void npcClicked(@Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click); + + void reload(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java index 25ef88a4..9b7e458e 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; import fr.skytasul.quests.utils.types.NumberedList; @@ -35,7 +35,7 @@ public void setMessages(@NotNull List<Message> messages) { this.messages = messages; } - public @NotNull String getNPCName(@Nullable BQNPC defaultNPC) { + public @NotNull String getNPCName(@Nullable BqNpc defaultNPC) { if (npcName != null) return npcName; if (defaultNPC == null) diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index 2f925c7a..d29a74f2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -14,7 +14,9 @@ import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.api.utils.AutoRegistered; +@AutoRegistered public abstract class QuestOption<T> implements Cloneable { private final @NotNull QuestOptionCreator<T, QuestOption<T>> creator; diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java index cd88f3f5..1620fa1b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionItem.java @@ -7,11 +7,11 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; +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.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.misc.ItemGUI; public abstract class QuestOptionItem extends QuestOption<ItemStack> { @@ -76,10 +76,10 @@ public void click(QuestCreationGuiClickEvent event) { setValue(null); event.getGui().updateOptionItem(this); }else { - new ItemGUI(is -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemSelection(is -> { setValue(is); - gui.inv.setItem(slot, getItemStack(null)); - gui.reopen(player); + event.getGui().updateOptionItem(this); + event.reopen(); }, event::reopen).open(event.getPlayer()); } } 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 82721a5d..8acb0b95 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 @@ -41,7 +41,7 @@ public interface QuestPool { void resetPlayerTimer(PlayerAccount acc); - boolean canGive(Player p, PlayerAccount acc); + boolean canGive(Player p); CompletableFuture<String> give(Player p); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 6a6c4b9f..1b851808 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -17,7 +17,9 @@ import fr.skytasul.quests.api.rewards.RewardList; import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.stages.options.StageOption; +import fr.skytasul.quests.api.utils.AutoRegistered; +@AutoRegistered public abstract class AbstractStage { protected final @NotNull StageController controller; 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 d9efb592..6bfceabd 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,7 +1,7 @@ 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.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; @@ -14,7 +14,7 @@ public interface Dialogable { DialogRunner getDialogRunner(); @Nullable - BQNPC getNPC(); + BqNpc getNPC(); default boolean hasDialog() { return getNPC() != null && getDialog() != null && !getDialog().getMessages().isEmpty(); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java b/api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java new file mode 100644 index 00000000..e2c3f01a --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java @@ -0,0 +1,18 @@ +package fr.skytasul.quests.api.utils; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import org.bukkit.event.Listener; + +/** + * Marks classes that will be automatically registered as event listener if they implement the + * {@link Listener} interface. + * + * @author SkytAsul + */ +@Retention(RUNTIME) +@Target(TYPE) +public @interface AutoRegistered { +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java index e75ce389..15062f24 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java @@ -11,8 +11,10 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; import net.md_5.bungee.api.ChatColor; public class MessageUtils { @@ -117,4 +119,13 @@ public static String format(@NotNull String msg, int i, @NotNull Supplier<Object return output.toString(); } + public static String formatDescription(DescriptionSource source, SplittableDescriptionConfiguration configuration, + String... elements) { + if (elements.length == 0) + return Lang.Unknown.toString(); + if (elements.length == 1 && configuration.isAloneSplitAmountShown(source)) + return MessageUtils.itemsToFormattedString(elements, configuration.getItemAmountColor()); + return String.join(configuration.getSplitPrefix(), elements); + } + } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java new file mode 100644 index 00000000..168f4e5c --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java @@ -0,0 +1,26 @@ +package fr.skytasul.quests.api.utils; + +import java.util.Set; +import fr.skytasul.quests.api.options.description.DescriptionSource; + +public interface SplittableDescriptionConfiguration { + + String getItemNameColor(); + + String getItemAmountColor(); + + String getSplitPrefix(); + + String getSplitAmountFormat(); + + boolean isAloneSplitAmountShown(); + + boolean isAloneSplitInlined(); + + Set<DescriptionSource> getSplitSources(); + + default boolean isAloneSplitAmountShown(DescriptionSource source) { + return getSplitSources().contains(source) && isAloneSplitAmountShown(); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 3c19fef1..d0430ef4 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -46,6 +46,7 @@ import fr.skytasul.quests.commands.CommandsManagerImplementation; import fr.skytasul.quests.editor.EditorManagerImplementation; import fr.skytasul.quests.gui.GuiManagerImplementation; +import fr.skytasul.quests.npcs.BqNpcManagerImplementation; import fr.skytasul.quests.options.OptionAutoQuest; import fr.skytasul.quests.players.AbstractPlayersManager; import fr.skytasul.quests.players.PlayersManagerDB; @@ -85,6 +86,7 @@ public class BeautyQuests extends JavaPlugin implements QuestsPlugin { /* --------- Datas --------- */ + private final @NotNull BqNpcManagerImplementation npcManager = new BqNpcManagerImplementation(); private @Nullable ScoreboardManager scoreboards; private @Nullable QuestsManagerImplementation quests; private @Nullable QuestPoolsManagerImplementation pools; @@ -160,7 +162,7 @@ public void onEnable(){ logger.severe("An error occurred while initializing compatibilities. Consider restarting.", ex); } - if (getAPI().getNPCsManager() == null) { + if (npcManager.getInternalFactory() == null) { throw new LoadingException("No NPC plugin installed - please install Citizens or znpcs"); } @@ -191,7 +193,7 @@ public void run() { logger.severe("An error occurred while loading plugin datas.", e); } } - }.runTaskLater(this, getAPI().getNPCsManager().getTimeToWaitForNPCs()); + }.runTaskLater(this, npcManager.getInternalFactory().getTimeToWaitForNPCs()); // Start of non-essential systems if (loggerHandler != null) loggerHandler.launchFlushTimer(); @@ -371,7 +373,7 @@ private void launchUpdateChecker(String pluginVersion) { private void loadConfigParameters(boolean init) throws LoadingException { try{ File configFile = new File(getDataFolder(), "config.yml"); - config = new QuestsConfigurationImplementation(this); + config = new QuestsConfigurationImplementation(getConfig()); if (config.update()) { config.getConfig().save(configFile); logger.info("Updated config."); @@ -543,7 +545,7 @@ public void saveAllConfig(boolean unload) throws Exception { } if (unload){ - getAPI().getNPCsManager().unload(); + npcManager.unload(); resetDatas(); } } @@ -775,6 +777,11 @@ public boolean hasSavingFailed() { return ensureLoaded(editorManager); } + @Override + public @NotNull BqNpcManagerImplementation getNpcManager() { + return npcManager; + } + @Override public @NotNull QuestsAPIImplementation getAPI() { return QuestsAPIImplementation.INSTANCE; diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java index 22af983f..33c86c42 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -8,8 +8,6 @@ import java.util.Set; import java.util.function.Consumer; import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.AbstractHolograms; @@ -21,7 +19,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.api.mobs.MobStacker; -import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.options.QuestOptionCreator; import fr.skytasul.quests.api.pools.QuestPoolsManager; @@ -32,6 +30,7 @@ import fr.skytasul.quests.api.rewards.RewardCreator; import fr.skytasul.quests.api.stages.StageTypeRegistry; import fr.skytasul.quests.blocks.BQBlocksManagerImplementation; +import fr.skytasul.quests.utils.QuestUtils; public class QuestsAPIImplementation implements QuestsAPI { @@ -45,7 +44,6 @@ public class QuestsAPIImplementation implements QuestsAPI { private final List<ItemComparison> itemComparisons = new LinkedList<>(); private final List<MobStacker> mobStackers = new ArrayList<>(); - private BQNPCsManager npcsManager = null; private AbstractHolograms<?> hologramsManager = null; private BossBarManager bossBarManager = null; private BQBlocksManagerImplementation blocksManager = new BQBlocksManagerImplementation(); @@ -67,7 +65,7 @@ private QuestsAPIImplementation() {} @Override public void registerMobFactory(@NotNull MobFactory<?> factory) { MobFactory.factories.add(factory); - Bukkit.getPluginManager().registerEvents(factory, BeautyQuests.getInstance()); + QuestUtils.autoRegister(factory); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Mob factory registered (id: " + factory.getID() + ")"); } @@ -121,19 +119,8 @@ public void registerMobStacker(@NotNull MobStacker stacker) { } @Override - public @NotNull BQNPCsManager getNPCsManager() { - return npcsManager; - } - - @Override - public void setNPCsManager(@NotNull BQNPCsManager newNpcsManager) { - if (npcsManager != null) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning(newNpcsManager.getClass().getSimpleName() + " will replace " - + npcsManager.getClass().getSimpleName() + " as the new NPCs manager."); - HandlerList.unregisterAll(npcsManager); - } - npcsManager = newNpcsManager; - Bukkit.getPluginManager().registerEvents(npcsManager, BeautyQuests.getInstance()); + public void setNpcFactory(@NotNull BqInternalNpcFactory factory) { + QuestsPlugin.getPlugin().getNpcManager().setInternalFactory(factory); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 7ef336b2..5392e019 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -75,12 +75,13 @@ public static QuestsConfigurationImplementation getConfiguration() { private StageDescriptionConfig stageDescription; private QuestDescriptionConfig questDescription; - QuestsConfigurationImplementation(BeautyQuests plugin) { - config = plugin.getConfig(); + QuestsConfigurationImplementation(FileConfiguration config) { + this.config = config; + quests = new QuestsConfig(); dialogs = new DialogsConfig(config.getConfigurationSection("dialogs")); menu = new QuestsMenuConfig(config.getConfigurationSection("questsMenu")); - stageDescription = new StageDescriptionConfig(); + stageDescription = new StageDescriptionConfig(config.getConfigurationSection("stageDescriptionItemsSplit")); questDescription = new QuestDescriptionConfig(config.getConfigurationSection("questDescription")); } @@ -88,6 +89,7 @@ boolean update() { boolean result = false; result |= dialogs.update(); result |= menu.update(); + result |= stageDescription.update(); return result; } @@ -125,9 +127,9 @@ void init() { dMinZoom = config.getInt("dynmap.minZoom"); if (MinecraftVersion.MAJOR >= 9) { - particleStart = loadParticles(config, "start", new ParticleEffect(Particle.REDSTONE, ParticleShape.POINT, Color.YELLOW)); - particleTalk = loadParticles(config, "talk", new ParticleEffect(Particle.VILLAGER_HAPPY, ParticleShape.BAR, null)); - particleNext = loadParticles(config, "next", new ParticleEffect(Particle.SMOKE_NORMAL, ParticleShape.SPOT, null)); + particleStart = loadParticles("start", new ParticleEffect(Particle.REDSTONE, ParticleShape.POINT, Color.YELLOW)); + particleTalk = loadParticles("talk", new ParticleEffect(Particle.VILLAGER_HAPPY, ParticleShape.BAR, null)); + particleNext = loadParticles("next", new ParticleEffect(Particle.SMOKE_NORMAL, ParticleShape.SPOT, null)); } holoLaunchItem = loadHologram("launchItem"); @@ -169,7 +171,7 @@ private void initializeTranslations() { } } - private ParticleEffect loadParticles(FileConfiguration config, String name, ParticleEffect defaultParticle) { + private ParticleEffect loadParticles(String name, ParticleEffect defaultParticle) { ParticleEffect particle = null; if (config.getBoolean(name + ".enabled")) { try{ @@ -658,15 +660,21 @@ public class StageDescriptionConfig implements QuestsConfiguration.StageDescript private boolean inlineAlone = true; private Set<DescriptionSource> descSources = EnumSet.noneOf(DescriptionSource.class); + private final ConfigurationSection config; + + public StageDescriptionConfig(ConfigurationSection config) { + this.config = config; + } + private void init() { itemNameColor = config.getString("itemNameColor"); itemAmountColor = config.getString("itemAmountColor"); - stageDescriptionFormat = config.getString("stageDescriptionFormat"); - descPrefix = "{nl}" + config.getString("stageDescriptionItemsSplit.prefix"); - descAmountFormat = config.getString("stageDescriptionItemsSplit.amountFormat"); - descXOne = config.getBoolean("stageDescriptionItemsSplit.showXOne"); - inlineAlone = config.getBoolean("stageDescriptionItemsSplit.inlineAlone"); - for (String s : config.getStringList("stageDescriptionItemsSplit.sources")) { + stageDescriptionFormat = config.getString("descriptionFormat"); + descPrefix = "{nl}" + config.getString("prefix"); + descAmountFormat = config.getString("amountFormat"); + descXOne = config.getBoolean("showXOne"); + inlineAlone = config.getBoolean("inlineAlone"); + for (String s : config.getStringList("sources")) { try { descSources.add(DescriptionSource.valueOf(s)); } catch (IllegalArgumentException ex) { @@ -676,6 +684,16 @@ private void init() { } } + private boolean update() { + boolean result = false; + if (config.getParent() != null) { + result |= migrateEntry(config, config.getParent(), "itemNameColor", "itemNameColor"); + result |= migrateEntry(config, config.getParent(), "itemAmountColor", "itemAmountColor"); + result |= migrateEntry(config, config.getParent(), "stageDescriptionFormat", "descriptionFormat"); + } + return result; + } + @Override public String getStageDescriptionFormat() { return stageDescriptionFormat; diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index dff711b7..57bff1f9 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -32,7 +32,7 @@ import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; @@ -54,7 +54,7 @@ public void onNPCClick(BQNPCClickEvent e) { return; Player p = e.getPlayer(); - BQNPC npc = e.getNPC(); + BqNpc npc = e.getNPC(); if (QuestsPlugin.getPlugin().getGuiManager().hasGuiOpened(p) || QuestsPlugin.getPlugin().getEditorManager().isInEditor(p)) @@ -89,7 +89,7 @@ public void onNPCClick(BQNPCClickEvent e) { Set<QuestPool> startablePools = npc.getPools().stream().filter(pool -> { try { - return pool.canGive(p, acc); + return pool.canGive(p); }catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("An exception occured when checking requirements on the pool " + pool.getId() + " for player " + p.getName(), ex); return false; @@ -114,7 +114,8 @@ public void onNPCClick(BQNPCClickEvent e) { }); }else if (!startablePools.isEmpty()) { QuestPool pool = startablePools.iterator().next(); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("NPC " + npc.getId() + ": " + startablePools.size() + " pools, result: " + pool.give(p)); + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug("NPC " + npc.getNpc().getId() + ": " + startablePools.size() + " pools, result: " + pool.give(p)); }else { if (!timer.isEmpty()) { timer.get(0).testTimer(acc, true); diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 6b2c29de..f18c2a88 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -21,7 +21,7 @@ import fr.skytasul.quests.api.editors.SelectNPC; import fr.skytasul.quests.api.gui.templates.ConfirmGUI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftNames; @@ -29,6 +29,7 @@ import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.gui.misc.ListBook; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; +import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.players.PlayersManagerDB; import fr.skytasul.quests.players.PlayersManagerYAML; @@ -284,8 +285,8 @@ public void setFirework(Player player, @Switch boolean remove) { @Subcommand ("testNPC") @CommandPermission (value = "beautyquests.command.create") @SecretCommand - public String testNPC(BukkitCommandActor actor, BQNPC npc) { - npc.toggleDebug(); + public String testNPC(BukkitCommandActor actor, BqNpc npc) { + ((BqNpcImplementation) npc).toggleDebug(); return npc.toString(); } 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 405e16ec..69244454 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -12,7 +12,7 @@ import fr.skytasul.quests.api.commands.CommandsManager; import fr.skytasul.quests.api.commands.OutsideEditor; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.MessageUtils; @@ -64,15 +64,15 @@ public CommandsManagerImplementation() { .map(pool -> Integer.toString(pool.getId())) .collect(Collectors.toList()))); - handler.registerValueResolver(BQNPC.class, context -> { + handler.registerValueResolver(BqNpc.class, context -> { int id = context.popInt(); - BQNPC npc = QuestsAPI.getAPI().getNPCsManager().getById(id); + BqNpc npc = QuestsPlugin.getPlugin().getNpcManager().getById(id); if (npc == null) throw new CommandErrorException(Lang.NPC_DOESNT_EXIST.format(id)); return npc; }); - handler.getAutoCompleter().registerParameterSuggestions(BQNPC.class, - SuggestionProvider.of(() -> QuestsAPI.getAPI().getNPCsManager().getIDs() + handler.getAutoCompleter().registerParameterSuggestions(BqNpc.class, + SuggestionProvider.of(() -> BeautyQuests.getInstance().getNpcManager().getInternalFactory().getIDs() .stream() .map(String::valueOf) .collect(Collectors.toList()))); diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index 35b40835..9a520cc2 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java @@ -40,9 +40,7 @@ public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPoolIm @Subcommand("start") @CommandPermission("beautyquests.command.pools.start") public void start(BukkitCommandActor actor, Player player, QuestPoolImplementation pool) { - PlayerAccount acc = PlayersManager.getPlayerAccount(player); - - if (!pool.canGive(player, acc)) { + if (!pool.canGive(player)) { Lang.POOL_START_ERROR.send(player, pool.getId(), player.getName()); return; } diff --git a/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java index 50eec768..8fbdde94 100644 --- a/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java @@ -53,6 +53,8 @@ public <T extends Editor> T start(@NotNull T editor) { .debug(player.getName() + " is entering editor " + editor.getClass().getName() + "."); editor.begin(); + QuestUtils.autoRegister(editor); + if (MinecraftVersion.MAJOR > 11) { player.sendTitle(Lang.ENTER_EDITOR_TITLE.toString(), Lang.ENTER_EDITOR_SUB.toString(), 5, 50, 5); } else { @@ -75,6 +77,8 @@ public void leave(@NotNull Player player) { if (bar != null) bar.removePlayer(player); editor.end(); + + QuestUtils.autoUnregister(editor); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java index 9b1e53db..110be026 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java @@ -8,7 +8,7 @@ import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.GuiFactory; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.gui.blocks.BlocksGUI; @@ -42,7 +42,7 @@ public class DefaultGuiFactory implements GuiFactory { } @Override - public @NotNull Gui createNpcSelection(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> callback, + public @NotNull Gui createNpcSelection(@NotNull Runnable cancel, @NotNull Consumer<BqNpc> callback, boolean nullable) { return NpcSelectGUI.select(cancel, callback, nullable); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java index aa03ad8a..98462d56 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java @@ -23,7 +23,8 @@ public static void openQuestBook(Player p){ QuestsAPI.getAPI().getQuestsManager().getQuests().stream().sorted().forEach(qu -> { StringBuilder stb = new StringBuilder(formatLine(Lang.BOOK_NAME.toString(), qu.getName()) + formatLine("ID", qu.getId() + "") - + ((qu.hasOption(OptionStarterNPC.class)) ? formatLine(Lang.BOOK_STARTER.toString(), qu.getOption(OptionStarterNPC.class).getValue().getName()) : "") + + ((qu.hasOption(OptionStarterNPC.class)) ? formatLine(Lang.BOOK_STARTER.toString(), + qu.getOption(OptionStarterNPC.class).getValue().getNpc().getName()) : "") //+ formatLine(Lang.BOOK_REWARDS.toString(), qu.getRewards().exp + " XP §3" + Lang.And.toString() + " §1" + qu.getRewards().itemsSize() + " " + Lang.Item.toString()) + formatLine(Lang.BOOK_SEVERAL.toString(), (qu.isRepeatable()) ? Lang.Yes.toString() : Lang.No.toString()) /*+ formatLine(Lang.BOOK_LVL.toString(), "" + qu.lvlRequired) diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index 89638e1e..a2512156 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -8,7 +8,8 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; import fr.skytasul.quests.api.gui.AbstractGui; @@ -17,7 +18,7 @@ import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; @@ -27,14 +28,14 @@ public class NpcCreateGUI extends AbstractGui { private static final ItemStack move = ItemUtils.item(XMaterial.MINECART, Lang.move.toString(), Lang.moveLore.toString()); public static ItemStack validMove = ItemUtils.item(XMaterial.EMERALD, Lang.moveItem.toString()); - private Consumer<BQNPC> end; + private Consumer<BqNpc> end; private Runnable cancel; private EntityType en; private String name; private String skin; - public NpcCreateGUI(Consumer<BQNPC> end, Runnable cancel) { + public NpcCreateGUI(Consumer<BqNpc> end, Runnable cancel) { this.end = end; this.cancel = cancel; } @@ -102,7 +103,9 @@ public void onClick(GuiClickEvent event) { new EntityTypeGUI(en -> { setType(en); event.reopen(); - }, x -> x != null && QuestsAPI.getAPI().getNPCsManager().isValidEntityType(x)).open(event.getPlayer()); + }, x -> x != null + && BeautyQuests.getInstance().getNpcManager().getInternalFactory().isValidEntityType(x)) + .open(event.getPlayer()); break; case 7: @@ -113,7 +116,7 @@ public void onClick(GuiClickEvent event) { case 8: event.close(); try { - end.accept(QuestsAPI.getAPI().getNPCsManager().createNPC(event.getPlayer().getLocation(), en, name, skin)); + end.accept(QuestsPlugin.getPlugin().getNpcManager().createNPC(event.getPlayer().getLocation(), en, name, skin)); }catch (Exception ex) { ex.printStackTrace(); Lang.ERROR_OCCURED.send(event.getPlayer(), "npc creation " + ex.getMessage()); diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index 5b7139ee..8c1cc52c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -13,7 +13,7 @@ import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.gui.layout.LayoutedGUI.Builder; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; public final class NpcSelectGUI { @@ -22,7 +22,7 @@ private NpcSelectGUI() {} public static ItemStack createNPC = ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.createNPC.toString()); public static ItemStack selectNPC = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); - public static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BQNPC> end, + public static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BqNpc> end, boolean nullable) { Builder builder = LayoutedGUI.newBuilder().addButton(1, LayoutedButton.create(createNPC, event -> { new NpcCreateGUI(end, event::reopen).open(event.getPlayer()); diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index 774aaa4c..86823e8d 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -123,7 +123,7 @@ public void onClick(GuiClickEvent event) { switch (event.getSlot()) { case SLOT_NPC: QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, npc -> { - npcID = npc.getId(); + npcID = npc.getNpc().getId(); ItemUtils.lore(event.getClicked(), getNPCLore()); handleDoneButton(getInventory()); reopen(event.getPlayer()); 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 a6f2575d..e2310d70 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 @@ -177,7 +177,8 @@ public Page getCurrentPage() { public ItemStack setMeta(ItemStack item) { ItemMeta meta = item.getItemMeta(); meta.setLore(getCurrentPage().lines); - meta.setDisplayName("§8" + objects.indexOf(this) + " (" + dialogable.getNPC().getName() + "§8) - " + getCurrentPage().header); + meta.setDisplayName("§8" + objects.indexOf(this) + " (" + dialogable.getNPC().getNpc().getName() + "§8) - " + + getCurrentPage().header); meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); item.setItemMeta(meta); return item; diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java similarity index 76% rename from api/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java rename to core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java index 44f8d67b..67ec653d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BQNPC.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java @@ -1,8 +1,8 @@ -package fr.skytasul.quests.api.npcs; +package fr.skytasul.quests.npcs; import java.util.*; import java.util.Map.Entry; -import java.util.function.BiPredicate; +import java.util.function.Predicate; import org.apache.commons.lang.StringUtils; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -12,13 +12,15 @@ 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.QuestsConfiguration; +import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.AbstractHolograms; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.pools.QuestPool; @@ -29,14 +31,15 @@ import fr.skytasul.quests.options.OptionHologramLaunchNo; import fr.skytasul.quests.options.OptionHologramText; import fr.skytasul.quests.options.OptionStarterNPC; +import fr.skytasul.quests.structure.pools.QuestPoolImplementation; -public abstract class BQNPC implements Located.LocatedEntity { +public class BqNpcImplementation implements Located.LocatedEntity, BqNpc { private Map<Quest, List<Player>> quests = new TreeMap<>(); private Set<QuestPool> pools = new TreeSet<>(); private List<Entry<Player, Object>> hiddenTickets = new ArrayList<>(); - private Map<Object, BiPredicate<Player, PlayerAccount>> startable = new HashMap<>(); + private Map<Object, Predicate<Player>> startable = new HashMap<>(); private BukkitTask launcheableTask; @@ -44,10 +47,21 @@ public abstract class BQNPC implements Located.LocatedEntity { private boolean debug = false; private BukkitTask hologramsTask; private boolean hologramsRemoved = true; - private Hologram hologramText = new Hologram(false, QuestsAPI.hasHologramsManager() && !QuestsConfiguration.isTextHologramDisabled(), Lang.HologramText.toString()); - private Hologram hologramLaunch = new Hologram(false, QuestsAPI.hasHologramsManager() && QuestsAPI.getHologramsManager().supportItems(), QuestsConfiguration.getHoloLaunchItem()); - private Hologram hologramLaunchNo = new Hologram(false, QuestsAPI.hasHologramsManager() && QuestsAPI.getHologramsManager().supportItems() && QuestsAPI.getHologramsManager().supportPerPlayerVisibility(), QuestsConfiguration.getHoloLaunchNoItem()); - private Hologram hologramPool = new Hologram(false, QuestsAPI.hasHologramsManager() && QuestsAPI.getHologramsManager().supportPerPlayerVisibility(), Lang.PoolHologramText.toString()) { + private Hologram hologramText = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() + && !QuestsConfigurationImplementation.getConfiguration().isTextHologramDisabled(), + Lang.HologramText.toString()); + private Hologram hologramLaunch = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems(), + QuestsConfigurationImplementation.getConfiguration().getHoloLaunchItem()); + private Hologram hologramLaunchNo = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() + && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility(), + QuestsConfigurationImplementation.getConfiguration().getHoloLaunchNoItem()); + private Hologram hologramPool = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() + && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility(), + Lang.PoolHologramText.toString()) { @Override public double getYAdd() { return hologramText.canAppear && hologramText.visible ? 0.55 : 0; @@ -55,46 +69,47 @@ public double getYAdd() { }; private final boolean holograms; - protected BQNPC() { + private BqInternalNpc npc; + + public BqNpcImplementation(BqInternalNpc npc) { + this.npc = npc; + holograms = hologramText.enabled || hologramLaunch.enabled || hologramLaunchNo.enabled || hologramPool.enabled; launcheableTask = startLauncheableTasks(); } - public abstract int getId(); - - public abstract @NotNull String getName(); - - public abstract boolean isSpawned(); - @Override - public abstract @NotNull Entity getEntity(); - + public BqInternalNpc getNpc() { + return npc; + } + + public void setNpc(BqInternalNpc npc) { + this.npc = npc; + } + @Override - public abstract @NotNull Location getLocation(); - - public abstract void setSkin(@Nullable String skin); - - /** - * Sets the "paused" state of the NPC navigation - * - * @param paused should the navigation be paused - * @return <code>true</code> if the navigation was - * paused before this call, <code>false</code> otherwise - */ - public abstract boolean setNavigationPaused(boolean paused); - + public @NotNull Entity getEntity() { + return npc.getEntity(); + } + + @Override + public @NotNull Location getLocation() { + return npc.getLocation(); + } + private BukkitTask startLauncheableTasks() { return new BukkitRunnable() { private int timer = 0; @Override public void run() { - if (!isSpawned()) return; + if (!npc.isSpawned()) + return; if (!(getEntity() instanceof LivingEntity)) return; LivingEntity en = (LivingEntity) getEntity(); if (timer-- == 0) { - timer = QuestsConfiguration.getRequirementUpdateTime(); + timer = QuestsConfiguration.getConfig().getQuestsConfig().requirementUpdateTime(); return; } @@ -105,25 +120,28 @@ public void run() { for (Player p : lc.getWorld().getPlayers()) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); if (acc == null) continue; - if (lc.distanceSquared(p.getLocation()) > QuestsConfiguration.getStartParticleDistanceSquared()) continue; + if (lc.distanceSquared(p.getLocation()) > Math + .pow(QuestsConfiguration.getConfig().getQuestsConfig().startParticleDistance(), 2)) + continue; playersInRadius.add(p); for (Entry<Quest, List<Player>> quest : quests.entrySet()) { - if (quest.getKey().isLauncheable(p, acc, false)) { + if (quest.getKey().canStart(p, false)) { quest.getValue().add(p); break; } } } - if (QuestsConfiguration.showStartParticles()) { - quests.forEach((quest, players) -> QuestsConfiguration.getParticleStart().send(en, players)); + if (QuestsConfigurationImplementation.getConfiguration().showStartParticles()) { + quests.forEach((quest, players) -> QuestsConfigurationImplementation.getConfiguration() + .getParticleStart().send(en, players)); } if (hologramPool.canAppear) { for (Player p : playersInRadius) { boolean visible = false; for (QuestPool pool : pools) { - if (pool.canGive(p, PlayersManager.getPlayerAccount(p))) { + if (pool.canGive(p)) { visible = true; break; } @@ -175,7 +193,7 @@ private BukkitTask startHologramsTask() { @Override public void run() { LivingEntity en = null; // check if NPC is spawned and living - if (isSpawned() && getEntity() instanceof LivingEntity) + if (npc.isSpawned() && getEntity() instanceof LivingEntity) en = (LivingEntity) getEntity(); if (en == null) { if (!hologramsRemoved) removeHolograms(false); // if the NPC is not living and holograms have not been already removed before @@ -191,6 +209,7 @@ public void run() { }.runTaskTimer(BeautyQuests.getInstance(), 20L, 1L); } + @Override public Set<Quest> getQuests() { return quests.keySet(); } @@ -214,7 +233,7 @@ public void addQuest(Quest quest) { if (hologramLaunch.enabled && quest.hasOption(OptionHologramLaunch.class)) hologramLaunch.setItem(quest.getOption(OptionHologramLaunch.class).getValue()); if (hologramLaunchNo.enabled && quest.hasOption(OptionHologramLaunchNo.class)) hologramLaunchNo.setItem(quest.getOption(OptionHologramLaunchNo.class).getValue()); hologramText.visible = true; - addStartablePredicate((p, acc) -> quest.isLauncheable(p, acc, false), quest); + addStartablePredicate(p -> quest.canStart(p, false), quest); updatedObjects(); } @@ -229,11 +248,13 @@ public boolean removeQuest(Quest quest) { return b; } + @Override public boolean hasQuestStarted(Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); return quests.keySet().stream().anyMatch(quest -> quest.hasStarted(acc)); } + @Override public Set<QuestPool> getPools() { return pools; } @@ -253,18 +274,22 @@ public boolean removePool(QuestPool pool) { return b; } - public void addStartablePredicate(BiPredicate<Player, PlayerAccount> predicate, Object holder) { + @Override + public void addStartablePredicate(Predicate<Player> predicate, Object holder) { startable.put(holder, predicate); } + @Override public void removeStartablePredicate(Object holder) { startable.remove(holder); } + @Override public void hideForPlayer(Player p, Object holder) { hiddenTickets.add(new AbstractMap.SimpleEntry<>(p, holder)); } + @Override public void removeHiddenForPlayer(Player p, Object holder) { for (Iterator<Entry<Player, Object>> iterator = hiddenTickets.iterator(); iterator.hasNext();) { Entry<Player, Object> entry = iterator.next(); @@ -275,9 +300,9 @@ public void removeHiddenForPlayer(Player p, Object holder) { } } + @Override public boolean canGiveSomething(Player p) { - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - return startable.values().stream().anyMatch(predicate -> predicate.test(p, acc)); + return startable.values().stream().anyMatch(predicate -> predicate.test(p)); } private void removeHolograms(boolean cancelRefresh) { @@ -313,15 +338,16 @@ public void unload() { } public void delete(String cause) { - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + getId()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + npc.getId()); for (Quest qu : quests.keySet()) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Starter NPC #" + getId() + " has been removed from quest " + qu.getId() + ". Reason: " + cause); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Starter NPC #" + npc.getId() + " has been removed from quest " + qu.getId() + ". Reason: " + cause); qu.removeOption(OptionStarterNPC.class); } quests = null; for (QuestPool pool : pools) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("NPC #" + getId() + " has been removed from pool " + pool.getID() + ". Reason: " + cause); - pool.unloadStarter(); + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("NPC #" + npc.getId() + " has been removed from pool " + pool.getId() + ". Reason: " + cause); + ((QuestPoolImplementation) pool).unloadStarter(); } unload(); } @@ -334,7 +360,7 @@ public void toggleDebug() { @Override public String toString() { - String npcInfo = "NPC #" + getId() + ", " + quests.size() + " quests, " + pools.size() + " pools"; + String npcInfo = "NPC #" + npc.getId() + ", " + quests.size() + " quests, " + pools.size() + " pools"; String hologramsInfo; if (!holograms) { hologramsInfo = "no holograms"; @@ -404,14 +430,15 @@ public void setItem(ItemStack item) { if (Objects.equals(item, this.item)) return; this.item = item; canAppear = enabled && item != null; - if (canAppear && QuestsConfiguration.isCustomHologramNameShown() && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) + if (canAppear && QuestsConfigurationImplementation.getConfiguration().isCustomHologramNameShown() + && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) this.text = item.getItemMeta().getDisplayName(); delete(); // delete to regenerate with new item } public void create(Location lc) { if (hologram != null) return; - hologram = QuestsAPI.getHologramsManager().createHologram(lc, visible); + hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(lc, visible); if (text != null) hologram.appendTextLine(text); if (item != null) hologram.appendItem(item); } diff --git a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java new file mode 100644 index 00000000..49613715 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -0,0 +1,108 @@ +package fr.skytasul.quests.npcs; + +import java.util.HashMap; +import java.util.Map; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; +import fr.skytasul.quests.api.npcs.BqNpc; +import fr.skytasul.quests.api.npcs.BqNpcManager; +import fr.skytasul.quests.api.npcs.NpcClickType; +import fr.skytasul.quests.utils.QuestUtils; + +public class BqNpcManagerImplementation implements BqNpcManager { + + private final Map<Integer, BqNpcImplementation> npcs = new HashMap<>(); + private @Nullable BqInternalNpcFactory internalFactory = null; + + @Override + public boolean isEnabled() { + return internalFactory != null; + } + + public @Nullable BqInternalNpcFactory getInternalFactory() { + return internalFactory; + } + + @Override + public void setInternalFactory(BqInternalNpcFactory internalFactory) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .info(internalFactory.getClass().getSimpleName() + " will replace " + + (this.internalFactory == null ? "none" : this.internalFactory.getClass().getSimpleName()) + + " as the new NPCs manager."); + + this.internalFactory = internalFactory; + + QuestUtils.autoRegister(internalFactory); + } + + @Override + public @NotNull BqNpc createNPC(@NotNull Location location, @NotNull EntityType type, @NotNull String name, + @Nullable String skin) { + BqInternalNpc internal = internalFactory.create(location, type, name); + try { + if (type == EntityType.PLAYER) + internal.setSkin(skin); + }catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe("Failed to set NPC skin", ex); + } + + BqNpcImplementation npc = new BqNpcImplementation(internal); + npcs.put(internal.getId(), npc); + return npc; + } + + @Override + public @Nullable BqNpcImplementation getById(int id) { + return npcs.computeIfAbsent(id, this::registerNPC); + } + + private BqNpcImplementation registerNPC(int id) { + return new BqNpcImplementation(internalFactory.fetchNPC(id)); + } + + @Override + public void npcRemoved(int id) { + BqNpcImplementation npc = npcs.get(id); + if (npc == null) return; + npc.delete("NPC #" + id + " removed"); + npcs.remove(id); + } + + @Override + public void npcClicked(@Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click) { + if (event != null && event.isCancelled()) + return; + BQNPCClickEvent newEvent = new BQNPCClickEvent(getById(npcID), p, click); + Bukkit.getPluginManager().callEvent(newEvent); + if (event != null) + event.setCancelled(newEvent.isCancelled()); + } + + @Override + public void reload() { + npcs.forEach((id, npc) -> { + BqInternalNpc newInternal = internalFactory.fetchNPC(id); + if (newInternal == null) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Unable to find NPC with ID " + id + " after a NPCs manager reload."); + } else { + npc.setNpc(newInternal); + } + }); + } + + public void unload() { + npcs.values().forEach(BqNpcImplementation::unload); + npcs.clear(); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java index 463fb063..11c5f57c 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java @@ -7,7 +7,7 @@ import fr.skytasul.quests.api.editors.DialogEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.options.OptionSet; @@ -73,7 +73,7 @@ public Dialog getDialog() { } @Override - public BQNPC getNPC() { + public BqNpc getNPC() { return getAttachedQuest().getOptionValueOrDef(OptionStarterNPC.class); } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 9ceff1fc..731b8110 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -9,12 +9,12 @@ 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.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; -public class OptionStarterNPC extends QuestOption<BQNPC> { +public class OptionStarterNPC extends QuestOption<BqNpc> { public OptionStarterNPC() { super(OptionQuestPool.class); @@ -22,16 +22,16 @@ public OptionStarterNPC() { @Override public Object save() { - return getValue().getId(); + return getValue().getNpc().getId(); } @Override public void load(ConfigurationSection config, String key) { - setValue(QuestsAPI.getAPI().getNPCsManager().getById(config.getInt(key))); + setValue(QuestsPlugin.getPlugin().getNpcManager().getById(config.getInt(key))); } @Override - public BQNPC cloneValue(BQNPC value) { + public BqNpc cloneValue(BqNpc value) { return value; } @@ -40,7 +40,8 @@ private List<String> getLore(OptionSet options) { lore.add(formatDescription(Lang.questStarterSelectLore.toString())); lore.add(null); if (options != null && options.hasOption(OptionQuestPool.class) && options.getOption(OptionQuestPool.class).hasCustomValue()) lore.add(Lang.questStarterSelectPool.toString()); - lore.add(getValue() == null ? Lang.NotSet.toString() : "§7" + getValue().getName() + " §8(" + getValue().getId() + ")"); + lore.add(getValue() == null ? Lang.NotSet.toString() + : "§7" + getValue().getNpc().getName() + " §8(" + getValue().getNpc().getId() + ")"); return lore; } 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 7451e4f6..8256302d 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -22,7 +22,6 @@ import com.google.gson.JsonObject; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; -import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.data.SavableData; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; @@ -226,7 +225,8 @@ public synchronized void unloadPlayer(@NotNull Player p) { @Override public @UnknownNullability PlayerAccountImplementation getAccount(@NotNull Player p) { - if (QuestsAPI.getAPI().getNPCsManager().isNPC(p)) return null; + if (BeautyQuests.getInstance().getNpcManager().getInternalFactory().isNPC(p)) + return null; if (!p.isOnline()) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Trying to fetch the account of an offline player (" + p.getName() + ")"); QuestsPlugin.getPlugin().getLoggerExpanded().debug("(via " + DebugUtils.stackTraces(2, 5) + ")"); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 9b63a632..88f026ad 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -22,10 +22,10 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.SplittableDescriptionConfiguration; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.items.ItemComparisonGUI; import fr.skytasul.quests.gui.items.ItemsGUI; -import fr.skytasul.quests.utils.QuestUtils; public class StageBringBack extends StageNPC{ @@ -49,23 +49,19 @@ public StageBringBack(StageController controller, ItemStack[] items, String cust } String[] array = new String[items.length]; // create messages on beginning + SplittableDescriptionConfiguration splitConfig = QuestsConfiguration.getConfig().getStageDescriptionConfig(); for (int i = 0; i < array.length; i++){ - array[i] = QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemNameColor() - + Utils.getStringFromItemStack(items[i], - QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), - QuestsConfiguration.getConfig().getStageDescriptionConfig() - .isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)); + array[i] = splitConfig.getItemNameColor() + Utils.getStringFromItemStack(items[i], + splitConfig.getItemAmountColor(), splitConfig.isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)); } - splitted = QuestUtils.descriptionLines(DescriptionSource.FORCESPLIT, array); - if (QuestsConfiguration.getConfig().getStageDescriptionConfig() - .isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)) { - for (int i = 0; i < array.length; i++){ - array[i] = QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemNameColor() + Utils - .getStringFromItemStack(items[i], - QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), false); + splitted = MessageUtils.formatDescription(DescriptionSource.FORCESPLIT, splitConfig, array); + if (splitConfig.isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)) { + for (int i = 0; i < array.length; i++) { + array[i] = splitConfig.getItemNameColor() + + Utils.getStringFromItemStack(items[i], splitConfig.getItemAmountColor(), false); } } - line = QuestUtils.descriptionLines(DescriptionSource.FORCELINE, array); + line = MessageUtils.formatDescription(DescriptionSource.FORCELINE, splitConfig, array); } public boolean checkItems(Player p, boolean msg){ @@ -129,7 +125,7 @@ public void started(PlayerAccount acc) { protected void initDialogRunner() { super.initDialogRunner(); - getNPC().addStartablePredicate((p, acc) -> { + getNPC().addStartablePredicate(p -> { return canUpdate(p, false) && checkItems(p, false); }, this); 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 77d66246..4ed17f3f 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -24,7 +24,7 @@ import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.options.QuestOption; @@ -47,7 +47,7 @@ @LocatableType (types = LocatedType.ENTITY) public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable { - private BQNPC npc; + private BqNpc npc; private int npcID; protected Dialog dialog = null; protected DialogRunnerImplementation dialogRunner = null; @@ -68,7 +68,7 @@ private void launchRefreshTask(){ List<Player> tmp = new ArrayList<>(); @Override public void run() { - Entity en = npc.getEntity(); + Entity en = npc.getNpc().getEntity(); if (en == null) return; if (!en.getType().isAlive()) return; Location lc = en.getLocation(); @@ -98,7 +98,7 @@ public void run() { private void createHoloLaunch(){ ItemStack item = QuestsConfigurationImplementation.getConfiguration().getHoloTalkItem(); - hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(npc.getLocation(), false); + hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(npc.getNpc().getLocation(), false); if (QuestsConfigurationImplementation.getConfiguration().isCustomHologramNameShown() && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) hologram.appendTextLine(item.getItemMeta().getDisplayName()); @@ -112,7 +112,7 @@ private void removeHoloLaunch(){ } @Override - public BQNPC getNPC() { + public BqNpc getNPC() { return npc; } @@ -122,7 +122,8 @@ public int getNPCID() { public void setNPC(int npcID) { this.npcID = npcID; - if (npcID >= 0) this.npc = QuestsAPI.getAPI().getNPCsManager().getById(npcID); + if (npcID >= 0) + this.npc = QuestsPlugin.getPlugin().getNpcManager().getById(npcID); if (npc == null) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("The NPC " + npcID + " does not exist for " + toString()); }else { @@ -198,7 +199,7 @@ protected String npcName(){ return "§c§lunknown NPC " + npcID; if (dialog != null && dialog.getNpcName() != null) return dialog.getNpcName(); - return npc.getName(); + return npc.getNpc().getName(); } @Override @@ -316,7 +317,7 @@ public void setupLine(@NotNull StageGuiLine line) { line.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString()), event -> { QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, newNPC -> { - setNPCId(newNPC.getId()); + setNPCId(newNPC.getNpc().getId()); event.reopen(); }, false).open(event.getPlayer()); }); @@ -354,7 +355,7 @@ public void setHidden(boolean hidden) { public void start(Player p) { super.start(p); QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(context::removeAndReopenGui, newNPC -> { - setNPCId(newNPC.getId()); + setNPCId(newNPC.getNpc().getId()); context.reopenGui(); }, false).open(p); } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index f84b2fb2..a065eaec 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -47,6 +47,7 @@ import fr.skytasul.quests.api.utils.PlayerListCategory; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.options.*; import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.rewards.MessageReward; @@ -504,7 +505,7 @@ public void delete(boolean silently, boolean keepDatas) { BeautyQuests.getInstance().getQuestsManager().removeQuest(this); unload(); if (hasOption(OptionStarterNPC.class)) - getOptionValueOrDef(OptionStarterNPC.class).removeQuest(this); + ((BqNpcImplementation) getOptionValueOrDef(OptionStarterNPC.class)).removeQuest(this); if (!keepDatas) { BeautyQuests.getInstance().getPlayersManager().removeQuestDatas(this).whenComplete( diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java index 6028d558..336c7f49 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java @@ -17,13 +17,13 @@ import org.jetbrains.annotations.Unmodifiable; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.npcs.BQNPC; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayerQuestDatas; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.quests.QuestsManager; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.options.OptionStartable; import fr.skytasul.quests.options.OptionStarterNPC; @@ -131,7 +131,7 @@ public void addQuest(@NotNull Quest quest) { lastID.set(Math.max(lastID.get(), quest.getId())); quests.add(qu); if (quest.hasOption(OptionStarterNPC.class)) { - BQNPC npc = quest.getOptionValueOrDef(OptionStarterNPC.class); + BqNpcImplementation npc = (BqNpcImplementation) quest.getOptionValueOrDef(OptionStarterNPC.class); if (npc != null) npc.addQuest(quest); } qu.load(); diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index b971517b..ad9614b3 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -5,11 +5,9 @@ import java.util.Objects; import java.util.function.Consumer; import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -147,15 +145,13 @@ public void leaves(@NotNull Player player) { } public void load() { - if (stage instanceof Listener) - Bukkit.getPluginManager().registerEvents((Listener) stage, QuestsPlugin.getPlugin()); + QuestUtils.autoRegister(stage); propagateStageHandlers(handler -> handler.stageLoad(this)); stage.load(); } public void unload() { - if (stage instanceof Listener) - HandlerList.unregisterAll((Listener) stage); + QuestUtils.autoUnregister(stage); propagateStageHandlers(handler -> handler.stageUnload(this)); stage.unload(); } 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 a8c285be..ed83ed28 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 @@ -11,11 +11,10 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.BeautyQuests; 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.npcs.BQNPC; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayerPoolDatas; import fr.skytasul.quests.api.players.PlayersManager; @@ -24,6 +23,7 @@ import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.players.PlayerPoolDatasImplementation; import fr.skytasul.quests.utils.QuestUtils; @@ -40,7 +40,7 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati private final boolean avoidDuplicates; private final RequirementList requirements; - BQNPC npc; + BqNpcImplementation npc; List<Quest> quests = new ArrayList<>(); QuestPoolImplementation(int id, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements) { @@ -55,7 +55,7 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati this.requirements = requirements; if (npcID >= 0) { - npc = QuestsAPI.getAPI().getNPCsManager().getById(npcID); + npc = BeautyQuests.getInstance().getNpcManager().getById(npcID); if (npc != null) { npc.addPool(this); return; @@ -132,7 +132,7 @@ public int compareTo(QuestPoolImplementation o) { @Override public ItemStack getItemStack(String action) { return ItemUtils.item(XMaterial.CHEST, Lang.poolItemName.format(id), - Lang.poolItemNPC.format(npcID + " (" + (npc == null ? "unknown" : npc.getName()) + Lang.poolItemNPC.format(npcID + " (" + (npc == null ? "unknown" : npc.getNpc().getName()) + ")"), Lang.poolItemMaxQuests.format(maxQuests), Lang.poolItemQuestsPerLaunch.format(questsPerLaunch), @@ -165,7 +165,8 @@ public void questCompleted(PlayerAccount acc, Quest quest) { } @Override - public boolean canGive(Player p, PlayerAccount acc) { + public boolean canGive(Player p) { + PlayerAccount acc = PlayersManager.getPlayerAccount(p); PlayerPoolDatas datas = acc.getPoolDatas(this); if (datas.getLastGive() + timeDiff > System.currentTimeMillis()) return false; 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 1ab2da28..673c592a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -7,15 +7,15 @@ import org.bukkit.Sound; import org.bukkit.entity.Firework; import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.metadata.FixedMetadataValue; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.utils.AutoRegistered; import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.api.utils.Utils; public class QuestUtils { @@ -66,18 +66,8 @@ public static void playPluginSound(Location lc, String sound, float volume) { } } - public static String descriptionLines(DescriptionSource source, String... elements) { - if (elements.length == 0) - return Lang.Unknown.toString(); - if (QuestsConfigurationImplementation.splitDescription(source) && (!QuestsConfigurationImplementation.inlineAlone() || elements.length > 1)) { - return QuestsConfigurationImplementation.getDescriptionItemPrefix() - + Utils.buildFromArray(elements, 0, QuestsConfigurationImplementation.getDescriptionItemPrefix()); - } - return MessageUtils.itemsToFormattedString(elements, QuestsConfigurationImplementation.getItemAmountColor()); - } - public static void spawnFirework(Location lc, FireworkMeta meta) { - if (!QuestsConfigurationImplementation.doFireworks() || meta == null) + if (!QuestsConfiguration.getConfig().getQuestsConfig().fireworks() || meta == null) return; runOrSync(() -> { Consumer<Firework> fwConsumer = fw -> { @@ -94,4 +84,24 @@ public static void spawnFirework(Location lc, FireworkMeta meta) { }); } + public static void autoRegister(Object object) { + if (!object.getClass().isAnnotationPresent(AutoRegistered.class)) + throw new IllegalArgumentException("The class " + object.getClass().getName() + + " does not have the @AutoRegistered annotation and thus cannot be automatically registed as evenet listener."); + + if (object instanceof Listener) { + Bukkit.getPluginManager().registerEvents((Listener) object, BeautyQuests.getInstance()); + } + } + + public static void autoUnregister(Object object) { + if (!object.getClass().isAnnotationPresent(AutoRegistered.class)) + throw new IllegalArgumentException("The class " + object.getClass().getName() + + " does not have the @AutoRegistered annotation and thus cannot be automatically registed as evenet listener."); + + if (object instanceof Listener) { + HandlerList.unregisterAll((Listener) object); + } + } + } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java index 80067af5..94eb28b6 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java @@ -44,7 +44,8 @@ public class DependenciesManager implements Listener { - public static final BQDependency znpcs = new BQDependency("ServersNPC", () -> QuestsAPI.getAPI().setNPCsManager(new BQServerNPCs()), null, plugin -> { + public static final BQDependency znpcs = + new BQDependency("ServersNPC", () -> QuestsAPI.getAPI().setNpcFactory(new BQServerNPCs()), null, plugin -> { if (plugin.getClass().getName().equals("io.github.znetworkw.znpcservers.ServersNPC")) // NOSONAR return true; @@ -53,7 +54,7 @@ public class DependenciesManager implements Listener { }); public static final BQDependency citizens = new BQDependency("Citizens", () -> { - QuestsAPI.getAPI().setNPCsManager(new BQCitizens()); + QuestsAPI.getAPI().setNpcFactory(new BQCitizens()); QuestsAPI.getAPI().registerMobFactory(new CitizensFactory()); }); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java index b44b873f..619ddf7f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java @@ -5,6 +5,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; @@ -13,7 +14,7 @@ import fr.skytasul.quests.api.mobs.MobFactory; import gcspawners.AdvancedEntityDeathEvent; -public class BQAdvancedSpawners implements MobFactory<String> { +public class BQAdvancedSpawners implements MobFactory<String>, Listener { @Override public String getID() { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java index 40832fa5..660da625 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java @@ -9,6 +9,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.mineacademy.boss.api.BossAPI; @@ -22,7 +23,7 @@ import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.api.utils.Utils; -public class BQBoss implements MobFactory<Boss> { +public class BQBoss implements MobFactory<Boss>, Listener { @Override public String getID() { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java index 3aa42a4e..1cdb5a7d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java @@ -8,6 +8,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; @@ -18,7 +19,7 @@ import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -public class BukkitEntityFactory implements MobFactory<EntityType> { +public class BukkitEntityFactory implements MobFactory<EntityType>, Listener { @Override public String getID() { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java index e866a0e5..97e6affe 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java @@ -9,6 +9,7 @@ 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 fr.skytasul.quests.api.editors.CancellableEditor; import fr.skytasul.quests.api.localization.Lang; @@ -20,7 +21,7 @@ import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.trait.MobType; -public class CitizensFactory implements MobFactory<NPC> { +public class CitizensFactory implements MobFactory<NPC>, Listener { @Override public String getID() { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java index 7b29e8d9..0df91091 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java @@ -8,6 +8,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; @@ -24,7 +25,7 @@ import io.lumine.xikage.mythicmobs.mobs.MythicMob; import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderString; -public class MythicMobs implements LeveledMobFactory<MythicMob> { +public class MythicMobs implements LeveledMobFactory<MythicMob>, Listener { @Override public String getID() { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java index 094318ff..924d2614 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java @@ -9,6 +9,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; @@ -26,7 +27,7 @@ import io.lumine.mythic.bukkit.MythicBukkit; import io.lumine.mythic.bukkit.events.MythicMobDeathEvent; -public class MythicMobs5 implements LeveledMobFactory<MythicMob> { +public class MythicMobs5 implements LeveledMobFactory<MythicMob>, Listener { @Override public String getID() { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java index 8ff45a01..4fbb57b7 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java @@ -11,8 +11,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; import fr.skytasul.quests.api.npcs.NpcClickType; import net.citizensnpcs.Settings; import net.citizensnpcs.api.CitizensAPI; @@ -24,7 +24,7 @@ import net.citizensnpcs.trait.LookClose; import net.citizensnpcs.trait.SkinTrait; -public class BQCitizens extends BQNPCsManager { +public class BQCitizens implements BqInternalNpcFactory { @Override public int getTimeToWaitForNPCs() { @@ -37,7 +37,7 @@ public boolean isNPC(Entity entity) { } @Override - protected BQNPC fetchNPC(int id) { + public BqInternalNpc fetchNPC(int id) { NPC npc = CitizensAPI.getNPCRegistry().getById(id); return npc == null ? null : new BQCitizensNPC(npc); } @@ -50,35 +50,27 @@ public Collection<Integer> getIDs() { @EventHandler (priority = EventPriority.HIGHEST) public void onNPCRightClick(NPCRightClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - super.clickEvent(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_RIGHT : NpcClickType.RIGHT); + npcClicked(e, e.getNPC().getId(), e.getClicker(), + e.getClicker().isSneaking() ? NpcClickType.SHIFT_RIGHT : NpcClickType.RIGHT); } @EventHandler (priority = EventPriority.HIGHEST) public void onNPCLeftClick(NPCLeftClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - super.clickEvent(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_LEFT : NpcClickType.LEFT); + npcClicked(e, e.getNPC().getId(), e.getClicker(), + e.getClicker().isSneaking() ? NpcClickType.SHIFT_LEFT : NpcClickType.LEFT); } @EventHandler public void onNPCRemove(NPCRemoveEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - super.removeEvent(e.getNPC().getId()); + npcRemoved(e.getNPC().getId()); } @EventHandler public void onCitizensReload(CitizensReloadEvent e) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Citizens has been reloaded whereas it is highly not recommended for plugins compatibilities. Unexpected behaviors may happen."); - npcs.forEach((id, npc) -> { - if (npc instanceof BQCitizensNPC) { - BQCitizensNPC bqnpc = (BQCitizensNPC) npc; - NPC cnpc = CitizensAPI.getNPCRegistry().getById(id); - if (cnpc == null) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unable to find NPC with ID " + id + " after a Citizens reload."); - }else { - bqnpc.npc = cnpc; - } - } - }); + npcsReloaded(); } @Override @@ -87,14 +79,14 @@ public boolean isValidEntityType(EntityType type) { } @Override - protected BQNPC create(Location location, EntityType type, String name) { + public BqInternalNpc create(Location location, EntityType type, String name) { NPC npc = CitizensAPI.getNPCRegistry().createNPC(type, name); if (!Settings.Setting.DEFAULT_LOOK_CLOSE.asBoolean()) npc.getOrAddTrait(LookClose.class).toggle(); npc.spawn(location); return new BQCitizensNPC(npc); } - public static class BQCitizensNPC extends BQNPC { + public static class BQCitizensNPC implements BqInternalNpc { private NPC npc; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java index 67fca6fa..b5acb583 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java @@ -6,9 +6,9 @@ import org.mcmonkey.sentinel.SentinelIntegration; import org.mcmonkey.sentinel.SentinelPlugin; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.players.PlayerAccountImplementation; -import fr.skytasul.quests.structure.QuestImplementation; +import fr.skytasul.quests.api.quests.Quest; public class BQSentinel { @@ -39,14 +39,14 @@ public String[] getTargetPrefixes() { public boolean isTarget(LivingEntity ent, String prefix, String value) { switch (prefix) { case "quest_in": - return test(ent, value, QuestImplementation::hasStarted); + return test(ent, value, Quest::hasStarted); case "quest_finished": - return test(ent, value, QuestImplementation::hasFinished); + return test(ent, value, Quest::hasFinished); } return false; } - private boolean test(LivingEntity ent, String value, BiPredicate<QuestImplementation, PlayerAccountImplementation> test) { + private boolean test(LivingEntity ent, String value, BiPredicate<Quest, PlayerAccount> test) { if (ent instanceof Player) { PlayerAccount acc = PlayersManager.getPlayerAccount((Player) ent); if (acc != null) { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java index 8e196d84..d601b6e9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java @@ -9,10 +9,11 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; +import org.jetbrains.annotations.NotNull; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import fr.skytasul.quests.api.npcs.BQNPC; -import fr.skytasul.quests.api.npcs.BQNPCsManager; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; import fr.skytasul.quests.api.npcs.NpcClickType; import io.github.znetworkw.znpcservers.ServersNPC; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; @@ -22,7 +23,7 @@ import io.github.znetworkw.znpcservers.npc.NPCType; import io.github.znetworkw.znpcservers.npc.event.NPCInteractEvent; -public class BQServerNPCs extends BQNPCsManager { +public class BQServerNPCs implements BqInternalNpcFactory { private Cache<Integer, Boolean> cachedNpcs = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); @@ -47,7 +48,7 @@ public boolean isNPC(Entity entity) { } @Override - protected BQNPC fetchNPC(int id) { + public BqInternalNpc fetchNPC(int id) { NPC npc = NPC.find(id); return npc == null ? null : new BQServerNPC(npc); } @@ -58,7 +59,7 @@ public boolean isValidEntityType(EntityType type) { } @Override - protected BQNPC create(Location location, EntityType type, String name) { + public @NotNull BqInternalNpc create(Location location, EntityType type, String name) { List<Integer> ids = ConfigurationConstants.NPC_LIST.stream().map(NPCModel::getId).collect(Collectors.toList()); int id = ids.size(); while (ids.contains(id)) id++; @@ -69,10 +70,11 @@ protected BQNPC create(Location location, EntityType type, String name) { @EventHandler public void onInteract(NPCInteractEvent e) { - super.clickEvent(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), NpcClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); + npcClicked(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), + NpcClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); } - public static class BQServerNPC extends BQNPC { + public static class BQServerNPC implements BqInternalNpc { private final NPC npc; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java index 44a45a1f..067c11e8 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java @@ -14,7 +14,7 @@ import com.sk89q.worldguard.session.Session; import com.sk89q.worldguard.session.SessionManager; import com.sk89q.worldguard.session.handler.Handler; -import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.BeautyQuests; public class WorldGuardEntryHandler extends Handler { @@ -53,7 +53,7 @@ public WorldGuardEntryHandler(Session session) { @Override public boolean onCrossBoundary(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) { Player bukkitPlayer = BukkitAdapter.adapt(player); - if (!QuestsAPI.getAPI().getNPCsManager().isNPC(bukkitPlayer)) { + if (!BeautyQuests.getInstance().getNpcManager().getInternalFactory().isNPC(bukkitPlayer)) { Bukkit.getPluginManager().callEvent(new WorldGuardEntryEvent(bukkitPlayer, entered)); Bukkit.getPluginManager().callEvent(new WorldGuardExitEvent(bukkitPlayer, exited)); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java index cfeb453c..4b246213 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java @@ -15,7 +15,7 @@ import fr.skytasul.quests.api.events.DialogSendEvent; import fr.skytasul.quests.api.events.DialogSendMessageEvent; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BQNPC; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.npcs.dialogs.Message; @@ -24,7 +24,7 @@ public class DialogRunnerImplementation implements DialogRunner { private final Dialog dialog; - private final BQNPC npc; + private final BqNpc npc; private List<Predicate<Player>> tests = new ArrayList<>(); private List<Predicate<Player>> testsCancelling = new ArrayList<>(); @@ -33,7 +33,7 @@ public class DialogRunnerImplementation implements DialogRunner { private Map<Player, PlayerStatus> players = new HashMap<>(); private Boolean navigationInitiallyPaused = null; - public DialogRunnerImplementation(Dialog dialog, BQNPC npc) { + public DialogRunnerImplementation(Dialog dialog, BqNpc npc) { this.dialog = dialog; this.npc = npc; } From 301ff348f02e7b5e9c578a574938de96c6b067b6 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 15 Jul 2023 21:24:14 +0200 Subject: [PATCH 26/95] :construction: Reworked message placeholders parsing --- .../skytasul/quests/api/blocks/BQBlock.java | 16 +- .../quests/api/editors/DialogEditor.java | 69 ++-- .../quests/api/editors/TextEditor.java | 6 +- .../quests/api/editors/TextListEditor.java | 17 +- .../api/editors/parsers/CollectionParser.java | 6 +- .../api/editors/parsers/NumberParser.java | 5 +- .../api/editors/parsers/PatternParser.java | 3 +- .../skytasul/quests/api/gui/GuiFactory.java | 12 + .../quests/api/gui/templates/ConfirmGUI.java | 6 - .../quests/api/localization/Lang.java | 110 +++--- .../quests/api/localization/Locale.java | 46 ++- .../quests/api/npcs/dialogs/Dialog.java | 11 +- .../quests/api/objects/QuestObject.java | 29 +- .../quests/api/options/QuestOption.java | 17 +- .../quests/api/options/QuestOptionObject.java | 4 +- .../api/options/QuestOptionRewards.java | 5 +- .../quests/api/players/PlayerAccount.java | 3 +- .../skytasul/quests/api/pools/QuestPool.java | 3 +- .../fr/skytasul/quests/api/quests/Quest.java | 3 +- .../api/requirements/AbstractRequirement.java | 16 +- .../api/requirements/RequirementList.java | 9 + .../requirements/TargetNumberRequirement.java | 20 +- .../quests/api/rewards/RewardList.java | 9 + .../quests/api/stages/AbstractStage.java | 31 +- .../skytasul/quests/api/stages/StageType.java | 10 +- .../api/stages/creation/StageCreation.java | 4 +- .../quests/api/utils/CountableObject.java | 9 +- .../quests/api/utils/MessageUtils.java | 131 -------- .../quests/api/utils}/NumberedList.java | 3 +- .../fr/skytasul/quests/api/utils/Utils.java | 1 + .../api/utils/logger/LoggerExpanded.java | 4 +- .../api/utils/messaging/DefaultErrors.java | 28 ++ .../api/utils/messaging/HasPlaceholders.java | 10 + .../api/utils/messaging/MessageType.java | 32 ++ .../api/utils/messaging/MessageUtils.java | 123 +++++++ .../api/utils/messaging/Placeholder.java | 69 ++++ .../utils/messaging/PlaceholderRegistry.java | 145 ++++++++ .../fr/skytasul/quests/QuestsListener.java | 6 +- .../quests/commands/CommandsAdmin.java | 29 +- .../CommandsManagerImplementation.java | 14 +- .../quests/commands/CommandsPlayer.java | 2 +- .../commands/CommandsPlayerManagement.java | 68 ++-- .../quests/commands/CommandsPools.java | 11 +- .../quests/commands/CommandsRoot.java | 7 +- .../quests/commands/CommandsScoreboard.java | 27 +- .../quests/gui/DefaultGuiFactory.java | 8 + .../quests/gui/GuiManagerImplementation.java | 6 +- .../skytasul/quests/gui/blocks/BlocksGUI.java | 4 +- .../quests/gui/blocks/SelectBlockGUI.java | 27 +- .../quest/QuestCreationGuiImplementation.java | 12 +- .../quests/gui/creation/stages/StagesGUI.java | 3 +- .../quests/gui/items/ItemCreatorGUI.java | 4 +- .../fr/skytasul/quests/gui/misc/TitleGUI.java | 26 +- .../skytasul/quests/gui/mobs/MobsListGUI.java | 2 +- .../skytasul/quests/gui/npc/NpcCreateGUI.java | 13 +- .../gui/particles/ParticleEffectGUI.java | 9 +- .../gui/permissions/PermissionListGUI.java | 4 +- .../quests/gui/pools/PoolEditGUI.java | 8 +- .../quests/gui/quests/DialogHistoryGUI.java | 6 +- .../quests/gui/quests/PlayerListGUI.java | 12 +- .../quests/options/OptionDescription.java | 6 +- .../quests/options/OptionEndRewards.java | 6 +- .../quests/options/OptionFailOnDeath.java | 2 +- .../quests/options/OptionRepeatable.java | 4 +- .../quests/options/OptionRequirements.java | 10 +- .../quests/options/OptionStartDialog.java | 2 +- .../quests/options/OptionStarterNPC.java | 1 - .../players/PlayerAccountImplementation.java | 15 + .../quests/requirements/ClassRequirement.java | 3 +- .../requirements/FactionRequirement.java | 3 +- .../requirements/JobLevelRequirement.java | 17 +- .../quests/requirements/LevelRequirement.java | 9 +- .../McCombatLevelRequirement.java | 9 +- .../requirements/McMMOSkillRequirement.java | 17 +- .../quests/requirements/MoneyRequirement.java | 14 +- .../requirements/PermissionsRequirement.java | 10 +- .../requirements/PlaceholderRequirement.java | 23 +- .../quests/requirements/QuestRequirement.java | 15 +- .../requirements/RegionRequirement.java | 9 + .../requirements/ScoreboardRequirement.java | 5 + .../SkillAPILevelRequirement.java | 9 +- .../logical/LogicalOrRequirement.java | 3 +- .../quests/rewards/CheckpointReward.java | 14 +- .../quests/rewards/CommandReward.java | 10 +- .../skytasul/quests/rewards/ItemReward.java | 22 +- .../quests/rewards/MessageReward.java | 16 +- .../skytasul/quests/rewards/MoneyReward.java | 9 + .../quests/rewards/PermissionReward.java | 11 +- .../skytasul/quests/rewards/RandomReward.java | 12 +- .../quests/rewards/RemoveItemsReward.java | 23 +- .../rewards/RequirementDependentReward.java | 8 +- .../skytasul/quests/rewards/WaitReward.java | 14 +- .../fr/skytasul/quests/rewards/XPReward.java | 24 +- .../quests/scoreboards/Scoreboard.java | 4 +- .../fr/skytasul/quests/stages/StageArea.java | 2 +- .../quests/stages/StageBringBack.java | 5 +- .../fr/skytasul/quests/stages/StageChat.java | 5 +- .../fr/skytasul/quests/stages/StageNPC.java | 2 +- .../BranchesManagerImplementation.java | 1 + .../structure/QuestBranchImplementation.java | 24 +- .../quests/structure/QuestImplementation.java | 48 ++- .../QuestsManagerImplementation.java | 1 + .../StageControllerImplementation.java | 7 +- .../pools/QuestPoolImplementation.java | 53 ++- .../QuestPoolsManagerImplementation.java | 1 + .../utils/compatibility/mobs/MythicMobs.java | 2 +- .../utils/compatibility/mobs/MythicMobs5.java | 2 +- .../skytasul/quests/utils/types/Command.java | 21 +- .../types/DialogRunnerImplementation.java | 23 +- .../quests/utils/types/Permission.java | 13 +- .../fr/skytasul/quests/utils/types/Title.java | 2 +- core/src/main/resources/config.yml | 8 +- core/src/main/resources/locales/en_US.yml | 315 +++++++++--------- 113 files changed, 1519 insertions(+), 708 deletions(-) delete mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java rename {core/src/main/java/fr/skytasul/quests/utils/types => api/src/main/java/fr/skytasul/quests/api/utils}/NumberedList.java (91%) create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/messaging/DefaultErrors.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/messaging/HasPlaceholders.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java diff --git a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java index 97cbc96e..94140e02 100644 --- a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java +++ b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java @@ -6,8 +6,10 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -public abstract class BQBlock { +public abstract class BQBlock implements HasPlaceholders { private final @NotNull BQBlockType type; private final @Nullable String customName; @@ -15,6 +17,8 @@ public abstract class BQBlock { private @Nullable XMaterial cachedMaterial; private @Nullable String cachedName; + private @Nullable PlaceholderRegistry placeholders; + protected BQBlock(@NotNull BQBlockOptions options) { this.type = options.getType(); this.customName = options.getCustomName(); @@ -60,4 +64,14 @@ public String toString() { return "BQBlock{" + getAsString() + "}"; } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry() + .registerIndexed("block_type", getAsString()) + .register("block_material", getMaterial().name()); + } + return placeholders; + } + } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java index df98486a..4bacd0b2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java @@ -5,8 +5,10 @@ import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.Message; import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class DialogEditor extends Editor{ @@ -42,12 +44,11 @@ public boolean chat(String coloredMessage, String strippedMessage){ case NPC: case PLAYER: if (!hasMsg){ - Lang.DIALOG_SYNTAX.send(player, cmd, ""); + Lang.DIALOG_MESSAGE_SYNTAX.send(player, PlaceholderRegistry.of("command", cmd)); break; } d.add(msg, Sender.valueOf(cmd.name())); - MessageUtils.sendPrefixedMessage(player, Lang.valueOf("DIALOG_MSG_ADDED_" + cmd.name()).toString(), msg, - cmd.name().toLowerCase()); + Lang.valueOf("DIALOG_MSG_ADDED_" + cmd.name()).send(player, PlaceholderRegistry.of("msg", msg)); break; case REMOVE: @@ -56,21 +57,22 @@ public boolean chat(String coloredMessage, String strippedMessage){ break; } try{ - Message removed = d.getMessages().remove(Integer.parseInt(args[1])); + int index = Integer.parseInt(args[1]); + Message removed = d.getMessages().remove(index); if (removed != null){ - Lang.DIALOG_MSG_REMOVED.send(player, removed.text); + Lang.DIALOG_MSG_REMOVED.send(player, PlaceholderRegistry.of("msg", removed.text)); } else - Lang.OUT_OF_BOUNDS.send(player, args[1], 0, d.getMessages().size()); + DefaultErrors.sendOutOfBounds(player, index, 0, d.getMessages().size()); }catch (IllegalArgumentException ex){ - Lang.NUMBER_INVALID.send(player); + DefaultErrors.sendInvalidNumber(player, args[1]); } break; case LIST: for (int i = 0; i < d.getMessages().size(); i++) { Message dmsg = d.getMessages().get(i); - MessageUtils.sendRawMessage(player, "§6{0}: §7\"{1}§7\"§e by §l{2}", false, i, dmsg.text, - dmsg.sender.name().toLowerCase()); + MessageUtils.sendRawMessage(player, "§6{index}: §7\"{msg}§7\"§e by §l{sender}", false, + PlaceholderRegistry.of("index", i, "msg", dmsg.text, "sender", dmsg.sender.name().toLowerCase())); } break; @@ -78,55 +80,54 @@ public boolean chat(String coloredMessage, String strippedMessage){ case NPCINSERT: case PLAYERINSERT: if (args.length < 3){ - Lang.DIALOG_SYNTAX.send(player, cmd, " <id>"); + Lang.DIALOG_MESSAGE_SYNTAX.send(player, PlaceholderRegistry.of("command", cmd + " <id>")); break; } try{ msg = Utils.buildFromArray(argsColored, 2, " "); Sender sender = Sender.valueOf(cmd.name().replace("INSERT", "")); d.insert(msg, sender, Integer.parseInt(args[1])); - MessageUtils.sendPrefixedMessage(player, Lang.valueOf("DIALOG_MSG_ADDED_" + sender.name()).toString(), msg, - sender.name().toLowerCase()); + Lang.valueOf("DIALOG_MSG_ADDED_" + cmd.name()).send(player, PlaceholderRegistry.of("msg", msg)); }catch (NumberFormatException ex){ - Lang.NUMBER_INVALID.send(player, args[1]); + DefaultErrors.sendInvalidNumber(player, args[1]); } break; case EDIT: if (args.length < 3){ - Lang.DIALOG_SYNTAX.send(player, cmd, " <id>"); + Lang.DIALOG_MESSAGE_SYNTAX.send(player, PlaceholderRegistry.of("command", cmd + " <id>")); break; } try{ Message message = d.getMessages().get(Integer.parseInt(args[1])); msg = Utils.buildFromArray(argsColored, 2, " "); message.text = msg; - Lang.DIALOG_MSG_EDITED.send(player, msg); + Lang.DIALOG_MSG_EDITED.send(player, PlaceholderRegistry.of("msg", msg)); }catch (IllegalArgumentException ex){ - Lang.NUMBER_INVALID.send(player); + DefaultErrors.sendInvalidNumber(player, args[1]); }catch (IndexOutOfBoundsException ex) { - Lang.OBJECT_DOESNT_EXIST.send(player, args[1]); + DefaultErrors.sendOutOfBounds(player, Integer.parseInt(args[1]), 0, d.getMessages().size()); } break; case ADDSOUND: if (args.length < 3){ - Lang.TEXTLIST_SYNTAX.send(player, "addSound <id> <sound>"); + Lang.TEXTLIST_SYNTAX.send(player, PlaceholderRegistry.of("command", "addSound <id> <sound>")); break; } try{ Message imsg = d.getMessages().get(Integer.parseInt(args[1])); - Lang.DIALOG_SOUND_ADDED.send(player, imsg.sound = args[2], args[1]); + Lang.DIALOG_SOUND_ADDED.send(player, PlaceholderRegistry.of("sound", imsg.sound = args[2], "msg", args[1])); }catch (IllegalArgumentException ex){ - Lang.NUMBER_INVALID.send(player); + DefaultErrors.sendInvalidNumber(player, args[1]); }catch (IndexOutOfBoundsException ex) { - Lang.OBJECT_DOESNT_EXIST.send(player, args[1]); + DefaultErrors.sendOutOfBounds(player, Integer.parseInt(args[1]), 0, d.getMessages().size()); } break; case SETTIME: if (args.length < 3) { - Lang.TEXTLIST_SYNTAX.send(player, "setTime <id> <time in ticks>"); + Lang.TEXTLIST_SYNTAX.send(player, PlaceholderRegistry.of("command", "setTime <id> <time in ticks>")); break; } try { @@ -134,26 +135,26 @@ public boolean chat(String coloredMessage, String strippedMessage){ int time = Integer.parseInt(args[2]); if (time < 0) { imsg.wait = -1; - Lang.DIALOG_TIME_REMOVED.send(player, args[1]); + Lang.DIALOG_TIME_REMOVED.send(player, PlaceholderRegistry.of("msg", args[1])); }else { imsg.wait = time; - Lang.DIALOG_TIME_SET.send(player, args[1], imsg.wait = time); + Lang.DIALOG_TIME_SET.send(player, PlaceholderRegistry.of("msg", args[1], "time", imsg.wait = time)); } }catch (IllegalArgumentException ex) { - Lang.NUMBER_INVALID.send(player); + DefaultErrors.sendInvalidNumber(player, args[1]); }catch (IndexOutOfBoundsException ex) { - Lang.OBJECT_DOESNT_EXIST.send(player, args[1]); + DefaultErrors.sendOutOfBounds(player, Integer.parseInt(args[1]), 0, d.getMessages().size()); } break; case NPCNAME: if (args.length < 2) { - Lang.DIALOG_NPCNAME_UNSET.send(player, d.getNpcName()); + Lang.DIALOG_NPCNAME_UNSET.send(player, PlaceholderRegistry.of("old_name", d.getNpcName())); d.setNpcName(null); } else { String oldName = d.getNpcName(); d.setNpcName(msg); - Lang.DIALOG_NPCNAME_SET.send(player, oldName, msg); + Lang.DIALOG_NPCNAME_SET.send(player, PlaceholderRegistry.of("old_name", oldName, "new_name", msg)); } break; @@ -161,21 +162,23 @@ public boolean chat(String coloredMessage, String strippedMessage){ String prev = d.getSkippableStatus(); if (args.length < 2) { d.setSkippable(null);; - Lang.DIALOG_SKIPPABLE_UNSET.send(player, prev); + Lang.DIALOG_SKIPPABLE_UNSET.send(player, PlaceholderRegistry.of("old_state", prev)); }else { d.setSkippable(Boolean.parseBoolean(args[1])); - Lang.DIALOG_SKIPPABLE_SET.send(player, prev, d.getSkippableStatus()); + Lang.DIALOG_SKIPPABLE_SET.send(player, + PlaceholderRegistry.of("old_state", prev, "new_state", d.getSkippableStatus())); } break; case CLEAR: - Lang.DIALOG_CLEARED.send(player, d.getMessages().size()); + Lang.DIALOG_CLEARED.send(player, PlaceholderRegistry.of("amount", d.getMessages().size())); d.getMessages().clear(); break; case HELP: for (Lang l : Lang.values()){ - if (l.getPath().startsWith("msg.editor.dialog.help.")) l.sendWP(player); + if (l.getPath().startsWith("msg.editor.dialog.help.")) + l.send(player); } break; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java index ea756a95..296dcba1 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/TextEditor.java @@ -5,6 +5,8 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.api.editors.parsers.AbstractParser; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class TextEditor<T> extends Editor { @@ -48,7 +50,7 @@ public TextEditor<T> useStrippedMessage() { public boolean chat(String msg, String strippedMessage){ if (strippedMessage.equals("null")) { if (nul == null && !nullIntoConsumer) { - Lang.ARG_NOT_SUPPORTED.send(player, "null"); + Lang.ARG_NOT_SUPPORTED.send(player, PlaceholderRegistry.of("arg", "null")); return false; } stop(); @@ -72,7 +74,7 @@ public boolean chat(String msg, String strippedMessage){ returnment = tmp; } }catch (Throwable ex){ - Lang.ERROR_OCCURED.send(player, strippedMessage + " parsingText"); + DefaultErrors.sendGeneric(player, strippedMessage + " parsingText"); invalid = true; ex.printStackTrace(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java index b84a03b5..71b760b2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class TextListEditor extends Editor{ @@ -49,23 +50,24 @@ public boolean chat(String coloredMessage, String strippedMessage){ case ADD: if (!hasMsg){ - Lang.TEXTLIST_SYNTAX.send(player, " add <message>"); + sendSyntax(" add <message>"); break; } if (valid != null){ if (!valid.test(msg)) break; } texts.add(msg); - Lang.TEXTLIST_TEXT_ADDED.send(player, msg); + Lang.TEXTLIST_TEXT_ADDED.send(player, PlaceholderRegistry.of("msg", msg)); break; case REMOVE: if (!hasMsg){ - Lang.TEXTLIST_SYNTAX.send(player, " remove <id>"); + sendSyntax(" remove <id>"); break; } try{ - Lang.TEXTLIST_TEXT_REMOVED.send(player, texts.remove(Integer.parseInt(args[1]))); + String removed = texts.remove(Integer.parseInt(args[1])); + Lang.TEXTLIST_TEXT_REMOVED.send(player, PlaceholderRegistry.of("msg", removed)); }catch (IllegalArgumentException ex){ Lang.NUMBER_INVALID.send(player); } @@ -81,7 +83,8 @@ public boolean chat(String coloredMessage, String strippedMessage){ case HELP: for (Lang l : Lang.values()){ - if (l.getPath().startsWith("msg.editor.textList.help.")) l.sendWP(player); + if (l.getPath().startsWith("msg.editor.textList.help.")) + l.send(player); } break; @@ -94,6 +97,10 @@ public boolean chat(String coloredMessage, String strippedMessage){ return true; } + private void sendSyntax(String command) { + Lang.TEXTLIST_SYNTAX.send(player, PlaceholderRegistry.of("command", command)); + } + private enum Command{ ADD, REMOVE, LIST, HELP, CLOSE; } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/parsers/CollectionParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/CollectionParser.java index b2b37eec..43e3facf 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/parsers/CollectionParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/CollectionParser.java @@ -6,6 +6,7 @@ import java.util.stream.Collectors; import org.bukkit.entity.Player; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class CollectionParser<T> implements AbstractParser<T> { @@ -20,7 +21,8 @@ public CollectionParser(Collection<T> collection, Function<T, String> namer) { @Override public T parse(Player p, String msg) throws Throwable { T obj = names.get(processName(msg)); - if (obj == null) Lang.NO_SUCH_ELEMENT.send(p, namesString); + if (obj == null) + Lang.NO_SUCH_ELEMENT.send(p, PlaceholderRegistry.of("available_elements", namesString)); return obj; } @@ -30,7 +32,7 @@ protected String processName(String msg) { @Override public void sendIndication(Player p) { - Lang.AVAILABLE_ELEMENTS.send(p, namesString); + Lang.AVAILABLE_ELEMENTS.send(p, PlaceholderRegistry.of("available_elements", namesString)); } public String getNames() { diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/parsers/NumberParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/NumberParser.java index 7e7a17f4..2380efbf 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/parsers/NumberParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/NumberParser.java @@ -3,6 +3,7 @@ import java.math.BigDecimal; import org.bukkit.entity.Player; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; public class NumberParser<T extends Number> implements AbstractParser<T> { @@ -51,13 +52,13 @@ public T parse(Player p, String msg) { if (min != null || max != null) { BigDecimal bd = new BigDecimal(msg); if ((min != null && bd.compareTo(min) < 0) || (max != null && bd.compareTo(max) > 0)) { - Lang.NUMBER_NOT_IN_BOUNDS.send(p, min, max); + DefaultErrors.sendOutOfBounds(p, min, max); return null; } } return number; }catch (Exception ex) {} - Lang.NUMBER_INVALID.send(p, msg); + DefaultErrors.sendInvalidNumber(p, msg); return null; } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/parsers/PatternParser.java b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/PatternParser.java index d7d80646..afb7a2ce 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/parsers/PatternParser.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/parsers/PatternParser.java @@ -4,6 +4,7 @@ import java.util.regex.PatternSyntaxException; import org.bukkit.entity.Player; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class PatternParser implements AbstractParser<Pattern> { @@ -16,7 +17,7 @@ public Pattern parse(Player p, String msg) throws Throwable { try { return Pattern.compile(msg); }catch (PatternSyntaxException ex) { - Lang.INVALID_PATTERN.send(p, msg); + Lang.INVALID_PATTERN.send(p, PlaceholderRegistry.of("input", msg)); return null; } } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java index 1023fc49..3e083c20 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java @@ -1,10 +1,12 @@ package fr.skytasul.quests.api.gui; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.function.Consumer; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; @@ -38,4 +40,14 @@ Gui createBlocksSelection(@NotNull Consumer<List<MutableCountableObject<BQBlock> @NotNull Gui createNpcSelection(@NotNull Runnable cancel, @NotNull Consumer<BqNpc> callback, boolean nullable); + @NotNull + default Gui createConfirmation(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + @NotNull String @Nullable... lore) { + return createConfirmation(yes, no, indication, Arrays.asList(lore)); + } + + @NotNull + Gui createConfirmation(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + @Nullable List<@Nullable String> lore); + } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java index 19f4dc1f..ad8a04e8 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ConfirmGUI.java @@ -1,6 +1,5 @@ package fr.skytasul.quests.api.gui.templates; -import java.util.Arrays; import java.util.Collections; import java.util.List; import org.bukkit.event.inventory.InventoryType; @@ -18,11 +17,6 @@ public final class ConfirmGUI { private ConfirmGUI() {} - public static AbstractGui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, - @Nullable String @Nullable... lore) { - return confirm(yes, no, indication, lore == null ? null : Arrays.asList(lore)); - } - public static AbstractGui confirm(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, @Nullable List<@Nullable String> lore) { return LayoutedGUI.newBuilder() 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 6c4d8bdb..b2486b2a 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 @@ -3,6 +3,7 @@ import java.util.Objects; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.utils.messaging.MessageType; /** * Stores all string paths and methods to format and send them to players. @@ -39,7 +40,7 @@ public enum Lang implements Locale { QUEST_CHECKPOINT("msg.quests.checkpoint"), QUEST_FAILED("msg.quests.failed"), - DIALOG_SKIPPED("msg.dialogs.skipped"), + DIALOG_SKIPPED("msg.dialogs.skipped", MessageType.UNPREFIXED), DIALOG_TOO_FAR("msg.dialogs.tooFar"), // 0: npc name POOL_NO_TIME("msg.pools.noTime"), // 0: time left @@ -95,7 +96,6 @@ public enum Lang implements Locale { REGION_DOESNT_EXIST("msg.regionDoesntExists"), NPC_DOESNT_EXIST("msg.npcDoesntExist"), - OBJECT_DOESNT_EXIST("msg.objectDoesntExist"), NUMBER_NEGATIVE("msg.number.negative"), NUMBER_ZERO("msg.number.zero"), NUMBER_INVALID("msg.number.invalid"), @@ -173,25 +173,25 @@ public enum Lang implements Locale { COMMAND_TRANSLATION_EXISTS("msg.command.downloadTranslations.exists"), // 0: file COMMAND_TRANSLATION_DOWNLOADED("msg.command.downloadTranslations.downloaded"), // 0: lang - COMMAND_HELP("msg.command.help.header"), - COMMAND_HELP_CREATE("msg.command.help.create"), - COMMAND_HELP_EDIT("msg.command.help.edit"), - COMMAND_HELP_REMOVE("msg.command.help.remove"), - COMMAND_HELP_FINISH("msg.command.help.finishAll"), - COMMAND_HELP_STAGE("msg.command.help.setStage"), - COMMAND_HELP_DIALOG("msg.command.help.startDialog"), - COMMAND_HELP_RESET("msg.command.help.resetPlayer"), - COMMAND_HELP_RESETQUEST("msg.command.help.resetPlayerQuest"), - COMMAND_HELP_SEE("msg.command.help.seePlayer"), - COMMAND_HELP_RELOAD("msg.command.help.reload"), - COMMAND_HELP_START("msg.command.help.start"), - COMMAND_HELP_SETITEM("msg.command.help.setItem"), - COMMAND_HELP_SETFIREWORK("msg.command.help.setFirework"), - COMMAND_HELP_ADMINMODE("msg.command.help.adminMode"), - COMMAND_HELP_VERSION("msg.command.help.version"), - COMMAND_HELP_DOWNLOAD_TRANSLATIONS("msg.command.help.downloadTranslations"), - COMMAND_HELP_SAVE("msg.command.help.save"), - COMMAND_HELP_LIST("msg.command.help.list"), + COMMAND_HELP("msg.command.help.header", MessageType.UNPREFIXED), + COMMAND_HELP_CREATE("msg.command.help.create", MessageType.UNPREFIXED), + COMMAND_HELP_EDIT("msg.command.help.edit", MessageType.UNPREFIXED), + COMMAND_HELP_REMOVE("msg.command.help.remove", MessageType.UNPREFIXED), + COMMAND_HELP_FINISH("msg.command.help.finishAll", MessageType.UNPREFIXED), + COMMAND_HELP_STAGE("msg.command.help.setStage", MessageType.UNPREFIXED), + COMMAND_HELP_DIALOG("msg.command.help.startDialog", MessageType.UNPREFIXED), + COMMAND_HELP_RESET("msg.command.help.resetPlayer", MessageType.UNPREFIXED), + COMMAND_HELP_RESETQUEST("msg.command.help.resetPlayerQuest", MessageType.UNPREFIXED), + COMMAND_HELP_SEE("msg.command.help.seePlayer", MessageType.UNPREFIXED), + COMMAND_HELP_RELOAD("msg.command.help.reload", MessageType.UNPREFIXED), + COMMAND_HELP_START("msg.command.help.start", MessageType.UNPREFIXED), + COMMAND_HELP_SETITEM("msg.command.help.setItem", MessageType.UNPREFIXED), + COMMAND_HELP_SETFIREWORK("msg.command.help.setFirework", MessageType.UNPREFIXED), + COMMAND_HELP_ADMINMODE("msg.command.help.adminMode", MessageType.UNPREFIXED), + COMMAND_HELP_VERSION("msg.command.help.version", MessageType.UNPREFIXED), + COMMAND_HELP_DOWNLOAD_TRANSLATIONS("msg.command.help.downloadTranslations", MessageType.UNPREFIXED), + COMMAND_HELP_SAVE("msg.command.help.save", MessageType.UNPREFIXED), + COMMAND_HELP_LIST("msg.command.help.list", MessageType.UNPREFIXED), // * Editors * ALREADY_EDITOR("msg.editor.already"), @@ -282,7 +282,7 @@ public enum Lang implements Locale { UNKNOWN_BLOCK_TYPE("msg.editor.itemCreator.unknownBlockType"), INVALID_BLOCK_TYPE("msg.editor.itemCreator.invalidBlockType"), - DIALOG_SYNTAX("msg.editor.dialog.syntax"), + DIALOG_MESSAGE_SYNTAX("msg.editor.dialog.syntaxMessage"), DIALOG_REMOVE_SYNTAX("msg.editor.dialog.syntaxRemove"), DIALOG_MSG_ADDED_PLAYER("msg.editor.dialog.player"), DIALOG_MSG_ADDED_NPC("msg.editor.dialog.npc"), @@ -297,22 +297,22 @@ public enum Lang implements Locale { DIALOG_SKIPPABLE_SET("msg.editor.dialog.skippable.set"), // 0: previous, 1: new DIALOG_SKIPPABLE_UNSET("msg.editor.dialog.skippable.unset"), // 0: previous DIALOG_CLEARED("msg.editor.dialog.cleared"), - DIALOG_HELP_HEADER("msg.editor.dialog.help.header"), - DIALOG_HELP_NPC("msg.editor.dialog.help.npc"), - DIALOG_HELP_PLAYER("msg.editor.dialog.help.player"), - DIALOG_HELP_NOTHING("msg.editor.dialog.help.nothing"), - DIALOG_HELP_REMOVE("msg.editor.dialog.help.remove"), - DIALOG_HELP_LIST("msg.editor.dialog.help.list"), - DIALOG_HELP_NPCINSERT("msg.editor.dialog.help.npcInsert"), - DIALOG_HELP_PLAYERINSERT("msg.editor.dialog.help.playerInsert"), - DIALOG_HELP_NOTHINGINSERT("msg.editor.dialog.help.nothingInsert"), - DIALOG_HELP_EDIT("msg.editor.dialog.help.edit"), - DIALOG_HELP_ADDSOUND("msg.editor.dialog.help.addSound"), - DIALOG_HELP_SETTIME("msg.editor.dialog.help.setTime"), - DIALOG_HELP_NPCNAME("msg.editor.dialog.help.npcName"), - DIALOG_HELP_SKIPPABLE("msg.editor.dialog.help.skippable"), - DIALOG_HELP_CLEAR("msg.editor.dialog.help.clear"), - DIALOG_HELP_CLOSE("msg.editor.dialog.help.close"), + DIALOG_HELP_HEADER("msg.editor.dialog.help.header", MessageType.UNPREFIXED), + DIALOG_HELP_NPC("msg.editor.dialog.help.npc", MessageType.UNPREFIXED), + DIALOG_HELP_PLAYER("msg.editor.dialog.help.player", MessageType.UNPREFIXED), + DIALOG_HELP_NOTHING("msg.editor.dialog.help.nothing", MessageType.UNPREFIXED), + DIALOG_HELP_REMOVE("msg.editor.dialog.help.remove", MessageType.UNPREFIXED), + DIALOG_HELP_LIST("msg.editor.dialog.help.list", MessageType.UNPREFIXED), + DIALOG_HELP_NPCINSERT("msg.editor.dialog.help.npcInsert", MessageType.UNPREFIXED), + DIALOG_HELP_PLAYERINSERT("msg.editor.dialog.help.playerInsert", MessageType.UNPREFIXED), + DIALOG_HELP_NOTHINGINSERT("msg.editor.dialog.help.nothingInsert", MessageType.UNPREFIXED), + DIALOG_HELP_EDIT("msg.editor.dialog.help.edit", MessageType.UNPREFIXED), + DIALOG_HELP_ADDSOUND("msg.editor.dialog.help.addSound", MessageType.UNPREFIXED), + DIALOG_HELP_SETTIME("msg.editor.dialog.help.setTime", MessageType.UNPREFIXED), + DIALOG_HELP_NPCNAME("msg.editor.dialog.help.npcName", MessageType.UNPREFIXED), + DIALOG_HELP_SKIPPABLE("msg.editor.dialog.help.skippable", MessageType.UNPREFIXED), + DIALOG_HELP_CLEAR("msg.editor.dialog.help.clear", MessageType.UNPREFIXED), + DIALOG_HELP_CLOSE("msg.editor.dialog.help.close", MessageType.UNPREFIXED), MYTHICMOB_LIST("msg.editor.mythicmobs.list"), MYTHICMOB_NOT_EXISTS("msg.editor.mythicmobs.isntMythicMob"), @@ -322,11 +322,11 @@ public enum Lang implements Locale { TEXTLIST_SYNTAX("msg.editor.textList.syntax"), TEXTLIST_TEXT_ADDED("msg.editor.textList.added"), TEXTLIST_TEXT_REMOVED("msg.editor.textList.removed"), - TEXTLIST_TEXT_HELP_HEADER("msg.editor.textList.help.header"), - TEXTLIST_TEXT_HELP_ADD("msg.editor.textList.help.add"), - TEXTLIST_TEXT_HELP_REMOVE("msg.editor.textList.help.remove"), - TEXTLIST_TEXT_HELP_LIST("msg.editor.textList.help.list"), - TEXTLIST_TEXT_HELP_CLOSE("msg.editor.textList.help.close"), + TEXTLIST_TEXT_HELP_HEADER("msg.editor.textList.help.header", MessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_ADD("msg.editor.textList.help.add", MessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_REMOVE("msg.editor.textList.help.remove", MessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_LIST("msg.editor.textList.help.list", MessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_CLOSE("msg.editor.textList.help.close", MessageType.UNPREFIXED), // * Quests lists* @@ -370,7 +370,6 @@ public enum Lang implements Locale { stageDealDamage("inv.create.dealDamage"), stageEatDrink("inv.create.eatDrink"), stageText("inv.create.NPCText"), - dialogLines("inv.create.dialogLines"), // 0: lines stageNPCSelect("inv.create.NPCSelect"), stageHide("inv.create.hideClues"), stageGPS("inv.create.gps"), @@ -518,7 +517,7 @@ public enum Lang implements Locale { INVENTORY_NPC("inv.npcCreate.name"), name("inv.npcCreate.setName"), skin("inv.npcCreate.setSkin"), - type("inv.npcCreate.setType"), + npcType("inv.npcCreate.setType"), move("inv.npcCreate.move.itemName"), moveLore("inv.npcCreate.move.itemLore"), moveItem("inv.npcCreate.moveItem"), @@ -830,6 +829,7 @@ public enum Lang implements Locale { AmountDialogLines("misc.amounts.dialogLines"), // 0: amount AmountPermissions("misc.amounts.permissions"), // 0: amount AmountMobs("misc.amounts.mobs"), // 0: amount + AmountXp("misc.amounts.xp"), HologramText("misc.hologramText"), PoolHologramText("misc.poolHologramText"), @@ -849,8 +849,6 @@ public enum Lang implements Locale { Reset("misc.reset"), Or("misc.or"), Amount("misc.amount"), - Item("misc.items"), - Exp("misc.expPoints"), Yes("misc.yes"), No("misc.no"), And("misc.and"); @@ -858,16 +856,27 @@ public enum Lang implements Locale { private static final String DEFAULT_STRING = "§cnot loaded"; private final @NotNull String path; + private final @NotNull MessageType type; private final @Nullable Lang prefix; private @NotNull String value = DEFAULT_STRING; + private Lang(@NotNull String path) { - this(path, null); + this(path, MessageType.PREFIXED, null); + } + + private Lang(@NotNull String path, @NotNull MessageType type) { + this(path, type, null); } private Lang(@NotNull String path, @Nullable Lang prefix) { + this(path, MessageType.PREFIXED, prefix); + } + + private Lang(@NotNull String path, @NotNull MessageType type, @Nullable Lang prefix) { this.path = path; + this.type = type; this.prefix = prefix; } @@ -876,6 +885,11 @@ private Lang(@NotNull String path, @Nullable Lang prefix) { return path; } + @Override + public @NotNull MessageType getType() { + return type; + } + @Override public void setValue(@NotNull String value) { this.value = Objects.requireNonNull(value); diff --git a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java index c66dbb0c..69c9e6aa 100644 --- a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java +++ b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java @@ -7,7 +7,6 @@ import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.util.function.Supplier; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; @@ -16,8 +15,11 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.utils.ChatColorUtils; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public interface Locale { @@ -27,24 +29,42 @@ public interface Locale { @NotNull String getValue(); + @NotNull + MessageType getType(); + void setValue(@NotNull String value); - default @NotNull String format(@Nullable Object @Nullable... replace) { - return MessageUtils.format(getValue(), replace); + default @NotNull String format(@Nullable HasPlaceholders placeholdersHolder) { + return MessageUtils.format(getValue(), + placeholdersHolder == null ? null : placeholdersHolder.getPlaceholdersRegistry()); } - - default @NotNull String format(@NotNull Supplier<Object> @Nullable... replace) { - return MessageUtils.format(getValue(), replace); + + default @NotNull String format(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { + return format(PlaceholderRegistry.combine(placeholdersHolders)); } - default void send(@NotNull CommandSender sender, @Nullable Object @Nullable... args) { - MessageUtils.sendPrefixedMessage(sender, getValue(), args); + default @NotNull String quickFormat(@NotNull String key1, @Nullable Object value1) { + // TODO maybe simplfy this for optimization? + return format(PlaceholderRegistry.of(key1, value1)); } - - default void sendWP(@NotNull CommandSender p, @Nullable Object @Nullable... args) { - MessageUtils.sendUnprefixedMessage(p, getValue(), args); + + default void send(@NotNull CommandSender sender) { + send(sender, (HasPlaceholders) null); } - + + default void send(@NotNull CommandSender sender, @Nullable HasPlaceholders placeholdersHolder) { + MessageUtils.sendMessage(sender, getValue(), getType(), + placeholdersHolder == null ? null : placeholdersHolder.getPlaceholdersRegistry()); + } + + default void send(@NotNull CommandSender sender, @NotNull HasPlaceholders @NotNull... placeholdersHolders) { + send(sender, PlaceholderRegistry.combine(placeholdersHolders)); + } + + default void quickSend(@NotNull CommandSender sender, @NotNull String key1, @Nullable Object value1) { + send(sender, PlaceholderRegistry.of(key1, value1)); + } + public static void loadStrings(@NotNull Locale @NotNull [] locales, @NotNull YamlConfiguration defaultConfig, @NotNull YamlConfiguration config) { for (Locale l : locales) { diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java index 9b7e458e..b0584534 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Dialog.java @@ -7,11 +7,11 @@ import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; -import fr.skytasul.quests.utils.types.NumberedList; +import fr.skytasul.quests.api.utils.NumberedList; public class Dialog implements Cloneable { @@ -40,7 +40,7 @@ public void setMessages(@NotNull List<Message> messages) { return npcName; if (defaultNPC == null) return Lang.Unknown.toString(); - return defaultNPC.getName(); + return defaultNPC.getNpc().getName(); } public @Nullable String getNpcName() { @@ -60,7 +60,8 @@ public void insert(String msg, Sender sender, int id){ } public boolean isSkippable() { - return skippable == null ? QuestsConfiguration.getDialogsConfig().isSkippableByDefault() : skippable.booleanValue(); + return skippable == null ? QuestsConfiguration.getConfig().getDialogsConfig().isSkippableByDefault() + : skippable.booleanValue(); } public void setSkippable(@Nullable Boolean skippable) { @@ -100,7 +101,7 @@ public static Dialog deserialize(ConfigurationSection section) { NumberedList<Message> tmpMessages = new NumberedList<>(); for (Map<?, ?> msg : section.getMapList("msgs")) { int id = (int) msg.get("id"); - tmpMessages.setSwitch(id, Message.deserialize((Map<String, Object>) msg.get("message"))); + tmpMessages.set(id, Message.deserialize((Map<String, Object>) msg.get("message"))); } Dialog di = new Dialog(tmpMessages.toList()); if (section.contains("npcName")) di.npcName = section.getString("npcName"); diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index 1d46e2c2..12f52f32 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -12,14 +12,19 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.serializable.SerializableObject; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -public abstract class QuestObject extends SerializableObject implements Cloneable { +public abstract class QuestObject extends SerializableObject implements Cloneable, HasPlaceholders { protected static final String CUSTOM_DESCRIPTION_KEY = "customDescription"; private Quest quest; private String customDescription; + private @Nullable PlaceholderRegistry placeholders; + protected QuestObject(@NotNull QuestObjectsRegistry registry, @Nullable String customDescription) { super(registry); this.customDescription = customDescription; @@ -58,6 +63,20 @@ public boolean isValid() { return true; } + @Override + public final @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry(); + createdPlaceholdersRegistry(placeholders); + } + return placeholders; + } + + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + placeholders.register("custom_description", () -> customDescription); + placeholders.register("object_type", creator.getID()); + } + @Override public abstract @NotNull QuestObject clone(); @@ -74,7 +93,9 @@ public void load(@NotNull ConfigurationSection section) { } public final @Nullable String getDescription(Player player) { - return customDescription == null ? getDefaultDescription(player) : customDescription; + String string = customDescription == null ? getDefaultDescription(player) : customDescription; + string = MessageUtils.format(string, getPlaceholdersRegistry()); + return string; } /** @@ -104,8 +125,8 @@ protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { description = "§cerror"; QuestsPlugin.getPlugin().getLoggerExpanded().warning("Could not get quest object description during edition", ex); } - loreBuilder.addDescription( - Lang.object_description.format(description + (customDescription == null ? " " + Lang.defaultValue : ""))); + loreBuilder.addDescription(Lang.object_description.format(PlaceholderRegistry.of("description", + description + (customDescription == null ? " " + Lang.defaultValue : "")))); } public @NotNull ItemStack getItemStack() { diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index d29a74f2..022f5608 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -15,6 +15,7 @@ import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.AutoRegistered; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @AutoRegistered public abstract class QuestOption<T> implements Cloneable { @@ -132,13 +133,19 @@ public void onDependenciesUpdated(@NotNull OptionSet options/* , @NotNull ItemSt return description == null ? null : "§8> §7" + description; } - public static @NotNull String formatNullableValue(@Nullable String valueString) { - return formatNullableValue(valueString, false); + public static @NotNull String formatNullableValue(@Nullable Object value) { + return formatNullableValue(value, false); } - public static @NotNull String formatNullableValue(@Nullable String valueString, boolean defaultValue) { - valueString = Lang.optionValue.format(valueString == null ? Lang.NotSet.toString() : valueString); - if (defaultValue) valueString += " " + Lang.defaultValue.toString(); + public static @NotNull String formatNullableValue(@Nullable Object value, @NotNull Object defaultValue) { + return formatNullableValue(value == null ? defaultValue : value, value == null); + } + + public static @NotNull String formatNullableValue(@Nullable Object value, boolean defaultValue) { + String valueString = + Lang.optionValue.format(PlaceholderRegistry.of("value", value == null ? Lang.NotSet.toString() : value)); + if (defaultValue) + valueString += " " + Lang.defaultValue.toString(); return valueString; } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java index 9de857c2..7656401a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionObject.java @@ -62,7 +62,7 @@ public void load(ConfigurationSection config, String key) { protected abstract T deserialize(Map<String, Object> map); - protected abstract String getSizeString(int size); + protected abstract String getSizeString(); protected abstract QuestObjectsRegistry<T, C> getObjectsRegistry(); @@ -74,7 +74,7 @@ public void load(ConfigurationSection config, String key) { } protected String[] getLore() { - String count = "§7" + getSizeString(getValue().size()); + String count = "§7" + getSizeString(); if (getItemDescription() == null) return new String[] { count }; return new String[] { formatDescription(getItemDescription()), "", count }; } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java index 3e6f727a..c57bb6ea 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionRewards.java @@ -3,7 +3,6 @@ import java.util.Collection; import java.util.Map; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.RewardCreator; @@ -17,8 +16,8 @@ protected AbstractReward deserialize(Map<String, Object> map) { } @Override - protected String getSizeString(int size) { - return Lang.rewards.format(size); + protected String getSizeString() { + return getValue().getSizeString(); } @Override diff --git a/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java b/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java index 1c7ac53c..99adab44 100644 --- a/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java +++ b/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java @@ -10,8 +10,9 @@ import fr.skytasul.quests.api.data.SavableData; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; -public interface PlayerAccount { +public interface PlayerAccount extends HasPlaceholders { /** * @return if this account is currently used by the player (if true, {@link #getPlayer()} cannot * return a null player) 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 8acb0b95..b49c08fb 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 @@ -8,8 +8,9 @@ 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; -public interface QuestPool { +public interface QuestPool extends HasPlaceholders { int getId(); diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java index f26dae4a..9c135e6b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java +++ b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java @@ -13,8 +13,9 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.quests.branches.QuestBranchesManager; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; -public interface Quest extends OptionSet, Comparable<Quest> { +public interface Quest extends OptionSet, Comparable<Quest>, HasPlaceholders { int getId(); diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index a5f61aa9..ba15a1cc 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -13,7 +13,9 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.serializable.SerializableObject; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public abstract class AbstractRequirement extends QuestObject { @@ -60,7 +62,7 @@ else if (customReason != null) reason = getDefaultReason(player); if (reason != null && !reason.isEmpty() && !"none".equals(reason)) { - MessageUtils.sendPrefixedMessage(player, reason); + MessageUtils.sendMessage(player, reason, MessageType.PREFIXED, getPlaceholdersRegistry()); return true; } @@ -82,6 +84,12 @@ else if (customReason != null) return "invalid requirement"; } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("custom_reason", () -> customReason); + } + protected @Nullable ClickType getCustomReasonClick() { return ClickType.SHIFT_RIGHT; } @@ -113,8 +121,8 @@ protected final void clickInternal(@NotNull QuestObjectClickEvent event) { @Override protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder - .addDescription(Lang.requirementReason.format(customReason == null ? Lang.NotSet.toString() : customReason)); + loreBuilder.addDescription(Lang.requirementReason.format( + PlaceholderRegistry.of("reason", customReason == null ? Lang.NotSet.toString() : customReason))); loreBuilder.addClick(getCustomReasonClick(), Lang.setRequirementReason.toString()); } diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java b/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java index 224f3cd0..39931042 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java @@ -7,6 +7,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.serializable.SerializableObject; @@ -46,6 +47,10 @@ public void detachQuest() { forEach(requirement -> requirement.detach()); } + public String getSizeString() { + return getSizeString(size()); + } + public @NotNull List<Map<String, Object>> serialize() { return SerializableObject.serializeList(this); } @@ -54,4 +59,8 @@ public static RequirementList deserialize(@NotNull List<Map<?, ?>> mapList) { return new RequirementList(SerializableObject.deserializeList(mapList, AbstractRequirement::deserialize)); } + public static String getSizeString(int size) { + return Lang.requirements.quickFormat("amount", size); + } + } diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java index 4438b7c7..ffab707b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java @@ -13,11 +13,13 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.ComparisonMethod; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public abstract class TargetNumberRequirement extends AbstractRequirement { protected ComparisonMethod comparison; protected double target; + private @NotNull PlaceholderRegistry placeholders; protected TargetNumberRequirement(@Nullable String customDescription, @Nullable String customReason, double target, @NotNull ComparisonMethod comparison) { @@ -45,19 +47,31 @@ public boolean test(@NotNull Player p) { } public @NotNull String getFormattedValue() { - return comparison.getTitle().format(getNumberFormat().format(target)); + return comparison.getTitle().format(PlaceholderRegistry.of("number", getNumberFormat().format(target))); } protected @NotNull NumberFormat getNumberFormat() { return numberClass() == Integer.class ? NumberFormat.getIntegerInstance() : NumberFormat.getInstance(); } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders + .registerIndexed("short_" + getPlaceholderName(), this::getShortFormattedValue) + .register("long_" + getPlaceholderName(), this::getFormattedValue) + .register("raw_" + getPlaceholderName(), () -> getNumberFormat().format(target)) + .register(getPlaceholderName() + "_comparison", () -> Character.toString(comparison.getSymbol())); + } + @Override protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(getFormattedValue())); } + protected abstract String getPlaceholderName(); + public abstract double getPlayerTarget(@NotNull Player p); public abstract @NotNull Class<? extends Number> numberClass(); @@ -86,7 +100,9 @@ public void itemClick(@NotNull QuestObjectClickEvent event) { event.reopenGUI(); }, number -> { target = number.doubleValue(); - Lang.COMPARISON_TYPE.send(event.getPlayer(), ComparisonMethod.getComparisonParser().getNames(), ComparisonMethod.GREATER_OR_EQUAL.name().toLowerCase()); + Lang.COMPARISON_TYPE.send(event.getPlayer(), + PlaceholderRegistry.of("available", ComparisonMethod.getComparisonParser().getNames(), "default", + ComparisonMethod.GREATER_OR_EQUAL.name().toLowerCase())); new TextEditor<>(event.getPlayer(), null, comp -> { this.comparison = comp == null ? ComparisonMethod.GREATER_OR_EQUAL : comp; event.reopenGUI(); diff --git a/api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java b/api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java index 340d46f5..2648f4aa 100644 --- a/api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java +++ b/api/src/main/java/fr/skytasul/quests/api/rewards/RewardList.java @@ -7,6 +7,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.serializable.SerializableObject; @@ -58,6 +59,10 @@ public boolean hasAsync() { return stream().anyMatch(AbstractReward::isAsync); } + public String getSizeString() { + return getSizeString(size()); + } + public @NotNull List<Map<String, Object>> serialize() { return SerializableObject.serializeList(this); } @@ -66,4 +71,8 @@ public static RewardList deserialize(@NotNull List<Map<?, ?>> mapList) { return new RewardList(SerializableObject.deserializeList(mapList, AbstractReward::deserialize)); } + public static String getSizeString(int size) { + return Lang.rewards.quickFormat("amount", size); + } + } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 1b851808..08ee6d32 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -18,9 +18,11 @@ import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.stages.options.StageOption; import fr.skytasul.quests.api.utils.AutoRegistered; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @AutoRegistered -public abstract class AbstractStage { +public abstract class AbstractStage implements HasPlaceholders { protected final @NotNull StageController controller; @@ -30,6 +32,8 @@ public abstract class AbstractStage { private @NotNull RequirementList validationRequirements = new RequirementList(); private @NotNull List<@NotNull StageOption> options; + + private @Nullable PlaceholderRegistry placeholders; protected AbstractStage(@NotNull StageController controller) { this.controller = controller; @@ -96,6 +100,21 @@ public boolean hasAsyncEnd() { return rewards.hasAsync(); } + @Override + public final @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry(); + createdPlaceholdersRegistry(placeholders); + } + return placeholders; + } + + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + placeholders.register("stage_type", controller.getStageType().getName()); + placeholders.register("stage_rewards", rewards.getSizeString()); + placeholders.register("stage_requirements", validationRequirements.getSizeString()); + } + protected final boolean canUpdate(@NotNull Player player) { return canUpdate(player, false); } @@ -154,16 +173,6 @@ public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull St */ public abstract @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); - /** - * Will be called only if there is a {@link #customText} - * @param acc PlayerAccount who has the stage in progress - * @param source source of the description request - * @return all strings that can be used to format the custom description text - */ - public @Nullable Object @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { - return null; - } - protected final void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullable Object dataValue) { controller.updateObjective(p, dataKey, dataValue); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java index 9f0b438c..b6e5d884 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java @@ -8,8 +8,10 @@ import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.options.StageOption; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -public class StageType<T extends AbstractStage> { +public class StageType<T extends AbstractStage> implements HasPlaceholders { private final @NotNull String id; private final @NotNull Class<T> clazz; @@ -19,6 +21,7 @@ public class StageType<T extends AbstractStage> { private final @NotNull StageCreationSupplier<T> creationSupplier; private final @NotNull SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> optionsRegistry; + private @NotNull PlaceholderRegistry placeholders; /** * Creates a stage type. @@ -70,6 +73,11 @@ public StageType(@NotNull String id, @NotNull Class<T> clazz, @NotNull String na return optionsRegistry; } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + return PlaceholderRegistry.of("stage_type", name, "stage_type_id", id); + } + @FunctionalInterface public static interface StageCreationSupplier<T extends AbstractStage> { diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java index d945f86f..66f055cd 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java @@ -59,7 +59,7 @@ public List<AbstractReward> getRewards() { public void setRewards(List<AbstractReward> rewards) { this.rewards = rewards; - getLine().refreshItemLore(1, QuestOption.formatDescription(Lang.rewards.format(rewards.size()))); + getLine().refreshItemLore(1, QuestOption.formatDescription(RewardList.getSizeString(rewards.size()))); } public List<AbstractRequirement> getRequirements() { @@ -67,7 +67,7 @@ public List<AbstractRequirement> getRequirements() { } public void setRequirements(List<AbstractRequirement> requirements) { - getLine().refreshItemLore(4, QuestOption.formatDescription(Lang.requirements.format(requirements.size()))); + getLine().refreshItemLore(4, QuestOption.formatDescription(RequirementList.getSizeString(requirements.size()))); this.requirements = requirements; } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java index e94ab891..891e7666 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java @@ -3,8 +3,10 @@ import java.util.Objects; import java.util.UUID; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -public interface CountableObject<T> { +public interface CountableObject<T> extends HasPlaceholders { @NotNull UUID getUUID(); @@ -18,6 +20,11 @@ public interface CountableObject<T> { return createMutable(getUUID(), getObject(), getAmount()); } + @Override + default @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + return PlaceholderRegistry.of("amount", getAmount()); + } + public interface MutableCountableObject<T> extends CountableObject<T> { void setObject(@NotNull T object); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java deleted file mode 100644 index 15062f24..00000000 --- a/api/src/main/java/fr/skytasul/quests/api/utils/MessageUtils.java +++ /dev/null @@ -1,131 +0,0 @@ -package fr.skytasul.quests.api.utils; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsConfiguration; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import net.md_5.bungee.api.ChatColor; - -public class MessageUtils { - - private MessageUtils() {} - - private static final Map<Integer, Pattern> REPLACEMENT_PATTERNS = new ConcurrentHashMap<>(); - private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); - - public static void sendPrefixedMessage(CommandSender sender, String msg, Object... replace) { - if (StringUtils.isEmpty(msg)) - return; - sendRawMessage(sender, QuestsPlugin.getPlugin().getPrefix() + msg, false, replace); - } - - public static void sendUnprefixedMessage(CommandSender sender, String msg, Object... replace) { - if (StringUtils.isEmpty(msg)) - return; - sendRawMessage(sender, "§6" + msg, false, replace); - } - - public static void sendRawMessage(CommandSender sender, String text, boolean playerName, Object... replace) { - sender.sendMessage(StringUtils.splitByWholeSeparator(finalFormat(sender, text, playerName, replace), "{nl}")); - } - - public static String finalFormat(CommandSender sender, String text, boolean playerName, Object... replace) { - if (DependenciesManager.papi.isEnabled() && sender instanceof Player) - text = QuestsPlaceholders.setPlaceholders((Player) sender, text); - if (playerName && sender != null) - text = text.replace("{PLAYER}", sender.getName()).replace("{PREFIX}", QuestsConfiguration.getPrefix()); - text = ChatColor.translateAlternateColorCodes('&', text); - return format(text, replace); - } - - public static void sendOffMessage(Player p, String msg, Object... replace) { - if (msg != null && !msg.isEmpty()) - sendRawMessage(p, Lang.OffText.format(msg, replace), true); - } - - public static String itemsToFormattedString(String[] items) { - return itemsToFormattedString(items, ""); - } - - public static String itemsToFormattedString(String[] items, String separator) { - if (items.length == 0) - return ""; - if (items.length == 1) - return items[0]; - if (items.length == 2) - return items[0] + " " + separator + Lang.And.toString() + " " + ChatColorUtils.getLastColors(null, items[0]) - + items[1]; - StringBuilder stb = new StringBuilder("§e" + items[0] + ", "); - for (int i = 1; i < items.length - 1; i++) { - stb.append(items[i] + ((i == items.length - 2) ? "" : ", ")); - } - stb.append(" " + Lang.And.toString() + " " + items[items.length - 1]); - return stb.toString(); - } - - public static @NotNull String format(@NotNull String msg, @NotNull Supplier<Object> @Nullable... replace) { - if (replace != null && replace.length != 0) { - for (int i = 0; i < replace.length; i++) { - Supplier<Object> supplier = replace[i]; - msg = format(msg, i, supplier); - } - } - return msg; - } - - public static @NotNull String format(@NotNull String msg, @Nullable Object @Nullable... replace) { - if (replace != null && replace.length != 0) { - for (int i = 0; i < replace.length; i++) { - Object replacement = replace[i]; - if (replacement instanceof Supplier) { - msg = format(msg, i, (Supplier<Object>) replacement); - } else { - msg = format(msg, i, () -> replacement); - } - } - } - return msg; - } - - public static String format(@NotNull String msg, int i, @NotNull Supplier<Object> replace) { - Pattern pattern = REPLACEMENT_PATTERNS.computeIfAbsent(i, __ -> Pattern.compile("\\{" + i + "\\}")); - Matcher matcher = pattern.matcher(msg); - StringBuilder output = new StringBuilder(msg.length()); - int lastAppend = 0; - String colors = ""; - String replacement = null; - while (matcher.find()) { - String substring = msg.substring(lastAppend, matcher.start()); - colors = ChatColorUtils.getLastColors(colors, substring); - output.append(substring); - if (replacement == null) - replacement = Objects.toString(replace.get()); - Matcher replMatcher = RESET_PATTERN.matcher(replacement); - output.append(replMatcher.replaceAll("§r" + colors)); - lastAppend = matcher.end(); - } - output.append(msg, lastAppend, msg.length()); - return output.toString(); - } - - public static String formatDescription(DescriptionSource source, SplittableDescriptionConfiguration configuration, - String... elements) { - if (elements.length == 0) - return Lang.Unknown.toString(); - if (elements.length == 1 && configuration.isAloneSplitAmountShown(source)) - return MessageUtils.itemsToFormattedString(elements, configuration.getItemAmountColor()); - return String.join(configuration.getSplitPrefix(), elements); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java b/api/src/main/java/fr/skytasul/quests/api/utils/NumberedList.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java rename to api/src/main/java/fr/skytasul/quests/api/utils/NumberedList.java index 657800c9..14e5e067 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/NumberedList.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/NumberedList.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.types; +package fr.skytasul.quests.api.utils; import java.util.ArrayList; import java.util.HashMap; @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import fr.skytasul.quests.api.utils.Utils; public class NumberedList<T> implements Iterable<T>, Cloneable{ diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java index d2601eca..74e94850 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java @@ -39,6 +39,7 @@ 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.utils.messaging.MessageUtils; import fr.skytasul.quests.utils.nms.NMS; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java b/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java index c30c14f9..dd70a883 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java @@ -8,7 +8,7 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; public class LoggerExpanded { @@ -62,7 +62,7 @@ public <T> BiConsumer<T, Throwable> logError(@Nullable Consumer<T> consumer, @Nu } if (sender != null) - Lang.ERROR_OCCURED.send(sender, friendlyErrorMessage); + DefaultErrors.sendGeneric(sender, friendlyErrorMessage); severe(friendlyErrorMessage, ex); } }; diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/DefaultErrors.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/DefaultErrors.java new file mode 100644 index 00000000..e3208900 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/DefaultErrors.java @@ -0,0 +1,28 @@ +package fr.skytasul.quests.api.utils.messaging; + +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.localization.Lang; + +public class DefaultErrors { + + private DefaultErrors() {} + + public static void sendInvalidNumber(@NotNull CommandSender sender, @Nullable String input) { + Lang.NUMBER_INVALID.send(sender, PlaceholderRegistry.of("input", input)); + } + + public static void sendOutOfBounds(@NotNull CommandSender sender, Number index, Number min, Number max) { + Lang.OUT_OF_BOUNDS.send(sender, PlaceholderRegistry.of("index", index, "min", min, "max", max)); + } + + public static void sendOutOfBounds(@NotNull CommandSender sender, Number min, Number max) { + Lang.NUMBER_NOT_IN_BOUNDS.send(sender, PlaceholderRegistry.of("min", min, "max", max)); + } + + public static void sendGeneric(@NotNull CommandSender sender, @Nullable String error) { + Lang.ERROR_OCCURED.send(sender, PlaceholderRegistry.of("error", error)); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/HasPlaceholders.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/HasPlaceholders.java new file mode 100644 index 00000000..052be077 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/HasPlaceholders.java @@ -0,0 +1,10 @@ +package fr.skytasul.quests.api.utils.messaging; + +import org.jetbrains.annotations.NotNull; + +public interface HasPlaceholders { + + @NotNull + PlaceholderRegistry getPlaceholdersRegistry(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java new file mode 100644 index 00000000..44a5bb68 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java @@ -0,0 +1,32 @@ +package fr.skytasul.quests.api.utils.messaging; + +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; + +public enum MessageType { + + PREFIXED() { + @Override + public @NotNull String process(@NotNull String msg) { + return QuestsPlugin.getPlugin().getPrefix() + msg; + } + }, + UNPREFIXED() { + @Override + public @NotNull String process(@NotNull String msg) { + return "§6" + msg; + } + }, + OFF() { + @Override + public @NotNull String process(@NotNull String msg) { + return Lang.OffText.format(msg); + } + }; + + public @NotNull String process(@NotNull String msg) { + return msg; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java new file mode 100644 index 00000000..4dc3a0cd --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -0,0 +1,123 @@ +package fr.skytasul.quests.api.utils.messaging; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.utils.ChatColorUtils; +import fr.skytasul.quests.api.utils.SplittableDescriptionConfiguration; +import net.md_5.bungee.api.ChatColor; + +public class MessageUtils { + + private MessageUtils() {} + + private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{([a-zA-Z0-9_-]+)\\}"); + private static final Pattern NEWLINE_PATTERN = Pattern.compile("(?:\\n|\\\\n|\\{nl\\})"); + + public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type) { + sendMessage(sender, message, type, null); + } + + public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type, + @Nullable PlaceholderRegistry placeholders) { + if (message == null || message.isEmpty()) + return; + + sendRawMessage(sender, type.process(message), false, placeholders); + } + + public static void sendRawMessage(@NotNull CommandSender sender, @Nullable String text, boolean playerName, + @Nullable PlaceholderRegistry placeholders) { + if (text == null || text.isEmpty()) + return; + + text = finalFormat(sender, text, playerName, placeholders); + sender.sendMessage(NEWLINE_PATTERN.split(text)); + } + + public static String finalFormat(@Nullable CommandSender sender, @NotNull String text, boolean playerName, + @Nullable PlaceholderRegistry placeholders) { + if (DependenciesManager.papi.isEnabled() && sender instanceof Player) + text = QuestsPlaceholders.setPlaceholders((Player) sender, text); + if (playerName && sender != null) + text = text.replace("{PLAYER}", sender.getName()).replace("{PREFIX}", QuestsConfiguration.getPrefix()); + text = ChatColor.translateAlternateColorCodes('&', text); + return format(text, placeholders); + } + + public static String itemsToFormattedString(String[] items) { + return itemsToFormattedString(items, ""); + } + + public static String itemsToFormattedString(String[] items, String separator) { + if (items.length == 0) + return ""; + if (items.length == 1) + return items[0]; + if (items.length == 2) + return items[0] + " " + separator + Lang.And.toString() + " " + ChatColorUtils.getLastColors(null, items[0]) + + items[1]; + StringBuilder stb = new StringBuilder("§e" + items[0] + ", "); + for (int i = 1; i < items.length - 1; i++) { + stb.append(items[i] + ((i == items.length - 2) ? "" : ", ")); + } + stb.append(" " + Lang.And.toString() + " " + items[items.length - 1]); + return stb.toString(); + } + + public static @NotNull String format(@NotNull String msg, @Nullable PlaceholderRegistry placeholders) { + if (placeholders != null) { + Matcher matcher = PLACEHOLDER_PATTERN.matcher(msg); + + // re-implementation of the "matcher.appendReplacement" system to allow replacement of colors + StringBuilder output = null; + int lastAppend = 0; + String colors = ""; + while (matcher.find()) { + if (output == null) + output = new StringBuilder(msg.length()); + + String key = matcher.group(1); + String replacement = placeholders.resolve(key); + String substring = msg.substring(lastAppend, matcher.start()); + colors = ChatColorUtils.getLastColors(colors, substring); + output.append(substring); + Matcher replMatcher = RESET_PATTERN.matcher(replacement); + output.append(replMatcher.replaceAll("§r" + colors)); + lastAppend = matcher.end(); + } + + if (output != null) { + output.append(msg, lastAppend, msg.length()); + msg = output.toString(); + } + } + + return msg; + } + + public static String formatDescription(DescriptionSource source, SplittableDescriptionConfiguration configuration, + String... elements) { + if (elements.length == 0) + return Lang.Unknown.toString(); + if (elements.length == 1 && configuration.isAloneSplitAmountShown(source)) + return MessageUtils.itemsToFormattedString(elements, configuration.getItemAmountColor()); + return String.join(configuration.getSplitPrefix(), elements); + } + + public static String getYesNo(boolean bool) { + return (bool ? Lang.Yes : Lang.No).toString(); + } + + public static String getEnabledDisabled(boolean bool) { + return (bool ? Lang.Enabled : Lang.Disabled).toString(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java new file mode 100644 index 00000000..1286da71 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java @@ -0,0 +1,69 @@ +package fr.skytasul.quests.api.utils.messaging; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface Placeholder { + + boolean matches(@NotNull String key); + + @Nullable + String resolve(@NotNull String key); + + static Placeholder of(@NotNull String key, @Nullable Object value) { + String string = Objects.toString(value); + return ofSupplier(key, () -> string); + } + + static Placeholder ofSupplier(@NotNull String key, @NotNull Supplier<@Nullable String> valueSupplier) { + return new Placeholder() { + + @Override + public @Nullable String resolve(@NotNull String key) { + return valueSupplier.get(); + } + + @Override + public boolean matches(@NotNull String keyToMatch) { + return keyToMatch.equals(key); + } + }; + } + + static Placeholder ofPattern(@NotNull String regex, + @NotNull Function<@NotNull Matcher, @Nullable String> valueFunction) { + return new Placeholder() { + private Pattern pattern = Pattern.compile(regex); + private Map<String, Matcher> matchers = new ConcurrentHashMap<>(); + + @Override + public @Nullable String resolve(@NotNull String key) { + Matcher matcher = matchers.remove(key); + if (matcher == null) { + matcher = pattern.matcher(key); + if (!matcher.matches()) + throw new IllegalStateException(); + } + return valueFunction.apply(matcher); + } + + @Override + public boolean matches(@NotNull String key) { + Matcher matcher = pattern.matcher(key); + if (matcher.matches()) { + matchers.put(key, matcher); + return true; + } + return false; + } + }; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java new file mode 100644 index 00000000..d9b5246b --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java @@ -0,0 +1,145 @@ +package fr.skytasul.quests.api.utils.messaging; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class PlaceholderRegistry implements HasPlaceholders { + + private final List<Placeholder> placeholders; + private final List<Placeholder> indexed; + + public PlaceholderRegistry() { + // effectively the same as the other constructor with no argument + // but without the overhead of creating an empty array and then an empty list + this.placeholders = new ArrayList<>(5); + this.indexed = new ArrayList<>(5); + } + + public PlaceholderRegistry(Placeholder... placeholders) { + this.placeholders = new ArrayList<>(Arrays.asList(placeholders)); + this.indexed = new ArrayList<>(5); + } + + public @Nullable Placeholder getPlaceholder(@NotNull String key) { + try { + int index = Integer.parseInt(key); + if (index < indexed.size()) + return indexed.get(index); + } catch (NumberFormatException ex) { + // means the key is not indexed + } + + for (Placeholder placeholder : placeholders) { + if (placeholder.matches(key)) + return placeholder; + } + return null; + } + + public boolean hasPlaceholder(@NotNull String key) { + return getPlaceholder(key) == null; + } + + public @Nullable String resolve(@NotNull String key) { + @Nullable + Placeholder placeholder = getPlaceholder(key); + + if (placeholder == null) + return null; + + return placeholder.resolve(key); + } + + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + return this; + } + + public @NotNull PlaceholderRegistry register(Placeholder placeholder) { + placeholders.add(placeholder); + return this; + } + + public @NotNull PlaceholderRegistry register(String key, Object value) { + return register(Placeholder.of(key, value)); + } + + public @NotNull PlaceholderRegistry register(String key, Supplier<String> valueSupplier) { + return register(Placeholder.ofSupplier(key, valueSupplier)); + } + + private @NotNull PlaceholderRegistry registerIndexed(Placeholder placeholder) { + placeholders.add(placeholder); + indexed.add(placeholder); + return this; + } + + public @NotNull PlaceholderRegistry registerIndexed(String key, Object value) { + return registerIndexed(Placeholder.of(key, value)); + } + + public @NotNull PlaceholderRegistry registerIndexed(String key, Supplier<String> valueSupplier) { + return registerIndexed(Placeholder.ofSupplier(key, valueSupplier)); + } + + public @NotNull PlaceholderRegistry with(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { + HasPlaceholders[] others = new HasPlaceholders[placeholdersHolders.length + 1]; + others[0] = this; + System.arraycopy(placeholdersHolders, 0, others, 1, placeholdersHolders.length); + return combine(others); + } + + public @NotNull PlaceholderRegistry shifted(@NotNull Placeholder placeholder) { + int index = indexed.indexOf(placeholder); + if (index == -1) + throw new IllegalArgumentException(); + + PlaceholderRegistry shifted = new PlaceholderRegistry(); + shifted.placeholders.addAll(this.placeholders); + Placeholder[] indexedShifted = new Placeholder[this.indexed.size() - index]; + System.arraycopy(this.indexed.toArray(new Placeholder[this.indexed.size()]), index, indexedShifted, 0, + this.indexed.size() - index); + shifted.indexed.addAll(Arrays.asList(indexedShifted)); + + return shifted; + } + + public @NotNull PlaceholderRegistry shifted(@NotNull String key) { + return shifted(getPlaceholder(key)); + } + + public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1) { + return new PlaceholderRegistry() + .registerIndexed(key1, value1); + } + + public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1, @NotNull String key2, + @Nullable Object value2) { + return new PlaceholderRegistry() + .registerIndexed(key1, value1) + .registerIndexed(key2, value2); + } + + public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1, @NotNull String key2, + @Nullable Object value2, @NotNull String key3, @Nullable Object value3) { + return new PlaceholderRegistry() + .registerIndexed(key1, value1) + .registerIndexed(key2, value2) + .registerIndexed(key3, value3); + } + + public static @NotNull PlaceholderRegistry combine(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { + PlaceholderRegistry result = new PlaceholderRegistry(); + for (HasPlaceholders holder : placeholdersHolders) { + result.placeholders.addAll(holder.getPlaceholdersRegistry().placeholders); + if (!holder.getPlaceholdersRegistry().indexed.isEmpty()) + result.indexed.addAll(holder.getPlaceholdersRegistry().indexed); + } + return result; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 57bff1f9..96dc0d55 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -36,8 +36,9 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.options.OptionAutoQuest; @@ -122,7 +123,8 @@ public void onNPCClick(BQNPCClickEvent e) { }else if (!requirements.isEmpty()) { requirements.get(0).testRequirements(p, acc, true); }else { - npc.getPools().iterator().next().give(p).thenAccept(result -> MessageUtils.sendPrefixedMessage(p, result)); + npc.getPools().iterator().next().give(p) + .thenAccept(result -> MessageUtils.sendMessage(p, result, MessageType.PREFIXED)); } e.setCancelled(false); } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index f18c2a88..830ca453 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -19,13 +19,14 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.commands.OutsideEditor; import fr.skytasul.quests.api.editors.SelectNPC; -import fr.skytasul.quests.api.gui.templates.ConfirmGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.gui.misc.ListBook; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; @@ -108,13 +109,13 @@ public void remove(BukkitCommandActor actor, @Optional Quest quest) { private void doRemove(BukkitCommandActor sender, Quest quest) { if (sender.isPlayer()) { - ConfirmGUI.confirm(() -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createConfirmation(() -> { quest.delete(false, false); - Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getName()); - }, null, Lang.INDICATION_REMOVE.format(quest.getName())).open(sender.getAsPlayer()); + Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getPlaceholdersRegistry()); + }, null, Lang.INDICATION_REMOVE.format(quest.getPlaceholdersRegistry())).open(sender.getAsPlayer()); }else { quest.delete(false, false); - Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getName()); + Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getPlaceholdersRegistry()); } } @@ -184,14 +185,14 @@ public void list(Player player) { if (NMS.isValid()) { ListBook.openQuestBook(player); } else - MessageUtils.sendPrefixedMessage(player, "Version not supported"); + MessageUtils.sendMessage(player, "Version not supported", MessageType.PREFIXED); } @Subcommand ("downloadTranslations") @CommandPermission ("beautyquests.command.manage") public void downloadTranslations(BukkitCommandActor actor, @Optional String lang, @Switch boolean overwrite) { if (MinecraftVersion.MAJOR < 13) - throw new CommandErrorException(Lang.VERSION_REQUIRED.format("≥ 1.13")); + throw new CommandErrorException(Lang.VERSION_REQUIRED.quickFormat("version", "≥ 1.13")); if (lang == null) throw new CommandErrorException(Lang.COMMAND_TRANSLATION_SYNTAX.toString()); @@ -202,22 +203,24 @@ public void downloadTranslations(BukkitCommandActor actor, @Optional String lang try { File destination = new File(BeautyQuests.getInstance().getDataFolder(), lang + ".json"); if (destination.isDirectory()) - throw new CommandErrorException(Lang.ERROR_OCCURED.format(lang + ".json is a directory")); + throw new CommandErrorException(Lang.ERROR_OCCURED.quickFormat("error", lang + ".json is a directory")); if (!overwrite && destination.exists()) - throw new CommandErrorException(Lang.COMMAND_TRANSLATION_EXISTS.format(lang + ".json")); + throw new CommandErrorException(Lang.COMMAND_TRANSLATION_EXISTS.quickFormat("file_name", lang + ".json")); try (ReadableByteChannel channel = Channels.newChannel(new URL(url).openStream())) { destination.createNewFile(); try (FileOutputStream output = new FileOutputStream(destination)) { output.getChannel().transferFrom(channel, 0, Long.MAX_VALUE); - Lang.COMMAND_TRANSLATION_DOWNLOADED.send(actor.getSender(), lang); + Lang.COMMAND_TRANSLATION_DOWNLOADED.quickSend(actor.getSender(), "lang", lang); } }catch (FileNotFoundException ex) { - throw new CommandErrorException(Lang.COMMAND_TRANSLATION_NOT_FOUND.format(lang, version)); + throw new CommandErrorException( + Lang.COMMAND_TRANSLATION_NOT_FOUND.format(PlaceholderRegistry.of("lang", lang, "version", version))); } }catch (IOException e) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while downloading translation.", e); - throw new CommandErrorException(Lang.ERROR_OCCURED.format("IO Exception when downloading translation.")); + throw new CommandErrorException( + Lang.ERROR_OCCURED.quickFormat("error", "IO Exception when downloading translation.")); } } 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 69244454..d1189016 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -15,7 +15,8 @@ import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.scoreboards.Scoreboard; import revxrsal.commands.autocomplete.SuggestionProvider; import revxrsal.commands.bukkit.BukkitCommandActor; @@ -42,7 +43,7 @@ public CommandsManagerImplementation() { int id = context.popInt(); Quest quest = QuestsAPI.getAPI().getQuestsManager().getQuest(id); if (quest == null) - throw new CommandErrorException(Lang.QUEST_INVALID.format(id)); + throw new CommandErrorException(Lang.QUEST_INVALID.quickFormat("quest_id", id)); return quest; }); handler.getAutoCompleter().registerParameterSuggestions(Quest.class, @@ -55,7 +56,7 @@ public CommandsManagerImplementation() { int id = context.popInt(); QuestPool pool = QuestsAPI.getAPI().getPoolsManager().getPool(id); if (pool == null) - throw new CommandErrorException(Lang.POOL_INVALID.format(id)); + throw new CommandErrorException(Lang.POOL_INVALID.quickFormat("pool_id", id)); return pool; }); handler.getAutoCompleter().registerParameterSuggestions(QuestPool.class, @@ -68,7 +69,7 @@ public CommandsManagerImplementation() { int id = context.popInt(); BqNpc npc = QuestsPlugin.getPlugin().getNpcManager().getById(id); if (npc == null) - throw new CommandErrorException(Lang.NPC_DOESNT_EXIST.format(id)); + throw new CommandErrorException(Lang.NPC_DOESNT_EXIST.quickFormat("npc_id", id)); return npc; }); handler.getAutoCompleter().registerParameterSuggestions(BqNpc.class, @@ -92,14 +93,15 @@ public CommandsManagerImplementation() { for (Lang lang : Lang.values()) { if (lang.getPath().startsWith("msg.command.help.")) { String cmdKey = lang.getPath().substring(17); - if (cmdKey.equalsIgnoreCase(command.getName())) return lang.format(command.getPath().get(0)); + if (cmdKey.equalsIgnoreCase(command.getName())) + return lang.quickFormat("label", command.getPath().get(0)); } } return null; }); handler.registerResponseHandler(String.class, (msg, actor, command) -> { - MessageUtils.sendPrefixedMessage(((BukkitCommandActor) actor).getSender(), msg); + MessageUtils.sendMessage(((BukkitCommandActor) actor).getSender(), msg, MessageType.PREFIXED); }); handler.registerContextResolver(Scoreboard.class, context -> { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java index 900e6454..0d6790bb 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java @@ -52,7 +52,7 @@ public void checkpoint(Player player, Quest quest) { return; } } - Lang.COMMAND_CHECKPOINT_NO.send(player, quest.getName()); + Lang.COMMAND_CHECKPOINT_NO.send(player, quest.getPlaceholdersRegistry()); }else Lang.COMMAND_CHECKPOINT_NOT_STARTED.send(player); } 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 17b13560..bc8ca6f0 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java @@ -26,6 +26,8 @@ import fr.skytasul.quests.api.quests.branches.EndingStage; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.types.Dialogable; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.gui.quests.QuestsListGUI; import fr.skytasul.quests.options.OptionStartDialog; @@ -68,7 +70,7 @@ public void finishAll(BukkitCommandActor actor, EntitySelector<Player> players) errors++; } } - Lang.LEAVE_ALL_RESULT.send(actor.getSender(), success, errors); + Lang.LEAVE_ALL_RESULT.send(actor.getSender(), PlaceholderRegistry.of("success", success, "errors", errors)); } } @@ -79,12 +81,12 @@ public void finish(BukkitCommandActor actor, EntitySelector<Player> players, Que try { if (force || quest.hasStarted(PlayersManager.getPlayerAccount(player))) { quest.finish(player); - Lang.LEAVE_ALL_RESULT.send(actor.getSender(), 1, 0); + Lang.LEAVE_ALL_RESULT.send(actor.getSender(), PlaceholderRegistry.of("success", 1, "errors", 0)); } }catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded() .severe("An error occurred while finishing quest " + quest.getId(), ex); - Lang.LEAVE_ALL_RESULT.send(actor.getSender(), 1, 1); + Lang.LEAVE_ALL_RESULT.send(actor.getSender(), PlaceholderRegistry.of("success", 0, "errors", 1)); } } } @@ -104,7 +106,7 @@ public void setStage( PlayerQuestDatas datas = acc.getQuestDatasIfPresent(quest); if (branchID == null && (datas == null || !datas.hasStarted())) { // start quest quest.start(player); - Lang.START_QUEST.send(actor.getSender(), quest.getName(), acc.debugName()); + Lang.START_QUEST.send(actor.getSender(), quest, acc); return; } if (datas == null) datas = acc.getQuestDatas(quest); // creates quest datas @@ -119,15 +121,17 @@ public void setStage( }else { QuestBranchImplementation branch = manager.getBranch(branchID); if (branch == null) - throw new CommandErrorException(Lang.COMMAND_SETSTAGE_BRANCH_DOESNTEXIST.format(branchID)); + throw new CommandErrorException(Lang.COMMAND_SETSTAGE_BRANCH_DOESNTEXIST.quickFormat("branch_id", branchID)); if (stageID != null) { if (currentBranch == null) - throw new CommandErrorException(Lang.ERROR_OCCURED.format("player " + acc.debugName() + " has not started quest")); + throw new CommandErrorException( + Lang.ERROR_OCCURED.quickFormat("error", "player " + acc.debugName() + " has not started quest")); if (branch.getRegularStages().size() <= stageID) - throw new CommandErrorException(Lang.COMMAND_SETSTAGE_STAGE_DOESNTEXIST.format(stageID)); + throw new CommandErrorException( + Lang.COMMAND_SETSTAGE_STAGE_DOESNTEXIST.quickFormat("stage_id", stageID)); } - Lang.COMMAND_SETSTAGE_SET.send(actor.getSender(), stageID); + Lang.COMMAND_SETSTAGE_SET.quickSend(actor.getSender(), "stage_id", stageID); if (currentBranch != null) { if (datas.isInEndingStages()) { for (EndingStage stage : currentBranch.getEndingStages()) @@ -177,7 +181,7 @@ public void startDialog(BukkitCommandActor actor, Player player, Quest quest) { Lang.COMMAND_STARTDIALOG_ALREADY.send(actor.getSender()); }else { runner.handleNext(player, DialogNextReason.COMMAND); - Lang.COMMAND_STARTDIALOG_SUCCESS.send(actor.getSender(), player.getName(), quest.getId()); + Lang.COMMAND_STARTDIALOG_SUCCESS.send(actor.getSender(), acc, quest); } } } @@ -221,8 +225,10 @@ public void resetPlayer(BukkitCommandActor actor, EntitySelector<Player> players .whenComplete(QuestUtils.runSyncConsumer(() -> { Bukkit.getPluginManager().callEvent(new PlayerAccountResetEvent(acc)); if (acc.isCurrent()) - Lang.DATA_REMOVED.send(player, questsFinal, actor.getName(), poolsFinal); - Lang.DATA_REMOVED_INFO.send(actor.getSender(), questsFinal, player.getName(), poolsFinal); + Lang.DATA_REMOVED.send(player, PlaceholderRegistry.of("quest_amount", questsFinal, + "deleter_name", actor.getName(), "pool_amount", poolsFinal)); + Lang.DATA_REMOVED_INFO.send(actor.getSender(), PlaceholderRegistry.of("quest_amount", questsFinal, + "player_name", player.getName(), "pool_amount", poolsFinal)); })); } @@ -231,21 +237,22 @@ public void resetPlayer(BukkitCommandActor actor, EntitySelector<Player> players @Subcommand ("resetPlayerQuest") @CommandPermission ("beautyquests.command.resetPlayer") public void resetPlayerQuest(BukkitCommandActor actor, Player player, @Optional Quest quest) { - PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (quest != null) { - reset(actor.getSender(), player, acc, quest); + reset(actor.getSender(), player, quest); }else { new QuestsListGUI(obj -> { - reset(actor.getSender(), player, acc, obj); - }, acc, true, false, true).open(actor.requirePlayer()); + reset(actor.getSender(), player, obj); + }, PlayersManager.getPlayerAccount(player), true, false, true).open(actor.requirePlayer()); } } - private void reset(CommandSender sender, Player target, PlayerAccount acc, Quest qu) { + private void reset(CommandSender sender, Player target, Quest qu) { + PlayerAccount acc = PlayersManager.getPlayerAccount(target); qu.resetPlayer(acc).whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError(__ -> { if (acc.isCurrent()) - Lang.DATA_QUEST_REMOVED.send(target, qu.getName(), sender.getName()); - Lang.DATA_QUEST_REMOVED_INFO.send(sender, target.getName(), qu.getName()); + Lang.DATA_QUEST_REMOVED.send(target, qu.getPlaceholdersRegistry(), + PlaceholderRegistry.of("deleter_name", sender.getName())); + Lang.DATA_QUEST_REMOVED_INFO.send(sender, acc, qu); }, "An error occurred while removing player quest data", sender)); } @@ -278,7 +285,8 @@ public void resetQuest(BukkitCommandActor actor, Quest quest) { BeautyQuests.getInstance().getPlayersManager().removeQuestDatas(quest) .whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError(removedAmount -> { - Lang.QUEST_PLAYERS_REMOVED.send(actor.getSender(), removedAmount + resetAmount); + Lang.QUEST_PLAYERS_REMOVED.quickSend(actor.getSender(), "player_amount", + removedAmount + resetAmount); }, "An error occurred while removing quest datas", actor.getSender())); }).whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError()); @@ -301,26 +309,24 @@ public void start(BukkitCommandActor actor, ExecutableCommand command, EntitySel } for (Player player : players) { - PlayerAccount acc = PlayersManager.getPlayerAccount(player); - if (quest == null) { new QuestsListGUI(obj -> { - start(actor.getSender(), player, acc, obj, overrideRequirements); - }, acc, false, true, false).open(actor.requirePlayer()); + start(actor.getSender(), player, obj, overrideRequirements); + }, PlayersManager.getPlayerAccount(player), false, true, false).open(actor.requirePlayer()); }else { - start(actor.getSender(), player, acc, quest, overrideRequirements); + start(actor.getSender(), player, quest, overrideRequirements); } } } - private void start(CommandSender sender, Player player, PlayerAccount acc, Quest quest, - boolean overrideRequirements) { + private void start(CommandSender sender, Player player, Quest quest, boolean overrideRequirements) { + PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (!overrideRequirements && !quest.canStart(player, true)) { - Lang.START_QUEST_NO_REQUIREMENT.send(sender, quest.getName()); + Lang.START_QUEST_NO_REQUIREMENT.send(sender, quest, acc); return; } quest.start(player); - Lang.START_QUEST.send(sender, quest.getName(), acc.getNameAndID()); + Lang.START_QUEST.send(sender, quest, acc); } @Subcommand ("cancel") @@ -347,17 +353,17 @@ public void cancel(BukkitCommandActor actor, ExecutableCommand command, EntitySe private void cancel(CommandSender sender, PlayerAccount acc, Quest quest) { if (!quest.isCancellable()) { - Lang.CANCEL_QUEST_UNAVAILABLE.send(sender, quest.getName()); + Lang.CANCEL_QUEST_UNAVAILABLE.send(sender, quest); return; } if (quest.cancelPlayer(acc)) { - Lang.CANCEL_QUEST.send(sender, quest.getName()); + Lang.CANCEL_QUEST.send(sender, quest); } else { if (sender.equals(acc.getPlayer())) { Lang.QUEST_NOT_STARTED.send(sender); } else { - Lang.ERROR_OCCURED.send(sender, + DefaultErrors.sendGeneric(sender, "Player " + acc.getName() + " does not have the quest " + quest.getId() + " started."); } } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index 9a520cc2..9642de0a 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java @@ -5,6 +5,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.pools.PoolsManageGUI; import fr.skytasul.quests.structure.pools.QuestPoolImplementation; import revxrsal.commands.annotation.Default; @@ -28,10 +29,10 @@ public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPoolIm PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (timer) { pool.resetPlayerTimer(acc); - Lang.POOL_RESET_TIMER.send(actor.getSender(), pool.getId(), player.getName()); + Lang.POOL_RESET_TIMER.send(actor.getSender(), pool, acc); } else { pool.resetPlayer(acc).whenComplete(QuestsPlugin.getPlugin().getLoggerExpanded().logError(__ -> { - Lang.POOL_RESET_FULL.send(actor.getSender(), pool.getId(), player.getName()); + Lang.POOL_RESET_FULL.send(actor.getSender(), pool, acc); }, "An error occurred while resetting pool " + pool.getId() + " to player " + player.getName(), actor.getSender())); } @@ -40,12 +41,14 @@ public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPoolIm @Subcommand("start") @CommandPermission("beautyquests.command.pools.start") public void start(BukkitCommandActor actor, Player player, QuestPoolImplementation pool) { + PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (!pool.canGive(player)) { - Lang.POOL_START_ERROR.send(player, pool.getId(), player.getName()); + Lang.POOL_START_ERROR.send(player, pool, acc); return; } - pool.give(player).thenAccept(result -> Lang.POOL_START_SUCCESS.send(player, pool.getId(), player.getName(), result)); + pool.give(player).thenAccept( + result -> Lang.POOL_START_SUCCESS.send(player, pool, acc, PlaceholderRegistry.of("result", result))); } } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java index f9eaa7d9..e4baf9e5 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java @@ -2,7 +2,8 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import revxrsal.commands.annotation.Command; import revxrsal.commands.annotation.Description; import revxrsal.commands.annotation.Subcommand; @@ -17,8 +18,8 @@ public class CommandsRoot { @Subcommand ("help") public void help(BukkitCommandActor actor, CommandHelp<String> helpEntries) { - Lang.COMMAND_HELP.sendWP(actor.getSender()); - helpEntries.forEach(help -> MessageUtils.sendUnprefixedMessage(actor.getSender(), help)); + Lang.COMMAND_HELP.send(actor.getSender()); + helpEntries.forEach(help -> MessageUtils.sendMessage(actor.getSender(), help, MessageType.UNPREFIXED)); } @Subcommand ("version") 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 77c89268..0dc5df81 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.scoreboards.Scoreboard; import revxrsal.commands.annotation.Default; import revxrsal.commands.annotation.Optional; @@ -28,27 +29,37 @@ public void scoreboardToggle(Player player, ExecutableCommand command, Scoreboar } } + private PlaceholderRegistry getLineRegistry(int line) { + return PlaceholderRegistry.of("line_id", line); + } + + private PlaceholderRegistry getPlayerRegistry(Player player) { + return PlaceholderRegistry.of("player_name", player.getName()); + } + @Subcommand ("setline") @CommandPermission ("beautyquests.command.scoreboard") public void setline(BukkitCommandActor actor, Player player, Scoreboard scoreboard, @Range (min = 0) int line, String text) { scoreboard.setCustomLine(line, text); - Lang.COMMAND_SCOREBOARD_LINESET.send(actor.getSender(), line); + 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) { if (scoreboard.removeLine(line)) { - Lang.COMMAND_SCOREBOARD_LINEREMOVE.send(actor.getSender(), line); - }else Lang.COMMAND_SCOREBOARD_LINENOEXIST.send(actor.getSender(), line); + Lang.COMMAND_SCOREBOARD_LINEREMOVE.send(actor.getSender(), getLineRegistry(line)); + } 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) { if (scoreboard.resetLine(line)) { - Lang.COMMAND_SCOREBOARD_LINERESET.send(actor.getSender(), line); - }else Lang.COMMAND_SCOREBOARD_LINENOEXIST.send(actor.getSender(), line); + Lang.COMMAND_SCOREBOARD_LINERESET.send(actor.getSender(), getLineRegistry(line)); + } else + Lang.COMMAND_SCOREBOARD_LINENOEXIST.send(actor.getSender(), getLineRegistry(line)); } @Subcommand ("resetall") @@ -56,21 +67,21 @@ public void resetline(BukkitCommandActor actor, Player player, Scoreboard scoreb public void resetall(BukkitCommandActor actor, Player player) { BeautyQuests.getInstance().getScoreboardManager().removePlayerScoreboard(player); BeautyQuests.getInstance().getScoreboardManager().create(player); - Lang.COMMAND_SCOREBOARD_RESETALL.send(actor.getSender(), player.getName()); + 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(), player.getName()); + 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(), player.getName()); + 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/DefaultGuiFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java index 110be026..ca17cb14 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java @@ -5,9 +5,11 @@ import java.util.function.Consumer; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.GuiFactory; +import fr.skytasul.quests.api.gui.templates.ConfirmGUI; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; @@ -47,4 +49,10 @@ public class DefaultGuiFactory implements GuiFactory { return NpcSelectGUI.select(cancel, callback, nullable); } + @Override + public @NotNull Gui createConfirmation(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, + @Nullable List<@Nullable String> lore) { + return ConfirmGUI.confirm(yes, no, indication, lore); + } + } diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index 613e9d59..b1831e07 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -24,8 +24,8 @@ import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.gui.close.OpenCloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.gui.templates.ConfirmGUI; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; import fr.skytasul.quests.utils.QuestUtils; public class GuiManagerImplementation implements GuiManager, Listener { @@ -116,7 +116,7 @@ public void onClose(InventoryCloseEvent event) { if (behavior instanceof StandardCloseBehavior) { switch ((StandardCloseBehavior) behavior) { case CONFIRM: - QuestUtils.runSync(() -> ConfirmGUI.confirm(() -> closeAndExit(player), () -> open(player, gui), + QuestUtils.runSync(() -> factory.createConfirmation(() -> closeAndExit(player), () -> open(player, gui), Lang.INDICATION_CLOSE.toString()).open(player)); break; case NOTHING: @@ -175,7 +175,7 @@ public void onClick(InventoryClickEvent event) { event.setCancelled(guiEvent.isCancelled()); } catch (Exception ex) { event.setCancelled(true); - Lang.ERROR_OCCURED.send(player, ex.getMessage() + " in " + gui.getClass().getSimpleName()); + DefaultErrors.sendGeneric(player, ex.getMessage() + " in " + gui.getClass().getSimpleName()); QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred when " + player.getName() + " clicked in inventory " + gui.getClass().getName() + " at slot " + event.getSlot(), ex); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java index c9dff223..c799a54c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java @@ -38,8 +38,8 @@ public void createObject(Function<MutableCountableObject<BQBlock>, ItemStack> ca @Override public ItemStack getObjectItemStack(MutableCountableObject<BQBlock> object) { - return item(object.getObject().getMaterial(), Lang.materialName.format(object.getObject().getAsString()), - Lang.Amount.format(object.getAmount())); + return item(object.getObject().getMaterial(), Lang.materialName.format(object.getObject()), + Lang.Amount.format(object)); } } 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 bced782a..57f811d5 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 @@ -25,6 +25,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.nms.NMS; public class SelectBlockGUI extends LayoutedGUI.LayoutedRowsGUI { @@ -42,8 +43,9 @@ public SelectBlockGUI(boolean allowAmount, BiConsumer<BQBlock, Integer> run) { this.run = run; if (allowAmount) - buttons.put(1, LayoutedButton.create(XMaterial.REDSTONE, () -> Lang.Amount.format(amount), Collections.emptyList(), - this::amountClick)); + buttons.put(1, + LayoutedButton.create(XMaterial.REDSTONE, () -> Lang.Amount.quickFormat("amount", amount), + Collections.emptyList(), this::amountClick)); buttons.put(2, LayoutedButton.create(XMaterial.NAME_TAG, Lang.blockName.toString(), Arrays.asList(QuestOption.formatNullableValue(customName, customName == null)), this::nameClick)); buttons.put(4, new LayoutedButton() { @@ -55,11 +57,13 @@ public void click(@NotNull LayoutedClickEvent event) { @Override public void place(@NotNull Inventory inventory, int slot) { - inventory.setItem(slot, ItemUtils.item(type, Lang.materialName.format(type.name()))); + 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.format(type.name()), - QuestOption.formatDescription(Lang.materialNotItemLore.format(type.name())))); + inventory.setItem(slot, + ItemUtils.item(XMaterial.STONE, Lang.materialName.quickFormat("block_type", type.name()), + QuestOption.formatDescription( + Lang.materialNotItemLore.quickFormat("block_type", type.name())))); } if (tag == null) ItemUtils.addEnchant(inventory.getItem(slot), Enchantment.DURABILITY, 1); @@ -112,7 +116,8 @@ private void typeClick(LayoutedClickEvent event) { try { Bukkit.createBlockData(type.parseMaterial(), blockData); } catch (Exception ex) { - Lang.INVALID_BLOCK_DATA.send(event.getPlayer(), blockData, type.name()); + Lang.INVALID_BLOCK_DATA.send(event.getPlayer(), + PlaceholderRegistry.of("block_data", blockData, "block_material", type.name())); blockData = null; } } @@ -121,7 +126,7 @@ private void typeClick(LayoutedClickEvent event) { } private void dataClick(LayoutedClickEvent event) { - Lang.BLOCK_DATA.send(event.getPlayer(), + Lang.BLOCK_DATA.quickSend(event.getPlayer(), "available_datas", String.join(", ", NMS.getNMS().getAvailableBlockProperties(type.parseMaterial()))); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { String tmp = "[" + obj + "]"; @@ -130,7 +135,8 @@ private void dataClick(LayoutedClickEvent event) { blockData = tmp; tag = null; } catch (Exception ex) { - Lang.INVALID_BLOCK_DATA.send(event.getPlayer(), tmp, type.name()); + Lang.INVALID_BLOCK_DATA.send(event.getPlayer(), + PlaceholderRegistry.of("block_data", tmp, "block_material", type.name())); } event.refreshGuiReopen(); }, () -> { @@ -140,11 +146,12 @@ private void dataClick(LayoutedClickEvent event) { } private void tagClick(LayoutedClickEvent event) { - Lang.BLOCK_TAGS.send(event.getPlayer(), String.join(", ", NMS.getNMS().getAvailableBlockTags())); + Lang.BLOCK_TAGS.quickSend(event.getPlayer(), "available_tags", + String.join(", ", NMS.getNMS().getAvailableBlockTags())); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { NamespacedKey key = NamespacedKey.fromString((String) obj); if (key == null || Bukkit.getTag("blocks", key, Material.class) == null) { - Lang.INVALID_BLOCK_TAG.send(event.getPlayer(), obj); + Lang.INVALID_BLOCK_TAG.quickSend(event.getPlayer(), "block_tag", obj); } else { tag = (String) obj; type = XMaterial.STONE; 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 a8154ecb..73354140 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 @@ -30,8 +30,9 @@ import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.creation.StageCreationContext; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.gui.creation.stages.StageCreationContextImplementation; import fr.skytasul.quests.gui.creation.stages.StagesGUI; @@ -200,9 +201,8 @@ private void finish(Player p) { } QuestsAPI.getAPI().getQuestsManager().addQuest(qu); - MessageUtils.sendPrefixedMessage(p, - ((!session.isEdition()) ? Lang.SUCCESFULLY_CREATED : Lang.SUCCESFULLY_EDITED).toString(), qu.getName(), - qu.getBranchesManager().getBranches().size()); + Lang msg = session.isEdition() ? Lang.SUCCESFULLY_EDITED : Lang.SUCCESFULLY_CREATED; + msg.send(p, qu, PlaceholderRegistry.of("quest_branches", qu.getBranchesManager().getBranches().size())); QuestUtils.playPluginSound(p, "ENTITY_VILLAGER_YES", 1); QuestsPlugin.getPlugin().getLoggerExpanded().info("New quest created: " + qu.getName() + ", ID " + qu.getId() + ", by " + p.getName()); if (session.isEdition()) { @@ -212,7 +212,7 @@ private void finish(Player p) { try { qu.saveToFile(); }catch (Exception e) { - Lang.ERROR_OCCURED.send(p, "initial quest save"); + DefaultErrors.sendGeneric(p, "initial quest save"); QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error when trying to save newly created quest.", e); } @@ -262,7 +262,7 @@ private boolean loadBranch(Player p, QuestBranchImplementation branch, StagesGUI }else branch.addRegularStage(stage); }catch (Exception ex) { failure = true; - Lang.ERROR_OCCURED.send(p, " lineToStage"); + DefaultErrors.sendGeneric(p, " lineToStage"); QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred wheh creating branch from GUI.", ex); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 1790ebbd..6042647d 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -225,8 +225,7 @@ <T extends AbstractStage> StageCreation<T> setStageCreation(StageType<T> type) { inv.setItem(SLOT_FINISH, ItemUtils.itemDone); int maxStages = ending ? 20 : 15; - ItemStack manageItem = - ItemUtils.item(XMaterial.BARRIER, Lang.stageType.format(type.getName()), getLineManageLore(lineId)); + ItemStack manageItem = ItemUtils.item(XMaterial.BARRIER, Lang.stageType.format(type), getLineManageLore(lineId)); lineObj.setItem(0, manageItem, event -> { switch (event.getClick()) { case LEFT: diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java index db47ee52..35e4e528 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java @@ -46,7 +46,7 @@ protected Inventory instanciate(@NotNull Player player) { @Override protected void populate(@NotNull Player player, @NotNull Inventory inventory) { inventory.setItem(0, ItemUtils.item(XMaterial.GRASS_BLOCK, Lang.itemType.toString())); - inventory.setItem(1, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1))); + inventory.setItem(1, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.quickFormat("amount", 1))); inventory.setItem(2, ItemUtils.itemSwitch(Lang.itemFlags.toString(), false)); inventory.setItem(3, ItemUtils.item(XMaterial.NAME_TAG, Lang.itemName.toString())); inventory.setItem(4, ItemUtils.item(XMaterial.FEATHER, Lang.itemLore.toString())); @@ -80,7 +80,7 @@ public void onClick(GuiClickEvent event) { Lang.CHOOSE_ITEM_AMOUNT.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { amount = /* Math.min(obj, 64) */ obj; - ItemUtils.name(event.getClicked(), Lang.Amount.format(amount)); + ItemUtils.name(event.getClicked(), Lang.Amount.quickFormat("amount", amount)); event.reopen(); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index e4c0f5de..9f38fa9e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -17,7 +17,6 @@ import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.utils.types.Title; public class TitleGUI extends AbstractGui { @@ -77,18 +76,19 @@ public void setSubtitle(String subtitle) { public void setFadeIn(int fadeIn) { this.fadeIn = fadeIn; ItemUtils.lore(inv.getItem(SLOT_FADE_IN), - QuestOption.formatNullableValue(Lang.Ticks.format(fadeIn), fadeIn == Title.FADE_IN)); + QuestOption.formatNullableValue(Lang.Ticks.quickFormat("ticks", fadeIn), fadeIn == Title.FADE_IN)); } public void setStay(int stay) { this.stay = stay; - ItemUtils.lore(inv.getItem(SLOT_STAY), QuestOption.formatNullableValue(Lang.Ticks.format(stay), stay == Title.STAY)); + ItemUtils.lore(inv.getItem(SLOT_STAY), + QuestOption.formatNullableValue(Lang.Ticks.quickFormat("ticks", stay), stay == Title.STAY)); } public void setFadeOut(int fadeOut) { this.fadeOut = fadeOut; ItemUtils.lore(inv.getItem(SLOT_FADE_OUT), - QuestOption.formatNullableValue(Lang.Ticks.format(fadeOut), fadeOut == Title.FADE_OUT)); + QuestOption.formatNullableValue(Lang.Ticks.quickFormat("ticks", fadeOut), fadeOut == Title.FADE_OUT)); } @Override @@ -120,19 +120,19 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { public void onClick(GuiClickEvent event) { switch (event.getSlot()) { case SLOT_TITLE: - startStringEditor(event.getPlayer(), Lang.TITLE_TITLE.toString(), this::setTitle); + startStringEditor(event.getPlayer(), Lang.TITLE_TITLE, this::setTitle); break; case SLOT_SUBTITLE: - startStringEditor(event.getPlayer(), Lang.TITLE_SUBTITLE.toString(), this::setSubtitle); + startStringEditor(event.getPlayer(), Lang.TITLE_SUBTITLE, this::setSubtitle); break; case SLOT_FADE_IN: - startIntEditor(event.getPlayer(), Lang.TITLE_FADEIN.toString(), this::setFadeIn); + startIntEditor(event.getPlayer(), Lang.TITLE_FADEIN, this::setFadeIn); break; case SLOT_STAY: - startIntEditor(event.getPlayer(), Lang.TITLE_STAY.toString(), this::setStay); + startIntEditor(event.getPlayer(), Lang.TITLE_STAY, this::setStay); break; case SLOT_FADE_OUT: - startIntEditor(event.getPlayer(), Lang.TITLE_FADEOUT.toString(), this::setFadeOut); + startIntEditor(event.getPlayer(), Lang.TITLE_FADEOUT, this::setFadeOut); break; case 7: close(event.getPlayer()); @@ -152,8 +152,8 @@ public CloseBehavior onClose(Player p) { return new DelayCloseBehavior(() -> end.accept(null)); } - private void startStringEditor(Player p, String helpMsg, Consumer<String> setter) { - MessageUtils.sendPrefixedMessage(p, helpMsg); + private void startStringEditor(Player p, Lang helpMsg, Consumer<String> setter) { + helpMsg.send(p); new TextEditor<String>(p, () -> { p.openInventory(inv); }, msg -> { @@ -163,8 +163,8 @@ private void startStringEditor(Player p, String helpMsg, Consumer<String> setter }).passNullIntoEndConsumer().start(); } - private void startIntEditor(Player p, String helpMsg, Consumer<Integer> setter) { - MessageUtils.sendPrefixedMessage(p, helpMsg); + private void startIntEditor(Player p, Lang helpMsg, Consumer<Integer> setter) { + helpMsg.send(p); new TextEditor<>(p, () -> { p.openInventory(inv); }, msg -> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java index f1514205..4424d922 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java @@ -80,7 +80,7 @@ public void createObject(Function<MutableCountableObject<Mob<?>>, ItemStack> cal @Override public ItemStack getObjectItemStack(MutableCountableObject<Mob<?>> mob) { List<String> lore = new ArrayList<>(); - lore.add(Lang.Amount.format(mob.getAmount())); + lore.add(Lang.Amount.format(mob)); lore.addAll(mob.getObject().getDescriptiveLore()); lore.add(""); lore.add(Lang.click.toString()); diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index a2512156..c5c17932 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -19,7 +19,9 @@ import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; public class NpcCreateGUI extends AbstractGui { @@ -58,21 +60,22 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { private void setName(String name) { this.name = name; - ItemUtils.lore(getInventory().getItem(1), Lang.optionValue.format(name)); + ItemUtils.lore(getInventory().getItem(1), QuestOption.formatNullableValue(name)); } private void setType(EntityType type) { this.en = type; if (en == EntityType.PLAYER) { - getInventory().setItem(5, ItemUtils.skull(Lang.type.toString(), null, Lang.optionValue.format("player"))); + getInventory().setItem(5, ItemUtils.skull(Lang.npcType.toString(), null, QuestOption.formatNullableValue("player"))); } else getInventory().setItem(5, - ItemUtils.item(Utils.mobItem(en), Lang.type.toString(), Lang.optionValue.format(en.getName()))); + ItemUtils.item(Utils.mobItem(en), Lang.npcType.toString(), + QuestOption.formatNullableValue(en.getName()))); } private void setSkin(String skin) { this.skin = skin; - getInventory().setItem(3, ItemUtils.skull(Lang.skin.toString(), skin, Lang.optionValue.format(skin))); + getInventory().setItem(3, ItemUtils.skull(Lang.skin.toString(), skin, QuestOption.formatNullableValue(skin))); } @Override @@ -119,7 +122,7 @@ public void onClick(GuiClickEvent event) { end.accept(QuestsPlugin.getPlugin().getNpcManager().createNPC(event.getPlayer().getLocation(), en, name, skin)); }catch (Exception ex) { ex.printStackTrace(); - Lang.ERROR_OCCURED.send(event.getPlayer(), "npc creation " + ex.getMessage()); + DefaultErrors.sendGeneric(event.getPlayer(), "npc creation " + ex.getMessage()); cancel.run(); } break; diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index 5b5b4333..f36442a7 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -19,6 +19,7 @@ import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; @@ -54,9 +55,9 @@ public ParticleEffectGUI(Consumer<ParticleEffect> end, Particle particle, Partic this.color = color; buttons.put(1, LayoutedButton.create(XMaterial.FIREWORK_STAR, Lang.particle_shape.toString(), - () -> Arrays.asList(Lang.optionValue.format(shape)), this::shapeClick)); + () -> Arrays.asList(QuestOption.formatNullableValue(shape)), this::shapeClick)); buttons.put(3, LayoutedButton.create(XMaterial.PAPER, Lang.particle_type.toString(), - () -> Arrays.asList(Lang.optionValue.format(particle)), this::particleClick)); + () -> Arrays.asList(QuestOption.formatNullableValue(particle)), this::particleClick)); buttons.put(4, new LayoutedButton.ItemButton() { @Override public void click(@NotNull LayoutedClickEvent event) { @@ -65,8 +66,8 @@ public void click(@NotNull LayoutedClickEvent event) { @Override public @Nullable ItemStack getItem() { - return ItemUtils.item(XMaterial.MAGENTA_DYE, Lang.particle_color.toString(), - Lang.optionValue.format("RGB: " + color.getRed() + " " + color.getGreen() + " " + color.getBlue())); + return ItemUtils.item(XMaterial.MAGENTA_DYE, Lang.particle_color.toString(), QuestOption + .formatNullableValue("RGB: " + color.getRed() + " " + color.getGreen() + " " + color.getBlue())); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java index 5eaefc9a..c3dc9f04 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java @@ -21,8 +21,10 @@ public PermissionListGUI(List<Permission> list, Consumer<List<Permission>> end) this.end = end; } + @Override public ItemStack getObjectItemStack(Permission object) { - return ItemUtils.item(XMaterial.PAPER, "§e" + object.permission, Lang.permRemoved.format(object.take ? Lang.Yes : Lang.No), Lang.permWorld.format(object.world == null ? Lang.worldGlobal.toString() : object.world)); + return ItemUtils.item(XMaterial.PAPER, "§e" + object.permission, Lang.permRemoved.format(object), + Lang.permWorld.format(object)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index 86823e8d..a3e28a29 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -71,11 +71,11 @@ private String[] getNPCLore() { } private String[] getHologramLore() { - return new String[] { "", hologram == null ? QuestOption.formatNullableValue(Lang.PoolHologramText.toString()) + " " + Lang.defaultValue.toString() : Lang.optionValue.format(hologram) }; + return new String[] { "", hologram == null ? QuestOption.formatNullableValue(Lang.PoolHologramText.toString()) + " " + Lang.defaultValue.toString() : QuestOption.formatNullableValue(hologram) }; } private String[] getMaxQuestsLore() { - return new String[] { "", Lang.optionValue.format(maxQuests) }; + return new String[] { "", QuestOption.formatNullableValue(maxQuests) }; } private String[] getQuestsPerLaunchLore() { @@ -83,11 +83,11 @@ private String[] getQuestsPerLaunchLore() { } private String[] getTimeLore() { - return new String[] { "", Lang.optionValue.format(Utils.millisToHumanString(timeDiff)) }; + return new String[] {"", QuestOption.formatNullableValue(Utils.millisToHumanString(timeDiff))}; } private String[] getRequirementsLore() { - return new String[] { "", QuestOption.formatDescription(Lang.requirements.format(requirements.size())) }; + return new String[] {"", QuestOption.formatDescription(requirements.getSizeString())}; } private void handleDoneButton(Inventory inv) { 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 e2310d70..10047a34 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 @@ -148,7 +148,8 @@ class WrappedDialogable { messagesInPage++; added = true; } - page.header = "§7§l" + messagesAdded + "§8 / §7§l" + Lang.dialogLines.format(messages.size()); + page.header = "§7§l" + messagesAdded + "§8 / §7§l" + + Lang.AmountDialogLines.quickFormat("amount", messages.size()); page.lines.addLast(" " + (pages.isEmpty() ? "§8" : "§7") + "◀ " + Lang.ClickLeft + " §8/ " + (last && !pageFull ? "§8" : "§7") + Lang.ClickRight + " ▶"); pages.add(page); @@ -163,7 +164,8 @@ class WrappedDialogable { } if (!page.lines.isEmpty()) { - page.header = "§7§l" + messagesAdded + "§8 / §7§l" + Lang.dialogLines.format(messages.size()); + page.header = + "§7§l" + messagesAdded + "§8 / §7§l" + Lang.AmountDialogLines.quickFormat("amount", messages.size()); page.lines.addLast( " " + (pages.isEmpty() ? "§8" : "§7") + "◀ " + Lang.ClickLeft + " §8/ " + Lang.ClickRight + " ▶"); pages.add(page); 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 9a45f8fb..1a1160d3 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 @@ -21,7 +21,6 @@ import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.gui.templates.ConfirmGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; @@ -56,7 +55,7 @@ public PlayerListGUI(PlayerAccountImplementation acc, boolean hide) { @Override protected Inventory instanciate(@NotNull Player player) { - return Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc.getOfflinePlayer().getName())); + return Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc)); } @Override @@ -177,7 +176,8 @@ private int setBarItem(int barSlot, ItemStack is){ } private ItemStack createQuestItem(Quest qu, List<String> lore) { - return ItemUtils.nameAndLore(qu.getQuestItem().clone(), open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu.getName(), qu.getId()) : Lang.formatNormal.format(qu.getName()), lore); + return ItemUtils.nameAndLore(qu.getQuestItem().clone(), + open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu) : Lang.formatNormal.format(qu), lore); } private void toggleCategorySelected() { @@ -246,8 +246,10 @@ public void onClick(GuiClickEvent event) { } else if (event.getClick().isLeftClick()) { if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { - ConfirmGUI.confirm(() -> qu.cancelPlayer(acc), event::reopen, - Lang.INDICATION_CANCEL.format(qu.getName())).open(event.getPlayer()); + QuestsPlugin.getPlugin().getGuiManager().getFactory() + .createConfirmation(() -> qu.cancelPlayer(acc), event::reopen, + Lang.INDICATION_CANCEL.format(qu)) + .open(event.getPlayer()); } } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java index df12533a..69963fc8 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java @@ -11,7 +11,7 @@ import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; public class OptionDescription extends QuestOptionString implements QuestDescriptionProvider { @@ -55,8 +55,8 @@ public boolean isMultiline() { public List<String> provideDescription(QuestDescriptionContext context) { List<String> description = cachedDescription.getIfPresent(context); if (description == null) { - description = - Arrays.asList("§7" + MessageUtils.finalFormat(context.getPlayerAccount().getPlayer(), getValue(), true)); + description = Arrays + .asList("§7" + MessageUtils.finalFormat(context.getPlayerAccount().getPlayer(), getValue(), true, null)); cachedDescription.put(context, description); } return description; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java index d62f3b74..7a85d720 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java @@ -9,8 +9,9 @@ import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class OptionEndRewards extends QuestOptionRewards implements QuestDescriptionProvider { @@ -42,7 +43,8 @@ public List<String> provideDescription(QuestDescriptionContext context) { .filter(Objects::nonNull) .flatMap(SPLIT_PATTERN::splitAsStream) .filter(x -> !x.isEmpty()) - .map(x -> MessageUtils.format(context.getDescriptionOptions().getRewardsFormat(), x)) + .map(x -> MessageUtils.format(context.getDescriptionOptions().getRewardsFormat(), + PlaceholderRegistry.of("reward_description", x))) .collect(Collectors.toList()); if (rewards.isEmpty()) return null; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java index 95d3f2be..62f89c51 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFailOnDeath.java @@ -26,7 +26,7 @@ public void onDeath(PlayerDeathEvent e) { if (acc == null) return; if (getAttachedQuest().hasStarted(acc)) { getAttachedQuest().cancelPlayer(acc); - Lang.QUEST_FAILED.send(e.getEntity(), getAttachedQuest().getName()); + Lang.QUEST_FAILED.send(e.getEntity(), getAttachedQuest()); } } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java b/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java index 99a3e7c7..47a79065 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRepeatable.java @@ -30,10 +30,10 @@ public List<String> provideDescription(QuestDescriptionContext context) { if (quest.testTimer(context.getPlayerAccount(), false)) { lore.add(Lang.canRedo.toString()); }else { - lore.add(Lang.timeWait.format(quest.getTimeLeft(context.getPlayerAccount()))); + lore.add(Lang.timeWait.quickFormat("time_left", quest.getTimeLeft(context.getPlayerAccount()))); } lore.add(null); - lore.add(Lang.timesFinished.format(context.getQuestDatas().getTimesFinished())); + lore.add(Lang.timesFinished.quickFormat("times_finished", context.getQuestDatas().getTimesFinished())); return lore; } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java index eb49622c..58a00f7a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java @@ -15,8 +15,9 @@ import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementCreator; import fr.skytasul.quests.api.requirements.RequirementList; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class OptionRequirements extends QuestOptionObject<AbstractRequirement, RequirementCreator, RequirementList> implements QuestDescriptionProvider { @@ -27,8 +28,8 @@ protected AbstractRequirement deserialize(Map<String, Object> map) { } @Override - protected String getSizeString(int size) { - return Lang.requirements.format(size); + protected String getSizeString() { + return RequirementList.getSizeString(getValue().size()); } @Override @@ -68,7 +69,8 @@ public List<String> provideDescription(QuestDescriptionContext context) { if (description != null) description = MessageUtils.format(x.test(context.getPlayerAccount().getPlayer()) ? context.getDescriptionOptions().getRequirementsValid() - : context.getDescriptionOptions().getRequirementsInvalid(), description); + : context.getDescriptionOptions().getRequirementsInvalid(), + PlaceholderRegistry.of("requirement_description", description)); return description; }) .filter(Objects::nonNull) diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java index 11c5f57c..990782de 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java @@ -49,7 +49,7 @@ public boolean shouldDisplay(OptionSet options) { private String[] getLore() { return new String[] {formatDescription(Lang.startDialogLore.toString()), "", getValue() == null ? Lang.NotSet.toString() - : "§7" + Lang.AmountDialogLines.format(getValue().getMessages().size())}; + : "§7" + Lang.AmountDialogLines.quickFormat("lines_amount", getValue().getMessages().size())}; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 731b8110..4000d43e 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -5,7 +5,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; 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 7ce4c08e..102c6fe5 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java @@ -20,6 +20,7 @@ import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.players.accounts.AbstractAccount; public class PlayerAccountImplementation implements PlayerAccount { @@ -31,6 +32,8 @@ public class PlayerAccountImplementation implements PlayerAccount { protected final Map<Integer, PlayerPoolDatasImplementation> poolDatas = new HashMap<>(); protected final Map<SavableData<?>, Object> additionalDatas = new HashMap<>(); protected final int index; + + private @Nullable PlaceholderRegistry placeholders; protected PlayerAccountImplementation(@NotNull AbstractAccount account, int index) { this.abstractAcc = account; @@ -157,6 +160,18 @@ public void resetDatas() { additionalDatas.clear(); } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry() + .registerIndexed("player", this::getNameAndID) + .register("player_name", this::getName) + .register("account_id", index) + .register("account_identifier", abstractAcc::getIdentifier); + } + return placeholders; + } + @Override public boolean equals(Object object) { if (object == this) diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java index 396e7167..5592e886 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java @@ -56,7 +56,8 @@ public boolean test(Player p) { @Override public String getDefaultDescription(Player p) { - return Lang.RDClass.format(String.join(" " + Lang.Or.toString() + " ", (Iterable<String>) () -> classes.stream().map(RPGClass::getName).iterator())); + return Lang.RDClass.quickFormat("classes", String.join(" " + Lang.Or.toString() + " ", + (Iterable<String>) () -> classes.stream().map(RPGClass::getName).iterator())); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java index e9f0f6a5..bbf53a32 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java @@ -43,7 +43,8 @@ public void addFaction(Object faction){ @Override public String getDefaultDescription(Player p) { - return Lang.RDFaction.format(String.join(" " + Lang.Or.toString() + " ", (Iterable<String>) () -> factions.stream().map(Faction::getName).iterator())); + return Lang.RDFaction.quickFormat("factions", String.join(" " + Lang.Or.toString() + " ", + (Iterable<String>) () -> factions.stream().map(Faction::getName).iterator())); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java index d158b816..41c540cd 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java @@ -2,6 +2,7 @@ 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.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -9,6 +10,7 @@ import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.Jobs; public class JobLevelRequirement extends TargetNumberRequirement { @@ -40,14 +42,25 @@ public void sendHelpString(Player p) { Lang.CHOOSE_XP_REQUIRED.send(p); } + @Override + protected String getPlaceholderName() { + return "level"; + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("job_name", () -> jobName); + } + @Override protected String getDefaultReason(Player player) { - return Lang.REQUIREMENT_JOB.format(getFormattedValue(), jobName); + return Lang.REQUIREMENT_JOB.format(this); } @Override public String getDefaultDescription(Player p) { - return Lang.RDJobLevel.format(Integer.toString((int) target), jobName); + return Lang.RDJobLevel.format(this); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java index 74928685..579e7355 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/LevelRequirement.java @@ -23,7 +23,7 @@ public double getPlayerTarget(Player p) { @Override protected String getDefaultReason(Player player) { - return Lang.REQUIREMENT_LEVEL.format(getFormattedValue()); + return Lang.REQUIREMENT_LEVEL.format(this); } @Override @@ -36,9 +36,14 @@ public void sendHelpString(Player p) { Lang.CHOOSE_XP_REQUIRED.send(p); } + @Override + protected String getPlaceholderName() { + return "level"; + } + @Override public String getDefaultDescription(Player p) { - return Lang.RDLevel.format(getShortFormattedValue()); + return Lang.RDLevel.format(this); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java index 662bce57..d5ff759d 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java @@ -23,14 +23,19 @@ public double getPlayerTarget(Player p) { return McCombatLevel.getCombatLevel(p); } + @Override + protected String getPlaceholderName() { + return "level"; + } + @Override protected String getDefaultReason(Player player) { - return Lang.REQUIREMENT_COMBAT_LEVEL.format(getFormattedValue()); + return Lang.REQUIREMENT_COMBAT_LEVEL.format(this); } @Override public String getDefaultDescription(Player p) { - return Lang.RDCombatLevel.format(Integer.toString((int) target)); + return Lang.RDCombatLevel.format(this); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java index 365c1add..f9576529 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java @@ -2,6 +2,7 @@ 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.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -9,6 +10,7 @@ import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.McMMO; public class McMMOSkillRequirement extends TargetNumberRequirement { @@ -28,14 +30,25 @@ public double getPlayerTarget(Player p) { return McMMO.getLevel(p, skillName); } + @Override + protected String getPlaceholderName() { + return "level"; + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("skill_name", () -> skillName); + } + @Override protected String getDefaultReason(Player player) { - return Lang.REQUIREMENT_SKILL.format(getFormattedValue(), skillName); + return Lang.REQUIREMENT_SKILL.format(this); } @Override public String getDefaultDescription(Player p) { - return Lang.RDSkillLevel.format(Integer.toString((int) target), skillName); + return Lang.RDSkillLevel.format(this); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java index 841111a7..18b85baf 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java @@ -2,13 +2,16 @@ 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.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.Actionnable; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.Vault; public class MoneyRequirement extends AbstractRequirement implements Actionnable { @@ -32,9 +35,16 @@ public void trigger(Player p) { Vault.withdrawPlayer(p, money); } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("money", Vault.format(money)); + placeholders.register("money_raw", money); + } + @Override protected String getDefaultReason(Player player) { - return Lang.REQUIREMENT_MONEY.format(Vault.format(money)); + return Lang.REQUIREMENT_MONEY.format(this); } @Override @@ -50,7 +60,7 @@ public AbstractRequirement clone() { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.optionValue.format(money)); + loreBuilder.addDescription(QuestOption.formatNullableValue(money)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java index 9a7f074e..a81e525f 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java @@ -8,6 +8,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; @@ -16,6 +17,7 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class PermissionsRequirement extends AbstractRequirement { @@ -38,10 +40,16 @@ public boolean test(Player p) { return true; } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("permissions_amount", permissions.size()); + } + @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.AmountPermissions.format(permissions.size())); + loreBuilder.addDescription(Lang.AmountPermissions.format(this)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java index 255b0605..f2383a8e 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java @@ -3,6 +3,7 @@ import java.math.BigDecimal; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.localization.Lang; @@ -11,7 +12,8 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; @@ -39,6 +41,15 @@ public PlaceholderRequirement(String customDescription, String customReason, Str this.comparison = comparison; } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("placeholder", () -> rawPlaceholder); + placeholders.register("target_value", () -> value); + placeholders.register("comparison", () -> Character.toString(comparison.getSymbol())); + placeholders.register("parse_value", () -> Boolean.toString(parseValue)); + } + @Override public boolean test(Player p){ if (hook == null) return false; @@ -59,7 +70,7 @@ public boolean test(Player p){ if (comparison == ComparisonMethod.DIFFERENT) return !value.equals(request); String value = this.value; if (parseValue) - value = MessageUtils.finalFormat(p, value, true); + value = MessageUtils.finalFormat(p, value, true, null); return value.equals(request); } @@ -128,7 +139,7 @@ public void load(ConfigurationSection section){ protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(rawPlaceholder)); - loreBuilder.addDescription(comparison.getTitle().format(value)); + loreBuilder.addDescription(comparison.getTitle().quickFormat("number", value)); } @Override @@ -136,7 +147,7 @@ public void itemClick(QuestObjectClickEvent event) { Lang.CHOOSE_PLACEHOLDER_REQUIRED_IDENTIFIER.send(event.getPlayer()); new TextEditor<String>(event.getPlayer(), event::cancel, id -> { setPlaceholder(id); - Lang.CHOOSE_PLACEHOLDER_REQUIRED_VALUE.send(event.getPlayer(), id); + Lang.CHOOSE_PLACEHOLDER_REQUIRED_VALUE.send(event.getPlayer(), this); new TextEditor<String>(event.getPlayer(), () -> { if (value == null) event.getGUI().remove(this); event.reopenGUI(); @@ -144,7 +155,9 @@ public void itemClick(QuestObjectClickEvent event) { this.value = value; try { new BigDecimal(value); // tests if the value is a number - Lang.COMPARISON_TYPE.send(event.getPlayer(), ComparisonMethod.getComparisonParser().getNames(), ComparisonMethod.EQUALS.name().toLowerCase()); + Lang.COMPARISON_TYPE.send(event.getPlayer(), + PlaceholderRegistry.of("available", ComparisonMethod.getComparisonParser().getNames(), "default", + ComparisonMethod.EQUALS.name().toLowerCase()).with(this)); new TextEditor<>(event.getPlayer(), null, comp -> { this.comparison = comp == null ? ComparisonMethod.EQUALS : comp; event.reopenGUI(); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java index 30144985..817625fc 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java @@ -2,6 +2,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -10,11 +11,12 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; public class QuestRequirement extends AbstractRequirement { - public int questId; + private int questId; private Quest cached; public QuestRequirement() { @@ -32,14 +34,21 @@ public boolean test(Player p) { return true; } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("quest_name", () -> exists() ? cached.getName() : Integer.toString(questId)); + placeholders.register("quest_id", () -> Integer.toString(questId)); + } + @Override protected String getDefaultReason(Player player) { - return exists() ? Lang.REQUIREMENT_QUEST.format(cached.getName()) : null; + return exists() ? Lang.REQUIREMENT_QUEST.format(cached) : null; } @Override public String getDefaultDescription(Player p) { - return Lang.RDQuest.format(exists() ? cached.getName() : questId); + return Lang.RDQuest.format(exists() ? cached : this); } private boolean exists(){ diff --git a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java index 8f9a6fe1..cdce3546 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java @@ -3,6 +3,7 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; @@ -11,6 +12,7 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; public class RegionRequirement extends AbstractRequirement { @@ -37,6 +39,13 @@ private void setRegionName(String regionName) { } } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("region_name", () -> regionName); + placeholders.register("region_world", () -> worldName); + } + @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java index 65f00666..1179ccc1 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java @@ -43,6 +43,11 @@ public Class<? extends Number> numberClass() { return Double.class; } + @Override + protected String getPlaceholderName() { + return "score"; + } + @Override public void sendHelpString(Player p) { Lang.CHOOSE_SCOREBOARD_TARGET.send(p); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java index e3614ead..cec669c5 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java @@ -23,9 +23,14 @@ public double getPlayerTarget(Player p) { return SkillAPI.getLevel(p); } + @Override + protected String getPlaceholderName() { + return "level"; + } + @Override protected String getDefaultReason(Player player) { - return Lang.REQUIREMENT_LEVEL.format(getFormattedValue()); + return Lang.REQUIREMENT_LEVEL.format(this); } @Override @@ -40,7 +45,7 @@ public void sendHelpString(Player p) { @Override public String getDefaultDescription(Player p) { - return Lang.RDLevel.format(Integer.toString((int) target)); + return Lang.RDLevel.format(this); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java index 85b32183..df79c2c0 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java @@ -3,7 +3,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; @@ -39,7 +38,7 @@ public void detach() { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.requirements.format(requirements.size())); + loreBuilder.addDescription(requirements.getSizeString()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java index c49bfc1e..7b1ac28a 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java @@ -3,6 +3,7 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; @@ -13,6 +14,7 @@ import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.rewards.RewardList; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class CheckpointReward extends AbstractReward { @@ -39,6 +41,16 @@ public void detach() { actions.detachQuest(); } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("actions_amount", this::getActionsSizeString); + } + + private @NotNull String getActionsSizeString() { + return Lang.actions.quickFormat("amount", actions.size()); + } + @Override public List<String> give(Player p) { Lang.QUEST_CHECKPOINT.send(p); @@ -61,7 +73,7 @@ public AbstractReward clone() { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.actions.format(actions.size())); + loreBuilder.addDescription(getActionsSizeString()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index 93742529..0452a93c 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.ListGUI; @@ -47,7 +48,11 @@ public AbstractReward clone() { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.commands.format(commands.size())); + loreBuilder.addDescription(getCommandsSizeString()); + } + + private @NotNull String getCommandsSizeString() { + return Lang.commands.quickFormat("amount", commands.size()); } @Override @@ -69,7 +74,8 @@ public void clickObject(Command object, ItemStack item, ClickType clickType) { @Override public ItemStack getObjectItemStack(Command cmd) { - return ItemUtils.item(XMaterial.CHAIN_COMMAND_BLOCK, Lang.commandsListValue.format(cmd.label), Lang.commandsListConsole.format(cmd.console ? Lang.Yes : Lang.No)); + return ItemUtils.item(XMaterial.CHAIN_COMMAND_BLOCK, Lang.commandsListValue.format(cmd), + Lang.commandsListConsole.format(cmd.getPlaceholdersRegistry().shifted("command_console"))); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java index 279c9b5d..cfc103fa 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java @@ -2,15 +2,18 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.items.ItemsGUI; public class ItemReward extends AbstractReward { @@ -29,8 +32,9 @@ public ItemReward(String customDescription, List<ItemStack> items) { @Override public List<String> give(Player p) { Utils.giveItems(p, items); - int amount = items.stream().mapToInt(ItemStack::getAmount).sum(); - return amount == 0 ? null : Arrays.asList(amount + " " + Lang.Item.toString()); + if (items.isEmpty()) + return Collections.emptyList(); + return Arrays.asList(getItemsSizeString()); } @Override @@ -40,13 +44,23 @@ public AbstractReward clone() { @Override public String getDefaultDescription(Player p) { - return items.stream().mapToInt(ItemStack::getAmount).sum() + " " + Lang.Item.toString(); + return getItemsSizeString(); + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("items_amount", this::getItemsSizeString); + } + + private String getItemsSizeString() { + return Lang.AmountItems.quickFormat("amount", items.stream().mapToInt(ItemStack::getAmount).sum()); } @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(items.size() + " " + Lang.Item.toString()); + loreBuilder.addDescription(getItemsSizeString()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java index f16a973d..46416020 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java @@ -1,14 +1,18 @@ package fr.skytasul.quests.rewards; +import java.util.Collections; 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.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class MessageReward extends AbstractReward { @@ -23,8 +27,8 @@ public MessageReward(String customDescription, String text) { @Override public List<String> give(Player p) { - MessageUtils.sendOffMessage(p, text); - return null; + MessageUtils.sendMessage(p, text, MessageType.OFF); + return Collections.emptyList(); } @Override @@ -32,6 +36,12 @@ public AbstractReward clone() { return new MessageReward(getCustomDescription(), text); } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("message", () -> text); + } + @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java index 51934a4a..6b8c40cb 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java @@ -4,12 +4,14 @@ 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.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.Vault; public class MoneyReward extends AbstractReward { @@ -36,6 +38,13 @@ public AbstractReward clone() { return new MoneyReward(getCustomDescription(), money); } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("money", Vault.format(money)); + placeholders.register("money_raw", money); + } + @Override public String getDefaultDescription(Player p) { return Vault.format(money); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java index e027aa5b..e67ee30c 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java @@ -4,10 +4,13 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.permissions.PermissionListGUI; import fr.skytasul.quests.utils.types.Permission; @@ -36,11 +39,17 @@ public List<String> give(Player p) { public AbstractReward clone() { return new PermissionReward(getCustomDescription(), new ArrayList<>(permissions)); } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("permissions_amount", permissions.size()); + } @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescriptionAsValue(permissions.size() + " permissions"); + loreBuilder.addDescriptionAsValue(Lang.AmountPermissions.format(this)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java index eb754153..c6f0e810 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java @@ -8,6 +8,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; @@ -20,6 +21,7 @@ import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.rewards.RewardList; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class RandomReward extends AbstractReward { @@ -57,6 +59,14 @@ public void detach() { rewards.forEach(AbstractReward::detach); } + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("min", () -> Integer.toString(min)); + placeholders.register("max", () -> Integer.toString(max)); + placeholders.register("rewards_amount", () -> rewards.getSizeString()); + } + @Override public List<String> give(Player p) throws InterruptingBranchException { ThreadLocalRandom random = ThreadLocalRandom.current(); @@ -103,7 +113,7 @@ public String getDefaultDescription(Player p) { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.actions.format(rewards.size())); + loreBuilder.addDescription(Lang.actions.quickFormat("amount", rewards.size())); loreBuilder.addDescriptionRaw("§8 | min: §7" + min + "§8 | max: §7" + max); loreBuilder.addClick(ClickType.LEFT, Lang.rewardRandomRewards.toString()); loreBuilder.addClick(ClickType.RIGHT, Lang.rewardRandomMinMax.toString()); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java index 3cefbf11..fc858e5b 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java @@ -8,12 +8,14 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.items.ItemComparisonGUI; import fr.skytasul.quests.gui.items.ItemsGUI; @@ -50,14 +52,29 @@ public AbstractReward clone() { @Override public String getDefaultDescription(Player p) { - return items.stream().mapToInt(ItemStack::getAmount).sum() + " " + Lang.Item.toString(); + return getItemsSizeString(); + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("items_amount", this::getItemsSizeString); + placeholders.register("comparisons_amount", this::getComparisonsSizeString); + } + + private String getItemsSizeString() { + return Lang.AmountItems.quickFormat("amount", items.stream().mapToInt(ItemStack::getAmount).sum()); } + private @NotNull String getComparisonsSizeString() { + return Lang.AmountComparisons.quickFormat("amount", comparisons.getEffective().size()); + } + @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.AmountItems.format(items.size())); - loreBuilder.addDescription(Lang.AmountComparisons.format(comparisons.getEffective().size())); + loreBuilder.addDescription(getItemsSizeString()); + loreBuilder.addDescription(getComparisonsSizeString()); loreBuilder.addClick(ClickType.LEFT, Lang.stageItems.toString()); loreBuilder.addClick(ClickType.RIGHT, Lang.stageItemsComparison.toString()); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 86944b39..687d03d6 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -86,18 +86,18 @@ public String getDefaultDescription(Player p) { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescription(Lang.rewards.format(rewards.size())); - loreBuilder.addDescription(Lang.requirements.format(requirements.size())); + loreBuilder.addDescription(rewards.getSizeString()); + loreBuilder.addDescription(requirements.getSizeString()); } @Override public void itemClick(QuestObjectClickEvent event) { LayoutedGUI.newBuilder() .addButton(0, - LayoutedButton.create(XMaterial.NETHER_STAR, () -> "§b" + Lang.requirements.format(requirements.size()), + LayoutedButton.create(XMaterial.NETHER_STAR, () -> "§b" + requirements.getSizeString(), Collections.emptyList(), this::editRequirements)) .addButton(1, - LayoutedButton.create(XMaterial.CHEST, () -> "§a" + Lang.rewards.format(rewards.size()), + LayoutedButton.create(XMaterial.CHEST, () -> "§a" + rewards.getSizeString(), Collections.emptyList(), this::editRewards)) .addButton(4, LayoutedButton.create(ItemUtils.itemDone, __ -> event.reopenGUI())) .setName(Lang.INVENTORY_REWARDS_WITH_REQUIREMENTS.toString()) diff --git a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java index 1b73d4ee..c87dbac6 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java @@ -3,12 +3,14 @@ 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.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class WaitReward extends AbstractReward { @@ -29,7 +31,17 @@ public boolean isAsync() { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescriptionAsValue(Lang.Ticks.format(delay)); + loreBuilder.addDescriptionAsValue(getTicksString()); + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("delay", this::getTicksString); + } + + private @NotNull String getTicksString() { + return Lang.Ticks.quickFormat("ticks", delay); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index e40f0ada..bd4bf3c8 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -4,6 +4,7 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; @@ -11,7 +12,7 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.compatibility.SkillAPI; @@ -32,7 +33,7 @@ public List<String> give(Player p) { && QuestsConfigurationImplementation.getConfiguration().xpOverridedSkillAPI()) { SkillAPI.giveExp(p, exp); }else p.giveExp(exp); - return Arrays.asList(exp + " " + Lang.Exp.toString()); + return Arrays.asList(getXpAmountString()); } @Override @@ -42,21 +43,32 @@ public AbstractReward clone() { @Override public String getDefaultDescription(Player p) { - return exp + " " + Lang.Exp.toString(); + return getXpAmountString(); } @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescriptionAsValue(exp + " " + Lang.Exp.toString()); + loreBuilder.addDescriptionAsValue(getXpAmountString()); + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("xp_amount", this::getXpAmountString); + } + + private @NotNull String getXpAmountString() { + return Lang.AmountXp.quickFormat("xp_amount", exp); } @Override public void itemClick(QuestObjectClickEvent event) { - MessageUtils.sendPrefixedMessage(event.getPlayer(), Lang.XP_GAIN.toString(), exp); + Lang.XP_GAIN.send(event.getPlayer(), this); new TextEditor<>(event.getPlayer(), event::cancel, obj -> { - MessageUtils.sendPrefixedMessage(event.getPlayer(), Lang.XP_EDITED.toString(), exp, obj); + int old = exp; exp = obj; + Lang.XP_EDITED.send(event.getPlayer(), PlaceholderRegistry.of("old_xp_amount", old).with(this)); event.reopenGUI(); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); } diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java index c629833f..2a7e4244 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java @@ -26,9 +26,9 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.ChatColorUtils; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; public class Scoreboard extends BukkitRunnable implements Listener { @@ -307,7 +307,7 @@ private boolean tryRefresh(boolean time) { lines = Collections.emptyList(); lastValue = null; } else { - text = MessageUtils.finalFormat(p, text, true); + text = MessageUtils.finalFormat(p, text, true, null); if (text.equals(lastValue)) return false; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java index ad634be8..41687402 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java @@ -26,7 +26,7 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardEntryEvent; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 88f026ad..91eed130 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -16,14 +16,15 @@ import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.SplittableDescriptionConfiguration; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.gui.items.ItemComparisonGUI; import fr.skytasul.quests.gui.items.ItemsGUI; @@ -219,7 +220,7 @@ public void setMessage(String message) { getLine().refreshItemLore(9, message == null ? Lang.optionValue.format(Lang.NEED_OBJECTS.toString()) + " " + Lang.defaultValue.toString() - : Lang.optionValue.format(message)); + : QuestOption.formatNullableValue(message)); } public void setComparisons(ItemComparisonMap comparisons) { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index d0bed7f5..a3bb41de 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -11,6 +11,7 @@ import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; @@ -18,7 +19,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; public class StageChat extends AbstractStage{ @@ -130,7 +131,7 @@ public void setupLine(@NotNull StageGuiLine line) { public void setText(String text) { this.text = text; - getLine().refreshItem(MESSAGE_SLOT, item -> ItemUtils.lore(item, Lang.optionValue.format(text))); + getLine().refreshItem(MESSAGE_SLOT, item -> ItemUtils.lore(item, QuestOption.formatNullableValue(text))); } public void setPlaceholders(boolean placeholders) { 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 4ed17f3f..8d278115 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -39,8 +39,8 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; diff --git a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java index d6e39dac..0ee6f66e 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java @@ -50,6 +50,7 @@ public int getId(@NotNull QuestBranch branch) { return -1; } + @SuppressWarnings("rawtypes") @Override public @UnmodifiableView @NotNull Collection<@NotNull QuestBranch> getBranches() { return (Collection) branches.values(); diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java index 64fcf43b..3523191b 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -26,7 +26,9 @@ import fr.skytasul.quests.api.requirements.Actionnable; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.QuestUtils; @@ -139,9 +141,10 @@ public boolean isEndingStage(StageController stage) { if (datas.getStage() < 0) return "§cerror: no stage set for branch " + getId(); if (datas.getStage() >= regularStages.size()) return "§cerror: datas do not match"; + return MessageUtils.format(QuestsConfiguration.getConfig().getStageDescriptionConfig().getStageDescriptionFormat(), - datas.getStage() + 1, - regularStages.size(), regularStages.get(datas.getStage()).getDescriptionLine(acc, source)); + PlaceholderRegistry.of("stage_index", datas.getStage() + 1, "stage_amount", regularStages.size(), + "stage_description", regularStages.get(datas.getStage()).getDescriptionLine(acc, source))); } @Override @@ -248,13 +251,14 @@ private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplem try { List<String> given = stage.getStage().getRewards().giveRewards(p); if (!given.isEmpty() && QuestsConfiguration.getConfig().getQuestsConfig().stageEndRewardsMessage()) - Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); + Lang.FINISHED_OBTAIN.quickSend(p, "rewards", + MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); } catch (InterruptingBranchException ex) { QuestsPlugin.getPlugin().getLoggerExpanded().debug( "Interrupted branching in async stage end for " + p.getName() + " via " + ex.toString()); return; }catch (Exception e) { - Lang.ERROR_OCCURED.send(p, "giving async rewards"); + DefaultErrors.sendGeneric(p, "giving async rewards"); QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while giving stage async end rewards.", e); } finally { // by using the try-catch, we ensure that "asyncReward#remove" is called @@ -267,7 +271,8 @@ private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplem try { List<String> given = stage.getStage().getRewards().giveRewards(p); if (!given.isEmpty() && QuestsConfiguration.getConfig().getQuestsConfig().stageEndRewardsMessage()) - Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); + Lang.FINISHED_OBTAIN.quickSend(p, "rewards", + MessageUtils.itemsToFormattedString(given.toArray(new String[0]))); runAfter.run(); } catch (InterruptingBranchException ex) { QuestsPlugin.getPlugin().getLoggerExpanded().debug( @@ -284,14 +289,15 @@ public void setStage(@NotNull PlayerAccount acc, int id) { StageControllerImplementation<?> stage = regularStages.get(id); Player p = acc.getPlayer(); if (stage == null){ - if (p != null) Lang.ERROR_OCCURED.send(p, " noStage"); + if (p != null) + DefaultErrors.sendGeneric(p, " noStage"); QuestsPlugin.getPlugin().getLoggerExpanded().severe("Error into the StageManager of quest " + getQuest().getName() + " : the stage " + id + " doesn't exists."); remove(acc, true); }else { PlayerQuestDatas questDatas = acc.getQuestDatas(getQuest()); if (QuestsConfiguration.getConfig().getQuestsConfig().playerQuestUpdateMessage() && p != null && questDatas.getStage() != -1) - Lang.QUEST_UPDATED.send(p, getQuest().getName()); + Lang.QUEST_UPDATED.send(p, getQuest()); questDatas.setStage(id); if (p != null) playNextStage(p); stage.start(acc); @@ -302,7 +308,7 @@ public void setStage(@NotNull PlayerAccount acc, int id) { public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { Player p = acc.getPlayer(); if (QuestsConfiguration.getConfig().getQuestsConfig().playerQuestUpdateMessage() && p != null && launchStage) - Lang.QUEST_UPDATED.send(p, getQuest().getName()); + Lang.QUEST_UPDATED.send(p, getQuest()); PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); datas.setInEndingStages(); for (EndingStageImplementation endStage : endStages) { diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index a065eaec..d2ae4733 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -30,7 +30,6 @@ import fr.skytasul.quests.api.events.QuestLaunchEvent; import fr.skytasul.quests.api.events.QuestPreLaunchEvent; import fr.skytasul.quests.api.events.QuestRemoveEvent; -import fr.skytasul.quests.api.gui.templates.ConfirmGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.QuestOptionCreator; @@ -43,10 +42,13 @@ import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.Actionnable; import fr.skytasul.quests.api.rewards.InterruptingBranchException; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.PlayerListCategory; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.options.*; import fr.skytasul.quests.players.AdminMode; @@ -68,6 +70,8 @@ public class QuestImplementation implements Quest, QuestDescriptionProvider { private boolean removed = false; public List<Player> inAsyncStart = new ArrayList<>(); + private PlaceholderRegistry placeholders; + public QuestImplementation(int id) { this(id, new File(BeautyQuests.getInstance().getQuestsManager().getSaveFolder(), id + ".yml")); } @@ -93,6 +97,7 @@ public boolean isValid() { return descriptions; } + @SuppressWarnings("rawtypes") @Override public Iterator<QuestOption> iterator() { return (Iterator) options.iterator(); @@ -152,6 +157,10 @@ public File getFile(){ return file; } + public String getNameAndId() { + return getName() + " (#" + id + ")"; + } + @Override public @Nullable String getName() { return getOptionValueOrDef(OptionName.class); @@ -314,7 +323,7 @@ public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boo } if (QuestsAPI.getAPI().getQuestsManager().getStartedSize(acc) >= playerMaxLaunchedQuest) { if (sendMessage) - Lang.QUESTS_MAX_LAUNCHED.send(p, playerMaxLaunchedQuest); + Lang.QUESTS_MAX_LAUNCHED.quickSend(p, "quests_max_amount", playerMaxLaunchedQuest); return false; } return true; @@ -324,7 +333,8 @@ public boolean testTimer(@NotNull PlayerAccount acc, boolean sendMessage) { if (isRepeatable() && acc.hasQuestDatas(this)) { long time = acc.getQuestDatas(this).getTimer(); if (time > System.currentTimeMillis()) { - if (sendMessage && acc.isCurrent()) Lang.QUEST_WAIT.send(acc.getPlayer(), getTimeLeft(acc)); + if (sendMessage && acc.isCurrent()) + Lang.QUEST_WAIT.quickSend(acc.getPlayer(), "time_left", getTimeLeft(acc)); return false; }else if (time != 0) acc.getQuestDatas(this).setTimer(0); } @@ -380,6 +390,18 @@ public double getDescriptionPriority() { return 15; } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry() + .registerIndexed("quest", this::getNameAndId) + .register("quest_name", this::getName) + .register("quest_id", id) + .register("quest_description", this::getDescription); + } + return placeholders; + } + @Override public @NotNull CompletableFuture<Boolean> attemptStart(@NotNull Player p) { if (!canStart(p, true)) @@ -389,12 +411,12 @@ public double getDescriptionPriority() { if (QuestsConfiguration.getConfig().getQuestsConfig().questConfirmGUI() && !"none".equals(confirm = getOptionValueOrDef(OptionConfirmMessage.class))) { CompletableFuture<Boolean> future = new CompletableFuture<>(); - ConfirmGUI.confirm(() -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createConfirmation(() -> { start(p); future.complete(true); }, () -> { future.complete(false); - }, Lang.INDICATION_START.format(getName()), confirm).open(p); + }, Lang.INDICATION_START.format(getPlaceholdersRegistry()), confirm).open(p); return future; }else { start(p); @@ -422,7 +444,7 @@ public void start(@NotNull Player p, boolean silently) { if (!silently) { String startMsg = getOptionValueOrDef(OptionStartMessage.class); if (!"none".equals(startMsg)) - MessageUtils.sendRawMessage(p, startMsg, true, getName()); + MessageUtils.sendRawMessage(p, startMsg, true, getPlaceholdersRegistry()); } Runnable run = () -> { @@ -434,7 +456,8 @@ public void start(@NotNull Player p, boolean silently) { } getOptionValueOrDef(OptionRequirements.class).stream().filter(Actionnable.class::isInstance).map(Actionnable.class::cast).forEach(x -> x.trigger(p)); if (!silently && !msg.isEmpty()) - Lang.FINISHED_OBTAIN.send(p, MessageUtils.itemsToFormattedString(msg.toArray(new String[0]))); + Lang.FINISHED_OBTAIN.quickSend(p, "rewards", + MessageUtils.itemsToFormattedString(msg.toArray(new String[0]))); inAsyncStart.remove(p); QuestUtils.runOrSync(() -> { @@ -462,12 +485,13 @@ public void finish(@NotNull Player p) { if (hasOption(OptionEndMessage.class)) { String endMsg = getOption(OptionEndMessage.class).getValue(); if (!"none".equals(endMsg)) - MessageUtils.sendRawMessage(p, endMsg, true, obtained); + MessageUtils.sendRawMessage(p, endMsg, true, PlaceholderRegistry.of("rewards", obtained).with(this)); } else - MessageUtils.sendPrefixedMessage(p, Lang.FINISHED_BASE.format(getName()) - + (msg.isEmpty() ? "" : " " + Lang.FINISHED_OBTAIN.format(obtained))); + MessageUtils.sendMessage(p, Lang.FINISHED_BASE.format(this) + + (msg.isEmpty() ? "" : " " + Lang.FINISHED_OBTAIN.quickFormat("rewards", obtained)), + MessageType.PREFIXED); }catch (Exception ex) { - Lang.ERROR_OCCURED.send(p, "reward message"); + DefaultErrors.sendGeneric(p, "reward message"); QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while giving quest end rewards.", ex); } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java index 336c7f49..350af26c 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestsManagerImplementation.java @@ -93,6 +93,7 @@ public int updateAll() throws IOException { return saveFolder; } + @SuppressWarnings("rawtypes") @Override public @NotNull List<Quest> getQuests() { return (List) quests; diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index ad9614b3..badc3dc8 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -22,7 +22,8 @@ import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageHandler; import fr.skytasul.quests.api.stages.StageType; -import fr.skytasul.quests.api.utils.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.utils.QuestUtils; public class StageControllerImplementation<T extends AbstractStage> implements StageController, Listener { @@ -94,7 +95,7 @@ public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nu @Override public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { if (stage.getCustomText() != null) - return "§e" + MessageUtils.format(stage.getCustomText(), stage.descriptionFormat(acc, source)); + return "§e" + MessageUtils.format(stage.getCustomText(), stage.getPlaceholdersRegistry()); try { return stage.descriptionLine(acc, source); @@ -120,7 +121,7 @@ private void propagateStageHandlers(@NotNull Consumer<@NotNull StageHandler> con public void start(@NotNull PlayerAccount acc) { if (acc.isCurrent()) - MessageUtils.sendOffMessage(acc.getPlayer(), stage.getStartMessage()); + MessageUtils.sendMessage(acc.getPlayer(), stage.getStartMessage(), MessageType.OFF); Map<String, Object> datas = new HashMap<>(); stage.initPlayerDatas(acc, datas); acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); 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 ed83ed28..9486bd11 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 @@ -10,11 +10,14 @@ 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 com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; 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.options.QuestOption; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayerPoolDatas; import fr.skytasul.quests.api.players.PlayersManager; @@ -23,6 +26,8 @@ import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.players.PlayerPoolDatasImplementation; import fr.skytasul.quests.utils.QuestUtils; @@ -42,6 +47,8 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati BqNpcImplementation npc; List<Quest> quests = new ArrayList<>(); + + private @Nullable PlaceholderRegistry placeholders; QuestPoolImplementation(int id, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements) { this.id = id; @@ -129,20 +136,37 @@ public int compareTo(QuestPoolImplementation o) { return Integer.compare(id, o.id); } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry() + .registerIndexed("pool", "#" + id) + .register("pool_id", id) + .register("pool_npc", () -> npcID + " (" + (npc == null ? "unknown" : npc.getNpc().getName()) + ")") + .register("pool_max_quests", maxQuests) + .register("pool_quests_per_launch", questsPerLaunch) + .register("pool_redo", MessageUtils.getYesNo(redoAllowed)) + .register("pool_duplicates", MessageUtils.getYesNo(avoidDuplicates)) + .register("pool_time", Utils.millisToHumanString(timeDiff)) + .register("pool_hologram", QuestOption.formatNullableValue(hologram, Lang.PoolHologramText)) + .register("pool_quests", + () -> quests.stream().map(x -> "#" + x.getId()).collect(Collectors.joining(", "))); + } + return placeholders; + } + @Override public ItemStack getItemStack(String action) { - return ItemUtils.item(XMaterial.CHEST, Lang.poolItemName.format(id), - Lang.poolItemNPC.format(npcID + " (" + (npc == null ? "unknown" : npc.getNpc().getName()) - + ")"), - Lang.poolItemMaxQuests.format(maxQuests), - Lang.poolItemQuestsPerLaunch.format(questsPerLaunch), - Lang.poolItemRedo.format(redoAllowed ? Lang.Enabled : Lang.Disabled), - Lang.poolItemTime.format(Utils.millisToHumanString(timeDiff)), - Lang.poolItemHologram.format(hologram == null ? "\n§7 > " + Lang.PoolHologramText.toString() + "\n§7 > " + Lang.defaultValue : hologram), - Lang.poolItemAvoidDuplicates.format(avoidDuplicates ? Lang.Enabled : Lang.Disabled), - "§7" + Lang.requirements.format(requirements.size()), - Lang.poolItemQuestsList.format(quests.size(), - quests.stream().map(x -> "#" + x.getId()).collect(Collectors.joining(", "))), + return ItemUtils.item(XMaterial.CHEST, Lang.poolItemName.format(this), + Lang.poolItemNPC.format(this), + Lang.poolItemMaxQuests.format(this), + Lang.poolItemQuestsPerLaunch.format(this), + Lang.poolItemRedo.format(this), + Lang.poolItemTime.format(this), + Lang.poolItemHologram.format(this), + Lang.poolItemAvoidDuplicates.format(this), + "§7" + requirements.getSizeString(), + Lang.poolItemQuestsList.format(this), "", action); } @@ -197,7 +221,8 @@ public CompletableFuture<String> give(Player p) { long time = (datas.getLastGive() + timeDiff) - System.currentTimeMillis(); if (time > 0) - return CompletableFuture.completedFuture(Lang.POOL_NO_TIME.format(Utils.millisToHumanString(time))); + return CompletableFuture + .completedFuture(Lang.POOL_NO_TIME.quickFormat("time_left", Utils.millisToHumanString(time))); return CompletableFuture.supplyAsync(() -> { List<Quest> started = new ArrayList<>(questsPerLaunch); @@ -240,7 +265,7 @@ private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, P } else if (acc.getQuestsDatas().stream().filter(quest -> quest.hasStarted() && quests.contains(quest.getQuest())) .count() >= maxQuests) { // player has too much quests in this pool to be able to start one more - return CompletableFuture.completedFuture(new PoolGiveResult(Lang.POOL_MAX_QUESTS.format(maxQuests))); + return CompletableFuture.completedFuture(new PoolGiveResult(Lang.POOL_MAX_QUESTS.format(this))); } List<Quest> notStarted = notCompleted.stream().filter(quest -> !quest.hasStarted(acc)).collect(Collectors.toList()); diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java index a3b39950..d769603a 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java @@ -97,6 +97,7 @@ public void removePool(int id) { return pools.get(id); } + @SuppressWarnings("rawtypes") @Override public @NotNull @UnmodifiableView Collection<QuestPool> getPools() { return (Collection) pools.values(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java index 0df91091..279de6cc 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java @@ -18,9 +18,9 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; import io.lumine.xikage.mythicmobs.mobs.MythicMob; import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderString; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java index 924d2614..e0595820 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java @@ -19,9 +19,9 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.utils.MessageUtils; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import io.lumine.mythic.api.mobs.MythicMob; import io.lumine.mythic.api.skills.placeholders.PlaceholderString; import io.lumine.mythic.bukkit.MythicBukkit; diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java index bb62b176..41487ae9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java @@ -5,18 +5,25 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +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.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; -public class Command { +public class Command implements HasPlaceholders { public final String label; public final boolean console; public final boolean parse; public final int delay; + private @Nullable PlaceholderRegistry placeholders; + public Command(String label, boolean console, boolean parse, int delay) { this.label = label; this.console = console; @@ -37,6 +44,18 @@ public void execute(Player o){ }else Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), run, delay); } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry() + .registerIndexed("command_label", label) + .registerIndexed("command_console", console ? Lang.Yes : Lang.No) + .register("command_parsed", parse ? Lang.Yes : Lang.No) + .register("command_delay", Lang.Ticks.quickFormat("ticks", delay)); + } + return placeholders; + } + public Map<String, Object> serialize(){ Map<String, Object> map = new HashMap<>(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java index 4b246213..6bc1e5ff 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java @@ -10,7 +10,7 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.DialogSendEvent; import fr.skytasul.quests.api.events.DialogSendMessageEvent; @@ -63,14 +63,17 @@ private TestResult test(Player p) { @Override public boolean canContinue(Player p) { - if (npc == null || QuestsConfigurationImplementation.getDialogsConfig().getMaxDistance() == 0) return true; - return p.getLocation().distanceSquared(npc.getLocation()) <= QuestsConfigurationImplementation.getDialogsConfig().getMaxDistanceSquared(); + if (npc == null || QuestsConfiguration.getConfig().getDialogsConfig().getMaxDistance() == 0) + return true; + return p.getLocation().distanceSquared(npc.getLocation()) <= QuestsConfiguration.getConfig().getDialogsConfig() + .getMaxDistanceSquared(); } private void end(Player p) { if (test(p) != TestResult.ALLOW) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Dialog predicates not completed for NPC " + npc.getId() - + " whereas the dialog should end. This is a bug."); + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Dialog predicates not completed for NPC " + npc.getNpc().getId() + + " whereas the dialog should end. This is a bug."); return; } @@ -79,13 +82,13 @@ private void end(Player p) { @Override public TestResult onClick(Player p) { - if (QuestsConfigurationImplementation.getDialogsConfig().isClickDisabled()) { + if (QuestsConfiguration.getConfig().getDialogsConfig().isClickDisabled()) { PlayerStatus status = players.get(p); if (status != null && status.task != null) return TestResult.DENY; } if (p.isSneaking() && dialog != null && dialog.isSkippable() && test(p) == TestResult.ALLOW) { - Lang.DIALOG_SKIPPED.sendWP(p); + Lang.DIALOG_SKIPPED.send(p); removePlayer(p); end(p); return TestResult.ALLOW; @@ -125,7 +128,7 @@ public TestResult handleNext(Player p, DialogNextReason reason) { if (canContinue(p)) { handleNext(p, DialogNextReason.AUTO_TIME); }else { - Lang.DIALOG_TOO_FAR.send(p, dialog.getNPCName(npc)); + Lang.DIALOG_TOO_FAR.quickSend(p, "npc_name", dialog.getNPCName(npc)); removePlayer(p); } }, message.getWaitTime()); @@ -194,7 +197,7 @@ public PlayerStatus addPlayer(Player player) { if (npc != null && navigationInitiallyPaused == null) { // pause NPC walking as there is a player in dialog - navigationInitiallyPaused = npc.setNavigationPaused(true); + navigationInitiallyPaused = npc.getNpc().setNavigationPaused(true); } return status; } @@ -213,7 +216,7 @@ public boolean removePlayer(Player player) { private void handlePlayerChanges() { if (players.isEmpty() && npc != null && navigationInitiallyPaused != null) { // if no more players are in dialog, resume NPC walking - npc.setNavigationPaused(navigationInitiallyPaused); + npc.getNpc().setNavigationPaused(navigationInitiallyPaused); navigationInitiallyPaused = null; } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java b/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java index ba2fe3f1..0e8b90ac 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java @@ -3,9 +3,14 @@ import java.util.HashMap; import java.util.Map; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.Vault; -public class Permission implements Cloneable { +public class Permission implements Cloneable, HasPlaceholders { public final String permission, world; public final boolean take; @@ -20,6 +25,12 @@ public void give(Player p) { Vault.changePermission(p, permission, take, world); } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + return PlaceholderRegistry.of("permission", permission, "permission_removed", MessageUtils.getYesNo(take), + "permission_world", world == null ? Lang.worldGlobal.toString() : world); + } + public Map<String, Object> serialize() { Map<String, Object> map = new HashMap<>(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Title.java b/core/src/main/java/fr/skytasul/quests/utils/types/Title.java index adb7690c..6155acac 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Title.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Title.java @@ -42,7 +42,7 @@ public void send(Player p) { @Override public String toString() { - return title + ", " + subtitle + ", " + Lang.Ticks.format(fadeIn + stay + fadeOut); + return title + ", " + subtitle + ", " + Lang.Ticks.quickFormat("ticks", fadeIn + stay + fadeOut); } public void serialize(ConfigurationSection section) { diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 7950e6b6..7059b01b 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -145,7 +145,7 @@ dynmap: # - Stage descriptions - # {0} = stage index, {1} = stage amount, {2} = stage description} -stageDescriptionFormat: "§8({0}/{1}) §e{2}" +stageDescriptionFormat: "§8({stage_index}/{stage_amount}) §e{stage_description}" # Prefix before object's name in lists (example: §6first, §6second and §6third) itemNameColor: "§6§o" # Prefix before object's amount in lists (example: first§ex2, second§ex7 and third§ex4) @@ -170,14 +170,14 @@ questDescription: # Enable the requirements section for quest description display: true # How to format requirements which match the player - valid: §a ✔ §7{0} + valid: §a ✔ §7{requirement_description} # How to format requirements which do not match the player - invalid: §c ✖ §7{0} + invalid: §c ✖ §7{requirement_description} rewards: # Enable the rewards section for quest description display: true # How to format rewards - format: §7- {0} + format: §7- {reward_description} # - Particles configuration - # enabled: will the particle be shown? diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 9a9a4af8..c2b8bc97 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -1,31 +1,31 @@ msg: quest: finished: - base: §aCongratulations! You have finished the quest §e{0}§a! - obtain: §aYou obtain {0}! + base: §aCongratulations! You have finished the quest §e{quest_name}§a! + obtain: §aYou obtain {rewards}! started: §aYou have started the quest §r§e{0}§o§6! - created: §aCongratulations! You have created the quest §e{0}§a which includes - {1} branch(es)! - edited: §aCongratulations! You have edited the quest §e{0}§a which includes now - {1} branch(es)! + created: §aCongratulations! You have created the quest §e{quest}§a which includes + {quest_branches} branch(es)! + edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes + {quest_branches} branch(es)! createCancelled: §cThe creation or edition has been cancelled by another plugin! cancelling: §cProcess of quest creation cancelled. editCancelling: §cProcess of quest edition cancelled. - invalidID: §cThe quest with the id {0} doesn't exist. - invalidPoolID: §cThe pool {0} does not exist. + invalidID: §cThe quest with the id {quest_id} doesn't exist. + invalidPoolID: §cThe pool {pool_id} does not exist. alreadyStarted: §cYou have already started the quest! notStarted: §cYou are not currently doing this quest. quests: - maxLaunched: §cYou cannot have more than {0} quest(s) at the same time... + maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same time... nopStep: §cThis quest doesn't have any step. - updated: §7Quest §e{0}§7 updated. + updated: §7Quest §e{quest_name}§7 updated. checkpoint: §7Quest checkpoint reached! - failed: §cYou have failed the quest {0}... + failed: §cYou have failed the quest {quest_name}... pools: - noTime: §cYou must wait {0} before doing another quest. + noTime: §cYou must wait {time_left} before doing another quest. allCompleted: §7You have completed all the quests! noAvailable: §7There is no more quest available... - maxQuests: §cYou cannot have more than {0} quest(s) at the same time... + maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same time... questItem: drop: §cYou can't drop a quest item! craft: §cYou can't use a quest item to craft! @@ -37,7 +37,7 @@ msg: "help" to receive help.)' writeRegionName: '§aWrite the name of the region required for the step:' writeXPGain: '§aWrite the amount of experience points the player will obtain: (Last - value: {0})' + value: {xp_amount})' writeMobAmount: '§aWrite the amount of mobs to kill:' writeMobName: '§aWrite the custom name of the mob to kill:' writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if @@ -69,65 +69,64 @@ msg: writeQuestDescription: '§aWrite the description of the quest, shown in the player''s quest GUI.' writeQuestMaterial: '§aWrite the material of the quest item.' requirements: - quest: §cYou must have finished the quest §e{0}§c! - level: §cYour level must be {0}! - job: §cYour level for the job §e{1}§c must be {0}! - skill: §cYour level for the skill §e{1}§c must be {0}! - combatLevel: §cYour combat level must be {0}! - money: §cYou must have {0}! - waitTime: §cYou must wait {0} before you can restart this quest! + quest: §cYou must have finished the quest §e{quest_name}§c! + level: §cYour level must be {long_level}! + job: §cYour level for the job §e{job_name}§c must be {long_level}! + skill: §cYour level for the skill §e{skill_name}§c must be {long_level}! + combatLevel: §cYour combat level must be {long_level}! + money: §cYou must have {money}! + waitTime: §cYou must wait {time_left} before you can restart this quest! experience: - edited: §aYou have changed the experience gain from {0} to {1} points. + edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} points. selectNPCToKill: §aSelect the NPC to kill. npc: remove: §aNPC deleted. talk: §aGo and talk to the NPC named §e{0}§a. regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) - npcDoesntExist: §cThe NPC with the id {0} doesn't exist. - objectDoesntExist: §cThe specified item with the id {0} doesn't exist. + npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. number: negative: §cYou must enter a positive number! zero: §cYou must enter a number other than 0! - invalid: §c{0} isn't a valid number. - notInBounds: §cYour number must be between {0} and {1}. - errorOccurred: '§cAn error occurred, contact an adminstrator! §4§lError code: {0}' + invalid: §c{input} isn't a valid number. + notInBounds: §cYour number must be between {min} and {max}. + errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: {error}' commandsDisabled: §cCurrently you aren't allowed to execute commands! - indexOutOfBounds: §cThe number {0} is out of bounds! It has to be between {1} and - {2}. - invalidBlockData: §cThe blockdata {0} is invalid or incompatible with the block {1}. - invalidBlockTag: §cUnavailable block tag {0}. + indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} and + {max}. + invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the block {block_material}. + invalidBlockTag: §cUnavailable block tag {block_tag}. bringBackObjects: Bring me back {0}. inventoryFull: §cYour inventory is full, the item has been dropped on the floor. playerNeverConnected: §cUnable to find informations about the player {0}. playerNotOnline: §cThe player {0} is offline. playerDataNotFound: §cDatas of player {0} not found. - versionRequired: 'Version required: §l{0}' + versionRequired: 'Version required: §l{version}' restartServer: '§7Restart your server to see the modifications.' dialogs: skipped: '§8§o Dialog skipped.' - tooFar: '§7§oYou are too far away from {0}...' + tooFar: '§7§oYou are too far away from {npc_name}...' command: downloadTranslations: syntax: '§cYou must specify a language to download. Example: "/quests downloadTranslations en_US".' - notFound: '§cLanguage {0} not found for version {1}.' - exists: '§cThe file {0} already exists. Append "-overwrite" to your command to overwrite it. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§aLanguage {0} has been downloaded! §7You must now edit the - file "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 with {0}, then restart the server.' + notFound: '§cLanguage {lang} not found for version {version}.' + exists: '§cThe file {file_name} already exists. Append "-overwrite" to your command to overwrite it. (/quests downloadTranslations <lang> -overwrite)' + downloaded: '§aLanguage {lang} has been downloaded! §7You must now edit the + file "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 with {lang}, then restart the server.' checkpoint: - noCheckpoint: §cNo checkpoint found for the quest {0}. + noCheckpoint: §cNo checkpoint found for the quest {quest}. questNotStarted: §cYou are not doing this quest. setStage: - branchDoesntExist: §cThe branch with the id {0} doesn't exist. - doesntExist: §cThe stage with the id {0} doesn't exist. + branchDoesntExist: §cThe branch with the id {branch_id} doesn't exist. + doesntExist: §cThe stage with the id {stage_id} doesn't exist. next: §aThe stage has been skipped. nextUnavailable: §cThe "skip" option is not available when the player is at the end of a branch. - set: §aStage {0} launched. + set: §aStage {stage_id} launched. startDialog: impossible: §cImpossible to start the dialog now. noDialog: §cThe player has no pending dialog. alreadyIn: §cThe player is already playing a dialog. - success: §aStarted dialog for player {0} in quest {1}! + success: §aStarted dialog for player {player} in quest {quest}! playerNeeded: §cYou must be a player to execute this command! incorrectSyntax: §cIncorrect syntax. noPermission: '§cYou haven''t enough permissions to execute this command! (Required: @@ -138,17 +137,17 @@ msg: needItem: §cYou must hold an item in your main hand! itemChanged: §aThe item has been edited. The changes will affect after a restart. itemRemoved: §aThe hologram item has been removed. - removed: §aThe quest {0} has successfully been removed. - leaveAll: '§aYou have forced the end of {0} quest(s). Errors: {1}' + removed: §aThe quest {quest_name} has successfully been removed. + leaveAll: '§aYou have forced the end of {success} quest(s). Errors: {errors}' resetPlayer: - player: §6All informations of your {0} quest(s) has/have been deleted by {1}. - remover: §6{0} quest information(s) (and {2} pools) of {1} has/have been deleted. + player: §6All informations of your {quest_amount} quest(s) has/have been deleted by {deleter_name}. + remover: §6{quest_amount} quest information(s) (and {quest_pool} pools) of {player} has/have been deleted. resetPlayerQuest: - player: §6All informations about the quest {0} have been deleted by {1}. - remover: §6{0} quest information(s) of {1} has/have been deleted. - resetQuest: §6Removed datas of the quest for {0} players. - startQuest: '§6You have forced starting of quest {0} (Player UUID: {1}).' - startQuestNoRequirements: '§cThe player does not meet the requirements for the quest {0}... + player: §6All informations about the quest {quest} have been deleted by {deleter_name}. + remover: §6{player} informations of quest {quest} has/have been deleted. + resetQuest: §6Removed datas of the quest for {player_amount} players. + startQuest: '§6You have forced starting of quest {quest} for {player}.' + startQuestNoRequirements: '§cThe player does not meet the requirements for the quest {quest}... Append "-overrideRequirements" at the end of your command to bypass the requirements check.' cancelQuest: §6You have cancelled the quest {0}. cancelQuestUnavailable: §cThe quest {0} can't be cancelled. @@ -159,54 +158,54 @@ msg: adminModeEntered: §aYou have entered the Admin Mode. adminModeLeft: §aYou have left the Admin Mode. resetPlayerPool: - timer: §aYou have reset the {0} pool timer of {1}. - full: §aYou have reset the {0} pool datas of {1}. + timer: §aYou have reset the {pool} pool timer of {player}. + full: §aYou have reset the {pool} pool datas of {player}. startPlayerPool: - error: 'Failed to start the pool {0} for {1}.' - success: 'Started pool {0} to {1}. Result: {2}' + error: 'Failed to start the pool {pool} for {player}.' + success: 'Started pool {pool} to {player}. Result: {result}' scoreboard: - lineSet: §6You have successfully edited the line {0}. - lineReset: §6You have successfully reset the line {0}. - lineRemoved: §6You have successfully removed the line {0}. - lineInexistant: §cThe line {0} doesn't exist. - resetAll: §6You have successfully reset the scoreboard of the player {0}. - hidden: §6The scoreboard of the player {0} has been hidden. - shown: §6The scoreboard of the player {0} has been shown. + lineSet: §6You have successfully edited the line {line_id}. + lineReset: §6You have successfully reset the line {line_id}. + lineRemoved: §6You have successfully removed the line {line_id}. + lineInexistant: §cThe line {line_id} doesn't exist. + resetAll: §6You have successfully reset the scoreboard of the player {player_name}. + hidden: §6The scoreboard of the player {player_name} has been hidden. + shown: §6The scoreboard of the player {player_name} has been shown. own: hidden: §6Your scoreboard is now hidden. shown: §6Your scoreboard is shown again. help: header: §6§lBeautyQuests — Help - create: '§6/{0} create: §eCreate a quest.' - edit: '§6/{0} edit: §eEdit a quest.' - remove: '§6/{0} remove <id>: §eDelete a quest with a specified id or click on + create: '§6/{label} create: §eCreate a quest.' + edit: '§6/{label} edit: §eEdit a quest.' + remove: '§6/{label} remove <id>: §eDelete a quest with a specified id or click on the NPC when not defined.' - finishAll: '§6/{0} finishAll <player>: §eFinish all quests of a player.' - setStage: '§6/{0} setStage <player> <id> [new branch] [new stage]: §eSkip the + finishAll: '§6/{label} finishAll <player>: §eFinish all quests of a player.' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eSkip the current stage/start the branch/set a stage for a branch.' - startDialog: '§6/{0} startDialog <player> <quest id>: §eStarts the pending dialog + startDialog: '§6/{label} startDialog <player> <quest id>: §eStarts the pending dialog for a NPC stage or the starting dialog for a quest.' - resetPlayer: '§6/{0} resetPlayer <player>: §eRemove all informations about a + resetPlayer: '§6/{label} resetPlayer <player>: §eRemove all informations about a player.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <player> [id]: §eDelete informations + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete informations of a quest for a player.' - seePlayer: '§6/{0} seePlayer <player>: §eView informations about a player.' - reload: '§6/{0} reload: §eSave and reload all configurations and files. (§cdeprecated§e)' - start: '§6/{0} start <player> [id]: §eForce the starting of a quest.' - setItem: '§6/{0} setItem <talk|launch>: §eSave the hologram item.' - setFirework: '§6/{0} setFirework: §eEdit the default ending firework.' - adminMode: '§6/{0} adminMode: §eToggle the Admin Mode. (Useful for displaying + seePlayer: '§6/{label} seePlayer <player>: §eView informations about a player.' + reload: '§6/{label} reload: §eSave and reload all configurations and files. (§cdeprecated§e)' + start: '§6/{label} start <player> [id]: §eForce the starting of a quest.' + setItem: '§6/{label} setItem <talk|launch>: §eSave the hologram item.' + setFirework: '§6/{label} setFirework: §eEdit the default ending firework.' + adminMode: '§6/{label} adminMode: §eToggle the Admin Mode. (Useful for displaying little log messages.)' - version: '§6/{0} version: §eSee the current plugin version.' - downloadTranslations: '§6/{0} downloadTranslations <language>: §eDownloads a vanilla translation file' - save: '§6/{0} save: §eMake a manual plugin save.' - list: '§6/{0} list: §eSee the quest list. (Only for supported versions.)' + version: '§6/{label} version: §eSee the current plugin version.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownloads a vanilla translation file' + save: '§6/{label} save: §eMake a manual plugin save.' + list: '§6/{label} list: §eSee the quest list. (Only for supported versions.)' typeCancel: §aWrite "cancel" to come back to the last text. editor: blockAmount: '§aWrite the amount of blocks:' blockName: '§aWrite the name of the block:' - blockData: '§aWrite the blockdata (available blockdatas: §7{0}§a):' - blockTag: '§aWrite the block tag (available tags: §7{0}§a):' + blockData: '§aWrite the blockdata (available blockdatas: §7{available_datas}§a):' + blockTag: '§aWrite the block tag (available tags: §7{available_tags}§a):' typeBucketAmount: '§aWrite the amount of buckets to fill:' typeDamageAmount: 'Write the amount of damage player have to deal:' goToLocation: §aGo to the wanted location for the stage. @@ -228,7 +227,7 @@ msg: choseStarter: §aChoose the NPC which starts the quest. notStarter: §cThis NPC isn't a quest starter. text: - argNotSupported: §cThe argument {0} not supported. + argNotSupported: §cThe argument {arg} not supported. chooseLvlRequired: '§aWrite the required amount of levels:' chooseJobRequired: '§aWrite name of the wanted job:' choosePermissionRequired: '§aWrite the required permission to start the quest:' @@ -237,7 +236,7 @@ msg: choosePlaceholderRequired: identifier: '§aWrite the name of the required placeholder without the percent characters:' - value: '§aWrite the required value for the placeholder §e%§e{0}§e%§a:' + value: '§aWrite the required value for the placeholder §e%§e{placeholder}§e%§a:' chooseSkillRequired: '§aWrite the name of the required skill:' chooseMoneyRequired: '§aWrite the amount of required money:' reward: @@ -269,15 +268,15 @@ msg: unknownBlockType: §cUnknown block type. invalidBlockType: §cInvalid block type. dialog: - syntax: '§cCorrect syntax: {0}{1} <message>' + syntaxMessage: '§cCorrect syntax: {command} <message>' syntaxRemove: '§cCorrect sytax: remove <id>' - player: §aMessage "§7{0}§a" added for the player. - npc: §aMessage "§7{0}§a" added for the NPC. - noSender: §aMessage "§7{0}§a" added without a sender. - messageRemoved: §aMessage "§7{0}§a" removed. - edited: §aMessage "§7{0}§a" edited. - soundAdded: §aSound "§7{0}§a" added for the message "§7{1}§a". - cleared: §aRemoved §2§l{0}§a message(s). + player: §aMessage "§7{msg}§a" added for the player. + npc: §aMessage "§7{msg}§a" added for the NPC. + noSender: §aMessage "§7{msg}§a" added without a sender. + messageRemoved: §aMessage "§7{msg}§a" removed. + edited: §aMessage "§7{msg}§a" edited. + soundAdded: §aSound "§7{sound}§a" added for the message "§7{msg}§a". + cleared: §aRemoved §2§l{amount}§a message(s). help: header: §6§lBeautyQuests — Dialog editor help npc: '§6npc <message>: §eAdd a message said by the NPC.' @@ -296,33 +295,33 @@ msg: setTime: '§6setTime <id> <time>: §eSet the time (in ticks) before the next msg plays automatically.' npcName: '§6npcName [custom NPC name]: §eSet (or reset to default) custom name of the NPC in the dialog' skippable: '§6skippable [true|false]: §eSet if the dialog can be skipped or not' - timeSet: '§aTime has been edited for message {0}: now {1} ticks.' - timeRemoved: '§aTime has been removed for message {0}.' + timeSet: '§aTime has been edited for message {msg}: now {time} ticks.' + timeRemoved: '§aTime has been removed for message {msg}.' npcName: - set: '§aCustom NPC name set to §7{1}§a (was §7{0}§a)' - unset: '§aCustom NPC name reset to default (was §7{0}§a)' + set: '§aCustom NPC name set to §7{new_name}§a (was §7{old_name}§a)' + unset: '§aCustom NPC name reset to default (was §7{old_name}§a)' skippable: - set: '§aThe dialog skippable status is now set to §7{1}§a (was §7{0}§a)' - unset: '§aThe dialog skippable status is reset to default (was §7{0}§a)' + set: '§aThe dialog skippable status is now set to §7{new_state}§a (was §7{old_state}§a)' + unset: '§aThe dialog skippable status is reset to default (was §7{old_state}§a)' mythicmobs: list: '§aA list of all Mythic Mobs:' isntMythicMob: §cThis Mythic Mob doesn't exist. disabled: §cMythicMob is disabled. advancedSpawnersMob: 'Write the name of the custom spawner mob to kill:' textList: - syntax: '§cCorrect syntax: ' - added: §aText "§7{0}§a" added. - removed: §aText "§7{0}§a" removed. + syntax: '§cCorrect syntax: {command}' + added: §aText "§7{msg}§a" added. + removed: §aText "§7{msg}§a" removed. help: header: §6§lBeautyQuests — List editor help add: '§6add <message>: §eAdd a text.' remove: '§6remove <id>: §eRemove a text.' list: '§6list: §eView all added texts.' close: '§6close: §eValidate the added texts.' - availableElements: 'Available elements: §e{0}' - noSuchElement: '§cThere is no such element. Allowed elements are: §e{0}' - invalidPattern: '§cInvalid regex pattern §4{0}§c.' - comparisonTypeDefault: '§aChoose the comparison type you want among {0}. Default comparison is: §e§l{1}§r§a. Type §onull§r§a to use it.' + availableElements: 'Available elements: §e{available_elements}' + noSuchElement: '§cThere is no such element. Allowed elements are: §e{available_elements}' + invalidPattern: '§cInvalid regex pattern §4{input}§c.' + comparisonTypeDefault: '§aChoose the comparison type you want among {available}. Default comparison is: §e§l{default}§r§a. Type §onull§r§a to use it.' scoreboardObjectiveNotFound: '§cUnknown scoreboard objective.' pool: hologramText: 'Write the custom hologram text for this pool (or "null" if you want the default one).' @@ -361,7 +360,7 @@ inv: stageRemove: §cDelete this step stageUp: Move up stageDown: Move down - stageType: '§7Stage type: §e{0}' + stageType: '§7Stage type: §e{stage_type}' cantFinish: §7You must create at least one stage before finishing quest creation! findNPC: §aFind NPC bringBack: §aBring back items @@ -384,7 +383,6 @@ inv: dealDamage: §cDeal damage to mobs eatDrink: §aEat or drink food or potions NPCText: §eEdit dialog - dialogLines: '{0} lines' NPCSelect: §eChoose or create NPC hideClues: Hide particles and holograms gps: Displays a compass towards the objective @@ -504,9 +502,9 @@ inv: hologramTextLore: Text displayed on the hologram above the Starter NPC's head. timer: §bRestart timer timerLore: Time before the player can start the quest again. - requirements: '{0} requirement(s)' - rewards: '{0} reward(s)' - actions: '{0} action(s)' + requirements: '{amount} requirement(s)' + rewards: '{amount} reward(s)' + actions: '{amount} action(s)' rewardsLore: Actions performed when the quest ends. customMaterial: '§eEdit quest item material' customMaterialLore: Item representative of this quest in the Quests Menu. @@ -525,7 +523,7 @@ inv: Force the plugin to preserve players datas, even though stages have been edited. §c§lWARNING §c- enabling this option may break your players datas. loreReset: '§e§lAll players'' advancement will be reset' - optionValue: '§8Value: §7{0}' + optionValue: '§8Value: §7{value}' defaultValue: '§8(default value)' requiredParameter: '§7Required parameter' itemsSelect: @@ -574,10 +572,10 @@ inv: requirements: name: Requirements setReason: Set custom reason - reason: '§8Custom reason: §7{0}' + reason: '§8Custom reason: §7{reason}' rewards: name: Rewards - commands: 'Commands: {0}' + commands: 'Commands: {amount}' teleportation: |- §aSelected: X: {0} @@ -596,7 +594,7 @@ inv: listAllQuests: name: Quests listPlayerQuests: - name: '{0}''s quests' + name: '{player_name}''s quests' listQuests: notStarted: Not started quests finished: Finished quests @@ -605,12 +603,12 @@ inv: loreCancelClick: §cCancel the quest loreStart: §a§oClick to start the quest. loreStartUnavailable: §c§oYou do not meet requirements to start the quest. - timeToWaitRedo: §3§oYou can restart this quest in {0}. + timeToWaitRedo: §3§oYou can restart this quest in {time_left}. canRedo: §3§oYou can restart this quest! - timesFinished: §3Quest done {0} times. + timesFinished: §3Quest done {times_finished} times. format: - normal: §6§l§o{0} - withId: §6§l§o{0}§r §e#{1} + normal: §6§l§o{quest_name} + withId: §6§l§o{quest_name}§r §e#{quest_id} itemCreator: name: Item creator itemType: §bItem type @@ -636,12 +634,12 @@ inv: noQuests: No quests have previously been created. commandsList: name: Command list - value: '§eCommand: {0}' - console: '§eConsole: {0}' + value: '§eCommand: {command_label}' + console: '§eConsole: {command_console}' block: name: Choose block - material: '§eMaterial: {0}' - materialNotItemLore: 'The block chosen cannot be displayed as an item. It is still correctly stored as {0}.' + material: '§eMaterial: {block_type}' + materialNotItemLore: 'The block chosen cannot be displayed as an item. It is still correctly stored as {block_material}.' blockName: '§bCustom block name' blockData: '§dBlockdata (advanced)' blockTag: '§dTag (advanced)' @@ -666,23 +664,23 @@ inv: removeLore: §7Permission will be taken off\n§7instead of given. permissionList: name: Permissions list - removed: '§eTaken off: §6{0}' - world: '§eWorld: §6{0}' + removed: '§eTaken off: §6{permission_removed}' + world: '§eWorld: §6{permission_world}' classesRequired.name: Classes required classesList.name: Classes list factionsRequired.name: Factions required factionsList.name: Factions list poolsManage: name: Quest Pools - itemName: '§aPool #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Max quests: §7{0}' - poolQuestsPerLaunch: '§8Quests given per launch: §7{0}' - poolRedo: '§8Can redo completed quests: §7{0}' - poolTime: '§8Time between quests: §7{0}' - poolHologram: '§8Hologram text: §7{0}' - poolAvoidDuplicates: '§8Avoid duplicates: §7{0}' - poolQuestsList: '§7{0} §8quest(s): §7{1}' + itemName: '§aPool {pool}' + poolNPC: '§8NPC: §7{pool_npc_id}' + poolMaxQuests: '§8Max quests: §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Quests given per launch: §7{pool_quests_per_launch}' + poolRedo: '§8Can redo completed quests: §7{pool_redo}' + poolTime: '§8Time between quests: §7{pool_time}' + poolHologram: '§8Hologram text: §7{pool_hologram}' + poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' + poolQuestsList: '§7{0} §8quest(s): §7{pool_quests}' create: §aCreate a quest pool edit: §e> §6§oEdit the pool... §e< choose: §e> §6§oChoose this pool §e< @@ -744,7 +742,7 @@ inv: name: Equipment slots questObjects: setCustomDescription: 'Set custom description' - description: '§8Description: §7{0}' + description: '§8Description: §7{description}' scoreboard: name: §6§lQuests @@ -778,20 +776,20 @@ scoreboard: mobs: §cDeal {0} damage to {1} eatDrink: §eConsume §6{0} indication: - startQuest: §7Do you want to start the quest {0}? + startQuest: §7Do you want to start the quest {quest_name}? closeInventory: §7Are you sure you want to close the GUI? - cancelQuest: §7Are you sure you want to cancel the quest {0}? - removeQuest: §7Are you sure you want to remove the quest {0}? + cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? + removeQuest: §7Are you sure you want to remove the quest {quest_name}? description: requirement: title: '§8§lRequirements:' - level: 'Level {0}' - jobLevel: 'Level {0} for {1}' - combatLevel: 'Combat level {0}' - skillLevel: 'Level {0} for {1}' - class: 'Class {0}' - faction: 'Faction {0}' - quest: 'Finish quest §e{0}' + level: 'Level {short_level}' + jobLevel: 'Level {short_level} for {job_name}' + combatLevel: 'Combat level {short_level}' + skillLevel: 'Level {short_level} for {skill_name}' + class: 'Class {class_name}' + faction: 'Faction {faction_name}' + quest: 'Finish quest §e{quest_name}' reward: title: '§8§lRewards:' @@ -833,12 +831,12 @@ misc: dealDamage: Deal damage eatDrink: Eat or drink comparison: - equals: equal to {0} - different: different to {0} - less: strictly less than {0} - lessOrEquals: less than {0} - greater: strictly greater than {0} - greaterOrEquals: greater than {0} + equals: equal to {number} + different: different to {number} + less: strictly less than {number} + lessOrEquals: less than {number} + greater: strictly greater than {number} + greaterOrEquals: greater than {number} requirement: logicalOr: §dLogical OR (requirements) skillAPILevel: §bSkillAPI level required @@ -867,12 +865,13 @@ misc: shift-left: Shift-left click middle: Middle click amounts: - items: '{0} item(s)' - comparisons: '{0} comparaison(s)' - dialogLines: '{0} line(s)' - permissions: '{0} permission(s)' - mobs: '{0} mob(s)' - ticks: '{0} ticks' + items: '{items_amount} item(s)' + comparisons: '{comparisons_amount} comparaison(s)' + dialogLines: '{lines_amount} line(s)' + permissions: '{permissions_amount} permission(s)' + mobs: '{mobs_amount} mob(s)' + xp: '{xp_amount} experience point(s)' + ticks: '{ticks} ticks' questItemLore: §e§oQuest Item hologramText: §8§lQuest NPC poolHologramText: §eNew quest available! @@ -889,9 +888,7 @@ misc: removeRaw: Remove reset: Reset or: or - amount: '§eAmount: {0}' - items: items - expPoints: experience points + amount: '§eAmount: {amount}' 'yes': 'Yes' 'no': 'No' and: and From f50cdc9417412ef9e32396ec7b75519e7c4bb086 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 30 Jul 2023 13:53:29 +0200 Subject: [PATCH 27/95] :fix: Fixed database migration command not working --- .../fr/skytasul/quests/commands/CommandsAdmin.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 6f12fa6f..ad197442 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -8,7 +8,6 @@ import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.file.Path; -import java.sql.SQLException; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -228,7 +227,10 @@ public void migrateDatas(BukkitCommandActor actor) { Utils.runAsync(() -> { actor.reply("§aConnecting to the database."); - try (Database db = new Database(BeautyQuests.getInstance().getConfig().getConfigurationSection("database"))) { + Database db = null; + try { + // no try-with-resource because the database is used in another thread + db = new Database(BeautyQuests.getInstance().getConfig().getConfigurationSection("database")); db.testConnection(); actor.reply("§aConnection to database etablished."); final Database fdb = db; @@ -236,14 +238,18 @@ public void migrateDatas(BukkitCommandActor actor) { actor.reply("§aStarting migration..."); try { actor.reply(PlayersManagerDB.migrate(fdb, (PlayersManagerYAML) PlayersManager.manager)); - }catch (Exception ex) { + } catch (Exception ex) { actor.error("An exception occured during migration. Process aborted. " + ex.getMessage()); BeautyQuests.logger.severe("Error during data migration", ex); + } finally { + fdb.close(); } }); - }catch (SQLException ex) { + } catch (Exception ex) { actor.error("§cConnection to database has failed. Aborting. " + ex.getMessage()); BeautyQuests.logger.severe("An error occurred while connecting to the database for datas migration.", ex); + if (db != null) + db.close(); } }); } From 0921ad507f21ca02d34a167149f7ca7f585a3636 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 5 Aug 2023 12:18:18 +0200 Subject: [PATCH 28/95] :construction: WIP --- .../quests/api/QuestsConfiguration.java | 240 +-- .../quests/api/editors/DialogEditor.java | 10 +- .../quests/api/editors/TextListEditor.java | 5 +- .../skytasul/quests/api/gui/GuiFactory.java | 8 + .../fr/skytasul/quests/api/gui/ItemUtils.java | 6 + .../quests/api/localization/Lang.java | 1 - .../quests/api/localization/Locale.java | 2 +- .../fr/skytasul/quests/api/npcs/BqNpc.java | 61 +- .../quests/api/npcs/dialogs/Message.java | 282 +-- .../quests/api/options/QuestOption.java | 4 +- .../quests/api/stages/AbstractStage.java | 8 +- .../StageDescriptionPlaceholdersContext.java | 46 + .../api/stages/creation/StageGuiLine.java | 4 + .../types/AbstractCountableBlockStage.java | 21 +- .../stages/types/AbstractCountableStage.java | 75 +- .../api/stages/types/AbstractEntityStage.java | 360 ++-- .../api/stages/types/AbstractItemStage.java | 24 +- .../quests/api/stages/types/HasProgress.java | 12 + .../quests/api/utils/CountableObject.java | 42 +- .../SplittableDescriptionConfiguration.java | 26 - .../fr/skytasul/quests/api/utils/Utils.java | 48 +- .../HasItemsDescriptionConfiguration.java | 85 + .../ItemsDescriptionConfiguration.java | 29 + .../ItemsDescriptionPlaceholders.java | 154 ++ .../api/utils/messaging/MessageType.java | 64 +- .../api/utils/messaging/MessageUtils.java | 248 +-- .../api/utils/messaging/Placeholder.java | 213 +- .../utils/messaging/PlaceholderRegistry.java | 337 ++-- .../utils/messaging/PlaceholdersContext.java | 62 + .../QuestsConfigurationImplementation.java | 93 +- .../blocks/BQBlocksManagerImplementation.java | 2 +- .../quests/gui/DefaultGuiFactory.java | 14 + .../quests/npcs/BqNpcImplementation.java | 942 ++++----- .../quests/options/OptionDescription.java | 4 +- .../requirements/PlaceholderRequirement.java | 3 +- .../quests/scoreboards/Scoreboard.java | 3 +- .../fr/skytasul/quests/stages/StageArea.java | 26 +- .../fr/skytasul/quests/stages/StageBreed.java | 117 +- .../quests/stages/StageBringBack.java | 80 +- .../skytasul/quests/stages/StageBucket.java | 47 +- .../fr/skytasul/quests/stages/StageChat.java | 27 +- .../fr/skytasul/quests/stages/StageCraft.java | 46 +- .../quests/stages/StageDealDamage.java | 55 +- .../fr/skytasul/quests/stages/StageDeath.java | 11 +- .../skytasul/quests/stages/StageEatDrink.java | 7 +- .../skytasul/quests/stages/StageEnchant.java | 9 +- .../fr/skytasul/quests/stages/StageFish.java | 7 +- .../skytasul/quests/stages/StageLocation.java | 22 +- .../fr/skytasul/quests/stages/StageMelt.java | 7 +- .../fr/skytasul/quests/stages/StageMine.java | 7 +- .../fr/skytasul/quests/stages/StageMobs.java | 19 +- .../fr/skytasul/quests/stages/StageNPC.java | 225 ++- .../quests/stages/StagePlaceBlocks.java | 7 +- .../skytasul/quests/stages/StagePlayTime.java | 37 +- .../fr/skytasul/quests/stages/StageTame.java | 7 +- .../quests/structure/QuestImplementation.java | 6 +- .../StageControllerImplementation.java | 427 ++-- .../compatibility/mobs/BQLevelledMobs.java | 92 +- core/src/main/resources/config.yml | 429 ++-- core/src/main/resources/locales/en_US.yml | 1787 ++++++++--------- 60 files changed, 3856 insertions(+), 3186 deletions(-) create mode 100755 api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java create mode 100755 api/src/main/java/fr/skytasul/quests/api/stages/types/HasProgress.java delete mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java create mode 100755 api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/HasItemsDescriptionConfiguration.java create mode 100644 api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionConfiguration.java create mode 100755 api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionPlaceholders.java create mode 100755 api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java index 8e7aeb31..983970e3 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -1,118 +1,122 @@ -package fr.skytasul.quests.api; - -import java.util.Collection; -import java.util.Set; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.npcs.NpcClickType; -import fr.skytasul.quests.api.options.description.QuestDescription; -import fr.skytasul.quests.api.utils.PlayerListCategory; -import fr.skytasul.quests.api.utils.SplittableDescriptionConfiguration; - -public interface QuestsConfiguration { - - static @NotNull QuestsConfiguration getConfig() { - return QuestsPlugin.getPlugin().getConfiguration(); - } - - @NotNull - Quests getQuestsConfig(); - - @NotNull - Dialogs getDialogsConfig(); - - @NotNull - QuestsMenu getQuestsMenuConfig(); - - @NotNull - StageDescription getStageDescriptionConfig(); - - @NotNull - QuestDescription getQuestDescriptionConfig(); - - interface Quests { - - int getDefaultTimer(); - - int maxLaunchedQuests(); - - boolean scoreboards(); - - boolean playerQuestUpdateMessage(); - - boolean playerStageStartMessage(); - - boolean questConfirmGUI(); - - boolean sounds(); - - String finishSound(); - - String nextStageSound(); - - boolean fireworks(); - - boolean mobsProgressBar(); - - int progressBarTimeoutSeconds(); - - Collection<NpcClickType> getNpcClicks(); - - boolean skipNpcGuiIfOnlyOneQuest(); - - ItemStack getDefaultQuestItem(); - - XMaterial getPageMaterial(); - - double startParticleDistance(); - - int requirementUpdateTime(); - - boolean requirementReasonOnMultipleQuests(); - - boolean stageEndRewardsMessage(); - - } - - interface Dialogs { - - boolean sendInActionBar(); - - int getDefaultTime(); - - boolean isSkippableByDefault(); - - boolean isClickDisabled(); - - boolean isHistoryEnabled(); - - int getMaxMessagesPerHistoryPage(); - - int getMaxDistance(); - - int getMaxDistanceSquared(); - - String getDefaultPlayerSound(); - - String getDefaultNPCSound(); - - } - - interface QuestsMenu { - - boolean isNotStartedTabOpenedWhenEmpty(); - - boolean allowPlayerCancelQuest(); - - Set<PlayerListCategory> getEnabledTabs(); - - } - - interface StageDescription extends SplittableDescriptionConfiguration { - - String getStageDescriptionFormat(); - - } - -} +package fr.skytasul.quests.api; + +import java.util.Collection; +import java.util.Set; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.npcs.NpcClickType; +import fr.skytasul.quests.api.options.description.QuestDescription; +import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionConfiguration; + +public interface QuestsConfiguration { + + static @NotNull QuestsConfiguration getConfig() { + return QuestsPlugin.getPlugin().getConfiguration(); + } + + @NotNull + Quests getQuestsConfig(); + + @NotNull + Dialogs getDialogsConfig(); + + @NotNull + QuestsMenu getQuestsMenuConfig(); + + @NotNull + StageDescription getStageDescriptionConfig(); + + @NotNull + QuestDescription getQuestDescriptionConfig(); + + interface Quests { + + int getDefaultTimer(); + + int maxLaunchedQuests(); + + boolean scoreboards(); + + boolean playerQuestUpdateMessage(); + + boolean playerStageStartMessage(); + + boolean questConfirmGUI(); + + boolean sounds(); + + String finishSound(); + + String nextStageSound(); + + boolean fireworks(); + + boolean mobsProgressBar(); + + int progressBarTimeoutSeconds(); + + Collection<NpcClickType> getNpcClicks(); + + boolean skipNpcGuiIfOnlyOneQuest(); + + ItemStack getDefaultQuestItem(); + + XMaterial getPageMaterial(); + + double startParticleDistance(); + + int requirementUpdateTime(); + + boolean requirementReasonOnMultipleQuests(); + + boolean stageEndRewardsMessage(); + + } + + interface Dialogs { + + boolean sendInActionBar(); + + int getDefaultTime(); + + boolean isSkippableByDefault(); + + boolean isClickDisabled(); + + boolean isHistoryEnabled(); + + int getMaxMessagesPerHistoryPage(); + + int getMaxDistance(); + + int getMaxDistanceSquared(); + + String getDefaultPlayerSound(); + + String getDefaultNPCSound(); + + } + + interface QuestsMenu { + + boolean isNotStartedTabOpenedWhenEmpty(); + + boolean allowPlayerCancelQuest(); + + Set<PlayerListCategory> getEnabledTabs(); + + } + + interface StageDescription extends ItemsDescriptionConfiguration { + + String getStageDescriptionFormat(); + + boolean areBossBarsEnabled(); + + String getBossBarFormat(); + + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java index 4bacd0b2..435a5640 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java @@ -1,5 +1,7 @@ package fr.skytasul.quests.api.editors; +import java.util.Arrays; +import java.util.stream.Collectors; import org.bukkit.entity.Player; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.dialogs.Dialog; @@ -9,6 +11,7 @@ import fr.skytasul.quests.api.utils.messaging.DefaultErrors; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; public class DialogEditor extends Editor{ @@ -35,7 +38,7 @@ public boolean chat(String coloredMessage, String strippedMessage){ return false; } if (args.length > 1){ - msg = Utils.buildFromArray(argsColored, 1, " "); + msg = Arrays.stream(argsColored).skip(1).collect(Collectors.joining(" ")); hasMsg = true; } switch (cmd) { @@ -71,8 +74,9 @@ public boolean chat(String coloredMessage, String strippedMessage){ case LIST: for (int i = 0; i < d.getMessages().size(); i++) { Message dmsg = d.getMessages().get(i); - MessageUtils.sendRawMessage(player, "§6{index}: §7\"{msg}§7\"§e by §l{sender}", false, - PlaceholderRegistry.of("index", i, "msg", dmsg.text, "sender", dmsg.sender.name().toLowerCase())); + MessageUtils.sendRawMessage(player, "§6{index}: §7\"{msg}§7\"§e by §l{sender}", + PlaceholderRegistry.of("index", i, "msg", dmsg.text, "sender", dmsg.sender.name().toLowerCase()), + PlaceholdersContext.DEFAULT_CONTEXT); } break; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java index 71b760b2..9563df47 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/TextListEditor.java @@ -1,13 +1,14 @@ package fr.skytasul.quests.api.editors; +import java.util.Arrays; import java.util.List; import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.stream.Collectors; import org.apache.commons.lang.Validate; import org.bukkit.entity.Player; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class TextListEditor extends Editor{ @@ -43,7 +44,7 @@ public boolean chat(String coloredMessage, String strippedMessage){ return false; } if (args.length > 1){ - msg = Utils.buildFromArray(coloredMessage.split(" "), 1, " "); + msg = Arrays.stream(coloredMessage.split(" ")).skip(1).collect(Collectors.joining(" ")); hasMsg = true; } switch (cmd) { diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java index 3e083c20..07e7cdf9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; @@ -33,6 +34,13 @@ default Gui createItemSelection(@NotNull Consumer<ItemStack> callback, Runnable @NotNull Gui createItemCreator(@NotNull Consumer<ItemStack> callback, boolean allowCancel); + @NotNull + Gui createItemsSelection(@NotNull Consumer<@NotNull List<@NotNull ItemStack>> callback, + @Nullable List<@Nullable ItemStack> existingItems); + + @NotNull + Gui createItemComparisonsSelection(@NotNull ItemComparisonMap comparisons, @NotNull Runnable validate); + @NotNull Gui createBlocksSelection(@NotNull Consumer<List<MutableCountableObject<BQBlock>>> callback, @NotNull Collection<MutableCountableObject<BQBlock>> existingBlocks); 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 12befd14..d64e23a2 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 @@ -16,9 +16,11 @@ import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.SkullMeta; +import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.ChatColorUtils; import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.api.utils.MinecraftVersion; @@ -173,6 +175,10 @@ public static ItemStack lore(ItemStack is, List<String> lore) { return is; } + public static ItemStack loreOptionValue(ItemStack is, @Nullable Object value) { + return lore(is, QuestOption.formatNullableValue(value)); + } + private static List<String> getLoreLines(String... lore) { if (lore != null) { List<String> finalLines = new ArrayList<>(); 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 b2486b2a..3d08ab2f 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 @@ -833,7 +833,6 @@ public enum Lang implements Locale { HologramText("misc.hologramText"), PoolHologramText("misc.poolHologramText"), - MobsProgression("misc.mobsProgression"), EntityType("misc.entityType"), EntityTypeAny("misc.entityTypeAny"), QuestItemLore("misc.questItemLore"), diff --git a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java index 69c9e6aa..5937963c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java +++ b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java @@ -44,7 +44,7 @@ public interface Locale { } default @NotNull String quickFormat(@NotNull String key1, @Nullable Object value1) { - // TODO maybe simplfy this for optimization? + // TODO maybe simplify this for optimization? return format(PlaceholderRegistry.of(key1, value1)); } diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java index 3d480d27..5974107e 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java @@ -1,30 +1,31 @@ -package fr.skytasul.quests.api.npcs; - -import java.util.Set; -import java.util.function.Predicate; -import org.bukkit.entity.Player; -import fr.skytasul.quests.api.pools.QuestPool; -import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.stages.types.Locatable; - -public interface BqNpc extends Locatable.Located.LocatedEntity { - - BqInternalNpc getNpc(); - - Set<Quest> getQuests(); - - boolean hasQuestStarted(Player p); - - Set<QuestPool> getPools(); - - void hideForPlayer(Player p, Object holder); - - void removeHiddenForPlayer(Player p, Object holder); - - boolean canGiveSomething(Player p); - - void addStartablePredicate(Predicate<Player> predicate, Object holder); - - void removeStartablePredicate(Object holder); - -} +package fr.skytasul.quests.api.npcs; + +import java.util.Set; +import java.util.function.Predicate; +import org.bukkit.entity.Player; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.types.Locatable; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; + +public interface BqNpc extends Locatable.Located.LocatedEntity, HasPlaceholders { + + BqInternalNpc getNpc(); + + Set<Quest> getQuests(); + + boolean hasQuestStarted(Player p); + + Set<QuestPool> getPools(); + + void hideForPlayer(Player p, Object holder); + + void removeHiddenForPlayer(Player p, Object holder); + + boolean canGiveSomething(Player p); + + void addStartablePredicate(Predicate<Player> predicate, Object holder); + + void removeStartablePredicate(Object holder); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java index b441daef..b7b0e400 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java @@ -1,142 +1,142 @@ -package fr.skytasul.quests.api.npcs.dialogs; - -import java.util.HashMap; -import java.util.Map; -import org.apache.commons.lang.StringUtils; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfiguration; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.Utils; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; - -public class Message implements Cloneable { - public String text; - public Sender sender; - public String sound; - public int wait = -1; - - public Message(String msg, Sender sender) { - this.text = msg; - this.sender = sender; - } - - public int getWaitTime() { - return wait == -1 ? QuestsConfiguration.getDialogsConfig().getDefaultTime() : wait; - } - - public BukkitTask sendMessage(Player p, String npc, int id, int size) { - BukkitTask task = null; - - String sent = formatMessage(p, npc, id, size); - if (QuestsConfiguration.getDialogsConfig().sendInActionBar()) { - BaseComponent[] components = TextComponent.fromLegacyText(sent.replace("{nl}", " ")); - p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); - if (getWaitTime() > 60) { - task = new BukkitRunnable() { - int time = 40; - - @Override - public void run() { - if (!p.isOnline()) { - cancel(); - return; - } - - time += 40; - if (time > getWaitTime()) - cancel(); - p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); - } - }.runTaskTimerAsynchronously(BeautyQuests.getInstance(), 40, 40); - } - } else - p.sendMessage(StringUtils.splitByWholeSeparator(sent, "{nl}")); - - if (!"none".equals(sound)) { - String sentSound = getSound(); - if (sentSound != null) - p.playSound(p.getLocation(), sentSound, 1, 1); - } - - return task; - } - - private String getSound() { - String sentSound = sound; - if (sentSound == null) { - if (sender == Sender.PLAYER) { - sentSound = QuestsConfiguration.getDialogsConfig().getDefaultPlayerSound(); - } else if (sender == Sender.NPC) { - sentSound = QuestsConfiguration.getDialogsConfig().getDefaultNPCSound(); - } - } - return sentSound; - } - - public String formatMessage(Player p, String npc, int id, int size) { - String sent = null; - switch (sender) { - case PLAYER: - sent = Utils.finalFormat(p, Lang.SelfText.format(p.getName(), text, id + 1, size), true); - break; - case NPC: - sent = Utils.finalFormat(p, Lang.NpcText.format(npc, text, id + 1, size), true); - break; - case NOSENDER: - sent = Utils.finalFormat(p, Utils.format(text, id + 1, size), true); - break; - } - return sent; - } - - public void finished(Player p, boolean endOfDialog, boolean forced) { - if (endOfDialog || !forced) - return; - String sentSound = getSound(); - if (sentSound != null) - p.stopSound(sentSound); - } - - @Override - public Message clone() { - Message clone = new Message(text, sender); - clone.sound = sound; - clone.wait = wait; - return clone; - } - - public Map<String, Object> serialize() { - Map<String, Object> map = new HashMap<>(); - map.put("text", text); - map.put("sender", sender.name()); - if (sound != null) - map.put("sound", sound); - if (wait != -1) - map.put("wait", wait); - return map; - } - - public static Message deserialize(Map<String, Object> map) { - Message msg = new Message((String) map.get("text"), Sender.fromString((String) map.get("sender"))); - if (map.containsKey("sound")) - msg.sound = (String) map.get("sound"); - if (map.containsKey("wait")) - msg.wait = (int) map.get("wait"); - return msg; - } - - public enum Sender { - PLAYER, NPC, NOSENDER; - - public static Sender fromString(String string) { - if (string.equalsIgnoreCase("NOTHING")) - return NOSENDER; - return valueOf(string.toUpperCase()); - } - } +package fr.skytasul.quests.api.npcs.dialogs; + +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.lang.StringUtils; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.Utils; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; + +public class Message implements Cloneable { + public String text; + public Sender sender; + public String sound; + public int wait = -1; + + public Message(String msg, Sender sender) { + this.text = msg; + this.sender = sender; + } + + public int getWaitTime() { + return wait == -1 ? QuestsConfiguration.getConfig().getDialogsConfig().getDefaultTime() : wait; + } + + public BukkitTask sendMessage(Player p, String npc, int id, int size) { + BukkitTask task = null; + + String sent = formatMessage(p, npc, id, size); + if (QuestsConfiguration.getConfig().getDialogsConfig().sendInActionBar()) { + BaseComponent[] components = TextComponent.fromLegacyText(sent.replace("{nl}", " ")); + p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); + if (getWaitTime() > 60) { + task = new BukkitRunnable() { + int time = 40; + + @Override + public void run() { + if (!p.isOnline()) { + cancel(); + return; + } + + time += 40; + if (time > getWaitTime()) + cancel(); + p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); + } + }.runTaskTimerAsynchronously(QuestsPlugin.getPlugin(), 40, 40); + } + } else + p.sendMessage(StringUtils.splitByWholeSeparator(sent, "{nl}")); + + if (!"none".equals(sound)) { + String sentSound = getSound(); + if (sentSound != null) + p.playSound(p.getLocation(), sentSound, 1, 1); + } + + return task; + } + + private String getSound() { + String sentSound = sound; + if (sentSound == null) { + if (sender == Sender.PLAYER) { + sentSound = QuestsConfiguration.getConfig().getDialogsConfig().getDefaultPlayerSound(); + } else if (sender == Sender.NPC) { + sentSound = QuestsConfiguration.getConfig().getDialogsConfig().getDefaultNPCSound(); + } + } + return sentSound; + } + + public String formatMessage(Player p, String npc, int id, int size) { + String sent = null; + switch (sender) { + case PLAYER: + sent = Utils.finalFormat(p, Lang.SelfText.format(p.getName(), text, id + 1, size), true); + break; + case NPC: + sent = Utils.finalFormat(p, Lang.NpcText.format(npc, text, id + 1, size), true); + break; + case NOSENDER: + sent = Utils.finalFormat(p, Utils.format(text, id + 1, size), true); + break; + } + return sent; + } + + public void finished(Player p, boolean endOfDialog, boolean forced) { + if (endOfDialog || !forced) + return; + String sentSound = getSound(); + if (sentSound != null) + p.stopSound(sentSound); + } + + @Override + public Message clone() { + Message clone = new Message(text, sender); + clone.sound = sound; + clone.wait = wait; + return clone; + } + + public Map<String, Object> serialize() { + Map<String, Object> map = new HashMap<>(); + map.put("text", text); + map.put("sender", sender.name()); + if (sound != null) + map.put("sound", sound); + if (wait != -1) + map.put("wait", wait); + return map; + } + + public static Message deserialize(Map<String, Object> map) { + Message msg = new Message((String) map.get("text"), Sender.fromString((String) map.get("sender"))); + if (map.containsKey("sound")) + msg.sound = (String) map.get("sound"); + if (map.containsKey("wait")) + msg.wait = (int) map.get("wait"); + return msg; + } + + public enum Sender { + PLAYER, NPC, NOSENDER; + + public static Sender fromString(String string) { + if (string.equalsIgnoreCase("NOTHING")) + return NOSENDER; + return valueOf(string.toUpperCase()); + } + } } \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index 022f5608..0cbb81e6 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -141,10 +141,10 @@ public void onDependenciesUpdated(@NotNull OptionSet options/* , @NotNull ItemSt return formatNullableValue(value == null ? defaultValue : value, value == null); } - public static @NotNull String formatNullableValue(@Nullable Object value, boolean defaultValue) { + public static @NotNull String formatNullableValue(@Nullable Object value, boolean isDefault) { String valueString = Lang.optionValue.format(PlaceholderRegistry.of("value", value == null ? Lang.NotSet.toString() : value)); - if (defaultValue) + if (isDefault) valueString += " " + Lang.defaultValue.toString(); return valueString; } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 08ee6d32..20bfcbc3 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -8,7 +8,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsConfiguration; -import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.Quest; @@ -166,12 +165,7 @@ public void left(@NotNull Player player) {} public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) {} - /** - * @param acc PlayerAccount who has the stage in progress - * @param source source of the description request - * @return the progress of the stage for the player - */ - public abstract @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); + public abstract @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context); protected final void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullable Object dataValue) { controller.updateObjective(p, dataKey, dataValue); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java new file mode 100755 index 00000000..f1848765 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java @@ -0,0 +1,46 @@ +package fr.skytasul.quests.api.stages; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; + +public interface StageDescriptionPlaceholdersContext extends PlaceholdersContext, PlayerPlaceholdersContext { + + @Override + @NotNull + PlayerAccount getPlayerAccount(); + + @NotNull + DescriptionSource getDescriptionSource(); + + static @NotNull StageDescriptionPlaceholdersContext of(boolean replacePluginPlaceholders, @NotNull PlayerAccount account, + @NotNull DescriptionSource source) { + return new StageDescriptionPlaceholdersContext() { + + @Override + public @Nullable Player getActor() { + return account.getPlayer(); + } + + @Override + public boolean replacePluginPlaceholders() { + return replacePluginPlaceholders; + } + + @Override + public @NotNull PlayerAccount getPlayerAccount() { + return account; + } + + @Override + public @NotNull DescriptionSource getDescriptionSource() { + return source; + } + }; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java index 23ad8ba2..ef575d24 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java @@ -28,6 +28,10 @@ default void refreshItemLore(int slot, List<String> lore) { refreshItem(slot, ItemUtils.lore(getItem(slot), lore)); } + default void refreshItemLoreOptionValue(int slot, @Nullable Object value) { + refreshItem(slot, ItemUtils.loreOptionValue(getItem(slot), value)); + } + default void refreshItemName(int slot, String name) { refreshItem(slot, ItemUtils.name(getItem(slot), name)); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java index b5cd48ed..9a51a93a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableBlockStage.java @@ -7,15 +7,15 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.blocks.BQBlock; -import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; -import fr.skytasul.quests.gui.blocks.BlocksGUI; public abstract class AbstractCountableBlockStage extends AbstractCountableStage<BQBlock> { @@ -30,6 +30,11 @@ protected boolean objectApplies(@NotNull BQBlock object, Object other) { return super.objectApplies(object, other); } + @Override + protected @NotNull String getPlaceholderKey() { + return "blocks"; + } + @Override protected @NotNull String getName(@NotNull BQBlock object) { return object.getName(); @@ -42,7 +47,7 @@ protected boolean objectApplies(@NotNull BQBlock object, Object other) { @Override protected @NotNull BQBlock deserialize(@NotNull Object object) { - return BQBlock.fromString((String) object); + return QuestsAPI.getAPI().getBlocksManager().deserialize((String) object); } public abstract static class AbstractCreator<T extends AbstractCountableBlockStage> extends StageCreation<T> { @@ -58,10 +63,10 @@ public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); line.setItem(getBlocksSlot(), getBlocksItem(), event -> { - new BlocksGUI(blocks, obj -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createBlocksSelection(obj -> { setBlocks(obj); event.reopen(); - }).open(event.getPlayer()); + }, blocks).open(event.getPlayer()); }); } @@ -77,16 +82,16 @@ protected int getBlocksSlot() { public void setBlocks(List<MutableCountableObject<BQBlock>> blocks) { this.blocks = blocks; - getLine().refreshItemLore(getBlocksSlot(), Lang.optionValue.format(blocks.size() + " blocks")); + getLine().refreshItemLoreOptionValue(getBlocksSlot(), blocks.size() + " blocks"); } @Override public void start(Player p) { super.start(p); - new BlocksGUI(Collections.emptyList(), obj -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createBlocksSelection(obj -> { setBlocks(obj); context.reopenGui(); - }).open(p); + }, Collections.emptyList()).open(p); } @Override diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index 42b622ce..ad136a3e 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -7,7 +7,6 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.UUID; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.boss.BarColor; @@ -23,16 +22,17 @@ import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; -import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasMultipleObjects; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -public abstract class AbstractCountableStage<T> extends AbstractStage { +public abstract class AbstractCountableStage<T> extends AbstractStage implements HasMultipleObjects<T> { protected final @NotNull List<@NotNull CountableObject<T>> objects; @@ -47,6 +47,7 @@ protected AbstractCountableStage(@NotNull StageController controller, calculateSize(); } + @Override public @NotNull List<@NotNull CountableObject<T>> getObjects() { return objects; } @@ -71,7 +72,8 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { } @SuppressWarnings("rawtypes") - public @NotNull Map<@NotNull UUID, @NotNull Integer> getPlayerRemainings(@NotNull PlayerAccount acc, boolean warnNull) { + public @UnknownNullability Map<@NotNull UUID, @NotNull Integer> getPlayerRemainings(@NotNull PlayerAccount acc, + boolean warnNull) { Map<?, Integer> remaining = getData(acc, "remaining"); if (warnNull && remaining == null) QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot retrieve stage datas for " + acc.getNameAndID() + " on " + super.toString()); @@ -104,6 +106,40 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { throw new UnsupportedOperationException(object.getClass().getName()); } + @Override + public @NotNull Map<CountableObject<T>, Integer> getPlayerAmounts(@NotNull PlayerAccount account) { + Map<@NotNull UUID, @NotNull Integer> remainings = getPlayerRemainings(account, false); + if (remainings == null || remainings.isEmpty()) + return (Map) remainings; + + return remainings.entrySet().stream() + .map(entry -> Map.entry(getObject(entry.getKey()).orElse(null), entry.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + @Override + public @Nullable CountableObject<T> getObject(int index) { + return index >= objects.size() ? null : objects.get(index); + } + + @Override + public int getPlayerAmount(@NotNull PlayerAccount account, CountableObject<T> object) { + // we do not use default implementation in HasMultipleObjects to avoid conversion from UUID to + // CountableObject + return getPlayerRemainings(account, false).get(object.getUUID()); + } + + @Override + public int getTotalPlayerAmount(@NotNull PlayerAccount account) { + // same as in getPlayerAmount + return getPlayerRemainings(account, false).values().stream().mapToInt(Integer::intValue).sum(); + } + + @Override + public @NotNull String getObjectName(CountableObject<T> object) { + return getName(object.getObject()); + } + protected void updatePlayerRemaining(@NotNull Player player, @NotNull Map<@NotNull UUID, @NotNull Integer> remaining) { updateObjective(player, "remaining", remaining.entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toString(), Entry::getValue))); @@ -115,30 +151,9 @@ protected void calculateSize() { } @Override - public @NotNull String descriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { - return Utils.descriptionLines(source, buildRemainingArray(acc, source)); - } - - @Override - public @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, - @NotNull DescriptionSource source) { - return new Supplier[] {() -> Utils.descriptionLines(source, buildRemainingArray(acc, source))}; - } - - private @NotNull String @NotNull [] buildRemainingArray(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { - Map<UUID, Integer> playerAmounts = getPlayerRemainings(acc, true); - if (playerAmounts == null) return new String[] { "§4§lerror" }; - String[] elements = new String[playerAmounts.size()]; - - int i = 0; - for (Entry<UUID, Integer> entry : playerAmounts.entrySet()) { - elements[i++] = getObject(entry.getKey()) - .map(object -> QuestsConfiguration.getItemNameColor() + Utils.getStringFromNameAndAmount( - getName(object.getObject()), QuestsConfiguration.getItemAmountColor(), entry.getValue(), - object.getAmount(), QuestsConfiguration.showDescriptionItemsXOne(source))) - .orElse("no object " + entry.getKey()); - } - return elements; + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + ItemsDescriptionPlaceholders.register(placeholders, getPlaceholderKey(), this); } @Override @@ -250,6 +265,8 @@ protected boolean objectApplies(@NotNull T object, @UnknownNullability Object ot return object; } + protected abstract @NotNull String getPlaceholderKey(); + protected abstract @NotNull String getName(@NotNull T object); protected abstract @NotNull Object serialize(@NotNull T object); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index a2ed8643..65e6e00a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -1,178 +1,184 @@ -package fr.skytasul.quests.api.stages.types; - -import java.util.AbstractMap; -import java.util.Comparator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.Supplier; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsConfiguration; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.editors.TextEditor; -import fr.skytasul.quests.api.editors.parsers.NumberParser; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.creation.StageCreation; -import fr.skytasul.quests.api.stages.creation.StageCreationContext; -import fr.skytasul.quests.api.stages.creation.StageGuiLine; -import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; -import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.MinecraftNames; -import fr.skytasul.quests.api.utils.Utils; - -@LocatableType (types = LocatedType.ENTITY) -public abstract class AbstractEntityStage extends AbstractStage implements Locatable.MultipleLocatable { - - protected final @NotNull EntityType entity; - protected final int amount; - - protected AbstractEntityStage(@NotNull StageController controller, @NotNull EntityType entity, int amount) { - super(controller); - this.entity = entity; - this.amount = amount; - } - - protected void event(@NotNull Player p, @NotNull EntityType type) { - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (hasStarted(p) && canUpdate(p)) { - if (entity == null || type.equals(entity)) { - Integer playerAmount = getPlayerAmount(acc); - if (playerAmount == null) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning(p.getName() + " does not have object datas for stage " + toString() + ". This is a bug!"); - }else if (playerAmount.intValue() <= 1) { - finishStage(p); - }else { - updateObjective(p, "amount", playerAmount.intValue() - 1); - } - } - } - } - - protected @Nullable Integer getPlayerAmount(@NotNull PlayerAccount acc) { - return getData(acc, "amount"); - } - - @Override - public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { - super.initPlayerDatas(acc, datas); - datas.put("amount", amount); - } - - @Override - protected void serialize(@NotNull ConfigurationSection section) { - section.set("entityType", entity == null ? "any" : entity.name()); - section.set("amount", amount); - } - - protected @NotNull String getMobsLeft(@NotNull PlayerAccount acc) { - Integer playerAmount = getPlayerAmount(acc); - if (playerAmount == null) return "§cerror: no datas"; - - return Utils.getStringFromNameAndAmount( - entity == null ? Lang.EntityTypeAny.toString() : MinecraftNames.getEntityName(entity), - QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), playerAmount, amount, - false); - } - - @Override - public @NotNull Supplier<Object> @NotNull [] descriptionFormat(@NotNull PlayerAccount acc, - @NotNull DescriptionSource source) { - return new Supplier[] { () -> getMobsLeft(acc) }; - } - - @Override - public boolean canBeFetchedAsynchronously() { - return false; - } - - @Override - public @NotNull Spliterator<@NotNull Located> getNearbyLocated(@NotNull NearbyFetcher fetcher) { - if (!fetcher.isTargeting(LocatedType.ENTITY)) return Spliterators.emptySpliterator(); - return fetcher.getCenter().getWorld() - .getEntitiesByClass(entity.getEntityClass()) - .stream() - .map(x -> { - double ds = x.getLocation().distanceSquared(fetcher.getCenter()); - if (ds > fetcher.getMaxDistanceSquared()) return null; - return new AbstractMap.SimpleEntry<>(x, ds); - }) - .filter(Objects::nonNull) - .sorted(Comparator.comparing(Entry::getValue)) - .<Located>map(entry -> Located.LocatedEntity.create(entry.getKey())) - .spliterator(); - } - - public abstract static class AbstractCreator<T extends AbstractEntityStage> extends StageCreation<T> { - - protected EntityType entity = null; - protected int amount = 1; - - protected AbstractCreator(@NotNull StageCreationContext<T> context) { - super(context); - } - - @Override - public void setupLine(@NotNull StageGuiLine line) { - super.setupLine(line); - - line.setItem(6, ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, Lang.changeEntityType.toString()), event -> { - new EntityTypeGUI(x -> { - setEntity(x); - event.reopen(); - }, x -> x == null ? canBeAnyEntity() : canUseEntity(x)).open(event.getPlayer()); - }); - - line.setItem(7, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1)), event -> { - new TextEditor<>(event.getPlayer(), event::reopen, x -> { - setAmount(x); - event.reopen(); - }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); - }); - } - - public void setEntity(EntityType entity) { - this.entity = entity; - getLine().refreshItemLore(6, - Lang.optionValue.format(entity == null ? Lang.EntityTypeAny.toString() : entity.name())); - } - - public void setAmount(int amount) { - this.amount = amount; - getLine().refreshItemName(7, Lang.Amount.format(amount)); - } - - @Override - public void start(Player p) { - super.start(p); - setEntity(null); - } - - @Override - public void edit(T stage) { - super.edit(stage); - setEntity(stage.entity); - setAmount(stage.amount); - } - - protected boolean canBeAnyEntity() { - return true; - } - - protected abstract boolean canUseEntity(@NotNull EntityType type); - - } - +package fr.skytasul.quests.api.stages.types; + +import java.util.AbstractMap; +import java.util.Comparator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.OptionalInt; +import java.util.Spliterator; +import java.util.Spliterators; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.editors.parsers.NumberParser; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; +import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.MinecraftNames; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; + +@LocatableType (types = LocatedType.ENTITY) +public abstract class AbstractEntityStage extends AbstractStage implements Locatable.MultipleLocatable, HasSingleObject { + + protected final @NotNull EntityType entity; + protected final int amount; + + protected AbstractEntityStage(@NotNull StageController controller, @NotNull EntityType entity, int amount) { + super(controller); + this.entity = entity; + this.amount = amount; + } + + protected void event(@NotNull Player p, @NotNull EntityType type) { + PlayerAccount acc = PlayersManager.getPlayerAccount(p); + if (hasStarted(p) && canUpdate(p)) { + if (entity == null || type.equals(entity)) { + OptionalInt playerAmount = getPlayerAmountOptional(acc); + if (!playerAmount.isPresent()) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning(p.getName() + " does not have object datas for stage " + toString() + ". This is a bug!"); + } else if (playerAmount.getAsInt() <= 1) { + finishStage(p); + }else { + updateObjective(p, "amount", playerAmount.getAsInt() - 1); + } + } + } + } + + protected @NotNull OptionalInt getPlayerAmountOptional(@NotNull PlayerAccount acc) { + Integer amount = getData(acc, "amount"); + return amount == null ? OptionalInt.empty() : OptionalInt.of(amount.intValue()); + } + + @Override + public int getPlayerAmount(@NotNull PlayerAccount account) { + return getPlayerAmountOptional(account).orElse(0); + } + + @Override + public int getObjectAmount() { + return amount; + } + + @Override + public @NotNull String getObjectName() { + return entity == null ? Lang.EntityTypeAny.toString() : MinecraftNames.getEntityName(entity); + } + + @Override + public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) { + super.initPlayerDatas(acc, datas); + datas.put("amount", amount); + } + + @Override + protected void serialize(@NotNull ConfigurationSection section) { + section.set("entityType", entity == null ? "any" : entity.name()); + section.set("amount", amount); + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + ItemsDescriptionPlaceholders.register(placeholders, "mobs", this); + } + + @Override + public boolean canBeFetchedAsynchronously() { + return false; + } + + @Override + public @NotNull Spliterator<@NotNull Located> getNearbyLocated(@NotNull NearbyFetcher fetcher) { + if (!fetcher.isTargeting(LocatedType.ENTITY)) return Spliterators.emptySpliterator(); + return fetcher.getCenter().getWorld() + .getEntitiesByClass(entity.getEntityClass()) + .stream() + .map(x -> { + double ds = x.getLocation().distanceSquared(fetcher.getCenter()); + if (ds > fetcher.getMaxDistanceSquared()) return null; + return new AbstractMap.SimpleEntry<>(x, ds); + }) + .filter(Objects::nonNull) + .sorted(Comparator.comparing(Entry::getValue)) + .<Located>map(entry -> Located.LocatedEntity.create(entry.getKey())) + .spliterator(); + } + + public abstract static class AbstractCreator<T extends AbstractEntityStage> extends StageCreation<T> { + + protected EntityType entity = null; + protected int amount = 1; + + protected AbstractCreator(@NotNull StageCreationContext<T> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); + + line.setItem(6, ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, Lang.changeEntityType.toString()), event -> { + new EntityTypeGUI(x -> { + setEntity(x); + event.reopen(); + }, x -> x == null ? canBeAnyEntity() : canUseEntity(x)).open(event.getPlayer()); + }); + + line.setItem(7, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1)), event -> { + new TextEditor<>(event.getPlayer(), event::reopen, x -> { + setAmount(x); + event.reopen(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); + }); + } + + public void setEntity(EntityType entity) { + this.entity = entity; + getLine().refreshItemLore(6, + Lang.optionValue.format(entity == null ? Lang.EntityTypeAny.toString() : entity.name())); + } + + public void setAmount(int amount) { + this.amount = amount; + getLine().refreshItemName(7, Lang.Amount.format(amount)); + } + + @Override + public void start(Player p) { + super.start(p); + setEntity(null); + } + + @Override + public void edit(T stage) { + super.edit(stage); + setEntity(stage.entity); + setAmount(stage.amount); + } + + protected boolean canBeAnyEntity() { + return true; + } + + protected abstract boolean canUseEntity(@NotNull EntityType type); + + } + } \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java index c3943565..6ec47793 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -20,8 +21,6 @@ import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.gui.creation.ItemsGUI; -import fr.skytasul.quests.gui.misc.ItemComparisonGUI; public abstract class AbstractItemStage extends AbstractCountableStage<ItemStack> { @@ -44,6 +43,11 @@ protected AbstractItemStage(@NotNull StageController controller, @NotNull Config super.deserialize(section); } + @Override + protected @NotNull String getPlaceholderKey() { + return "items"; + } + @Override protected @NotNull ItemStack cloneObject(@NotNull ItemStack object) { return object.clone(); @@ -91,15 +95,15 @@ public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); line.setItem(6, getEditItem().clone(), event -> { - new ItemsGUI(items -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemsSelection(items -> { setItems(items); - reopenGUI(player, true); + event.reopen(); }, items).open(event.getPlayer()); }); line.setItem(7, stageComparison.clone(), event -> { - new ItemComparisonGUI(comparisons, () -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemComparisonsSelection(comparisons, () -> { setComparisons(comparisons); - reopenGUI(player, true); + event.reopen(); }).open(event.getPlayer()); }); } @@ -108,19 +112,19 @@ public void setupLine(@NotNull StageGuiLine line) { public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); - getLine().refreshItemLore(6, Lang.optionValue.format(Lang.AmountItems.format(this.items.size()))); + getLine().refreshItemLoreOptionValue(6, Lang.AmountItems.quickFormat("amount", this.items.size())); } public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; - getLine().refreshItemLore(7, - Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size()))); + getLine().refreshItemLoreOptionValue(7, + Lang.AmountComparisons.quickFormat("amount", this.comparisons.getEffective().size())); } @Override public void start(Player p) { super.start(p); - new ItemsGUI(items -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemsSelection(items -> { setItems(items); context.reopenGui(); }, Collections.emptyList()).open(p); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/HasProgress.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/HasProgress.java new file mode 100755 index 00000000..e7444b4d --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/HasProgress.java @@ -0,0 +1,12 @@ +package fr.skytasul.quests.api.stages.types; + +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.players.PlayerAccount; + +public interface HasProgress { + + int getPlayerAmount(@NotNull PlayerAccount account); + + int getTotalAmount(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java index 891e7666..8a226fa8 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/CountableObject.java @@ -47,9 +47,9 @@ static <T> CountableObject<T> create(@NotNull UUID uuid, @NotNull T object, int class DummyCountableObject<T> implements CountableObject<T> { - private final UUID uuid; - private final T object; - private final int amount; + protected final UUID uuid; + protected T object; + protected int amount; public DummyCountableObject(UUID uuid, T object, int amount) { this.uuid = Objects.requireNonNull(uuid); @@ -72,28 +72,25 @@ public int getAmount() { return amount; } - } - - class DummyMutableCountableObject<T> implements MutableCountableObject<T> { - - private final UUID uuid; - private T object; - private int amount; - - public DummyMutableCountableObject(UUID uuid, T object, int amount) { - this.uuid = Objects.requireNonNull(uuid); - this.object = Objects.requireNonNull(object); - this.amount = amount; + @Override + public int hashCode() { + return uuid.hashCode(); } @Override - public UUID getUUID() { - return uuid; + public boolean equals(Object obj) { + if (!(obj instanceof CountableObject)) + return false; + CountableObject<T> other = (CountableObject<T>) obj; + return other.getUUID().equals(uuid); } - @Override - public T getObject() { - return object; + } + + class DummyMutableCountableObject<T> extends DummyCountableObject<T> implements MutableCountableObject<T> { + + public DummyMutableCountableObject(UUID uuid, T object, int amount) { + super(uuid, object, amount); } @Override @@ -101,11 +98,6 @@ public void setObject(T object) { this.object = object; } - @Override - public int getAmount() { - return amount; - } - @Override public void setAmount(int amount) { this.amount = amount; diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java deleted file mode 100644 index 168f4e5c..00000000 --- a/api/src/main/java/fr/skytasul/quests/api/utils/SplittableDescriptionConfiguration.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.skytasul.quests.api.utils; - -import java.util.Set; -import fr.skytasul.quests.api.options.description.DescriptionSource; - -public interface SplittableDescriptionConfiguration { - - String getItemNameColor(); - - String getItemAmountColor(); - - String getSplitPrefix(); - - String getSplitAmountFormat(); - - boolean isAloneSplitAmountShown(); - - boolean isAloneSplitInlined(); - - Set<DescriptionSource> getSplitSources(); - - default boolean isAloneSplitAmountShown(DescriptionSource source) { - return getSplitSources().contains(source) && isAloneSplitAmountShown(); - } - -} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java index 74e94850..d87a7550 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java @@ -24,7 +24,6 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemoryConfiguration; import org.bukkit.entity.EntityType; @@ -162,15 +161,16 @@ public static void giveItems(Player p, List<ItemStack> items) { Lang.ITEM_DROPPED.send(p); } } - + public static <T, E> T getKeyByValue(Map<T, E> map, E value) { - if (value == null) return null; - for (Entry<T, E> entry : map.entrySet()) { - if (value.equals(entry.getValue())) { - return entry.getKey(); - } - } - return null; + if (value == null) + return null; + for (Entry<T, E> entry : map.entrySet()) { + if (value.equals(entry.getValue())) { + return entry.getKey(); + } + } + return null; } public static <T, E> List<T> getKeysByValue(Map<T, E> map, E value) { @@ -184,41 +184,11 @@ public static <T, E> List<T> getKeysByValue(Map<T, E> map, E value) { return list; } - public static String buildFromArray(Object[] array, int start, String insert){ - if (array == null || array.length == 0) return ""; - StringBuilder stb = new StringBuilder(); - for (int i = start; i < array.length; i++){ - stb.append(array[i] + ((i == array.length - 1) ? "" : insert)); - } - return stb.toString(); - } - - public static Integer parseInt(CommandSender sender, String arg){ - try{ - return Integer.parseInt(arg); - }catch (NumberFormatException ex){ - Lang.NUMBER_INVALID.send(sender, arg); - return null; - } - } - - public static int parseInt(Object obj){ - if (obj instanceof Number) return ((Number) obj).intValue(); - if (obj instanceof String) return Integer.parseInt((String) obj); - return 0; - } - public static long parseLong(Object obj) { if (obj instanceof Number) return ((Number) obj).longValue(); if (obj instanceof String) return Long.parseLong((String) obj); return 0; } - - public static double parseDouble(Object obj) { - if (obj instanceof Number) return ((Number) obj).doubleValue(); - if (obj instanceof String) return Double.parseDouble((String) obj); - return 0; - } public static void walkResources(Class<?> clazz, String path, int depth, Consumer<Path> consumer) throws URISyntaxException, IOException { URI uri = clazz.getResource(path).toURI(); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/HasItemsDescriptionConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/HasItemsDescriptionConfiguration.java new file mode 100755 index 00000000..ebeb2976 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/HasItemsDescriptionConfiguration.java @@ -0,0 +1,85 @@ +package fr.skytasul.quests.api.utils.itemdescription; + +import java.util.Collection; +import java.util.Map; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.stages.types.HasProgress; +import fr.skytasul.quests.api.utils.CountableObject; + +public interface HasItemsDescriptionConfiguration { + + @NotNull + default ItemsDescriptionConfiguration getItemsDescriptionConfiguration() { + return QuestsConfiguration.getConfig().getStageDescriptionConfig(); + } + + public interface HasSingleObject extends HasItemsDescriptionConfiguration, HasProgress { + + @NotNull + String getObjectName(); + + int getObjectAmount(); + + @Override + int getPlayerAmount(@NotNull PlayerAccount account); + + @Override + default int getTotalAmount() { + return getObjectAmount(); + } + + } + + public interface HasMultipleObjects<T> extends HasItemsDescriptionConfiguration { + + @NotNull + Collection<CountableObject<T>> getObjects(); + + default @Nullable CountableObject<T> getObject(int index) { + return index >= getObjects().size() ? null : (CountableObject<T>) getObjects().toArray()[index]; + } + + @NotNull + String getObjectName(CountableObject<T> object); + + @NotNull + Map<CountableObject<T>, Integer> getPlayerAmounts(@NotNull PlayerAccount account); + + default int getTotalPlayerAmount(@NotNull PlayerAccount account) { + return getPlayerAmounts(account).values().stream().mapToInt(Integer::intValue).sum(); + } + + default int getPlayerAmount(@NotNull PlayerAccount account, CountableObject<T> object) { + return getPlayerAmounts(account).get(object); + } + + default @NotNull HasSingleObject asTotalObject() { + return new HasSingleObject() { + @Override + public @NotNull ItemsDescriptionConfiguration getItemsDescriptionConfiguration() { + return getItemsDescriptionConfiguration(); + } + + @Override + public int getPlayerAmount(@NotNull PlayerAccount account) { + return getTotalPlayerAmount(account); + } + + @Override + public @NotNull String getObjectName() { + return "total"; + } + + @Override + public int getObjectAmount() { + return getObjects().stream().mapToInt(CountableObject::getAmount).sum(); + } + }; + } + + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionConfiguration.java new file mode 100644 index 00000000..f8778266 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionConfiguration.java @@ -0,0 +1,29 @@ +package fr.skytasul.quests.api.utils.itemdescription; + +import java.util.Set; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.options.description.DescriptionSource; + +public interface ItemsDescriptionConfiguration { + + @NotNull + String getSingleItemFormat(); + + @NotNull + String getMultipleItemsFormat(); + + String getSplitPrefix(); + + boolean isAloneSplitInlined(); + + Set<DescriptionSource> getSplitSources(); + + default boolean isSourceSplit(@NotNull DescriptionSource source) { + if (source == DescriptionSource.FORCESPLIT) + return true; + if (source == DescriptionSource.FORCELINE) + return false; + return getSplitSources().contains(source); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionPlaceholders.java b/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionPlaceholders.java new file mode 100755 index 00000000..88b7cf69 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionPlaceholders.java @@ -0,0 +1,154 @@ +package fr.skytasul.quests.api.utils.itemdescription; + +import java.util.Map; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; +import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasMultipleObjects; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.Placeholder; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; + +public final class ItemsDescriptionPlaceholders { + + private static final PlaceholderRegistry DESCRIPTION_REGISTRY = new PlaceholderRegistry() + .registerIndexedContextual("remaining", DescriptionPlaceholderContext.class, + context -> Integer.toString(context.getItem().getPlayerAmount(context.getPlayerAccount()))) + .registerIndexedContextual("done", DescriptionPlaceholderContext.class, + context -> Integer.toString(context.getItem().getObjectAmount() + - context.getItem().getPlayerAmount(context.getPlayerAccount()))) + .registerIndexedContextual("amount", DescriptionPlaceholderContext.class, + context -> Integer.toString(context.getItem().getObjectAmount())) + .registerIndexedContextual("percentage", DescriptionPlaceholderContext.class, + context -> Integer.toString((int) (context.getItem().getPlayerAmount(context.getPlayerAccount()) * 100D + / context.getItem().getObjectAmount()))) + .registerIndexedContextual("name", DescriptionPlaceholderContext.class, + context -> context.getItem().getObjectName()); + + private ItemsDescriptionPlaceholders() {} + + public static void register(@NotNull PlaceholderRegistry placeholders, @NotNull String key, + @NotNull HasSingleObject object) { + placeholders.registerIndexedContextual(key, PlayerPlaceholdersContext.class, + context -> formatObject(object, context)); + + placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|amount|percentage|name)", + PlayerPlaceholdersContext.class, (matcher, context) -> { + return DESCRIPTION_REGISTRY.resolve(matcher.group(1), new DescriptionPlaceholderContext( + context.getActor(), context.replacePluginPlaceholders(), object)); + })); + } + + public static <T> void register(@NotNull PlaceholderRegistry placeholders, @NotNull String key, + @NotNull HasMultipleObjects<T> objects) { + placeholders.registerIndexedContextual(key, StageDescriptionPlaceholdersContext.class, context -> { + Map<CountableObject<T>, Integer> amounts = objects.getPlayerAmounts(context.getPlayerAccount()); + String[] objectsDescription = amounts.entrySet().stream() + .map(entry -> formatObject(buildFrom(objects, entry.getKey(), entry.getValue()), context)) + .toArray(String[]::new); + return formatObjectList(context.getDescriptionSource(), objects.getItemsDescriptionConfiguration(), + objectsDescription); + }); + + placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|amount|percentage)", + PlayerPlaceholdersContext.class, (matcher, context) -> { + return DESCRIPTION_REGISTRY.resolve(matcher.group(1), new DescriptionPlaceholderContext( + context.getActor(), context.replacePluginPlaceholders(), objects.asTotalObject())); + })); + + placeholders.register(Placeholder.ofPatternContextual(key + "_(\\d+)(?:_(remaining|done|amount|percentage))?", + PlayerPlaceholdersContext.class, (matcher, context) -> { + int index = Integer.parseInt(matcher.group(1)); + CountableObject<T> object = objects.getObject(index); + if (object == null) + return Lang.Unknown.toString(); + HasSingleObject item = + buildFrom(objects, object, objects.getPlayerAmount(context.getPlayerAccount(), object)); + + String operation = matcher.group(2); + if (operation == null) + return formatObject(item, context); + + return DESCRIPTION_REGISTRY.resolve(operation, new DescriptionPlaceholderContext(context.getActor(), + context.replacePluginPlaceholders(), item)); + })); + } + + private static <T> @NotNull HasSingleObject buildFrom(@NotNull HasMultipleObjects<T> objects, CountableObject<T> object, + int amount) { + return new HasSingleObject() { + @Override + public @NotNull ItemsDescriptionConfiguration getItemsDescriptionConfiguration() { + return objects.getItemsDescriptionConfiguration(); + } + + @Override + public int getPlayerAmount(@NotNull PlayerAccount account) { + return amount; + } + + @Override + public @NotNull String getObjectName() { + return objects.getObjectName(object); + } + + @Override + public int getObjectAmount() { + return object.getAmount(); + } + }; + } + + public static @NotNull String formatObject(@NotNull HasSingleObject object, @NotNull PlayerPlaceholdersContext context) { + String formatString = object.getPlayerAmount(context.getPlayerAccount()) > 1 + ? object.getItemsDescriptionConfiguration().getMultipleItemsFormat() + : object.getItemsDescriptionConfiguration().getSingleItemFormat(); + return MessageUtils.format(formatString, DESCRIPTION_REGISTRY, + new DescriptionPlaceholderContext(context.getActor(), context.replacePluginPlaceholders(), object)); + } + + public static @NotNull String formatObjectList(@NotNull DescriptionSource source, + @NotNull ItemsDescriptionConfiguration configuration, @NotNull String @NotNull... elements) { + if (elements.length == 0) + return Lang.Unknown.toString(); + if ((elements.length == 1 && configuration.isAloneSplitInlined()) || configuration.isSourceSplit(source)) + return MessageUtils.itemsToFormattedString(elements, "§r"); + return String.join(configuration.getSplitPrefix(), elements); + } + + private static class DescriptionPlaceholderContext implements PlayerPlaceholdersContext { + + private final @NotNull Player player; + private final boolean replacePluginPlaceholders; + private final @NotNull HasSingleObject item; + + public DescriptionPlaceholderContext(@NotNull Player player, boolean replacePluginPlaceholders, + @NotNull HasSingleObject item) { + this.player = player; + this.replacePluginPlaceholders = replacePluginPlaceholders; + this.item = item; + } + + @Override + public @NotNull Player getActor() { + return player; + } + + @Override + public boolean replacePluginPlaceholders() { + return replacePluginPlaceholders; + } + + public @NotNull HasSingleObject getItem() { + return item; + } + + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java index 44a5bb68..d368b860 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java @@ -1,32 +1,32 @@ -package fr.skytasul.quests.api.utils.messaging; - -import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.localization.Lang; - -public enum MessageType { - - PREFIXED() { - @Override - public @NotNull String process(@NotNull String msg) { - return QuestsPlugin.getPlugin().getPrefix() + msg; - } - }, - UNPREFIXED() { - @Override - public @NotNull String process(@NotNull String msg) { - return "§6" + msg; - } - }, - OFF() { - @Override - public @NotNull String process(@NotNull String msg) { - return Lang.OffText.format(msg); - } - }; - - public @NotNull String process(@NotNull String msg) { - return msg; - } - -} +package fr.skytasul.quests.api.utils.messaging; + +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; + +public enum MessageType { + + PREFIXED() { + @Override + public @NotNull String process(@NotNull String msg) { + return QuestsPlugin.getPlugin().getPrefix() + msg; + } + }, + UNPREFIXED() { + @Override + public @NotNull String process(@NotNull String msg) { + return "§6" + msg; + } + }, + OFF() { + @Override + public @NotNull String process(@NotNull String msg) { + return Lang.OffText.quickFormat("message", msg); + } + }; + + public @NotNull String process(@NotNull String msg) { + return msg; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java index 4dc3a0cd..967d0909 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -1,123 +1,125 @@ -package fr.skytasul.quests.api.utils.messaging; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsConfiguration; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.utils.ChatColorUtils; -import fr.skytasul.quests.api.utils.SplittableDescriptionConfiguration; -import net.md_5.bungee.api.ChatColor; - -public class MessageUtils { - - private MessageUtils() {} - - private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); - private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{([a-zA-Z0-9_-]+)\\}"); - private static final Pattern NEWLINE_PATTERN = Pattern.compile("(?:\\n|\\\\n|\\{nl\\})"); - - public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type) { - sendMessage(sender, message, type, null); - } - - public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type, - @Nullable PlaceholderRegistry placeholders) { - if (message == null || message.isEmpty()) - return; - - sendRawMessage(sender, type.process(message), false, placeholders); - } - - public static void sendRawMessage(@NotNull CommandSender sender, @Nullable String text, boolean playerName, - @Nullable PlaceholderRegistry placeholders) { - if (text == null || text.isEmpty()) - return; - - text = finalFormat(sender, text, playerName, placeholders); - sender.sendMessage(NEWLINE_PATTERN.split(text)); - } - - public static String finalFormat(@Nullable CommandSender sender, @NotNull String text, boolean playerName, - @Nullable PlaceholderRegistry placeholders) { - if (DependenciesManager.papi.isEnabled() && sender instanceof Player) - text = QuestsPlaceholders.setPlaceholders((Player) sender, text); - if (playerName && sender != null) - text = text.replace("{PLAYER}", sender.getName()).replace("{PREFIX}", QuestsConfiguration.getPrefix()); - text = ChatColor.translateAlternateColorCodes('&', text); - return format(text, placeholders); - } - - public static String itemsToFormattedString(String[] items) { - return itemsToFormattedString(items, ""); - } - - public static String itemsToFormattedString(String[] items, String separator) { - if (items.length == 0) - return ""; - if (items.length == 1) - return items[0]; - if (items.length == 2) - return items[0] + " " + separator + Lang.And.toString() + " " + ChatColorUtils.getLastColors(null, items[0]) - + items[1]; - StringBuilder stb = new StringBuilder("§e" + items[0] + ", "); - for (int i = 1; i < items.length - 1; i++) { - stb.append(items[i] + ((i == items.length - 2) ? "" : ", ")); - } - stb.append(" " + Lang.And.toString() + " " + items[items.length - 1]); - return stb.toString(); - } - - public static @NotNull String format(@NotNull String msg, @Nullable PlaceholderRegistry placeholders) { - if (placeholders != null) { - Matcher matcher = PLACEHOLDER_PATTERN.matcher(msg); - - // re-implementation of the "matcher.appendReplacement" system to allow replacement of colors - StringBuilder output = null; - int lastAppend = 0; - String colors = ""; - while (matcher.find()) { - if (output == null) - output = new StringBuilder(msg.length()); - - String key = matcher.group(1); - String replacement = placeholders.resolve(key); - String substring = msg.substring(lastAppend, matcher.start()); - colors = ChatColorUtils.getLastColors(colors, substring); - output.append(substring); - Matcher replMatcher = RESET_PATTERN.matcher(replacement); - output.append(replMatcher.replaceAll("§r" + colors)); - lastAppend = matcher.end(); - } - - if (output != null) { - output.append(msg, lastAppend, msg.length()); - msg = output.toString(); - } - } - - return msg; - } - - public static String formatDescription(DescriptionSource source, SplittableDescriptionConfiguration configuration, - String... elements) { - if (elements.length == 0) - return Lang.Unknown.toString(); - if (elements.length == 1 && configuration.isAloneSplitAmountShown(source)) - return MessageUtils.itemsToFormattedString(elements, configuration.getItemAmountColor()); - return String.join(configuration.getSplitPrefix(), elements); - } - - public static String getYesNo(boolean bool) { - return (bool ? Lang.Yes : Lang.No).toString(); - } - - public static String getEnabledDisabled(boolean bool) { - return (bool ? Lang.Enabled : Lang.Disabled).toString(); - } - -} +package fr.skytasul.quests.api.utils.messaging; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.ChatColorUtils; +import net.md_5.bungee.api.ChatColor; + +public class MessageUtils { + + private MessageUtils() {} + + private static final Pattern RESET_PATTERN = Pattern.compile("§[rR]"); + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{([a-zA-Z0-9_-]+)\\}"); + private static final Pattern NEWLINE_PATTERN = Pattern.compile("(?:\\n|\\\\n|\\{nl\\})"); + + public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type) { + sendMessage(sender, message, type, null); + } + + public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type, + @Nullable PlaceholderRegistry placeholders) { + sendMessage(sender, message, type, placeholders, PlaceholdersContext.of(sender, false)); + } + + public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type, + @Nullable PlaceholderRegistry placeholders, @NotNull PlaceholdersContext context) { + if (message == null || message.isEmpty()) + return; + + sendRawMessage(sender, type.process(message), placeholders, context); + } + + public static void sendRawMessage(@NotNull CommandSender sender, @Nullable String text, + @Nullable PlaceholderRegistry placeholders, @NotNull PlaceholdersContext context) { + if (text == null || text.isEmpty()) + return; + + text = finalFormat(text, placeholders, context); + sender.sendMessage(NEWLINE_PATTERN.split(text)); + } + + public static String finalFormat(@NotNull String text, @Nullable PlaceholderRegistry placeholders, + @NotNull PlaceholdersContext context) { + if (DependenciesManager.papi.isEnabled() && context.getActor() instanceof Player) + text = QuestsPlaceholders.setPlaceholders((Player) context.getActor(), text); + if (context.replacePluginPlaceholders()) { + text = text + .replace("{PLAYER}", context.getActor().getName()) + .replace("{PREFIX}", QuestsPlugin.getPlugin().getPrefix()); + } + text = ChatColor.translateAlternateColorCodes('&', text); + return format(text, placeholders, context); + } + + public static String itemsToFormattedString(String[] items) { + return itemsToFormattedString(items, ""); + } + + public static String itemsToFormattedString(String[] items, String separator) { + if (items.length == 0) + return ""; + if (items.length == 1) + return items[0]; + if (items.length == 2) + return items[0] + " " + separator + Lang.And.toString() + " " + ChatColorUtils.getLastColors(null, items[0]) + + items[1]; + StringBuilder stb = new StringBuilder("§e" + items[0] + ", "); + for (int i = 1; i < items.length - 1; i++) { + stb.append(items[i] + ((i == items.length - 2) ? "" : ", ")); + } + stb.append(" " + Lang.And.toString() + " " + items[items.length - 1]); + return stb.toString(); + } + + public static @NotNull String format(@NotNull String msg, @Nullable PlaceholderRegistry placeholders) { + return format(msg, placeholders, PlaceholdersContext.DEFAULT_CONTEXT); + } + + public static @NotNull String format(@NotNull String msg, @Nullable PlaceholderRegistry placeholders, + @NotNull PlaceholdersContext context) { + if (placeholders != null) { + Matcher matcher = PLACEHOLDER_PATTERN.matcher(msg); + + // re-implementation of the "matcher.appendReplacement" system to allow replacement of colors + StringBuilder output = null; + int lastAppend = 0; + String colors = ""; + while (matcher.find()) { + if (output == null) + output = new StringBuilder(msg.length()); + + String key = matcher.group(1); + String replacement = placeholders.resolve(key, context); + String substring = msg.substring(lastAppend, matcher.start()); + colors = ChatColorUtils.getLastColors(colors, substring); + output.append(substring); + Matcher replMatcher = RESET_PATTERN.matcher(replacement); + output.append(replMatcher.replaceAll("§r" + colors)); + lastAppend = matcher.end(); + } + + if (output != null) { + output.append(msg, lastAppend, msg.length()); + msg = output.toString(); + } + } + + return msg; + } + + public static String getYesNo(boolean bool) { + return (bool ? Lang.Yes : Lang.No).toString(); + } + + public static String getEnabledDisabled(boolean bool) { + return (bool ? Lang.Enabled : Lang.Disabled).toString(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java index 1286da71..c527ffce 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/Placeholder.java @@ -1,69 +1,144 @@ -package fr.skytasul.quests.api.utils.messaging; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface Placeholder { - - boolean matches(@NotNull String key); - - @Nullable - String resolve(@NotNull String key); - - static Placeholder of(@NotNull String key, @Nullable Object value) { - String string = Objects.toString(value); - return ofSupplier(key, () -> string); - } - - static Placeholder ofSupplier(@NotNull String key, @NotNull Supplier<@Nullable String> valueSupplier) { - return new Placeholder() { - - @Override - public @Nullable String resolve(@NotNull String key) { - return valueSupplier.get(); - } - - @Override - public boolean matches(@NotNull String keyToMatch) { - return keyToMatch.equals(key); - } - }; - } - - static Placeholder ofPattern(@NotNull String regex, - @NotNull Function<@NotNull Matcher, @Nullable String> valueFunction) { - return new Placeholder() { - private Pattern pattern = Pattern.compile(regex); - private Map<String, Matcher> matchers = new ConcurrentHashMap<>(); - - @Override - public @Nullable String resolve(@NotNull String key) { - Matcher matcher = matchers.remove(key); - if (matcher == null) { - matcher = pattern.matcher(key); - if (!matcher.matches()) - throw new IllegalStateException(); - } - return valueFunction.apply(matcher); - } - - @Override - public boolean matches(@NotNull String key) { - Matcher matcher = pattern.matcher(key); - if (matcher.matches()) { - matchers.put(key, matcher); - return true; - } - return false; - } - }; - } - -} +package fr.skytasul.quests.api.utils.messaging; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface Placeholder { + + boolean matches(@NotNull String key); + + @Nullable + String resolve(@NotNull String key, @NotNull PlaceholdersContext context); + + static Placeholder of(@NotNull String key, @Nullable Object value) { + String string = Objects.toString(value); + return ofSupplier(key, () -> string); + } + + static Placeholder ofSupplier(@NotNull String key, @NotNull Supplier<@Nullable String> valueSupplier) { + return new Placeholder() { + + @Override + public @Nullable String resolve(@NotNull String key, @NotNull PlaceholdersContext context) { + return valueSupplier.get(); + } + + @Override + public boolean matches(@NotNull String keyToMatch) { + return keyToMatch.equals(key); + } + }; + } + + static Placeholder ofPattern(@NotNull String regex, + @NotNull Function<@NotNull Matcher, @Nullable String> valueFunction) { + return new Placeholder() { + private Pattern pattern = Pattern.compile(regex); + private Map<String, Matcher> matchers = new ConcurrentHashMap<>(); + + @Override + public @Nullable String resolve(@NotNull String key, @NotNull PlaceholdersContext context) { + Matcher matcher = matchers.remove(key); + if (matcher == null) { + matcher = pattern.matcher(key); + if (!matcher.matches()) + throw new IllegalStateException(); + } + return valueFunction.apply(matcher); + } + + @Override + public boolean matches(@NotNull String key) { + Matcher matcher = pattern.matcher(key); + if (matcher.matches()) { + matchers.put(key, matcher); + return true; + } + return false; + } + }; + } + + static <T extends PlaceholdersContext> Placeholder ofContextual(@NotNull String key, @NotNull Class<T> contextClass, + @NotNull Function<T, String> valueFunction) { + return new ContextualizedPlaceholder<T>() { + + @Override + public boolean matches(@NotNull String keyToMatch) { + return keyToMatch.equals(key); + } + + @Override + public @NotNull Class<T> getContextClass() { + return contextClass; + } + + @Override + public @Nullable String resolveContextual(@NotNull String key, T context) { + return valueFunction.apply(context); + } + }; + } + + static <T extends PlaceholdersContext> Placeholder ofPatternContextual(@NotNull String regex, + @NotNull Class<T> contextClass, + @NotNull BiFunction<@NotNull Matcher, @NotNull T, @Nullable String> valueFunction) { + return new ContextualizedPlaceholder<T>() { + private Pattern pattern = Pattern.compile(regex); + private Map<String, Matcher> matchers = new ConcurrentHashMap<>(); + + @Override + public @Nullable String resolveContextual(@NotNull String key, @NotNull T context) { + Matcher matcher = matchers.remove(key); + if (matcher == null) { + matcher = pattern.matcher(key); + if (!matcher.matches()) + throw new IllegalStateException(); + } + return valueFunction.apply(matcher, context); + } + + @Override + public boolean matches(@NotNull String key) { + Matcher matcher = pattern.matcher(key); + if (matcher.matches()) { + matchers.put(key, matcher); + return true; + } + return false; + } + + @Override + public @NotNull Class<T> getContextClass() { + return contextClass; + } + }; + } + + public interface ContextualizedPlaceholder<T extends PlaceholdersContext> extends Placeholder { + + @NotNull + Class<T> getContextClass(); + + @Override + default @Nullable String resolve(@NotNull String key, @NotNull PlaceholdersContext context) { + if (!getContextClass().isInstance(context)) + throw new IllegalArgumentException("Context is not of type " + getContextClass().getName()); + + return resolveContextual(key, getContextClass().cast(context)); + } + + @Nullable + String resolveContextual(@NotNull String key, T context); + + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java index d9b5246b..c624aa73 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java @@ -1,145 +1,192 @@ -package fr.skytasul.quests.api.utils.messaging; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Supplier; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public final class PlaceholderRegistry implements HasPlaceholders { - - private final List<Placeholder> placeholders; - private final List<Placeholder> indexed; - - public PlaceholderRegistry() { - // effectively the same as the other constructor with no argument - // but without the overhead of creating an empty array and then an empty list - this.placeholders = new ArrayList<>(5); - this.indexed = new ArrayList<>(5); - } - - public PlaceholderRegistry(Placeholder... placeholders) { - this.placeholders = new ArrayList<>(Arrays.asList(placeholders)); - this.indexed = new ArrayList<>(5); - } - - public @Nullable Placeholder getPlaceholder(@NotNull String key) { - try { - int index = Integer.parseInt(key); - if (index < indexed.size()) - return indexed.get(index); - } catch (NumberFormatException ex) { - // means the key is not indexed - } - - for (Placeholder placeholder : placeholders) { - if (placeholder.matches(key)) - return placeholder; - } - return null; - } - - public boolean hasPlaceholder(@NotNull String key) { - return getPlaceholder(key) == null; - } - - public @Nullable String resolve(@NotNull String key) { - @Nullable - Placeholder placeholder = getPlaceholder(key); - - if (placeholder == null) - return null; - - return placeholder.resolve(key); - } - - @Override - public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { - return this; - } - - public @NotNull PlaceholderRegistry register(Placeholder placeholder) { - placeholders.add(placeholder); - return this; - } - - public @NotNull PlaceholderRegistry register(String key, Object value) { - return register(Placeholder.of(key, value)); - } - - public @NotNull PlaceholderRegistry register(String key, Supplier<String> valueSupplier) { - return register(Placeholder.ofSupplier(key, valueSupplier)); - } - - private @NotNull PlaceholderRegistry registerIndexed(Placeholder placeholder) { - placeholders.add(placeholder); - indexed.add(placeholder); - return this; - } - - public @NotNull PlaceholderRegistry registerIndexed(String key, Object value) { - return registerIndexed(Placeholder.of(key, value)); - } - - public @NotNull PlaceholderRegistry registerIndexed(String key, Supplier<String> valueSupplier) { - return registerIndexed(Placeholder.ofSupplier(key, valueSupplier)); - } - - public @NotNull PlaceholderRegistry with(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { - HasPlaceholders[] others = new HasPlaceholders[placeholdersHolders.length + 1]; - others[0] = this; - System.arraycopy(placeholdersHolders, 0, others, 1, placeholdersHolders.length); - return combine(others); - } - - public @NotNull PlaceholderRegistry shifted(@NotNull Placeholder placeholder) { - int index = indexed.indexOf(placeholder); - if (index == -1) - throw new IllegalArgumentException(); - - PlaceholderRegistry shifted = new PlaceholderRegistry(); - shifted.placeholders.addAll(this.placeholders); - Placeholder[] indexedShifted = new Placeholder[this.indexed.size() - index]; - System.arraycopy(this.indexed.toArray(new Placeholder[this.indexed.size()]), index, indexedShifted, 0, - this.indexed.size() - index); - shifted.indexed.addAll(Arrays.asList(indexedShifted)); - - return shifted; - } - - public @NotNull PlaceholderRegistry shifted(@NotNull String key) { - return shifted(getPlaceholder(key)); - } - - public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1) { - return new PlaceholderRegistry() - .registerIndexed(key1, value1); - } - - public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1, @NotNull String key2, - @Nullable Object value2) { - return new PlaceholderRegistry() - .registerIndexed(key1, value1) - .registerIndexed(key2, value2); - } - - public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1, @NotNull String key2, - @Nullable Object value2, @NotNull String key3, @Nullable Object value3) { - return new PlaceholderRegistry() - .registerIndexed(key1, value1) - .registerIndexed(key2, value2) - .registerIndexed(key3, value3); - } - - public static @NotNull PlaceholderRegistry combine(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { - PlaceholderRegistry result = new PlaceholderRegistry(); - for (HasPlaceholders holder : placeholdersHolders) { - result.placeholders.addAll(holder.getPlaceholdersRegistry().placeholders); - if (!holder.getPlaceholdersRegistry().indexed.isEmpty()) - result.indexed.addAll(holder.getPlaceholdersRegistry().indexed); - } - return result; - } - -} +package fr.skytasul.quests.api.utils.messaging; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class PlaceholderRegistry implements HasPlaceholders { + + private final List<Placeholder> placeholders; + private final List<Placeholder> indexed = new ArrayList<>(2); + + public PlaceholderRegistry() { + // effectively the same as the other constructor with no argument + // but without the overhead of creating an empty array and then an empty list + this.placeholders = new ArrayList<>(3); + } + + public PlaceholderRegistry(Placeholder... placeholders) { + this.placeholders = new ArrayList<>(Arrays.asList(placeholders)); + } + + public @Nullable Placeholder getPlaceholder(@NotNull String key) { + try { + int index = Integer.parseInt(key); + if (index < indexed.size()) + return indexed.get(index); + } catch (NumberFormatException ex) { + // means the key is not indexed + } + + for (Placeholder placeholder : placeholders) { + if (placeholder.matches(key)) + return placeholder; + } + return null; + } + + public boolean hasPlaceholder(@NotNull String key) { + return getPlaceholder(key) == null; + } + + public @Nullable String resolve(@NotNull String key, @NotNull PlaceholdersContext context) { + @Nullable + Placeholder placeholder = getPlaceholder(key); + + if (placeholder == null) + return null; + + return placeholder.resolve(key, context); + } + + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + return this; + } + + public @NotNull PlaceholderRegistry register(Placeholder placeholder) { + placeholders.add(placeholder); + return this; + } + + public @NotNull PlaceholderRegistry register(String key, Object value) { + return register(Placeholder.of(key, value)); + } + + public @NotNull PlaceholderRegistry register(String key, Supplier<String> valueSupplier) { + return register(Placeholder.ofSupplier(key, valueSupplier)); + } + + public @NotNull <T extends PlaceholdersContext> PlaceholderRegistry registerContextual(@NotNull String key, + @NotNull Class<T> contextClass, @NotNull Function<T, String> valueFunction) { + return register(Placeholder.ofContextual(key, contextClass, valueFunction)); + } + + private @NotNull PlaceholderRegistry registerIndexed(Placeholder placeholder) { + placeholders.add(placeholder); + indexed.add(placeholder); + return this; + } + + public @NotNull PlaceholderRegistry registerIndexed(String key, Object value) { + return registerIndexed(Placeholder.of(key, value)); + } + + public @NotNull PlaceholderRegistry registerIndexed(String key, Supplier<String> valueSupplier) { + return registerIndexed(Placeholder.ofSupplier(key, valueSupplier)); + } + + public @NotNull <T extends PlaceholdersContext> PlaceholderRegistry registerIndexedContextual(@NotNull String key, + @NotNull Class<T> contextClass, @NotNull Function<T, String> valueFunction) { + return registerIndexed(Placeholder.ofContextual(key, contextClass, valueFunction)); + } + + /** + * Adds all the placeholders from the passed placeholders holders to this placeholders registry. + * + * @param placeholdersHolders holders to get the placeholders from + * @return this placeholder registry + */ + public @NotNull PlaceholderRegistry compose(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { + for (HasPlaceholders holder : placeholdersHolders) { + this.placeholders.addAll(holder.getPlaceholdersRegistry().placeholders); + if (!holder.getPlaceholdersRegistry().indexed.isEmpty()) + this.indexed.addAll(holder.getPlaceholdersRegistry().indexed); + } + return this; + } + + /** + * Creates a <i>new</i> placeholders registry containing the placeholders of this instance in + * addition with those from the passed placeholders holders. + * + * @param placeholdersHolders holders to get the placeholders from + * @return a new placeholder registry containing all placeholders + * @see #combine(HasPlaceholders...) + */ + public @NotNull PlaceholderRegistry with(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { + HasPlaceholders[] others = new HasPlaceholders[placeholdersHolders.length + 1]; + others[0] = this; + System.arraycopy(placeholdersHolders, 0, others, 1, placeholdersHolders.length); + return combine(others); + } + + /** + * Creates a <i>new</i> placeholders registry containing the same placeholders as this instance but + * with the indexed placeholers being shifted so that the passed placeholder is the first one. + * + * @param placeholder first placeholder to be indexed + * @return a copy of this registry with the indexed placeholders shifted + */ + public @NotNull PlaceholderRegistry shifted(@NotNull Placeholder placeholder) { + int index = indexed.indexOf(placeholder); + if (index == -1) + throw new IllegalArgumentException(); + + PlaceholderRegistry shifted = new PlaceholderRegistry(); + shifted.placeholders.addAll(this.placeholders); + Placeholder[] indexedShifted = new Placeholder[this.indexed.size() - index]; + System.arraycopy(this.indexed.toArray(new Placeholder[this.indexed.size()]), index, indexedShifted, 0, + this.indexed.size() - index); + shifted.indexed.addAll(Arrays.asList(indexedShifted)); + + return shifted; + } + + public @NotNull PlaceholderRegistry shifted(@NotNull String key) { + return shifted(Objects.requireNonNull(getPlaceholder(key))); + } + + public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1) { + return new PlaceholderRegistry() + .registerIndexed(key1, value1); + } + + public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1, @NotNull String key2, + @Nullable Object value2) { + return new PlaceholderRegistry() + .registerIndexed(key1, value1) + .registerIndexed(key2, value2); + } + + public static @NotNull PlaceholderRegistry of(@NotNull String key1, @Nullable Object value1, @NotNull String key2, + @Nullable Object value2, @NotNull String key3, @Nullable Object value3) { + return new PlaceholderRegistry() + .registerIndexed(key1, value1) + .registerIndexed(key2, value2) + .registerIndexed(key3, value3); + } + + /** + * Creates a placeholders registry containing the placeholders of all the passed placeholder + * holders. + * + * @param placeholdersHolders holders to get the placeholders from + * @return a new placeholder registry containing all placeholders + */ + public static @NotNull PlaceholderRegistry combine(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { + PlaceholderRegistry result = new PlaceholderRegistry(); + for (HasPlaceholders holder : placeholdersHolders) { + result.placeholders.addAll(holder.getPlaceholdersRegistry().placeholders); + if (!holder.getPlaceholdersRegistry().indexed.isEmpty()) + result.indexed.addAll(holder.getPlaceholdersRegistry().indexed); + } + return result; + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java new file mode 100755 index 00000000..e2327332 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java @@ -0,0 +1,62 @@ +package fr.skytasul.quests.api.utils.messaging; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; + +public interface PlaceholdersContext { + + static final @NotNull PlaceholdersContext DEFAULT_CONTEXT = of(null, true); + + @Nullable + CommandSender getActor(); + + boolean replacePluginPlaceholders(); + + static PlaceholdersContext of(@Nullable CommandSender actor, boolean replacePluginPlaceholders) { + return new PlaceholdersContext() { + + @Override + public boolean replacePluginPlaceholders() { + return replacePluginPlaceholders; + } + + @Override + public @Nullable CommandSender getActor() { + return actor; + } + }; + } + + static PlayerPlaceholdersContext of(@Nullable Player actor, boolean replacePluginPlaceholders) { + return new PlayerPlaceholdersContext() { + + @Override + public boolean replacePluginPlaceholders() { + return replacePluginPlaceholders; + } + + @Override + public @NotNull Player getActor() { + return actor; + } + }; + } + + public interface PlayerPlaceholdersContext extends PlaceholdersContext { + + @Override + @Nullable + Player getActor(); + + @NotNull + default PlayerAccount getPlayerAccount() { + return PlayersManager.getPlayerAccount(getActor()); + } + + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 5392e019..9a0b3d23 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -81,7 +81,7 @@ public static QuestsConfigurationImplementation getConfiguration() { quests = new QuestsConfig(); dialogs = new DialogsConfig(config.getConfigurationSection("dialogs")); menu = new QuestsMenuConfig(config.getConfigurationSection("questsMenu")); - stageDescription = new StageDescriptionConfig(config.getConfigurationSection("stageDescriptionItemsSplit")); + stageDescription = new StageDescriptionConfig(config.getConfigurationSection("stage description")); questDescription = new QuestDescriptionConfig(config.getConfigurationSection("questDescription")); } @@ -651,30 +651,27 @@ public Set<PlayerListCategory> getEnabledTabs() { public class StageDescriptionConfig implements QuestsConfiguration.StageDescription { - private String itemNameColor; - private String itemAmountColor; - private String stageDescriptionFormat = "§8({0}/{1}) §e{2}"; + private String itemSingleFormat, itemMultipleFormat; + private String stageDescriptionFormat; private String descPrefix = "{nl}§e- §6"; - private String descAmountFormat = "x{0}"; - private boolean descXOne = true; private boolean inlineAlone = true; private Set<DescriptionSource> descSources = EnumSet.noneOf(DescriptionSource.class); + private boolean bossBars = true; + private String bossBarFormat; - private final ConfigurationSection config; + private ConfigurationSection config; public StageDescriptionConfig(ConfigurationSection config) { this.config = config; } private void init() { - itemNameColor = config.getString("itemNameColor"); - itemAmountColor = config.getString("itemAmountColor"); - stageDescriptionFormat = config.getString("descriptionFormat"); + itemSingleFormat = config.getString("item formats.single"); + itemMultipleFormat = config.getString("item formats.multiple"); + stageDescriptionFormat = config.getString("description format"); descPrefix = "{nl}" + config.getString("prefix"); - descAmountFormat = config.getString("amountFormat"); - descXOne = config.getBoolean("showXOne"); - inlineAlone = config.getBoolean("inlineAlone"); - for (String s : config.getStringList("sources")) { + inlineAlone = config.getBoolean("inline alone"); + for (String s : config.getStringList("split sources")) { try { descSources.add(DescriptionSource.valueOf(s)); } catch (IllegalArgumentException ex) { @@ -682,15 +679,43 @@ private void init() { .warning("Loading of description splitted sources failed : source " + s + " does not exist"); } } + bossBars = config.getBoolean("boss bars"); + bossBarFormat = config.getString("boss bar format"); } private boolean update() { boolean result = false; - if (config.getParent() != null) { - result |= migrateEntry(config, config.getParent(), "itemNameColor", "itemNameColor"); - result |= migrateEntry(config, config.getParent(), "itemAmountColor", "itemAmountColor"); - result |= migrateEntry(config, config.getParent(), "stageDescriptionFormat", "descriptionFormat"); + + if (config == null) { + migrateEntry(QuestsConfigurationImplementation.this.config, QuestsConfigurationImplementation.this.config, + "stageDescriptionItemsSplit", "stage description"); + config = QuestsConfigurationImplementation.this.config.getConfigurationSection("stage description"); + result = true; } + + result |= migrateEntry(config, config.getParent(), "stageDescriptionFormat", "description format"); + result |= migrateEntry(config, config, "prefix", "line prefix"); + result |= migrateEntry(config, config, "sources", "split sources"); + if (config.contains("amountFormat")) { + String amountFormat = config.getString("amountFormat"); + boolean showXOne = config.getBoolean("showXOne"); + String itemNameColor = config.getParent().getString("itemNameColor"); + String itemAmountColor = config.getParent().getString("itemAmountColor"); + + String multipleFormat = itemNameColor + "{name}" + itemAmountColor + " " + amountFormat; + String singleFormat = showXOne ? multipleFormat : (itemNameColor + "{name}"); + config.set("item formats.multiple", multipleFormat); + config.set("item formats.single", singleFormat); + + config.set("amountFormat", null); + config.set("showXOne", null); + config.getParent().set("itemNameColor", null); + config.getParent().set("itemAmountColor", null); + result = true; + } + + result |= migrateEntry(config, config.getParent(), "mobsProgressBar", "boss bars"); + return result; } @@ -700,13 +725,13 @@ public String getStageDescriptionFormat() { } @Override - public String getItemNameColor() { - return itemNameColor; + public @NotNull String getSingleItemFormat() { + return itemSingleFormat; } @Override - public String getItemAmountColor() { - return itemAmountColor; + public @NotNull String getMultipleItemsFormat() { + return itemMultipleFormat; } @Override @@ -714,16 +739,6 @@ public String getSplitPrefix() { return descPrefix; } - @Override - public String getSplitAmountFormat() { - return descAmountFormat; - } - - @Override - public boolean isAloneSplitAmountShown() { - return descXOne; - } - @Override public boolean isAloneSplitInlined() { return inlineAlone; @@ -734,16 +749,14 @@ public Set<DescriptionSource> getSplitSources() { return descSources; } - public boolean showDescriptionItemsXOne(DescriptionSource source) { - return splitDescription(source) && descXOne; + @Override + public boolean areBossBarsEnabled() { + return bossBars; } - public boolean splitDescription(DescriptionSource source) { - if (source == DescriptionSource.FORCESPLIT) - return true; - if (source == DescriptionSource.FORCELINE) - return false; - return descSources.contains(source); + @Override + public String getBossBarFormat() { + return bossBarFormat; } } diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java index ee24238a..e914eae0 100644 --- a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java @@ -161,7 +161,7 @@ public Located next() { } public @NotNull BQBlock createBlockdata(@NotNull String blockData, @Nullable String customName) { - return new Post1_13.BQBlockData(new BQBlockOptions(tagType, customName), blockData); + return new Post1_13.BQBlockData(new BQBlockOptions(blockdataType, customName), blockData); } public @NotNull BQBlock createTag(@NotNull String tag, @Nullable String customName) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java index ca17cb14..409471b4 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.Gui; import fr.skytasul.quests.api.gui.GuiFactory; import fr.skytasul.quests.api.gui.templates.ConfirmGUI; @@ -14,8 +15,10 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.gui.blocks.BlocksGUI; +import fr.skytasul.quests.gui.items.ItemComparisonGUI; import fr.skytasul.quests.gui.items.ItemCreatorGUI; import fr.skytasul.quests.gui.items.ItemGUI; +import fr.skytasul.quests.gui.items.ItemsGUI; import fr.skytasul.quests.gui.npc.NpcSelectGUI; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.players.PlayerAccountImplementation; @@ -37,6 +40,17 @@ public class DefaultGuiFactory implements GuiFactory { return new ItemCreatorGUI(callback, allowCancel); } + @Override + public @NotNull Gui createItemsSelection(@NotNull Consumer<@NotNull List<@NotNull ItemStack>> callback, + @Nullable List<@Nullable ItemStack> existingItems) { + return new ItemsGUI(callback, existingItems); + } + + @Override + public @NotNull Gui createItemComparisonsSelection(@NotNull ItemComparisonMap comparisons, @NotNull Runnable validate) { + return new ItemComparisonGUI(comparisons, validate); + } + @Override public @NotNull Gui createBlocksSelection(@NotNull Consumer<List<MutableCountableObject<BQBlock>>> callback, @NotNull Collection<MutableCountableObject<BQBlock>> existingBlocks) { 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 67ec653d..08f032dd 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java @@ -1,465 +1,479 @@ -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 fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.QuestsConfigurationImplementation; -import fr.skytasul.quests.api.AbstractHolograms; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsConfiguration; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.npcs.BqInternalNpc; -import fr.skytasul.quests.api.npcs.BqNpc; -import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.api.pools.QuestPool; -import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.stages.types.Locatable.Located; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.options.OptionHologramLaunch; -import fr.skytasul.quests.options.OptionHologramLaunchNo; -import fr.skytasul.quests.options.OptionHologramText; -import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.structure.pools.QuestPoolImplementation; - -public class BqNpcImplementation implements Located.LocatedEntity, BqNpc { - - private Map<Quest, List<Player>> quests = new TreeMap<>(); - private Set<QuestPool> pools = new TreeSet<>(); - - private List<Entry<Player, Object>> hiddenTickets = new ArrayList<>(); - private Map<Object, Predicate<Player>> startable = new HashMap<>(); - - private BukkitTask launcheableTask; - - /* Holograms */ - private boolean debug = false; - private BukkitTask hologramsTask; - private boolean hologramsRemoved = true; - private Hologram hologramText = new Hologram(false, - QuestsAPI.getAPI().hasHologramsManager() - && !QuestsConfigurationImplementation.getConfiguration().isTextHologramDisabled(), - Lang.HologramText.toString()); - private Hologram hologramLaunch = new Hologram(false, - QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems(), - QuestsConfigurationImplementation.getConfiguration().getHoloLaunchItem()); - private Hologram hologramLaunchNo = new Hologram(false, - QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() - && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility(), - QuestsConfigurationImplementation.getConfiguration().getHoloLaunchNoItem()); - private Hologram hologramPool = new Hologram(false, - QuestsAPI.getAPI().hasHologramsManager() - && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility(), - Lang.PoolHologramText.toString()) { - @Override - public double getYAdd() { - return hologramText.canAppear && hologramText.visible ? 0.55 : 0; - } - }; - private final boolean holograms; - - private BqInternalNpc npc; - - public BqNpcImplementation(BqInternalNpc npc) { - this.npc = npc; - - holograms = hologramText.enabled || hologramLaunch.enabled || hologramLaunchNo.enabled || hologramPool.enabled; - launcheableTask = startLauncheableTasks(); - } - - @Override - public BqInternalNpc getNpc() { - return npc; - } - - public void setNpc(BqInternalNpc npc) { - this.npc = npc; - } - - @Override - public @NotNull Entity getEntity() { - return npc.getEntity(); - } - - @Override - public @NotNull Location getLocation() { - return npc.getLocation(); - } - - private BukkitTask startLauncheableTasks() { - return new BukkitRunnable() { - private int timer = 0; - - @Override - public void run() { - if (!npc.isSpawned()) - return; - if (!(getEntity() instanceof LivingEntity)) return; - LivingEntity en = (LivingEntity) getEntity(); - - if (timer-- == 0) { - timer = QuestsConfiguration.getConfig().getQuestsConfig().requirementUpdateTime(); - return; - } - - quests.values().forEach(List::clear); - - Set<Player> playersInRadius = new HashSet<>(); - Location lc = en.getLocation(); - for (Player p : lc.getWorld().getPlayers()) { - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - if (acc == null) continue; - if (lc.distanceSquared(p.getLocation()) > Math - .pow(QuestsConfiguration.getConfig().getQuestsConfig().startParticleDistance(), 2)) - continue; - playersInRadius.add(p); - for (Entry<Quest, List<Player>> quest : quests.entrySet()) { - if (quest.getKey().canStart(p, false)) { - quest.getValue().add(p); - break; - } - } - } - - if (QuestsConfigurationImplementation.getConfiguration().showStartParticles()) { - quests.forEach((quest, players) -> QuestsConfigurationImplementation.getConfiguration() - .getParticleStart().send(en, players)); - } - - if (hologramPool.canAppear) { - for (Player p : playersInRadius) { - boolean visible = false; - for (QuestPool pool : pools) { - if (pool.canGive(p)) { - visible = true; - break; - } - } - hologramPool.setVisible(p, visible); - } - } - if (hologramLaunch.canAppear || hologramLaunchNo.canAppear) { - List<Player> launcheable = new ArrayList<>(); - List<Player> unlauncheable = new ArrayList<>(); - for (Iterator<Player> iterator = playersInRadius.iterator(); iterator.hasNext();) { - Player player = iterator.next(); - if (hiddenTickets.stream().anyMatch(entry -> entry.getKey() == player)) { - iterator.remove(); - continue; - } - PlayerAccount acc = PlayersManager.getPlayerAccount(player); - boolean launchYes = false; - boolean launchNo = false; - for (Entry<Quest, List<Player>> qu : quests.entrySet()) { - if (!qu.getKey().hasStarted(acc)) { - boolean pLauncheable = qu.getValue().contains(player); - if (hologramLaunch.enabled && pLauncheable) { - launchYes = true; - break; // launcheable take priority over not launcheable - }else if (hologramLaunchNo.enabled && !pLauncheable) { - launchNo = true; - } - } - } - if (launchYes) { - launcheable.add(player); - iterator.remove(); - }else if (launchNo) { - unlauncheable.add(player); - iterator.remove(); - } - } - hologramLaunch.setVisible(launcheable); - hologramLaunchNo.setVisible(unlauncheable); - } - - } - }.runTaskTimer(BeautyQuests.getInstance(), 20L, 20L); - } - - private BukkitTask startHologramsTask() { - return new BukkitRunnable() { - @Override - public void run() { - LivingEntity en = null; // check if NPC is spawned and living - if (npc.isSpawned() && getEntity() instanceof LivingEntity) - en = (LivingEntity) getEntity(); - if (en == null) { - if (!hologramsRemoved) removeHolograms(false); // if the NPC is not living and holograms have not been already removed before - return; - } - hologramsRemoved = false; - - if (hologramText.canAppear && hologramText.visible) hologramText.refresh(en); - if (hologramLaunch.canAppear) hologramLaunch.refresh(en); - if (hologramLaunchNo.canAppear) hologramLaunchNo.refresh(en); - if (hologramPool.canAppear) hologramPool.refresh(en); - } - }.runTaskTimer(BeautyQuests.getInstance(), 20L, 1L); - } - - @Override - public Set<Quest> getQuests() { - return quests.keySet(); - } - - public Hologram getHologramText() { - return hologramText; - } - - public Hologram getHologramLaunch() { - return hologramLaunch; - } - - public Hologram getHologramLaunchNo() { - return hologramLaunchNo; - } - - public void addQuest(Quest quest) { - if (quests.containsKey(quest)) return; - quests.put(quest, new ArrayList<>()); - if (hologramText.enabled && quest.hasOption(OptionHologramText.class)) hologramText.setText(quest.getOption(OptionHologramText.class).getValue()); - if (hologramLaunch.enabled && quest.hasOption(OptionHologramLaunch.class)) hologramLaunch.setItem(quest.getOption(OptionHologramLaunch.class).getValue()); - if (hologramLaunchNo.enabled && quest.hasOption(OptionHologramLaunchNo.class)) hologramLaunchNo.setItem(quest.getOption(OptionHologramLaunchNo.class).getValue()); - hologramText.visible = true; - addStartablePredicate(p -> quest.canStart(p, false), quest); - updatedObjects(); - } - - public boolean removeQuest(Quest quest) { - boolean b = quests.remove(quest) == null; - removeStartablePredicate(quest); - updatedObjects(); - if (quests.isEmpty()) { - hologramText.visible = false; - hologramText.delete(); - } - return b; - } - - @Override - public boolean hasQuestStarted(Player p) { - PlayerAccount acc = PlayersManager.getPlayerAccount(p); - return quests.keySet().stream().anyMatch(quest -> quest.hasStarted(acc)); - } - - @Override - public Set<QuestPool> getPools() { - return pools; - } - - public void addPool(QuestPool pool) { - if (!pools.add(pool)) return; - if (hologramPool.enabled && (pool.getHologram() != null)) hologramPool.setText(pool.getHologram()); - addStartablePredicate(pool::canGive, pool); - updatedObjects(); - } - - public boolean removePool(QuestPool pool) { - boolean b = pools.remove(pool); - removeStartablePredicate(pool); - updatedObjects(); - if (pools.isEmpty()) hologramPool.delete(); - return b; - } - - @Override - public void addStartablePredicate(Predicate<Player> predicate, Object holder) { - startable.put(holder, predicate); - } - - @Override - public void removeStartablePredicate(Object holder) { - startable.remove(holder); - } - - @Override - public void hideForPlayer(Player p, Object holder) { - hiddenTickets.add(new AbstractMap.SimpleEntry<>(p, holder)); - } - - @Override - public void removeHiddenForPlayer(Player p, Object holder) { - for (Iterator<Entry<Player, Object>> iterator = hiddenTickets.iterator(); iterator.hasNext();) { - Entry<Player, Object> entry = iterator.next(); - if (entry.getKey() == p && entry.getValue() == holder) { - iterator.remove(); - return; - } - } - } - - @Override - public boolean canGiveSomething(Player p) { - return startable.values().stream().anyMatch(predicate -> predicate.test(p)); - } - - private void removeHolograms(boolean cancelRefresh) { - hologramText.delete(); - hologramLaunch.delete(); - hologramLaunchNo.delete(); - hologramPool.delete(); - hologramsRemoved = true; - if (cancelRefresh && hologramsTask != null) { - hologramsTask.cancel(); - hologramsTask = null; - } - } - - private boolean isEmpty() { - return quests.isEmpty() && pools.isEmpty(); - } - - private void updatedObjects() { - if (isEmpty()) { - removeHolograms(true); - }else if (holograms && hologramsTask == null) { - hologramsTask = startHologramsTask(); - } - } - - public void unload() { - removeHolograms(true); - if (launcheableTask != null) { - launcheableTask.cancel(); - launcheableTask = null; - } - } - - public void delete(String cause) { - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + npc.getId()); - for (Quest qu : quests.keySet()) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Starter NPC #" + npc.getId() + " has been removed from quest " + qu.getId() + ". Reason: " + cause); - qu.removeOption(OptionStarterNPC.class); - } - quests = null; - for (QuestPool pool : pools) { - QuestsPlugin.getPlugin().getLoggerExpanded() - .warning("NPC #" + npc.getId() + " has been removed from pool " + pool.getId() + ". Reason: " + cause); - ((QuestPoolImplementation) pool).unloadStarter(); - } - unload(); - } - - public void toggleDebug() { - if (debug) - debug = false; - else debug = true; - } - - @Override - public String toString() { - String npcInfo = "NPC #" + npc.getId() + ", " + quests.size() + " quests, " + pools.size() + " pools"; - String hologramsInfo; - if (!holograms) { - hologramsInfo = "no holograms"; - }else if (hologramsRemoved) { - hologramsInfo = "holograms removed"; - }else { - hologramsInfo = "holograms:"; - hologramsInfo += "\n- text=" + hologramText.toString(); - hologramsInfo += "\n- launch=" + hologramLaunch.toString(); - hologramsInfo += "\n- launchNo=" + hologramLaunchNo.toString(); - hologramsInfo += "\n- pool=" + hologramPool.toString(); - } - return npcInfo + " " + hologramsInfo; - } - - public class Hologram { - final boolean enabled; - boolean visible; - boolean canAppear; - AbstractHolograms<?>.BQHologram hologram; - - String text; - ItemStack item; - - public Hologram(boolean visible, boolean enabled, String text) { - this.visible = visible; - this.enabled = enabled; - setText(text); - } - - public Hologram(boolean visible, boolean enabled, ItemStack item) { - this.visible = visible; - this.enabled = enabled; - setItem(item); - } - - public void refresh(LivingEntity en) { - Location lc = Utils.upLocationForEntity(en, getYAdd()); - if (debug) System.out.println("refreshing " + toString() + " (hologram null: " + (hologram == null) + ")"); - if (hologram == null) { - create(lc); - }else { - hologram.teleport(lc); - } - } - - public double getYAdd() { - return item == null ? 0 : 1; - } - - public void setVisible(List<Player> players) { - if (hologram != null) hologram.setPlayersVisible(players); - } - - public void setVisible(Player p, boolean visibility) { - if (hologram != null) hologram.setPlayerVisibility(p, visibility); - } - - public void setText(String text) { - if (Objects.equals(text, this.text)) return; - this.text = text; - canAppear = enabled && !StringUtils.isEmpty(text) && !"none".equals(text); - delete(); // delete to regenerate with new text - } - - public void setItem(ItemStack item) { - if (Objects.equals(item, this.item)) return; - this.item = item; - canAppear = enabled && item != null; - if (canAppear && QuestsConfigurationImplementation.getConfiguration().isCustomHologramNameShown() - && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) - this.text = item.getItemMeta().getDisplayName(); - delete(); // delete to regenerate with new item - } - - public void create(Location lc) { - if (hologram != null) return; - hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(lc, visible); - if (text != null) hologram.appendTextLine(text); - if (item != null) hologram.appendItem(item); - } - - public void delete() { - if (debug) System.out.println("deleting " + toString()); - if (hologram == null) return; - hologram.delete(); - hologram = null; - } - - @Override - public String toString() { - if (!enabled) return "disabled"; - if (!canAppear) return "cannot appear"; - return (visible ? "visible" : "invisible") + " by default, " - + (item == null ? "" : item.getType().name() + ", ") - + (text == null ? "no text" : "text=" + text) + ", " - + (hologram == null ? " not spawned" : "spawned"); - } - - } - +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; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqNpc; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.types.Locatable.Located; +import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.options.OptionHologramLaunch; +import fr.skytasul.quests.options.OptionHologramLaunchNo; +import fr.skytasul.quests.options.OptionHologramText; +import fr.skytasul.quests.options.OptionStarterNPC; +import fr.skytasul.quests.structure.pools.QuestPoolImplementation; + +public class BqNpcImplementation implements Located.LocatedEntity, BqNpc { + + private Map<Quest, List<Player>> quests = new TreeMap<>(); + private Set<QuestPool> pools = new TreeSet<>(); + + private List<Entry<Player, Object>> hiddenTickets = new ArrayList<>(); + private Map<Object, Predicate<Player>> startable = new HashMap<>(); + + private BukkitTask launcheableTask; + + /* Holograms */ + private boolean debug = false; + private BukkitTask hologramsTask; + private boolean hologramsRemoved = true; + private Hologram hologramText = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() + && !QuestsConfigurationImplementation.getConfiguration().isTextHologramDisabled(), + Lang.HologramText.toString()); + private Hologram hologramLaunch = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems(), + QuestsConfigurationImplementation.getConfiguration().getHoloLaunchItem()); + private Hologram hologramLaunchNo = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() + && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility(), + QuestsConfigurationImplementation.getConfiguration().getHoloLaunchNoItem()); + private Hologram hologramPool = new Hologram(false, + QuestsAPI.getAPI().hasHologramsManager() + && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility(), + Lang.PoolHologramText.toString()) { + @Override + public double getYAdd() { + return hologramText.canAppear && hologramText.visible ? 0.55 : 0; + } + }; + private final boolean holograms; + + private BqInternalNpc npc; + + private @Nullable PlaceholderRegistry placeholders; + + public BqNpcImplementation(BqInternalNpc npc) { + this.npc = npc; + + holograms = hologramText.enabled || hologramLaunch.enabled || hologramLaunchNo.enabled || hologramPool.enabled; + launcheableTask = startLauncheableTasks(); + } + + @Override + public BqInternalNpc getNpc() { + return npc; + } + + public void setNpc(BqInternalNpc npc) { + this.npc = npc; + } + + @Override + public @NotNull Entity getEntity() { + return npc.getEntity(); + } + + @Override + public @NotNull Location getLocation() { + return npc.getLocation(); + } + + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry() + .register("npc_name", npc.getName()) + .register("npc_id", npc.getId()); + } + return placeholders; + } + + private BukkitTask startLauncheableTasks() { + return new BukkitRunnable() { + private int timer = 0; + + @Override + public void run() { + if (!npc.isSpawned()) + return; + if (!(getEntity() instanceof LivingEntity)) return; + LivingEntity en = (LivingEntity) getEntity(); + + if (timer-- == 0) { + timer = QuestsConfiguration.getConfig().getQuestsConfig().requirementUpdateTime(); + return; + } + + quests.values().forEach(List::clear); + + Set<Player> playersInRadius = new HashSet<>(); + Location lc = en.getLocation(); + for (Player p : lc.getWorld().getPlayers()) { + PlayerAccount acc = PlayersManager.getPlayerAccount(p); + if (acc == null) continue; + if (lc.distanceSquared(p.getLocation()) > Math + .pow(QuestsConfiguration.getConfig().getQuestsConfig().startParticleDistance(), 2)) + continue; + playersInRadius.add(p); + for (Entry<Quest, List<Player>> quest : quests.entrySet()) { + if (quest.getKey().canStart(p, false)) { + quest.getValue().add(p); + break; + } + } + } + + if (QuestsConfigurationImplementation.getConfiguration().showStartParticles()) { + quests.forEach((quest, players) -> QuestsConfigurationImplementation.getConfiguration() + .getParticleStart().send(en, players)); + } + + if (hologramPool.canAppear) { + for (Player p : playersInRadius) { + boolean visible = false; + for (QuestPool pool : pools) { + if (pool.canGive(p)) { + visible = true; + break; + } + } + hologramPool.setVisible(p, visible); + } + } + if (hologramLaunch.canAppear || hologramLaunchNo.canAppear) { + List<Player> launcheable = new ArrayList<>(); + List<Player> unlauncheable = new ArrayList<>(); + for (Iterator<Player> iterator = playersInRadius.iterator(); iterator.hasNext();) { + Player player = iterator.next(); + if (hiddenTickets.stream().anyMatch(entry -> entry.getKey() == player)) { + iterator.remove(); + continue; + } + PlayerAccount acc = PlayersManager.getPlayerAccount(player); + boolean launchYes = false; + boolean launchNo = false; + for (Entry<Quest, List<Player>> qu : quests.entrySet()) { + if (!qu.getKey().hasStarted(acc)) { + boolean pLauncheable = qu.getValue().contains(player); + if (hologramLaunch.enabled && pLauncheable) { + launchYes = true; + break; // launcheable take priority over not launcheable + }else if (hologramLaunchNo.enabled && !pLauncheable) { + launchNo = true; + } + } + } + if (launchYes) { + launcheable.add(player); + iterator.remove(); + }else if (launchNo) { + unlauncheable.add(player); + iterator.remove(); + } + } + hologramLaunch.setVisible(launcheable); + hologramLaunchNo.setVisible(unlauncheable); + } + + } + }.runTaskTimer(BeautyQuests.getInstance(), 20L, 20L); + } + + private BukkitTask startHologramsTask() { + return new BukkitRunnable() { + @Override + public void run() { + LivingEntity en = null; // check if NPC is spawned and living + if (npc.isSpawned() && getEntity() instanceof LivingEntity) + en = (LivingEntity) getEntity(); + if (en == null) { + if (!hologramsRemoved) removeHolograms(false); // if the NPC is not living and holograms have not been already removed before + return; + } + hologramsRemoved = false; + + if (hologramText.canAppear && hologramText.visible) hologramText.refresh(en); + if (hologramLaunch.canAppear) hologramLaunch.refresh(en); + if (hologramLaunchNo.canAppear) hologramLaunchNo.refresh(en); + if (hologramPool.canAppear) hologramPool.refresh(en); + } + }.runTaskTimer(BeautyQuests.getInstance(), 20L, 1L); + } + + @Override + public Set<Quest> getQuests() { + return quests.keySet(); + } + + public Hologram getHologramText() { + return hologramText; + } + + public Hologram getHologramLaunch() { + return hologramLaunch; + } + + public Hologram getHologramLaunchNo() { + return hologramLaunchNo; + } + + public void addQuest(Quest quest) { + if (quests.containsKey(quest)) return; + quests.put(quest, new ArrayList<>()); + if (hologramText.enabled && quest.hasOption(OptionHologramText.class)) hologramText.setText(quest.getOption(OptionHologramText.class).getValue()); + if (hologramLaunch.enabled && quest.hasOption(OptionHologramLaunch.class)) hologramLaunch.setItem(quest.getOption(OptionHologramLaunch.class).getValue()); + if (hologramLaunchNo.enabled && quest.hasOption(OptionHologramLaunchNo.class)) hologramLaunchNo.setItem(quest.getOption(OptionHologramLaunchNo.class).getValue()); + hologramText.visible = true; + addStartablePredicate(p -> quest.canStart(p, false), quest); + updatedObjects(); + } + + public boolean removeQuest(Quest quest) { + boolean b = quests.remove(quest) == null; + removeStartablePredicate(quest); + updatedObjects(); + if (quests.isEmpty()) { + hologramText.visible = false; + hologramText.delete(); + } + return b; + } + + @Override + public boolean hasQuestStarted(Player p) { + PlayerAccount acc = PlayersManager.getPlayerAccount(p); + return quests.keySet().stream().anyMatch(quest -> quest.hasStarted(acc)); + } + + @Override + public Set<QuestPool> getPools() { + return pools; + } + + public void addPool(QuestPool pool) { + if (!pools.add(pool)) return; + if (hologramPool.enabled && (pool.getHologram() != null)) hologramPool.setText(pool.getHologram()); + addStartablePredicate(pool::canGive, pool); + updatedObjects(); + } + + public boolean removePool(QuestPool pool) { + boolean b = pools.remove(pool); + removeStartablePredicate(pool); + updatedObjects(); + if (pools.isEmpty()) hologramPool.delete(); + return b; + } + + @Override + public void addStartablePredicate(Predicate<Player> predicate, Object holder) { + startable.put(holder, predicate); + } + + @Override + public void removeStartablePredicate(Object holder) { + startable.remove(holder); + } + + @Override + public void hideForPlayer(Player p, Object holder) { + hiddenTickets.add(new AbstractMap.SimpleEntry<>(p, holder)); + } + + @Override + public void removeHiddenForPlayer(Player p, Object holder) { + for (Iterator<Entry<Player, Object>> iterator = hiddenTickets.iterator(); iterator.hasNext();) { + Entry<Player, Object> entry = iterator.next(); + if (entry.getKey() == p && entry.getValue() == holder) { + iterator.remove(); + return; + } + } + } + + @Override + public boolean canGiveSomething(Player p) { + return startable.values().stream().anyMatch(predicate -> predicate.test(p)); + } + + private void removeHolograms(boolean cancelRefresh) { + hologramText.delete(); + hologramLaunch.delete(); + hologramLaunchNo.delete(); + hologramPool.delete(); + hologramsRemoved = true; + if (cancelRefresh && hologramsTask != null) { + hologramsTask.cancel(); + hologramsTask = null; + } + } + + private boolean isEmpty() { + return quests.isEmpty() && pools.isEmpty(); + } + + private void updatedObjects() { + if (isEmpty()) { + removeHolograms(true); + }else if (holograms && hologramsTask == null) { + hologramsTask = startHologramsTask(); + } + } + + public void unload() { + removeHolograms(true); + if (launcheableTask != null) { + launcheableTask.cancel(); + launcheableTask = null; + } + } + + public void delete(String cause) { + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + npc.getId()); + for (Quest qu : quests.keySet()) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Starter NPC #" + npc.getId() + " has been removed from quest " + qu.getId() + ". Reason: " + cause); + qu.removeOption(OptionStarterNPC.class); + } + quests = null; + for (QuestPool pool : pools) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("NPC #" + npc.getId() + " has been removed from pool " + pool.getId() + ". Reason: " + cause); + ((QuestPoolImplementation) pool).unloadStarter(); + } + unload(); + } + + public void toggleDebug() { + if (debug) + debug = false; + else debug = true; + } + + @Override + public String toString() { + String npcInfo = "NPC #" + npc.getId() + ", " + quests.size() + " quests, " + pools.size() + " pools"; + String hologramsInfo; + if (!holograms) { + hologramsInfo = "no holograms"; + }else if (hologramsRemoved) { + hologramsInfo = "holograms removed"; + }else { + hologramsInfo = "holograms:"; + hologramsInfo += "\n- text=" + hologramText.toString(); + hologramsInfo += "\n- launch=" + hologramLaunch.toString(); + hologramsInfo += "\n- launchNo=" + hologramLaunchNo.toString(); + hologramsInfo += "\n- pool=" + hologramPool.toString(); + } + return npcInfo + " " + hologramsInfo; + } + + public class Hologram { + final boolean enabled; + boolean visible; + boolean canAppear; + AbstractHolograms<?>.BQHologram hologram; + + String text; + ItemStack item; + + public Hologram(boolean visible, boolean enabled, String text) { + this.visible = visible; + this.enabled = enabled; + setText(text); + } + + public Hologram(boolean visible, boolean enabled, ItemStack item) { + this.visible = visible; + this.enabled = enabled; + setItem(item); + } + + public void refresh(LivingEntity en) { + Location lc = Utils.upLocationForEntity(en, getYAdd()); + if (debug) System.out.println("refreshing " + toString() + " (hologram null: " + (hologram == null) + ")"); + if (hologram == null) { + create(lc); + }else { + hologram.teleport(lc); + } + } + + public double getYAdd() { + return item == null ? 0 : 1; + } + + public void setVisible(List<Player> players) { + if (hologram != null) hologram.setPlayersVisible(players); + } + + public void setVisible(Player p, boolean visibility) { + if (hologram != null) hologram.setPlayerVisibility(p, visibility); + } + + public void setText(String text) { + if (Objects.equals(text, this.text)) return; + this.text = text; + canAppear = enabled && !StringUtils.isEmpty(text) && !"none".equals(text); + delete(); // delete to regenerate with new text + } + + public void setItem(ItemStack item) { + if (Objects.equals(item, this.item)) return; + this.item = item; + canAppear = enabled && item != null; + if (canAppear && QuestsConfigurationImplementation.getConfiguration().isCustomHologramNameShown() + && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) + this.text = item.getItemMeta().getDisplayName(); + delete(); // delete to regenerate with new item + } + + public void create(Location lc) { + if (hologram != null) return; + hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(lc, visible); + if (text != null) hologram.appendTextLine(text); + if (item != null) hologram.appendItem(item); + } + + public void delete() { + if (debug) System.out.println("deleting " + toString()); + if (hologram == null) return; + hologram.delete(); + hologram = null; + } + + @Override + public String toString() { + if (!enabled) return "disabled"; + if (!canAppear) return "cannot appear"; + return (visible ? "visible" : "invisible") + " by default, " + + (item == null ? "" : item.getType().name() + ", ") + + (text == null ? "no text" : "text=" + text) + ", " + + (hologram == null ? " not spawned" : "spawned"); + } + + } + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java index 69963fc8..e535046e 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java @@ -12,6 +12,7 @@ import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; public class OptionDescription extends QuestOptionString implements QuestDescriptionProvider { @@ -56,7 +57,8 @@ public List<String> provideDescription(QuestDescriptionContext context) { List<String> description = cachedDescription.getIfPresent(context); if (description == null) { description = Arrays - .asList("§7" + MessageUtils.finalFormat(context.getPlayerAccount().getPlayer(), getValue(), true, null)); + .asList("§7" + MessageUtils.finalFormat(getValue(), null, + PlaceholdersContext.of(context.getPlayerAccount().getPlayer(), true))); cachedDescription.put(context, description); } return description; diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java index f2383a8e..91ee97e6 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java @@ -14,6 +14,7 @@ import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; @@ -70,7 +71,7 @@ public boolean test(Player p){ if (comparison == ComparisonMethod.DIFFERENT) return !value.equals(request); String value = this.value; if (parseValue) - value = MessageUtils.finalFormat(p, value, true, null); + value = MessageUtils.finalFormat(value, null, PlaceholdersContext.of(p, true)); return value.equals(request); } diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java index 2a7e4244..d1f00552 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java @@ -29,6 +29,7 @@ import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.PlayerListCategory; import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; public class Scoreboard extends BukkitRunnable implements Listener { @@ -307,7 +308,7 @@ private boolean tryRefresh(boolean time) { lines = Collections.emptyList(); lastValue = null; } else { - text = MessageUtils.finalFormat(p, text, true, null); + text = MessageUtils.finalFormat(text, null, PlaceholdersContext.of(p, true)); if (text.equals(lastValue)) return false; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java index 41687402..30dffdb5 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageArea.java @@ -16,17 +16,19 @@ import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.DebugUtils; import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardEntryEvent; @@ -97,13 +99,15 @@ public void onRegionExit(WorldGuardExitEvent e) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return MessageUtils.format(Lang.SCOREBOARD_REG.toString(), region.getId()); + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("region_id", region.getId()); + placeholders.register("region_world", world.getName()); } - + @Override - public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new String[]{region.getId()}; + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_REG.toString(); } @Override @@ -164,7 +168,7 @@ public void setupLine(@NotNull StageGuiLine line) { public void setRegion(String regionName, String worldName) { this.regionName = regionName; this.worldName = worldName; - getLine().refreshItemLore(7, Lang.optionValue.format(regionName + " (" + worldName + ")")); + getLine().refreshItemLore(7, QuestOption.formatNullableValue(regionName + " (" + worldName + ")")); } public void setExit(boolean exit) { @@ -175,8 +179,8 @@ public void setExit(boolean exit) { } private void launchRegionEditor(Player p, boolean first) { - MessageUtils.sendPrefixedMessage(p, - Lang.REGION_NAME.toString() + (first ? "" : "\n" + Lang.TYPE_CANCEL.toString())); + MessageUtils.sendMessage(p, Lang.REGION_NAME.toString() + (first ? "" : "\n" + Lang.TYPE_CANCEL.toString()), + MessageType.PREFIXED); new TextEditor<String>(p, () -> { if (first) context.remove(); @@ -185,7 +189,7 @@ private void launchRegionEditor(Player p, boolean first) { if (BQWorldGuard.getInstance().regionExists(obj, p.getWorld())) { setRegion(obj, p.getWorld().getName()); }else { - MessageUtils.sendPrefixedMessage(p, Lang.REGION_DOESNT_EXIST.toString()); + Lang.REGION_DOESNT_EXIST.send(p); if (first) context.remove(); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java index 0f208e98..0bc13d15 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java @@ -1,59 +1,58 @@ -package fr.skytasul.quests.stages; - -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Breedable; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.entity.EntityBreedEvent; -import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.creation.StageCreationContext; -import fr.skytasul.quests.api.stages.types.AbstractEntityStage; - -public class StageBreed extends AbstractEntityStage { - - public StageBreed(StageController controller, EntityType entity, int amount) { - super(controller, entity, amount); - } - - @EventHandler - public void onBreed(EntityBreedEvent e) { - if (e.getBreeder() instanceof Player) { - Player p = (Player) e.getBreeder(); - event(p, e.getEntityType()); - } - } - - @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_BREED.format(getMobsLeft(acc)); - } - - public static StageBreed deserialize(ConfigurationSection section, StageController controller) { - String type = section.getString("entityType"); - return new StageBreed(controller, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); - } - - public static class Creator extends AbstractEntityStage.AbstractCreator<StageBreed> { - - public Creator(@NotNull StageCreationContext<StageBreed> context) { - super(context); - } - - @Override - protected boolean canUseEntity(EntityType type) { - return Breedable.class.isAssignableFrom(type.getEntityClass()); - } - - @Override - protected StageBreed finishStage(StageController controller) { - return new StageBreed(controller, entity, amount); - } - - } - -} +package fr.skytasul.quests.stages; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Breedable; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityBreedEvent; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.types.AbstractEntityStage; + +public class StageBreed extends AbstractEntityStage { + + public StageBreed(StageController controller, EntityType entity, int amount) { + super(controller, entity, amount); + } + + @EventHandler + public void onBreed(EntityBreedEvent e) { + if (e.getBreeder() instanceof Player) { + Player p = (Player) e.getBreeder(); + event(p, e.getEntityType()); + } + } + + @Override + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_BREED.toString(); + } + + public static StageBreed deserialize(ConfigurationSection section, StageController controller) { + String type = section.getString("entityType"); + return new StageBreed(controller, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); + } + + public static class Creator extends AbstractEntityStage.AbstractCreator<StageBreed> { + + public Creator(@NotNull StageCreationContext<StageBreed> context) { + super(context); + } + + @Override + protected boolean canUseEntity(EntityType type) { + return Breedable.class.isAssignableFrom(type.getEntityClass()); + } + + @Override + protected StageBreed finishStage(StageController controller) { + return new StageBreed(controller, entity, amount); + } + + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 91eed130..3a83eb2a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -16,15 +16,22 @@ import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.dialogs.Message; +import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; -import fr.skytasul.quests.api.utils.SplittableDescriptionConfiguration; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.gui.items.ItemComparisonGUI; import fr.skytasul.quests.gui.items.ItemsGUI; @@ -35,8 +42,7 @@ public class StageBringBack extends StageNPC{ protected final ItemComparisonMap comparisons; protected final Map<ItemStack, Integer> amountsMap = new HashMap<>(); - protected final String splitted; - protected final String line; + protected final String[] itemsDescriptions; public StageBringBack(StageController controller, ItemStack[] items, String customMessage, ItemComparisonMap comparisons) { super(controller); @@ -49,20 +55,24 @@ public StageBringBack(StageController controller, ItemStack[] items, String cust amountsMap.put(item, amount); } - String[] array = new String[items.length]; // create messages on beginning - SplittableDescriptionConfiguration splitConfig = QuestsConfiguration.getConfig().getStageDescriptionConfig(); - for (int i = 0; i < array.length; i++){ - array[i] = splitConfig.getItemNameColor() + Utils.getStringFromItemStack(items[i], - splitConfig.getItemAmountColor(), splitConfig.isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)); - } - splitted = MessageUtils.formatDescription(DescriptionSource.FORCESPLIT, splitConfig, array); - if (splitConfig.isAloneSplitAmountShown(DescriptionSource.FORCESPLIT)) { - for (int i = 0; i < array.length; i++) { - array[i] = splitConfig.getItemNameColor() - + Utils.getStringFromItemStack(items[i], splitConfig.getItemAmountColor(), false); - } - } - line = MessageUtils.formatDescription(DescriptionSource.FORCELINE, splitConfig, array); + itemsDescriptions = + Arrays.stream(items).map(item -> ItemsDescriptionPlaceholders.formatObject(new HasSingleObject() { + + @Override + public int getPlayerAmount(@NotNull PlayerAccount account) { + return item.getAmount(); + } + + @Override + public @NotNull String getObjectName() { + return ItemUtils.getName(item); + } + + @Override + public int getObjectAmount() { + return item.getAmount(); + } + }, PlaceholdersContext.of((Player) null, false))).toArray(String[]::new); } public boolean checkItems(Player p, boolean msg){ @@ -79,9 +89,8 @@ public boolean checkItems(Player p, boolean msg){ } public void sendNeedMessage(Player p) { - String message = getMessage(); - if (message != null && !message.isEmpty() && !message.equals("none")) - Lang.NpcText.sendWP(p, npcName(), MessageUtils.format(message, line), 1, 1); + new Message(MessageUtils.format(getMessage(), getPlaceholdersRegistry(), StageDescriptionPlaceholdersContext.of(true, + PlayersManager.getPlayerAccount(p), DescriptionSource.FORCELINE)), Sender.NPC).sendMessage(p, npcName(), 1, 1); } public void removeItems(Player p){ @@ -100,19 +109,16 @@ protected String getMessage() { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return MessageUtils.format(Lang.SCOREBOARD_ITEMS.toString() + " " - + (QuestsConfiguration.getConfig().getStageDescriptionConfig().getSplitSources().contains(source) ? splitted - : line), - npcName()); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_ITEMS.toString(); } - + @Override - public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new String[] { - QuestsConfiguration.getConfig().getStageDescriptionConfig().getSplitSources().contains(source) ? splitted - : line, - npcName()}; + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexedContextual("items", StageDescriptionPlaceholdersContext.class, + context -> ItemsDescriptionPlaceholders.formatObjectList(context.getDescriptionSource(), + QuestsConfiguration.getConfig().getStageDescriptionConfig(), itemsDescriptions)); } @Override @@ -212,21 +218,21 @@ public void setupLine(@NotNull StageGuiLine line) { public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); - getLine().refreshItemLore(5, Lang.optionValue.format(Lang.AmountItems.format(this.items.size()))); + getLine().refreshItemLore(5, + QuestOption.formatNullableValue(Lang.AmountItems.quickFormat("amount", this.items.size()))); } public void setMessage(String message) { this.message = message; - getLine().refreshItemLore(9, - message == null - ? Lang.optionValue.format(Lang.NEED_OBJECTS.toString()) + " " + Lang.defaultValue.toString() - : QuestOption.formatNullableValue(message)); + getLine().refreshItemLore(9, QuestOption.formatNullableValue(message, Lang.NEED_OBJECTS)); } public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; getLine().refreshItemLore(10, - Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size()))); + QuestOption.formatNullableValue( + Lang.AmountComparisons.quickFormat("amount", this.comparisons.getEffective().size()), + comparisons.isDefault())); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 0db0891f..0bd06782 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.stages; import java.util.Map; -import java.util.function.Supplier; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -15,19 +14,23 @@ import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionConfiguration; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.misc.BucketTypeGUI; -public class StageBucket extends AbstractStage { +public class StageBucket extends AbstractStage implements HasSingleObject { private BucketType bucket; private int amount; @@ -42,10 +45,25 @@ public BucketType getBucketType() { return bucket; } + @Override + public @NotNull String getObjectName() { + return bucket.getName(); + } + public int getBucketAmount() { return amount; } + @Override + public int getObjectAmount() { + return amount; + } + + @Override + public @NotNull ItemsDescriptionConfiguration getItemsDescriptionConfiguration() { + return QuestsConfiguration.getConfig().getStageDescriptionConfig(); + } + @EventHandler (priority = EventPriority.MONITOR) public void onBucketFill(PlayerBucketFillEvent e) { Player p = e.getPlayer(); @@ -61,7 +79,8 @@ public void onBucketFill(PlayerBucketFillEvent e) { } } - private int getPlayerAmount(PlayerAccount acc) { + @Override + public int getPlayerAmount(PlayerAccount acc) { return getData(acc, "amount"); } @@ -71,17 +90,15 @@ public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_BUCKET.format(Utils.getStringFromNameAndAmount(bucket.getName(), - QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), - amount, false)); + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.register("bucket_type", bucket.getName()); + ItemsDescriptionPlaceholders.register(placeholders, "buckets", this); } @Override - public Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Supplier[] {() -> Utils.getStringFromNameAndAmount(bucket.getName(), - QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), - amount, false)}; + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_BUCKET.toString(); } @Override @@ -166,14 +183,14 @@ public void setupLine(@NotNull StageGuiLine line) { public void setBucket(BucketType bucket) { this.bucket = bucket; - ItemStack newItem = ItemUtils.lore(getLine().getItem(7), Lang.optionValue.format(bucket.getName())); + ItemStack newItem = ItemUtils.lore(getLine().getItem(7), QuestOption.formatNullableValue(bucket.getName())); newItem.setType(bucket.type.parseMaterial()); getLine().refreshItem(7, newItem); } public void setAmount(int amount) { this.amount = amount; - getLine().refreshItemLore(6, Lang.Amount.format(amount)); + getLine().refreshItemLore(6, Lang.Amount.quickFormat("amount", amount)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index a3bb41de..f2a6490e 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -12,23 +12,23 @@ import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; public class StageChat extends AbstractStage{ - private String text; - private boolean cancel; - private boolean ignoreCase; - private boolean placeholders; - - private boolean command; + private final String text; + private final boolean cancel; + private final boolean ignoreCase; + private final boolean placeholders; + private final boolean command; public StageChat(StageController controller, String text, boolean cancel, boolean ignoreCase, boolean placeholders) { super(controller); @@ -43,13 +43,14 @@ public StageChat(StageController controller, String text, boolean cancel, boolea } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Lang.SCOREBOARD_CHAT.format(text); + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("text", text); } @Override - public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new String[]{text}; + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_CHAT.toString(); } public String getText() { @@ -78,7 +79,7 @@ public void onCommand(PlayerCommandPreprocessEvent e) { private boolean check(String message, Player p) { if (placeholders) - message = MessageUtils.finalFormat(p, message, true); + message = MessageUtils.finalFormat(text, null, PlaceholdersContext.of(p, true)); if (!(ignoreCase ? message.equalsIgnoreCase(text) : message.equals(text))) return false; if (!hasStarted(p)) return false; if (canUpdate(p)) finishStage(p); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index d4c1524a..14df5bc1 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.stages; import java.util.Map; -import java.util.function.Supplier; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -12,29 +11,32 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.events.internal.BQCraftEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.items.ItemComparisonGUI; /** * @author SkytAsul, ezeiger92, TheBusyBiscuit */ -public class StageCraft extends AbstractStage { +public class StageCraft extends AbstractStage implements HasSingleObject { - private ItemStack result; + private final ItemStack result; private final ItemComparisonMap comparisons; public StageCraft(StageController controller, ItemStack result, ItemComparisonMap comparisons) { @@ -127,25 +129,33 @@ public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { datas.put("amount", result.getAmount()); } - private int getPlayerAmount(PlayerAccount acc) { + @Override + public int getPlayerAmount(PlayerAccount acc) { Integer amount = getData(acc, "amount"); return amount == null ? 0 : amount.intValue(); } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_CRAFT.format(Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), - QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), - result.getAmount(), false)); + public @NotNull String getObjectName() { + return ItemUtils.getName(result, true); } @Override - public Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Supplier[] {() -> Utils.getStringFromNameAndAmount(ItemUtils.getName(result, true), - QuestsConfiguration.getConfig().getStageDescriptionConfig().getItemAmountColor(), getPlayerAmount(acc), - result.getAmount(), false)}; + public int getObjectAmount() { + return result.getAmount(); } - + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + ItemsDescriptionPlaceholders.register(placeholders, "items", this); + } + + @Override + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_CRAFT.toString(); + } + @Override protected void serialize(ConfigurationSection section) { section.set("result", result.serialize()); @@ -202,13 +212,15 @@ public void setupLine(@NotNull StageGuiLine line) { public void setItem(ItemStack item) { this.item = item; getLine().refreshItem(ITEM_SLOT, - item2 -> ItemUtils.lore(item2, Lang.optionValue.format(Utils.getStringFromItemStack(item, "§8", true)))); + item2 -> ItemUtils.lore(item2, + QuestOption.formatNullableValue(Utils.getStringFromItemStack(item, "§8", true)))); } public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; getLine().refreshItem(COMPARISONS_SLOT, item -> ItemUtils.lore(item, - Lang.optionValue.format(Lang.AmountComparisons.format(this.comparisons.getEffective().size())))); + QuestOption.formatNullableValue( + Lang.AmountComparisons.quickFormat("amount", this.comparisons.getEffective().size())))); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index c71e9f81..7d483b37 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -4,7 +4,6 @@ import java.util.List; import java.util.Map; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.bukkit.DyeColor; import org.bukkit.configuration.ConfigurationSection; @@ -23,36 +22,30 @@ import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.mobs.MobSelectionGUI; import fr.skytasul.quests.mobs.Mob; @SuppressWarnings ("rawtypes") -public class StageDealDamage extends AbstractStage { +public class StageDealDamage extends AbstractStage implements HasSingleObject { private final double damage; private final List<Mob> targetMobs; - private final String targetMobsString; - public StageDealDamage(StageController controller, double damage, List<Mob> targetMobs) { super(controller); this.damage = damage; this.targetMobs = targetMobs; - - targetMobsString = getTargetMobsString(targetMobs); - } - - private static String getTargetMobsString(List<Mob> targetMobs) { - if (targetMobs == null || targetMobs.isEmpty()) return Lang.EntityTypeAny.toString(); - return targetMobs.stream().map(Mob::getName).collect(Collectors.joining(", ")); } @Override @@ -89,14 +82,36 @@ public void onDamage(EntityDamageByEntityEvent event) { } } + public double getPlayerAmountDouble(@NotNull PlayerAccount account) { + return getData(account, "amount"); + } + @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return (targetMobs == null || targetMobs.isEmpty() ? Lang.SCOREBOARD_DEAL_DAMAGE_ANY : Lang.SCOREBOARD_DEAL_DAMAGE_MOBS).format(descriptionFormat(acc, source)); + public int getPlayerAmount(@NotNull PlayerAccount account) { + return (int) Math.ceil(getPlayerAmountDouble(account)); } - + @Override - public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Object[] { (Supplier<String>) () -> Integer.toString(super.<Double>getData(acc, "amount").intValue()), targetMobsString }; + public int getObjectAmount() { + return (int) damage; + } + + @Override + public @NotNull String getObjectName() { + return "damage"; + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + ItemsDescriptionPlaceholders.register(placeholders, "damage", this); + placeholders.registerIndexed("target_mobs", getTargetMobsString(targetMobs)); + } + + @Override + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return targetMobs == null || targetMobs.isEmpty() ? Lang.SCOREBOARD_DEAL_DAMAGE_ANY.toString() + : Lang.SCOREBOARD_DEAL_DAMAGE_MOBS.toString(); } @Override @@ -112,6 +127,12 @@ public static StageDealDamage deserialize(ConfigurationSection section, StageCon section.contains("targetMobs") ? section.getMapList("targetMobs").stream().map(map -> Mob.deserialize((Map) map)).collect(Collectors.toList()) : null); } + private static String getTargetMobsString(List<Mob> targetMobs) { + if (targetMobs == null || targetMobs.isEmpty()) + return Lang.EntityTypeAny.toString(); + return targetMobs.stream().map(Mob::getName).collect(Collectors.joining(", ")); + } + public static class Creator extends StageCreation<StageDealDamage> { private static final int SLOT_DAMAGE = 6; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java index 30128a24..4fee91e4 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java @@ -13,10 +13,10 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; @@ -46,7 +46,7 @@ public void onPlayerDeath(PlayerDeathEvent event) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_DIE.toString(); } @@ -89,8 +89,9 @@ public void setupLine(@NotNull StageGuiLine line) { public void setCauses(List<DamageCause> causes) { this.causes = causes; - getLine().refreshItem(CAUSES_SLOT, item -> ItemUtils.lore(item, Lang.optionValue - .format(causes.isEmpty() ? Lang.stageDeathCauseAny : Lang.stageDeathCausesSet.format(causes.size())))); + getLine().refreshItem(CAUSES_SLOT, + item -> ItemUtils.lore(item, QuestOption.formatNullableValue(causes.isEmpty() ? Lang.stageDeathCauseAny + : Lang.stageDeathCausesSet.quickFormat("causes_amount", causes.size())))); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java index 954bd5e5..9aaf4f00 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java @@ -10,9 +10,8 @@ import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; @@ -28,8 +27,8 @@ public StageEatDrink(ConfigurationSection section, StageController controller) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_EAT_DRINK.format(super.descriptionLine(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_EAT_DRINK.toString(); } @EventHandler diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java index 1fd17e54..0c9a0d59 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java @@ -12,9 +12,8 @@ import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; @@ -43,10 +42,10 @@ public void onEnchant(EnchantItemEvent e) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_ENCHANT.format(super.descriptionLine(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_ENCHANT.toString(); } - + public static StageEnchant deserialize(ConfigurationSection section, StageController controller) { return new StageEnchant(controller, section); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java index 722d62e1..901e1b6c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java @@ -14,9 +14,8 @@ import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; @@ -44,8 +43,8 @@ public void onFish(PlayerFishEvent e){ } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_FISH.format(super.descriptionLine(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_FISH.toString(); } public static StageFish deserialize(ConfigurationSection section, StageController controller) { 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 a793a865..94e44eec 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -16,10 +16,10 @@ import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; @@ -27,6 +27,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.BQLocation; @@ -39,16 +40,12 @@ public class StageLocation extends AbstractStage implements Locatable.PreciseLoc private final int radiusSquared; private final boolean gps; - private String descMessage; - public StageLocation(StageController controller, BQLocation lc, int radius, boolean gps) { super(controller); this.lc = lc; this.radius = radius; this.radiusSquared = radius * radius; this.gps = gps; - - this.descMessage = Lang.SCOREBOARD_LOCATION.format(lc.getBlockX(), lc.getBlockY(), lc.getBlockZ(), lc.getWorldName()); } public BQLocation getLocation() { @@ -121,13 +118,17 @@ public void ended(PlayerAccount acc) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return descMessage; + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("target_x", lc.getBlockX()); + placeholders.registerIndexed("target_y", lc.getBlockY()); + placeholders.registerIndexed("target_z", lc.getBlockZ()); + placeholders.registerIndexed("target_world", lc.getWorldName()); } @Override - public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Object[] { lc.getBlockX(), lc.getBlockY(), lc.getBlockZ(), lc.getWorldName() }; + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_LOCATION.toString(); } @Override @@ -195,7 +196,8 @@ public void setLocation(Location location) { public void setRadius(int radius) { this.radius = radius; - getLine().refreshItem(SLOT_RADIUS, item -> ItemUtils.lore(item, Lang.stageLocationCurrentRadius.format(radius))); + getLine().refreshItem(SLOT_RADIUS, + item -> ItemUtils.lore(item, Lang.stageLocationCurrentRadius.quickFormat("radius", radius))); } public void setPattern(Pattern pattern) { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java index 4b05899d..5fb52819 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java @@ -11,9 +11,8 @@ import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; @@ -34,8 +33,8 @@ public void onMelt(FurnaceExtractEvent event) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_MELT.format(super.descriptionLine(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_MELT.toString(); } public static StageMelt deserialize(ConfigurationSection section, StageController controller) { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index c41afc0b..da042945 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -25,10 +25,9 @@ import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; @@ -55,8 +54,8 @@ public void setPlaceCancelled(boolean cancelPlaced) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Lang.SCOREBOARD_MINE.format(super.descriptionLine(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_MINE.toString(); } @EventHandler (priority = EventPriority.MONITOR) diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index d011a7d2..dd79bbc1 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -24,6 +24,7 @@ import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; @@ -33,6 +34,8 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.gui.mobs.MobsListGUI; import fr.skytasul.quests.mobs.Mob; @@ -81,15 +84,23 @@ protected boolean objectApplies(Mob<?> object, Object other) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Lang.SCOREBOARD_MOBS.format(super.descriptionLine(acc, source)); + protected @NotNull String getPlaceholderKey() { + return "mobs"; + } + + @Override + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_NONE.toString(); } @Override public void started(PlayerAccount acc) { super.started(acc); if (acc.isCurrent() && sendStartMessage()) { - Lang.STAGE_MOBSLIST.send(acc.getPlayer(), (Object[]) super.descriptionFormat(acc, DescriptionSource.FORCELINE)); + MessageUtils.sendMessage(acc.getPlayer(), Lang.STAGE_MOBSLIST.toString(), MessageType.PREFIXED, + getPlaceholdersRegistry(), + StageDescriptionPlaceholdersContext.of(true, acc, DescriptionSource.FORCELINE)); + Lang.STAGE_MOBSLIST.send(acc.getPlayer(), this); } } @@ -175,7 +186,7 @@ public void setupLine(@NotNull StageGuiLine line) { public void setMobs(List<MutableCountableObject<Mob<?>>> mobs) { this.mobs = mobs; getLine().refreshItem(7, - item -> ItemUtils.lore(item, Lang.optionValue.format(Lang.AmountMobs.format(mobs.size())))); + item -> ItemUtils.loreOptionValue(item, Lang.AmountMobs.quickFormat("mobs_amount", mobs.size()))); } public void setShoot(boolean shoot) { 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 8d278115..25b87afe 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -28,10 +28,10 @@ import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; @@ -40,63 +40,71 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; -@LocatableType (types = LocatedType.ENTITY) +@LocatableType(types = LocatedType.ENTITY) public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable { - + private BqNpc npc; private int npcID; protected Dialog dialog = null; protected DialogRunnerImplementation dialogRunner = null; protected boolean hide = false; - + private BukkitTask task; - + private List<Player> cached = new ArrayList<>(); protected AbstractHolograms<?>.BQHologram hologram; - + public StageNPC(StageController controller) { super(controller); } - - private void launchRefreshTask(){ - if (npc == null) return; + + private void launchRefreshTask() { + if (npc == null) + return; task = new BukkitRunnable() { List<Player> tmp = new ArrayList<>(); + @Override public void run() { Entity en = npc.getNpc().getEntity(); - if (en == null) return; - if (!en.getType().isAlive()) return; + if (en == null) + return; + if (!en.getType().isAlive()) + return; Location lc = en.getLocation(); tmp.clear(); for (Player p : cached) { - if (p.getWorld() != lc.getWorld()) continue; - if (lc.distance(p.getLocation()) > 50) continue; + if (p.getWorld() != lc.getWorld()) + continue; + if (lc.distance(p.getLocation()) > 50) + continue; tmp.add(p); } - + if (QuestsConfigurationImplementation.getConfiguration().getHoloTalkItem() != null && QuestsAPI.getAPI().hasHologramsManager() && QuestsAPI.getAPI().getHologramsManager().supportItems() && QuestsAPI.getAPI().getHologramsManager().supportPerPlayerVisibility()) { - if (hologram == null) createHoloLaunch(); + if (hologram == null) + createHoloLaunch(); hologram.setPlayersVisible(tmp); hologram.teleport(Utils.upLocationForEntity((LivingEntity) en, 1)); } - + if (QuestsConfigurationImplementation.getConfiguration().showTalkParticles()) { - if (tmp.isEmpty()) return; + if (tmp.isEmpty()) + return; QuestsConfigurationImplementation.getConfiguration().getParticleTalk().send(en, tmp); } } }.runTaskTimer(BeautyQuests.getInstance(), 20L, 6L); } - - private void createHoloLaunch(){ + + private void createHoloLaunch() { ItemStack item = QuestsConfigurationImplementation.getConfiguration().getHoloTalkItem(); hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(npc.getNpc().getLocation(), false); if (QuestsConfigurationImplementation.getConfiguration().isCustomHologramNameShown() && item.hasItemMeta() @@ -104,9 +112,10 @@ private void createHoloLaunch(){ hologram.appendTextLine(item.getItemMeta().getDisplayName()); hologram.appendItem(item); } - - private void removeHoloLaunch(){ - if (hologram == null) return; + + private void removeHoloLaunch() { + if (hologram == null) + return; hologram.delete(); hologram = null; } @@ -115,7 +124,7 @@ private void removeHoloLaunch(){ public BqNpc getNPC() { return npc; } - + public int getNPCID() { return npcID; } @@ -126,33 +135,33 @@ public void setNPC(int npcID) { this.npc = QuestsPlugin.getPlugin().getNpcManager().getById(npcID); if (npc == null) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("The NPC " + npcID + " does not exist for " + toString()); - }else { + } else { initDialogRunner(); } } - - public void setDialog(Dialog dialog){ + + public void setDialog(Dialog dialog) { this.dialog = dialog; } - + @Override - public Dialog getDialog(){ + public Dialog getDialog() { return dialog; } - + @Override public DialogRunner getDialogRunner() { return dialogRunner; } - public boolean isHid(){ + public boolean isHid() { return hide; } - public void setHid(boolean hide){ + public void setHid(boolean hide) { this.hide = hide; } - + @Override public boolean isShown(Player player) { return !hide; @@ -162,46 +171,51 @@ public boolean isShown(Player player) { public Located getLocated() { return npc; } - + @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return MessageUtils.format(Lang.SCOREBOARD_NPC.toString(), descriptionFormat(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_NPC.toString(); } - + @Override - public Object[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new String[] { npcName() }; + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("dialog_npc_name", this::npcName); + placeholders.compose(npc); } - + protected void initDialogRunner() { - if (dialogRunner != null) throw new IllegalStateException("Dialog runner already initialized"); - + if (dialogRunner != null) + throw new IllegalStateException("Dialog runner already initialized"); + dialogRunner = new DialogRunnerImplementation(dialog, npc); dialogRunner.addTest(super::hasStarted); dialogRunner.addTestCancelling(p -> canUpdate(p, true)); - + dialogRunner.addEndAction(this::finishStage); } - - @EventHandler (priority = EventPriority.HIGH, ignoreCancelled = true) + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onClick(BQNPCClickEvent e) { - if (e.isCancelled()) return; - if (e.getNPC() != npc) return; + if (e.isCancelled()) + return; + if (e.getNPC() != npc) + return; if (!QuestsConfiguration.getConfig().getQuestsConfig().getNpcClicks().contains(e.getClick())) return; Player p = e.getPlayer(); e.setCancelled(dialogRunner.onClick(p).shouldCancel()); } - - protected String npcName(){ + + protected String npcName() { if (npc == null) return "§c§lunknown NPC " + npcID; if (dialog != null && dialog.getNpcName() != null) return dialog.getNpcName(); return npc.getNpc().getName(); } - + @Override public void joined(Player p) { super.joined(p); @@ -212,29 +226,33 @@ public void joined(Player p) { private void cachePlayer(Player p) { cached.add(p); - if (npc != null) npc.hideForPlayer(p, this); + if (npc != null) + npc.hideForPlayer(p, this); } - + private void uncachePlayer(Player p) { cached.remove(p); - if (npc != null) npc.removeHiddenForPlayer(p, this); + if (npc != null) + npc.removeHiddenForPlayer(p, this); } - + private void uncacheAll() { if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) cached.forEach(GPS::stopCompass); - if (npc != null) cached.forEach(p -> npc.removeHiddenForPlayer(p, this)); + if (npc != null) + cached.forEach(p -> npc.removeHiddenForPlayer(p, this)); } - + @Override public void left(Player p) { super.left(p); uncachePlayer(p); if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) GPS.stopCompass(p); - if (dialogRunner != null) dialogRunner.removePlayer(p); + if (dialogRunner != null) + dialogRunner.removePlayer(p); } - + @Override public void started(PlayerAccount acc) { super.started(acc); @@ -245,52 +263,61 @@ public void started(PlayerAccount acc) { GPS.launchCompass(p, npc.getLocation()); } } - + @Override public void ended(PlayerAccount acc) { super.ended(acc); if (acc.isCurrent()) { Player p = acc.getPlayer(); - if (dialogRunner != null) dialogRunner.removePlayer(p); + if (dialogRunner != null) + dialogRunner.removePlayer(p); uncachePlayer(p); if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) GPS.stopCompass(p); } } - + @Override public void unload() { super.unload(); - if (task != null) task.cancel(); - if (dialogRunner != null) dialogRunner.unload(); + if (task != null) + task.cancel(); + if (dialogRunner != null) + dialogRunner.unload(); removeHoloLaunch(); uncacheAll(); } - + @Override - public void load(){ + public void load() { super.load(); if (QuestsConfigurationImplementation.getConfiguration().showTalkParticles() || QuestsConfigurationImplementation.getConfiguration().getHoloTalkItem() != null) { - if (!hide) launchRefreshTask(); + if (!hide) + launchRefreshTask(); } } protected void loadDatas(ConfigurationSection section) { - if (section.contains("msg")) setDialog(Dialog.deserialize(section.getConfigurationSection("msg"))); + if (section.contains("msg")) + setDialog(Dialog.deserialize(section.getConfigurationSection("msg"))); if (section.contains("npcID")) { setNPC(section.getInt("npcID")); - }else QuestsPlugin.getPlugin().getLoggerExpanded().warning("No NPC specified for " + toString()); - if (section.contains("hid")) hide = section.getBoolean("hid"); + } else + QuestsPlugin.getPlugin().getLoggerExpanded().warning("No NPC specified for " + toString()); + if (section.contains("hid")) + hide = section.getBoolean("hid"); } - + @Override public void serialize(ConfigurationSection section) { section.set("npcID", npcID); - if (dialog != null) dialog.serialize(section.createSection("msg")); - if (hide) section.set("hid", true); + if (dialog != null) + dialog.serialize(section.createSection("msg")); + if (hide) + section.set("hid", true); } - + public static StageNPC deserialize(ConfigurationSection section, StageController controller) { StageNPC st = new StageNPC(controller); st.loadDatas(section); @@ -298,15 +325,15 @@ public static StageNPC deserialize(ConfigurationSection section, StageController } public abstract static class AbstractCreator<T extends StageNPC> extends StageCreation<T> { - + private static final int SLOT_HIDE = 6; private static final int SLOT_NPC = 7; private static final int SLOT_DIALOG = 8; - + private int npcID = -1; private Dialog dialog = null; private boolean hidden = false; - + protected AbstractCreator(@NotNull StageCreationContext<T> context) { super(context); } @@ -314,36 +341,40 @@ protected AbstractCreator(@NotNull StageCreationContext<T> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString()), event -> { QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, newNPC -> { setNPCId(newNPC.getNpc().getId()); event.reopen(); }, false).open(event.getPlayer()); }); - - line.setItem(SLOT_DIALOG, ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.stageText.toString(), Lang.NotSet.toString()), event -> { - Lang.NPC_TEXT.send(event.getPlayer()); - new DialogEditor(event.getPlayer(), () -> { - setDialog(dialog); - event.reopen(); - }, dialog == null ? dialog = new Dialog() : dialog).start(); - }); - + + line.setItem(SLOT_DIALOG, + ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.stageText.toString(), Lang.NotSet.toString()), event -> { + Lang.NPC_TEXT.send(event.getPlayer()); + new DialogEditor(event.getPlayer(), () -> { + setDialog(dialog); + event.reopen(); + }, dialog == null ? dialog = new Dialog() : dialog).start(); + }); + line.setItem(SLOT_HIDE, ItemUtils.itemSwitch(Lang.stageHide.toString(), hidden), event -> setHidden(!hidden)); } - + public void setNPCId(int npcID) { this.npcID = npcID; getLine().refreshItem(SLOT_NPC, item -> ItemUtils.lore(item, QuestOption.formatDescription("ID: §l" + npcID))); } - + public void setDialog(Dialog dialog) { this.dialog = dialog; - getLine().refreshItem(SLOT_DIALOG, item -> ItemUtils.lore(item, dialog == null ? Lang.NotSet.toString() - : QuestOption.formatDescription(Lang.dialogLines.format(dialog.getMessages().size())))); + getLine() + .refreshItemLore(SLOT_DIALOG, + dialog == null ? Lang.NotSet.toString() + : QuestOption.formatDescription( + Lang.AmountDialogLines.quickFormat("amount", dialog.getMessages().size()))); } - + public void setHidden(boolean hidden) { if (this.hidden != hidden) { this.hidden = hidden; @@ -359,7 +390,7 @@ public void start(Player p) { context.reopenGui(); }, false).open(p); } - + @Override public void edit(T stage) { super.edit(stage); @@ -367,7 +398,7 @@ public void edit(T stage) { setDialog(stage.dialog); setHidden(stage.hide); } - + @Override protected final T finishStage(StageController controller) { T stage = createStage(controller); @@ -376,13 +407,13 @@ protected final T finishStage(StageController controller) { stage.setHid(hidden); return stage; } - + protected abstract T createStage(StageController controller); } - + public static class Creator extends AbstractCreator<StageNPC> { - + public Creator(@NotNull StageCreationContext<StageNPC> context) { super(context); } @@ -391,7 +422,7 @@ public Creator(@NotNull StageCreationContext<StageNPC> context) { protected @NotNull StageNPC createStage(@NotNull StageController controller) { return new StageNPC(controller); } - + } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index 0c4e9a5b..4dbced9f 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -13,9 +13,8 @@ import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; import fr.skytasul.quests.api.utils.CountableObject; @@ -27,8 +26,8 @@ public StagePlaceBlocks(StageController controller, List<CountableObject<BQBlock } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source){ - return Lang.SCOREBOARD_PLACE.format(super.descriptionLine(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_PLACE.toString(); } @EventHandler (priority = EventPriority.MONITOR) diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index 8aa9ac5c..5414e5b5 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -2,7 +2,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.function.Supplier; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -15,17 +14,21 @@ import fr.skytasul.quests.api.editors.parsers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; -public class StagePlayTime extends AbstractStage { +public class StagePlayTime extends AbstractStage implements HasSingleObject { private final long playTicks; @@ -41,13 +44,16 @@ public long getTicksToPlay() { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_PLAY_TIME.format(descriptionFormat(acc, source)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_PLAY_TIME.toString(); } @Override - public Supplier<Object>[] descriptionFormat(PlayerAccount acc, DescriptionSource source) { - return new Supplier[] { () -> Utils.millisToHumanString(getRemaining(acc) * 50L) }; + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerContextual("time_remaining_human", PlayerPlaceholdersContext.class, + context -> Utils.millisToHumanString(getPlayerAmount(context.getPlayerAccount()))); + ItemsDescriptionPlaceholders.register(placeholders, "time", this); } private long getRemaining(PlayerAccount acc) { @@ -62,6 +68,21 @@ private void launchTask(Player p, long remaining) { remaining < 0 ? 0 : remaining)); } + @Override + public int getPlayerAmount(@NotNull PlayerAccount account) { + return (int) (getRemaining(account) * 50L); + } + + @Override + public int getObjectAmount() { + return (int) (playTicks * 50L); + } + + @Override + public @NotNull String getObjectName() { + return "time"; + } + @Override public void joined(Player p) { super.joined(p); @@ -148,7 +169,7 @@ public void setupLine(@NotNull StageGuiLine line) { public void setTicks(long ticks) { this.ticks = ticks; - getLine().refreshItemLore(7, Lang.optionValue.format(ticks + " ticks")); + getLine().refreshItemLoreOptionValue(7, Lang.Ticks.quickFormat("ticks", ticks + " ticks")); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java index f830c857..db725a97 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java @@ -8,9 +8,8 @@ import org.bukkit.event.entity.EntityTameEvent; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractEntityStage; @@ -29,8 +28,8 @@ public void onTame(EntityTameEvent e) { } @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return Lang.SCOREBOARD_TAME.format(getMobsLeft(acc)); + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_TAME.toString(); } public static StageTame deserialize(ConfigurationSection section, StageController controller) { diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index d2ae4733..ee681320 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -49,6 +49,7 @@ import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.options.*; import fr.skytasul.quests.players.AdminMode; @@ -444,7 +445,7 @@ public void start(@NotNull Player p, boolean silently) { if (!silently) { String startMsg = getOptionValueOrDef(OptionStartMessage.class); if (!"none".equals(startMsg)) - MessageUtils.sendRawMessage(p, startMsg, true, getPlaceholdersRegistry()); + MessageUtils.sendRawMessage(p, startMsg, getPlaceholdersRegistry(), PlaceholdersContext.of(p, true)); } Runnable run = () -> { @@ -485,7 +486,8 @@ public void finish(@NotNull Player p) { if (hasOption(OptionEndMessage.class)) { String endMsg = getOption(OptionEndMessage.class).getValue(); if (!"none".equals(endMsg)) - MessageUtils.sendRawMessage(p, endMsg, true, PlaceholderRegistry.of("rewards", obtained).with(this)); + MessageUtils.sendRawMessage(p, endMsg, PlaceholderRegistry.of("rewards", obtained).with(this), + PlaceholdersContext.of(p, true)); } else MessageUtils.sendMessage(p, Lang.FINISHED_BASE.format(this) + (msg.isEmpty() ? "" : " " + Lang.FINISHED_OBTAIN.quickFormat("rewards", obtained)), diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index badc3dc8..1551ab93 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -1,213 +1,214 @@ -package fr.skytasul.quests.structure; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Consumer; -import org.apache.commons.lang.Validate; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; -import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageHandler; -import fr.skytasul.quests.api.stages.StageType; -import fr.skytasul.quests.api.utils.messaging.MessageType; -import fr.skytasul.quests.api.utils.messaging.MessageUtils; -import fr.skytasul.quests.utils.QuestUtils; - -public class StageControllerImplementation<T extends AbstractStage> implements StageController, Listener { - - private final @NotNull QuestBranchImplementation branch; - private final @NotNull StageType<T> type; - - private @Nullable T stage; - - public StageControllerImplementation(@NotNull QuestBranchImplementation branch, @NotNull StageType<T> type) { - this.branch = Objects.requireNonNull(branch); - this.type = Objects.requireNonNull(type); - } - - public void setStage(@NotNull T stage) { - if (this.stage != null) - throw new IllegalStateException("Stage was already set"); - - type.getStageClass().cast(stage); // to throw ClassCastException if needed - - this.stage = Objects.requireNonNull(stage); - } - - @Override - public @NotNull QuestBranchImplementation getBranch() { - return branch; - } - - @Override - public @NotNull AbstractStage getStage() { - if (stage == null) - throw new IllegalStateException("Stage has not been loaded yet"); - return stage; - } - - @Override - public @NotNull StageType<T> getStageType() { - if (type == null) - throw new IllegalStateException("Stage has not been loaded yet"); - return type; - } - - @Override - public void finishStage(@NotNull Player player) { - QuestUtils.runSync(() -> branch.finishStage(player, this)); - } - - @Override - public boolean hasStarted(@NotNull PlayerAccount acc) { - return branch.hasStageLaunched(acc, this); - } - - @Override - public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nullable Object dataValue) { - PlayerAccount acc = PlayersManager.getPlayerAccount(player); - Map<String, Object> datas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); - Validate.notNull(datas, "Account " + acc.debugName() + " does not have datas for " + toString()); - datas.put(dataKey, dataValue); - acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); - branch.getManager().objectiveUpdated(player); - } - - @Override - public <D> @Nullable D getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { - Map<String, Object> stageDatas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); - return stageDatas == null ? null : (D) stageDatas.get(dataKey); - } - - @Override - public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { - if (stage.getCustomText() != null) - return "§e" + MessageUtils.format(stage.getCustomText(), stage.getPlaceholdersRegistry()); - - try { - return stage.descriptionLine(acc, source); - } catch (Exception ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe( - "An error occurred while getting the description line for player " + acc.getName() + " in " + toString(), - ex); - return "§a" + type.getName(); - } - } - - private void propagateStageHandlers(@NotNull Consumer<@NotNull StageHandler> consumer) { - Consumer<StageHandler> newConsumer = handler -> { - try { - consumer.accept(handler); - } catch (Exception ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while updating stage handler.", ex); - } - }; - QuestsAPI.getAPI().getQuestsHandlers().forEach(newConsumer); - stage.getOptions().forEach(newConsumer); - } - - public void start(@NotNull PlayerAccount acc) { - if (acc.isCurrent()) - MessageUtils.sendMessage(acc.getPlayer(), stage.getStartMessage(), MessageType.OFF); - Map<String, Object> datas = new HashMap<>(); - stage.initPlayerDatas(acc, datas); - acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); - propagateStageHandlers(handler -> handler.stageStart(acc, this)); - stage.started(acc); - } - - public void end(@NotNull PlayerAccount acc) { - acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), null); - propagateStageHandlers(handler -> handler.stageEnd(acc, this)); - stage.ended(acc); - } - - public void joins(@NotNull Player player) { - propagateStageHandlers(handler -> handler.stageJoin(player, this)); - stage.joined(player); - } - - public void leaves(@NotNull Player player) { - propagateStageHandlers(handler -> handler.stageLeave(player, this)); - stage.left(player); - } - - public void load() { - QuestUtils.autoRegister(stage); - propagateStageHandlers(handler -> handler.stageLoad(this)); - stage.load(); - } - - public void unload() { - QuestUtils.autoUnregister(stage); - propagateStageHandlers(handler -> handler.stageUnload(this)); - stage.unload(); - } - - @EventHandler - public void onJoin(PlayerAccountJoinEvent e) { - if (e.isFirstJoin()) - return; - - if (hasStarted(e.getPlayerAccount())) - joins(e.getPlayer()); - } - - @EventHandler - public void onLeave(PlayerAccountLeaveEvent e) { - if (hasStarted(e.getPlayerAccount())) - leaves(e.getPlayer()); - } - - @Override - public @NotNull String getFlowId() { - if (branch.isEndingStage(this)) - return "E" + branch.getEndingStageId(this); - return Integer.toString(branch.getRegularStageId(this)); - } - - public int getStorageId() { - return branch.isEndingStage(this) ? branch.getEndingStageId(this) : branch.getRegularStageId(this); - } - - @Override - public String toString() { - return "stage " + getFlowId() + " (" + type.getID() + ") of quest " + branch.getQuest().getId() + ", branch " - + branch.getId(); - } - - public static @NotNull StageControllerImplementation<?> loadFromConfig(@NotNull QuestBranchImplementation branch, - @NotNull ConfigurationSection section) { - String typeID = section.getString("stageType"); - - StageType<?> stageType = QuestsAPI.getAPI().getStages().getType(typeID) - .orElseThrow(() -> new IllegalArgumentException("Unknown stage type " + typeID)); - - return loadFromConfig(branch, section, stageType); - } - - private static <T extends AbstractStage> @NotNull StageControllerImplementation<T> loadFromConfig( - @NotNull QuestBranchImplementation branch, @NotNull ConfigurationSection section, StageType<T> type) { - // we need to separate into two methods to trick the generics - - StageControllerImplementation<T> controller = new StageControllerImplementation<>(branch, type); - T stage = type.getLoader().supply(section, controller); - controller.setStage(stage); - stage.load(section); - return controller; - } - -} +package fr.skytasul.quests.structure; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; +import org.apache.commons.lang.Validate; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; +import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; +import fr.skytasul.quests.api.stages.StageHandler; +import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.utils.messaging.MessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.utils.QuestUtils; + +public class StageControllerImplementation<T extends AbstractStage> implements StageController, Listener { + + private final @NotNull QuestBranchImplementation branch; + private final @NotNull StageType<T> type; + + private @Nullable T stage; + + public StageControllerImplementation(@NotNull QuestBranchImplementation branch, @NotNull StageType<T> type) { + this.branch = Objects.requireNonNull(branch); + this.type = Objects.requireNonNull(type); + } + + public void setStage(@NotNull T stage) { + if (this.stage != null) + throw new IllegalStateException("Stage was already set"); + + type.getStageClass().cast(stage); // to throw ClassCastException if needed + + this.stage = Objects.requireNonNull(stage); + } + + @Override + public @NotNull QuestBranchImplementation getBranch() { + return branch; + } + + @Override + public @NotNull AbstractStage getStage() { + if (stage == null) + throw new IllegalStateException("Stage has not been loaded yet"); + return stage; + } + + @Override + public @NotNull StageType<T> getStageType() { + if (type == null) + throw new IllegalStateException("Stage has not been loaded yet"); + return type; + } + + @Override + public void finishStage(@NotNull Player player) { + QuestUtils.runSync(() -> branch.finishStage(player, this)); + } + + @Override + public boolean hasStarted(@NotNull PlayerAccount acc) { + return branch.hasStageLaunched(acc, this); + } + + @Override + public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nullable Object dataValue) { + PlayerAccount acc = PlayersManager.getPlayerAccount(player); + Map<String, Object> datas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); + Validate.notNull(datas, "Account " + acc.debugName() + " does not have datas for " + toString()); + datas.put(dataKey, dataValue); + acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); + branch.getManager().objectiveUpdated(player); + } + + @Override + public <D> @Nullable D getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { + Map<String, Object> stageDatas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); + return stageDatas == null ? null : (D) stageDatas.get(dataKey); + } + + @Override + public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { + try { + StageDescriptionPlaceholdersContext context = StageDescriptionPlaceholdersContext.of(true, acc, source); + String description = + stage.getCustomText() == null ? stage.getDefaultDescription(context) : ("§e" + stage.getCustomText()); + return MessageUtils.finalFormat(description, stage.getPlaceholdersRegistry(), context); + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "An error occurred while getting the description line for player " + acc.getName() + " in " + toString(), + ex); + return "§a" + type.getName(); + } + } + + private void propagateStageHandlers(@NotNull Consumer<@NotNull StageHandler> consumer) { + Consumer<StageHandler> newConsumer = handler -> { + try { + consumer.accept(handler); + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while updating stage handler.", ex); + } + }; + QuestsAPI.getAPI().getQuestsHandlers().forEach(newConsumer); + stage.getOptions().forEach(newConsumer); + } + + public void start(@NotNull PlayerAccount acc) { + if (acc.isCurrent()) + MessageUtils.sendMessage(acc.getPlayer(), stage.getStartMessage(), MessageType.OFF); + Map<String, Object> datas = new HashMap<>(); + stage.initPlayerDatas(acc, datas); + acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); + propagateStageHandlers(handler -> handler.stageStart(acc, this)); + stage.started(acc); + } + + public void end(@NotNull PlayerAccount acc) { + acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), null); + propagateStageHandlers(handler -> handler.stageEnd(acc, this)); + stage.ended(acc); + } + + public void joins(@NotNull Player player) { + propagateStageHandlers(handler -> handler.stageJoin(player, this)); + stage.joined(player); + } + + public void leaves(@NotNull Player player) { + propagateStageHandlers(handler -> handler.stageLeave(player, this)); + stage.left(player); + } + + public void load() { + QuestUtils.autoRegister(stage); + propagateStageHandlers(handler -> handler.stageLoad(this)); + stage.load(); + } + + public void unload() { + QuestUtils.autoUnregister(stage); + propagateStageHandlers(handler -> handler.stageUnload(this)); + stage.unload(); + } + + @EventHandler + public void onJoin(PlayerAccountJoinEvent e) { + if (e.isFirstJoin()) + return; + + if (hasStarted(e.getPlayerAccount())) + joins(e.getPlayer()); + } + + @EventHandler + public void onLeave(PlayerAccountLeaveEvent e) { + if (hasStarted(e.getPlayerAccount())) + leaves(e.getPlayer()); + } + + @Override + public @NotNull String getFlowId() { + if (branch.isEndingStage(this)) + return "E" + branch.getEndingStageId(this); + return Integer.toString(branch.getRegularStageId(this)); + } + + public int getStorageId() { + return branch.isEndingStage(this) ? branch.getEndingStageId(this) : branch.getRegularStageId(this); + } + + @Override + public String toString() { + return "stage " + getFlowId() + " (" + type.getID() + ") of quest " + branch.getQuest().getId() + ", branch " + + branch.getId(); + } + + public static @NotNull StageControllerImplementation<?> loadFromConfig(@NotNull QuestBranchImplementation branch, + @NotNull ConfigurationSection section) { + String typeID = section.getString("stageType"); + + StageType<?> stageType = QuestsAPI.getAPI().getStages().getType(typeID) + .orElseThrow(() -> new IllegalArgumentException("Unknown stage type " + typeID)); + + return loadFromConfig(branch, section, stageType); + } + + private static <T extends AbstractStage> @NotNull StageControllerImplementation<T> loadFromConfig( + @NotNull QuestBranchImplementation branch, @NotNull ConfigurationSection section, StageType<T> type) { + // we need to separate into two methods to trick the generics + + StageControllerImplementation<T> controller = new StageControllerImplementation<>(branch, type); + T stage = type.getLoader().supply(section, controller); + controller.setStage(stage); + stage.load(section); + return controller; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java index dbc09962..49a621dc 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java @@ -1,46 +1,46 @@ -package fr.skytasul.quests.utils.compatibility.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.event.entity.EntityDeathEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.java.JavaPlugin; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.mobs.LeveledMobFactory; -import fr.skytasul.quests.gui.mobs.EntityTypeGUI; -import me.lokka30.levelledmobs.LevelledMobs; - -public class BQLevelledMobs extends BukkitEntityFactory implements LeveledMobFactory<EntityType> { - - @Override - public String getID() { - return "levelledMobs"; - } - - private ItemStack item = ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, "§eLevelledMobs"); - - @Override - public ItemStack getFactoryItem() { - return item; - } - - @Override - public void itemClick(Player p, Consumer<EntityType> run) { - new EntityTypeGUI(run, x -> x != null && x.isAlive()).open(p); - } - - @Override - public double getMobLevel(EntityType type, Entity entity) { - return JavaPlugin.getPlugin(LevelledMobs.class).levelInterface.getLevelOfMob((LivingEntity) entity); - } - - @Override - public void onEntityKilled(EntityDeathEvent e) { - // do nothing as the original BukkitEntityFactory will manage the event itself - } - -} +package fr.skytasul.quests.utils.compatibility.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.event.entity.EntityDeathEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.mobs.LeveledMobFactory; +import fr.skytasul.quests.gui.mobs.EntityTypeGUI; +import me.lokka30.levelledmobs.LevelledMobs; + +public class BQLevelledMobs extends BukkitEntityFactory implements LeveledMobFactory<EntityType> { + + @Override + public String getID() { + return "levelledMobs"; + } + + private ItemStack item = ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, "§eLevelledMobs"); + + @Override + public ItemStack getFactoryItem() { + return item; + } + + @Override + public void itemClick(Player p, Consumer<EntityType> run) { + new EntityTypeGUI(run, x -> x != null && x.isAlive()).open(p); + } + + @Override + public double getMobLevel(EntityType type, Entity entity) { + return JavaPlugin.getPlugin(LevelledMobs.class).levelInterface.getLevelOfMob((LivingEntity) entity); + } + + @Override + public void onEntityKilled(EntityDeathEvent e) { + // do nothing as the original BukkitEntityFactory will manage the event itself + } + +} diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 7059b01b..1e89b377 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -1,214 +1,217 @@ -# - General configuration - -# Chosen lang (file name) Available by default: fr_FR, en_US, zh_CN, zh_HK, de_DE, it_IT, es_ES, pt_PT, pt_BR, sv_SE, hu_HU, ru_RU, pl_PL, th_TH, lt_LT, vi_VN -lang: en_US -# (1.13 and above) Minecraft vanilla translations (JSON file name). Some can be found on SkytAsul's Discord server -minecraftTranslationsFile: '' -# Enable or disable update checking on the loading -checkUpdates: true -# Enable or disable prefix before plugin message -enablePrefix: true -# Number of minutes between two periodic saves -saveCycle: 15 -# Enable "periodic save" message in console -saveCycleMessage: true -# Database configuration -database: - enabled: false - host: "localhost" - port: 3306 - database: "beautyquests" - username: "unknown" - password: "unknown" - ssl: false - tables: - playerAccounts: "player_accounts" - playerQuests: "player_quests" - playerPools: "player_pools" - -# - Quests behaviors - -# Number of minutes before the quest can be redone -redoMinuts: 5 -# Maximum amount of quests that can be started at the same time by a player. -# This limit can also be set by player by giving the permission "beautyquests.start.<max launched quests>" -# to a group or a player with your permissions plugin. -# It is possible not to count some quests in this limit with the "Bypass limit" quest option. -maxLaunchedQuests: 0 -# Enable or disable the scoreboards - more options in scoreboard.yml -scoreboards: true -# Enable or disable message when a quest is updated (next stage) -playerQuestUpdateMessage: true -# Enable or disable default messages when a stage starts -playerStageStartMessage: true -# Shows a Yes/No GUI to let the player choose if he wants to accept the quest or not -questConfirmGUI: false -# Enable of disable playing sounds on various actions -sounds: true -# Sound played at the end of a quest -finishSound: ENTITY_PLAYER_LEVELUP -# Sound played when the player updates its quest -nextStageSound: ITEM_FIRECHARGE_USE -# Enable or disable end fireworks -fireworks: true -# Show a progress bar (bossbar) when a player has to kill some mobs for a quest -mobsProgressBar: false -# Amount of seconds before the progress bar will disappear (set it to 0 to make it persistent) -progressBarTimeoutSeconds: 15 -# Which clicks are acceptable for a player to do on the NPC in order to start a quest, follow a dialog... -# (can be: RIGHT, LEFT, SHIFT_RIGHT, SHIFT_LEFT) -npcClick: [RIGHT, SHIFT_RIGHT] -# If enabled, the "choose a quest from this NPC" GUI will not open if there is only 1 quest attached to the NPC -skip npc gui if only one quest: true -# Default item shown for a quest in the menus -item: BOOK -# Page item material -pageItem: ARROW -# Maxmium distance where starting particles are shown -startParticleDistance: 20 -# Number of seconds before the plugin checks every requirements for the player to show the starting particle -requirementUpdateTime: 1 -# When there is several quests on the same NPC, will the server send the reason to the player if it does not match a requirement -requirementReasonOnMultipleQuests: true -# Enables the sending of the "you obtain xxx" when a player terminates a stage with end rewards -stageEndRewardsMessage: true - -# - Dialogs - -# Various options related to dialogs -dialogs: - # Dialogs are shown in the action bar instead of the chat - inActionBar: false - # Default time between two dialogs lines (in ticks: 1s = 20 ticks). 0 to disable. - defaultTime: 100 - # Are dialogs skippable by default - defaultSkippable: false - # If enabled, players will not be allowed to click on the NPC to pass a line of dialog - disableClick: false - # Enables the dialog history in the Quests menu - history: true - # Limits the maximum amount of messages per history page. - # If -1 then the plugin will try to put as many messages as possible until the page is full. - max messages per history page: -1 - # Maximum distance the player can be from the NPC for the dialog to continue. 0 to disable. - maxDistance: 15 - # Default dialog sound when players are speaking - defaultPlayerSound: 'none' - # Default dialog sound when NPCs are speaking - defaultNPCSound: 'none' - -# - 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] - # 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 - allowPlayerCancelQuest: true - -# - Integrations - -# Enable GPS integration -gps: false -# Enable or disable SkillAPI experience overriding in xp reward/requirement -skillAPIoverride: true -# Enable or disable AccountsHook managing player accounts -accountsHook: false -# If set to "true" and the PlayerBlockTracker plugin is enabled on this server, then player-placed blocks will be tracked -# using PlayerBlockTracker: it allows for persistence after restart, piston tracking, and more. -usePlayerBlockTracker: true -# (HolographicDisplays) Disable the hologram above NPC's head -disableTextHologram: false -# (HolographicDisplays) Value added to the hologram height (decimal value) -hologramsHeight: 0.0 -# (HolographicDisplays) Material name of the hologram showed above head of Quests starter. If ProtocolLib is enabled, holograms will be visible only by players who can start the quest -holoLaunchItemName: BOOK -# (HolographicDisplays) Material name of the hologram showed above head of Stage NPC. If ProtocolLib is enabled, holograms will be visible only by players who has to talk with this NPC -holoTalkItemName: COAL -# (HolographicDisplays) Is the custom name of the hologram in datas.yml shown -showCustomHologramName: true -# (PlaceholdersAPI) Configuration for %beautyquests_started_ordered_X% placeholder -startedQuestsPlaceholder: - # Max length of a line if using splitted placeholder - lineLength: 30 - # Time (in seconds) before the shown quest change in placeholder - changeTime: 10 - # Format of the placeholder %beautyquests_started_ordered_X%. Available placeholders: {questName} and {questDescription}, use \n to skip a line - splitPlaceholderFormat: "§6{questName}\n{questDescription}" - # Format of the empty placeholder %beautyquests_started_ordered%. Available placeholders: {questName} and {questDescription} - inlinePlaceholderFormat: "§6{questName}§e: §o{questDescription}" -# dynmap integration options -dynmap: - # Name of the marker set. To disable dynmap integration, put an empty string - markerSetName: "" - # Icon for quest markers - markerIcon: "bookshelf" - # Minimum zoom level for markers to be displayed - minZoom: 0 - -# - Stage descriptions - -# {0} = stage index, {1} = stage amount, {2} = stage description} -stageDescriptionFormat: "§8({stage_index}/{stage_amount}) §e{stage_description}" -# Prefix before object's name in lists (example: §6first, §6second and §6third) -itemNameColor: "§6§o" -# Prefix before object's amount in lists (example: first§ex2, second§ex7 and third§ex4) -itemAmountColor: "§e" -# Describes the way stage with multiple objects are described -stageDescriptionItemsSplit: - # Prefix before each line - prefix: "§e- §6" - # Format of object amounts. Placeholders: {0} = remaining (decreasing), {1} = done (increasing), {2} = total, {3} = percentage (0 to 100). Example: "{1}/{2}" - amountFormat: "x{0}" - # Show amount format if there is only one object remaining - showXOne: true - # When there is only one object, do not put it on a new line - inlineAlone: true - # From which sources the text has to be split (available sources: SCOREBOARD, MENU, PLACEHOLDER) - sources: [SCOREBOARD, MENU, PLACEHOLDER] - -# - Quest descriptions - -# How is formatted the quest description in GUIs -questDescription: - requirements: - # Enable the requirements section for quest description - display: true - # How to format requirements which match the player - valid: §a ✔ §7{requirement_description} - # How to format requirements which do not match the player - invalid: §c ✖ §7{requirement_description} - rewards: - # Enable the rewards section for quest description - display: true - # How to format rewards - format: §7- {reward_description} - -# - Particles configuration - -# enabled: will the particle be shown? -# particleEffect: name of the particle -# particleColor: for colored particles, RGB value of the color -# particleShape: shape of the particle effect (available: point, near, bar, exclamation, spot) - -# Particles shown on a NPC when the player can start the quest -start: - enabled: true - particleEffect: redstone - particleColor: - RED: 255 - BLUE: 0 - GREEN: 255 - particleShape: point -# Particles shown on the NPC to which the player has to talk -talk: - enabled: true - particleEffect: villager_happy - particleColor: - RED: 255 - BLUE: 0 - GREEN: 255 - particleShape: bar -# Particles shown when the player finish a stage of a quest -next: - enabled: true - particleEffect: smoke_normal - particleColor: - RED: 255 - BLUE: 0 - GREEN: 255 +# - General configuration - +# Chosen lang (file name) Available by default: fr_FR, en_US, zh_CN, zh_HK, de_DE, it_IT, es_ES, pt_PT, pt_BR, sv_SE, hu_HU, ru_RU, pl_PL, th_TH, lt_LT, vi_VN +lang: en_US +# (1.13 and above) Minecraft vanilla translations (JSON file name). Some can be found on SkytAsul's Discord server +minecraftTranslationsFile: '' +# Enable or disable update checking on the loading +checkUpdates: true +# Enable or disable prefix before plugin message +enablePrefix: true +# Number of minutes between two periodic saves +saveCycle: 15 +# Enable "periodic save" message in console +saveCycleMessage: true +# Database configuration +database: + enabled: false + host: "localhost" + port: 3306 + database: "beautyquests" + username: "unknown" + password: "unknown" + ssl: false + tables: + playerAccounts: "player_accounts" + playerQuests: "player_quests" + playerPools: "player_pools" + +# - Quests behaviors - +# Number of minutes before the quest can be redone +redoMinuts: 5 +# Maximum amount of quests that can be started at the same time by a player. +# This limit can also be set by player by giving the permission "beautyquests.start.<max launched quests>" +# to a group or a player with your permissions plugin. +# It is possible not to count some quests in this limit with the "Bypass limit" quest option. +maxLaunchedQuests: 0 +# Enable or disable the scoreboards - more options in scoreboard.yml +scoreboards: true +# Enable or disable message when a quest is updated (next stage) +playerQuestUpdateMessage: true +# Enable or disable default messages when a stage starts +playerStageStartMessage: true +# Shows a Yes/No GUI to let the player choose if he wants to accept the quest or not +questConfirmGUI: false +# Enable of disable playing sounds on various actions +sounds: true +# Sound played at the end of a quest +finishSound: ENTITY_PLAYER_LEVELUP +# Sound played when the player updates its quest +nextStageSound: ITEM_FIRECHARGE_USE +# Enable or disable end fireworks +fireworks: true +# Amount of seconds before the progress bar will disappear (set it to 0 to make it persistent) +progressBarTimeoutSeconds: 15 +# Which clicks are acceptable for a player to do on the NPC in order to start a quest, follow a dialog... +# (can be: RIGHT, LEFT, SHIFT_RIGHT, SHIFT_LEFT) +npcClick: [RIGHT, SHIFT_RIGHT] +# If enabled, the "choose a quest from this NPC" GUI will not open if there is only 1 quest attached to the NPC +skip npc gui if only one quest: true +# Default item shown for a quest in the menus +item: BOOK +# Page item material +pageItem: ARROW +# Maxmium distance where starting particles are shown +startParticleDistance: 20 +# Number of seconds before the plugin checks every requirements for the player to show the starting particle +requirementUpdateTime: 1 +# When there is several quests on the same NPC, will the server send the reason to the player if it does not match a requirement +requirementReasonOnMultipleQuests: true +# Enables the sending of the "you obtain xxx" when a player terminates a stage with end rewards +stageEndRewardsMessage: true + +# - Dialogs - +# Various options related to dialogs +dialogs: + # Dialogs are shown in the action bar instead of the chat + inActionBar: false + # Default time between two dialogs lines (in ticks: 1s = 20 ticks). 0 to disable. + defaultTime: 100 + # Are dialogs skippable by default + defaultSkippable: false + # If enabled, players will not be allowed to click on the NPC to pass a line of dialog + disableClick: false + # Enables the dialog history in the Quests menu + history: true + # Limits the maximum amount of messages per history page. + # If -1 then the plugin will try to put as many messages as possible until the page is full. + max messages per history page: -1 + # Maximum distance the player can be from the NPC for the dialog to continue. 0 to disable. + maxDistance: 15 + # Default dialog sound when players are speaking + defaultPlayerSound: 'none' + # Default dialog sound when NPCs are speaking + defaultNPCSound: 'none' + +# - 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] + # 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 + allowPlayerCancelQuest: true + +# - Integrations - +# Enable GPS integration +gps: false +# Enable or disable SkillAPI experience overriding in xp reward/requirement +skillAPIoverride: true +# Enable or disable AccountsHook managing player accounts +accountsHook: false +# If set to "true" and the PlayerBlockTracker plugin is enabled on this server, then player-placed blocks will be tracked +# using PlayerBlockTracker: it allows for persistence after restart, piston tracking, and more. +usePlayerBlockTracker: true +# (HolographicDisplays) Disable the hologram above NPC's head +disableTextHologram: false +# (HolographicDisplays) Value added to the hologram height (decimal value) +hologramsHeight: 0.0 +# (HolographicDisplays) Material name of the hologram showed above head of Quests starter. If ProtocolLib is enabled, holograms will be visible only by players who can start the quest +holoLaunchItemName: BOOK +# (HolographicDisplays) Material name of the hologram showed above head of Stage NPC. If ProtocolLib is enabled, holograms will be visible only by players who has to talk with this NPC +holoTalkItemName: COAL +# (HolographicDisplays) Is the custom name of the hologram in datas.yml shown +showCustomHologramName: true +# (PlaceholdersAPI) Configuration for %beautyquests_started_ordered_X% placeholder +startedQuestsPlaceholder: + # Max length of a line if using splitted placeholder + lineLength: 30 + # Time (in seconds) before the shown quest change in placeholder + changeTime: 10 + # Format of the placeholder %beautyquests_started_ordered_X%. Available placeholders: {questName} and {questDescription}, use \n to skip a line + splitPlaceholderFormat: "§6{questName}\n{questDescription}" + # Format of the empty placeholder %beautyquests_started_ordered%. Available placeholders: {questName} and {questDescription} + inlinePlaceholderFormat: "§6{questName}§e: §o{questDescription}" +# dynmap integration options +dynmap: + # Name of the marker set. To disable dynmap integration, put an empty string + markerSetName: "" + # Icon for quest markers + markerIcon: "bookshelf" + # Minimum zoom level for markers to be displayed + minZoom: 0 + +# - Stage descriptions - +# Describes the way stage with multiple objects are described +stage description: + # Available placeholders are: {stage_index}, {stage_amount}, {stage_description} + descriptionFormat: "§8({stage_index}/{stage_amount}) §e{stage_description}" + # Format used for items, mobs, buckets... in stage descriptions. + # Available placeholders are: {name}, {remaining} (decreasing), {done} (increasing), {total}, {percentage} (0 to 100). + # Example: "{name} {done}/{total}" + item formats: + # Used in the case there is only one item left + single: "§6§o{name}" + # Used in the case there are multiple items left + multiple: "§6§o{name}§e x{remaining}" + # Prefix before each split line + line prefix: "§e- §6" + # When there is only one object, do not put it on a new line + inline alone: true + # From which sources the text has to be split (available sources: SCOREBOARD, MENU, PLACEHOLDER) + split sources: [SCOREBOARD, MENU, PLACEHOLDER] + # Show boss bars for stages with progress + boss bars: true + # Format of the boss bar for stages with progress. + # Available placeholders are: {quest_name}, {stage_done}, {stage_remaining}, {stage_total}, {stage_percentage} + boss bar format: "§6{quest_name}: §e{stage_done}/{stage_total}" + +# - Quest descriptions - +# How is formatted the quest description in GUIs +questDescription: + requirements: + # Enable the requirements section for quest description + display: true + # How to format requirements which match the player + valid: §a ✔ §7{requirement_description} + # How to format requirements which do not match the player + invalid: §c ✖ §7{requirement_description} + rewards: + # Enable the rewards section for quest description + display: true + # How to format rewards + format: §7- {reward_description} + +# - Particles configuration - +# enabled: will the particle be shown? +# particleEffect: name of the particle +# particleColor: for colored particles, RGB value of the color +# particleShape: shape of the particle effect (available: point, near, bar, exclamation, spot) + +# Particles shown on a NPC when the player can start the quest +start: + enabled: true + particleEffect: redstone + particleColor: + RED: 255 + BLUE: 0 + GREEN: 255 + particleShape: point +# Particles shown on the NPC to which the player has to talk +talk: + enabled: true + particleEffect: villager_happy + particleColor: + RED: 255 + BLUE: 0 + GREEN: 255 + particleShape: bar +# Particles shown when the player finish a stage of a quest +next: + enabled: true + particleEffect: smoke_normal + particleColor: + RED: 255 + BLUE: 0 + GREEN: 255 particleShape: spot \ No newline at end of file diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index c2b8bc97..d561c270 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -1,894 +1,893 @@ -msg: - quest: - finished: - base: §aCongratulations! You have finished the quest §e{quest_name}§a! - obtain: §aYou obtain {rewards}! - started: §aYou have started the quest §r§e{0}§o§6! - created: §aCongratulations! You have created the quest §e{quest}§a which includes - {quest_branches} branch(es)! - edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes - {quest_branches} branch(es)! - createCancelled: §cThe creation or edition has been cancelled by another plugin! - cancelling: §cProcess of quest creation cancelled. - editCancelling: §cProcess of quest edition cancelled. - invalidID: §cThe quest with the id {quest_id} doesn't exist. - invalidPoolID: §cThe pool {pool_id} does not exist. - alreadyStarted: §cYou have already started the quest! - notStarted: §cYou are not currently doing this quest. - quests: - maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same time... - nopStep: §cThis quest doesn't have any step. - updated: §7Quest §e{quest_name}§7 updated. - checkpoint: §7Quest checkpoint reached! - failed: §cYou have failed the quest {quest_name}... - pools: - noTime: §cYou must wait {time_left} before doing another quest. - allCompleted: §7You have completed all the quests! - noAvailable: §7There is no more quest available... - maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same time... - questItem: - drop: §cYou can't drop a quest item! - craft: §cYou can't use a quest item to craft! - eat: §cYou cannot eat a quest item! - stageMobs: - noMobs: §cThis stage doesn't need any mobs to kill. - listMobs: §aYou must kill {0}. - writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write - "help" to receive help.)' - writeRegionName: '§aWrite the name of the region required for the step:' - writeXPGain: '§aWrite the amount of experience points the player will obtain: (Last - value: {xp_amount})' - writeMobAmount: '§aWrite the amount of mobs to kill:' - writeMobName: '§aWrite the custom name of the mob to kill:' - writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if - you want a command.)' - writeMessage: '§aWrite the message that will be sent to the player' - writeStartMessage: '§aWrite the message that will be sent at the beginning of the quest, - "null" if you want the default one or "none" if you want none:' - writeEndMsg: '§aWrite the message that will be sent at the end of the quest, - "null" if you want the default one or "none" if you want none. You can use "{0}" which - will be replaced with the rewards obtained.' - writeEndSound: '§aWrite the sound name that will be played to the player at the end of - the quest, "null" if you want the default one or "none" if you want none:' - writeDescriptionText: '§aWrite the text which describes the goal of the stage:' - writeStageText: '§aWrite the text that will be sent to the player at the beginning - of the step:' - moveToTeleportPoint: §aGo to the wanted teleport location. - writeNpcName: '§aWrite the name of the NPC:' - writeNpcSkinName: '§aWrite the name of the skin of the NPC:' - writeQuestName: '§aWrite the name of your quest:' - writeCommand: '§aWrite the wanted command: (The command is without the "/" and the - placeholder "{PLAYER}" is supported. It will be replaced with the name of the - executor.)' - writeHologramText: '§aWrite text of the hologram: (Write "none" if you don''t want - a hologram and "null" if you want the default text.)' - writeQuestTimer: '§aWrite the required time (in minutes) before you can restart - the quest: (Write "null" if you want the default timer.)' - writeConfirmMessage: '§aWrite the confirmation message shown when a player is about - to start the quest: (Write "null" if you want the default message.)' - writeQuestDescription: '§aWrite the description of the quest, shown in the player''s quest GUI.' - writeQuestMaterial: '§aWrite the material of the quest item.' - requirements: - quest: §cYou must have finished the quest §e{quest_name}§c! - level: §cYour level must be {long_level}! - job: §cYour level for the job §e{job_name}§c must be {long_level}! - skill: §cYour level for the skill §e{skill_name}§c must be {long_level}! - combatLevel: §cYour combat level must be {long_level}! - money: §cYou must have {money}! - waitTime: §cYou must wait {time_left} before you can restart this quest! - experience: - edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} points. - selectNPCToKill: §aSelect the NPC to kill. - npc: - remove: §aNPC deleted. - talk: §aGo and talk to the NPC named §e{0}§a. - regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) - npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. - number: - negative: §cYou must enter a positive number! - zero: §cYou must enter a number other than 0! - invalid: §c{input} isn't a valid number. - notInBounds: §cYour number must be between {min} and {max}. - errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: {error}' - commandsDisabled: §cCurrently you aren't allowed to execute commands! - indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} and - {max}. - invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the block {block_material}. - invalidBlockTag: §cUnavailable block tag {block_tag}. - bringBackObjects: Bring me back {0}. - inventoryFull: §cYour inventory is full, the item has been dropped on the floor. - playerNeverConnected: §cUnable to find informations about the player {0}. - playerNotOnline: §cThe player {0} is offline. - playerDataNotFound: §cDatas of player {0} not found. - versionRequired: 'Version required: §l{version}' - restartServer: '§7Restart your server to see the modifications.' - dialogs: - skipped: '§8§o Dialog skipped.' - tooFar: '§7§oYou are too far away from {npc_name}...' - command: - downloadTranslations: - syntax: '§cYou must specify a language to download. Example: "/quests downloadTranslations en_US".' - notFound: '§cLanguage {lang} not found for version {version}.' - exists: '§cThe file {file_name} already exists. Append "-overwrite" to your command to overwrite it. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§aLanguage {lang} has been downloaded! §7You must now edit the - file "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 with {lang}, then restart the server.' - checkpoint: - noCheckpoint: §cNo checkpoint found for the quest {quest}. - questNotStarted: §cYou are not doing this quest. - setStage: - branchDoesntExist: §cThe branch with the id {branch_id} doesn't exist. - doesntExist: §cThe stage with the id {stage_id} doesn't exist. - next: §aThe stage has been skipped. - nextUnavailable: §cThe "skip" option is not available when the player is at - the end of a branch. - set: §aStage {stage_id} launched. - startDialog: - impossible: §cImpossible to start the dialog now. - noDialog: §cThe player has no pending dialog. - alreadyIn: §cThe player is already playing a dialog. - success: §aStarted dialog for player {player} in quest {quest}! - playerNeeded: §cYou must be a player to execute this command! - incorrectSyntax: §cIncorrect syntax. - noPermission: '§cYou haven''t enough permissions to execute this command! (Required: - {0})' - invalidCommand: - quests: §cThis command doesn't exist, write §e/quests help§c. - simple: §cThis command doesn't exist, write §ehelp§c. - needItem: §cYou must hold an item in your main hand! - itemChanged: §aThe item has been edited. The changes will affect after a restart. - itemRemoved: §aThe hologram item has been removed. - removed: §aThe quest {quest_name} has successfully been removed. - leaveAll: '§aYou have forced the end of {success} quest(s). Errors: {errors}' - resetPlayer: - player: §6All informations of your {quest_amount} quest(s) has/have been deleted by {deleter_name}. - remover: §6{quest_amount} quest information(s) (and {quest_pool} pools) of {player} has/have been deleted. - resetPlayerQuest: - player: §6All informations about the quest {quest} have been deleted by {deleter_name}. - remover: §6{player} informations of quest {quest} has/have been deleted. - resetQuest: §6Removed datas of the quest for {player_amount} players. - startQuest: '§6You have forced starting of quest {quest} for {player}.' - startQuestNoRequirements: '§cThe player does not meet the requirements for the quest {quest}... - Append "-overrideRequirements" at the end of your command to bypass the requirements check.' - cancelQuest: §6You have cancelled the quest {0}. - cancelQuestUnavailable: §cThe quest {0} can't be cancelled. - backupCreated: §6You have successfully created backups of all quests and player - informations. - backupPlayersFailed: §cCreating a backup for all the player informations has failed. - backupQuestsFailed: §cCreating a backup for all the quests has failed. - adminModeEntered: §aYou have entered the Admin Mode. - adminModeLeft: §aYou have left the Admin Mode. - resetPlayerPool: - timer: §aYou have reset the {pool} pool timer of {player}. - full: §aYou have reset the {pool} pool datas of {player}. - startPlayerPool: - error: 'Failed to start the pool {pool} for {player}.' - success: 'Started pool {pool} to {player}. Result: {result}' - scoreboard: - lineSet: §6You have successfully edited the line {line_id}. - lineReset: §6You have successfully reset the line {line_id}. - lineRemoved: §6You have successfully removed the line {line_id}. - lineInexistant: §cThe line {line_id} doesn't exist. - resetAll: §6You have successfully reset the scoreboard of the player {player_name}. - hidden: §6The scoreboard of the player {player_name} has been hidden. - shown: §6The scoreboard of the player {player_name} has been shown. - own: - hidden: §6Your scoreboard is now hidden. - shown: §6Your scoreboard is shown again. - help: - header: §6§lBeautyQuests — Help - create: '§6/{label} create: §eCreate a quest.' - edit: '§6/{label} edit: §eEdit a quest.' - remove: '§6/{label} remove <id>: §eDelete a quest with a specified id or click on - the NPC when not defined.' - finishAll: '§6/{label} finishAll <player>: §eFinish all quests of a player.' - setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eSkip the - current stage/start the branch/set a stage for a branch.' - startDialog: '§6/{label} startDialog <player> <quest id>: §eStarts the pending dialog - for a NPC stage or the starting dialog for a quest.' - resetPlayer: '§6/{label} resetPlayer <player>: §eRemove all informations about a - player.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete informations - of a quest for a player.' - seePlayer: '§6/{label} seePlayer <player>: §eView informations about a player.' - reload: '§6/{label} reload: §eSave and reload all configurations and files. (§cdeprecated§e)' - start: '§6/{label} start <player> [id]: §eForce the starting of a quest.' - setItem: '§6/{label} setItem <talk|launch>: §eSave the hologram item.' - setFirework: '§6/{label} setFirework: §eEdit the default ending firework.' - adminMode: '§6/{label} adminMode: §eToggle the Admin Mode. (Useful for displaying - little log messages.)' - version: '§6/{label} version: §eSee the current plugin version.' - downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownloads a vanilla translation file' - save: '§6/{label} save: §eMake a manual plugin save.' - list: '§6/{label} list: §eSee the quest list. (Only for supported versions.)' - typeCancel: §aWrite "cancel" to come back to the last text. - editor: - blockAmount: '§aWrite the amount of blocks:' - blockName: '§aWrite the name of the block:' - blockData: '§aWrite the blockdata (available blockdatas: §7{available_datas}§a):' - blockTag: '§aWrite the block tag (available tags: §7{available_tags}§a):' - typeBucketAmount: '§aWrite the amount of buckets to fill:' - typeDamageAmount: 'Write the amount of damage player have to deal:' - goToLocation: §aGo to the wanted location for the stage. - typeLocationRadius: '§aWrite the required distance from the location:' - typeGameTicks: '§aWrite the required game ticks:' - already: §cYou are already in the editor. - stage: - location: - typeWorldPattern: '§aWrite a regex for world names:' - enter: - title: §6~ Editor Mode ~ - subtitle: §6Write "/quests exitEditor" to force quit the editor. - list: '§c⚠ §7You have entered a "list" editor. Use "add" to add lines. Refer to "help" (without slash) for help. §e§lType "close" to exit editor.' - chat: §6You are currently in the Editor Mode. Write "/quests exitEditor" to force - leaving the editor. (Highly not recommended, consider using commands such as - "close" or "cancel" to come back to the previous inventory.) - npc: - enter: §aClick on a NPC, or write "cancel". - choseStarter: §aChoose the NPC which starts the quest. - notStarter: §cThis NPC isn't a quest starter. - text: - argNotSupported: §cThe argument {arg} not supported. - chooseLvlRequired: '§aWrite the required amount of levels:' - chooseJobRequired: '§aWrite name of the wanted job:' - choosePermissionRequired: '§aWrite the required permission to start the quest:' - choosePermissionMessage: §aYou can choose a rejection message if the player - doesn't have the required permission. (To skip this step, write "null".) - choosePlaceholderRequired: - identifier: '§aWrite the name of the required placeholder without the percent - characters:' - value: '§aWrite the required value for the placeholder §e%§e{placeholder}§e%§a:' - chooseSkillRequired: '§aWrite the name of the required skill:' - chooseMoneyRequired: '§aWrite the amount of required money:' - reward: - permissionName: §aWrite the permission name. - permissionWorld: §aWrite the world in which the permission will be edited, - or "null" if you want to be global. - money: '§aWrite the amount of the received money:' - wait: '§aWrite the amount of game ticks to wait: (1 second = 20 game ticks)' - random: - min: '§aWrite the minimum amount of rewards given to the player (inclusive).' - max: '§aWrite the maximum amount of rewards given to the player (inclusive).' - chooseObjectiveRequired: §aWrite the objective name. - chooseObjectiveTargetScore: §aWrite the target score for the objective. - chooseRegionRequired: §aWrite the name of the required region (you must be in the same world). - chooseRequirementCustomReason: 'Write the custom reason for this requirement. If the player does - not meet the requirement but tries to start the quest anyway, this message will appear in the chat.' - chooseRequirementCustomDescription: 'Write the custom description for this requirement. It will appear - in the description of the quest in the menu.' - chooseRewardCustomDescription: 'Write the custom description for this reward. It will appear - in the description of the quest in the menu.' - selectWantedBlock: §aClick with the stick on the wanted block for the stage. - itemCreator: - itemType: '§aWrite the name of the wanted item type:' - itemAmount: '§aWrite the amount of item(s):' - itemName: '§aWrite the item name:' - itemLore: '§aModify the item lore: (Write "help" for help.)' - unknownItemType: §cUnknown item type. - invalidItemType: §cInvalid item type. (The item can't be a block.) - unknownBlockType: §cUnknown block type. - invalidBlockType: §cInvalid block type. - dialog: - syntaxMessage: '§cCorrect syntax: {command} <message>' - syntaxRemove: '§cCorrect sytax: remove <id>' - player: §aMessage "§7{msg}§a" added for the player. - npc: §aMessage "§7{msg}§a" added for the NPC. - noSender: §aMessage "§7{msg}§a" added without a sender. - messageRemoved: §aMessage "§7{msg}§a" removed. - edited: §aMessage "§7{msg}§a" edited. - soundAdded: §aSound "§7{sound}§a" added for the message "§7{msg}§a". - cleared: §aRemoved §2§l{amount}§a message(s). - help: - header: §6§lBeautyQuests — Dialog editor help - npc: '§6npc <message>: §eAdd a message said by the NPC.' - player: '§6player <message>: §eAdd a message said by the player.' - nothing: '§6noSender <message>: §eAdd a message without a sender.' - remove: '§6remove <id>: §eRemove a message.' - list: '§6list: §eView all messages.' - npcInsert: '§6npcInsert <id> <message>: §eInsert a message said by the NPC.' - playerInsert: '§6playerInsert <id> <message>: §eInsert a message said by player.' - nothingInsert: '§6nothingInsert <id> <message>: §eInsert a message without - any prefix.' - edit: '§6edit <id> <message>: §eEdit a message.' - addSound: '§6addSound <id> <sound>: §eAdd a sound to a message.' - clear: '§6clear: §eRemove all messages.' - close: '§6close: §eValidate all messages.' - setTime: '§6setTime <id> <time>: §eSet the time (in ticks) before the next msg plays automatically.' - npcName: '§6npcName [custom NPC name]: §eSet (or reset to default) custom name of the NPC in the dialog' - skippable: '§6skippable [true|false]: §eSet if the dialog can be skipped or not' - timeSet: '§aTime has been edited for message {msg}: now {time} ticks.' - timeRemoved: '§aTime has been removed for message {msg}.' - npcName: - set: '§aCustom NPC name set to §7{new_name}§a (was §7{old_name}§a)' - unset: '§aCustom NPC name reset to default (was §7{old_name}§a)' - skippable: - set: '§aThe dialog skippable status is now set to §7{new_state}§a (was §7{old_state}§a)' - unset: '§aThe dialog skippable status is reset to default (was §7{old_state}§a)' - mythicmobs: - list: '§aA list of all Mythic Mobs:' - isntMythicMob: §cThis Mythic Mob doesn't exist. - disabled: §cMythicMob is disabled. - advancedSpawnersMob: 'Write the name of the custom spawner mob to kill:' - textList: - syntax: '§cCorrect syntax: {command}' - added: §aText "§7{msg}§a" added. - removed: §aText "§7{msg}§a" removed. - help: - header: §6§lBeautyQuests — List editor help - add: '§6add <message>: §eAdd a text.' - remove: '§6remove <id>: §eRemove a text.' - list: '§6list: §eView all added texts.' - close: '§6close: §eValidate the added texts.' - availableElements: 'Available elements: §e{available_elements}' - noSuchElement: '§cThere is no such element. Allowed elements are: §e{available_elements}' - invalidPattern: '§cInvalid regex pattern §4{input}§c.' - comparisonTypeDefault: '§aChoose the comparison type you want among {available}. Default comparison is: §e§l{default}§r§a. Type §onull§r§a to use it.' - scoreboardObjectiveNotFound: '§cUnknown scoreboard objective.' - pool: - hologramText: 'Write the custom hologram text for this pool (or "null" if you want the default one).' - maxQuests: 'Write the maximum amount of quests launcheable from this pool.' - questsPerLaunch: 'Write the amount of quests given when players click on the NPC.' - timeMsg: 'Write the time before players can take a new quest. (default unit: days)' - title: - title: 'Write the title text (or "null" if you want none).' - subtitle: 'Write the subtitle text (or "null" if you want none).' - fadeIn: 'Write the "fade-in" duration, in ticks (20 ticks = 1 second).' - stay: 'Write the "stay" duration, in ticks (20 ticks = 1 second).' - fadeOut: 'Write the "fade-out" duration, in ticks (20 ticks = 1 second).' - colorNamed: 'Enter the name of a color.' - color: 'Enter a color in the hexadecimal format (#XXXXX) or RGB format (RED GRE BLU).' - invalidColor: 'The color you entered is invalid. It must be either hexadecimal or RGB.' - firework: - invalid: 'This item is not a valid firework.' - invalidHand: 'You must hold a firework in your main hand.' - edited: 'Edited the quest firework!' - removed: 'Removed the quest firework!' - writeCommandDelay: '§aWrite the desired command delay, in ticks.' -advancement: - finished: Finished - notStarted: Not started -inv: - validate: §b§lValidate - cancel: §c§lCancel - search: §e§lSearch - addObject: §aAdd an object - confirm: - name: Are you sure? - 'yes': §aConfirm - 'no': §cCancel - create: - stageCreate: §aCreate new step - stageRemove: §cDelete this step - stageUp: Move up - stageDown: Move down - stageType: '§7Stage type: §e{stage_type}' - cantFinish: §7You must create at least one stage before finishing quest creation! - findNPC: §aFind NPC - bringBack: §aBring back items - findRegion: §aFind region - killMobs: §aKill mobs - mineBlocks: §aBreak blocks - placeBlocks: §aPlace blocks - talkChat: §aWrite in chat - interact: §aInteract with block - fish: §aCatch fishes - melt: §6Melt items - enchant: §dEnchant items - craft: §aCraft item - bucket: §aFill buckets - location: §aGo to location - playTime: §ePlay time - breedAnimals: §aBreed animals - tameAnimals: §aTame animals - death: §cDie - dealDamage: §cDeal damage to mobs - eatDrink: §aEat or drink food or potions - NPCText: §eEdit dialog - NPCSelect: §eChoose or create NPC - hideClues: Hide particles and holograms - gps: Displays a compass towards the objective - editMobsKill: §eEdit mobs to kill - mobsKillFromAFar: Needs to be killed with projectile - editBlocksMine: §eEdit blocks to break - preventBlockPlace: Prevent players to break their own blocks - editBlocksPlace: §eEdit blocks to place - editMessageType: §eEdit message to write - cancelMessage: Cancel sending - ignoreCase: Ignore the case of the message - replacePlaceholders: Replace {PLAYER} and placeholders from PAPI - selectItems: §eEdit required items - selectItemsMessage: §eEdit asking message - selectItemsComparisons: §eSelect items comparisons (ADVANCED) - selectRegion: §7Choose region - toggleRegionExit: On exit - stageStartMsg: §eEdit starting message - selectBlockLocation: §eSelect block location - selectBlockMaterial: §eSelect block material - leftClick: Click must be left-click - editFishes: §eEdit fishes to catch - editItemsToMelt: §eEdit items to melt - editItemsToEnchant: §eEdit items to enchant - editItem: §eEdit item to craft - editBucketType: §eEdit type of bucket to fill - editBucketAmount: §eEdit amount of buckets to fill - editLocation: §eEdit location - editRadius: §eEdit distance from location - currentRadius: '§eCurrent distance: §6{0}' - changeTicksRequired: '§eChange played ticks required' - changeEntityType: '§eChange entity type' - stage: - location: - worldPattern: '§aSet world name pattern §d(ADVANCED)' - worldPatternLore: 'If you want the stage to be completed for any world matching a specific pattern, enter a regex (regular expression) here.' - death: - causes: '§aSet death causes §d(ADVANCED)' - anyCause: Any death cause - setCauses: '{0} death cause(s)' - dealDamage: - damage: '§eDamage to deal' - targetMobs: '§cMobs to damage' - eatDrink: - items: '§eEdit items to eat or drink' - stages: - name: Create stages - nextPage: §eNext page - laterPage: §ePrevious page - endingItem: §eEdit end rewards - descriptionTextItem: §eEdit description - regularPage: §aRegular stages - branchesPage: §dBranch stages - previousBranch: §eBack to previous branch - newBranch: §eGo to new branch - validationRequirements: §eValidation requirements - validationRequirementsLore: All the requirements must match the player that tries to complete the stage. If not, the stage can not be completed. - details: - hologramLaunch: §eEdit "launch" hologram item - hologramLaunchLore: Hologram displayed above Starter NPC's head when the player can start the quest. - hologramLaunchNo: §eEdit "launch unavailable" hologram item - hologramLaunchNoLore: Hologram displayed above Starter NPC's head when the player can NOT start the quest. - customConfirmMessage: §eEdit quest confirmation message - customConfirmMessageLore: Message displayed in the Confirmation GUI when a player is about to start the quest. - customDescription: §eEdit quest description - customDescriptionLore: Description shown below the name of the quest in GUIs. - name: Last quest details - multipleTime: - itemName: Toggle repeatable - itemLore: Can the quest be done several times? - cancellable: Cancellable by player - cancellableLore: Allows the player to cancel the quest through its Quests Menu. - startableFromGUI: Startable from GUI - startableFromGUILore: Allows the player to start the quest from the Quests Menu. - scoreboardItem: Enable scoreboard - scoreboardItemLore: If disabled, the quest will not be tracked through the scoreboard. - hideNoRequirementsItem: Hide when requirements not met - hideNoRequirementsItemLore: If enabled, the quest will not be displayed in the Quests Menu when the requirements are not met. - bypassLimit: Don't count quest limit - bypassLimitLore: If enabled, the quest will be startable even if the player has reached its maximum amount of started quests. - auto: Start automatically on first join - autoLore: If enabled, the quest will be started automatically when the player joins the server for the first time. - questName: §a§lEdit quest name - questNameLore: A name must be set to complete quest creation. - setItemsRewards: §eEdit reward items - removeItemsReward: §eRemove items from inventory - setXPRewards: §eEdit reward experience - setCheckpointReward: §eEdit checkpoint rewards - setRewardStopQuest: §cStop the quest - setRewardsWithRequirements: §eRewards with requirements - setRewardsRandom: §dRandom rewards - setPermReward: §eEdit permissions - setMoneyReward: §eEdit money reward - setWaitReward: '§eEdit "wait" reward' - setTitleReward: '§eEdit title reward' - selectStarterNPC: §e§lSelect NPC starter - selectStarterNPCLore: Clicking on the selected NPC will start the quest. - selectStarterNPCPool: §c⚠ A quest pool is selected - createQuestName: §lCreate quest - createQuestLore: You must define a quest name. - editQuestName: §lEdit quest - endMessage: §eEdit end message - endMessageLore: Message which will be sent to the player at the end of the quest. - endSound: §eEdit end sound - endSoundLore: Sound which will be played at the end of the quest. - startMessage: §eEdit start message - startMessageLore: Message which will be sent to the player at the beginning of the quest. - startDialog: §eEdit start dialog - startDialogLore: Dialog which will be played before the quests start when players click on the Starter NPC. - editRequirements: §eEdit requirements - editRequirementsLore: Every requirements must apply to the player before it can start the quest. - startRewards: §6Start rewards - startRewardsLore: Actions performed when the quest starts. - cancelRewards: §cCancel actions - cancelRewardsLore: Actions performed when players cancel this quest. - hologramText: §eHologram text - hologramTextLore: Text displayed on the hologram above the Starter NPC's head. - timer: §bRestart timer - timerLore: Time before the player can start the quest again. - requirements: '{amount} requirement(s)' - rewards: '{amount} reward(s)' - actions: '{amount} action(s)' - rewardsLore: Actions performed when the quest ends. - customMaterial: '§eEdit quest item material' - customMaterialLore: Item representative of this quest in the Quests Menu. - failOnDeath: Fail on death - failOnDeathLore: Will the quest be cancelled when the player dies? - questPool: §eQuest Pool - questPoolLore: Attach this quest to a quest pool - firework: §dEnding Firework - fireworkLore: Firework launched when the player finishes the quest - fireworkLoreDrop: Drop your custom firework here - visibility: §bQuest visibility - visibilityLore: Choose in which tabs of the menu will the quest be shown, and if - the quest is visible on dynamic maps. - keepDatas: Preserve players datas - keepDatasLore: |- - Force the plugin to preserve players datas, even though stages have been edited. - §c§lWARNING §c- enabling this option may break your players datas. - loreReset: '§e§lAll players'' advancement will be reset' - optionValue: '§8Value: §7{value}' - defaultValue: '§8(default value)' - requiredParameter: '§7Required parameter' - itemsSelect: - name: Edit items - none: |- - §aMove an item to here or - click to open the item editor. - itemSelect: - name: Choose item - npcCreate: - name: Create NPC - setName: §eEdit NPC name - setSkin: §eEdit NPC skin - setType: §eEdit NPC type - move: - itemName: §eMove - itemLore: §aChange the NPC location. - moveItem: §a§lValidate place - npcSelect: - name: Select or create? - selectStageNPC: §eSelect existing NPC - createStageNPC: §eCreate NPC - entityType: - name: Choose entity type - chooseQuest: - name: Which quest? - menu: §aQuests Menu - menuLore: Gets you to your Quests Menu. - mobs: - name: Select mobs - none: §aClick to add a mob. - clickLore: |- - §a§lLeft-click§a to edit amount. - §a§l§nShift§a§l + left-click§a to edit mob name. - §c§lRight-click§c to delete. - setLevel: Set minimum level - mobSelect: - name: Select mob type - bukkitEntityType: §eSelect entity type - mythicMob: §6Select Mythic Mob - epicBoss: §6Select Epic Boss - boss: §6Select a Boss - stageEnding: - locationTeleport: §eEdit teleport location - command: §eEdit executed command - requirements: - name: Requirements - setReason: Set custom reason - reason: '§8Custom reason: §7{reason}' - rewards: - name: Rewards - commands: 'Commands: {amount}' - teleportation: |- - §aSelected: - X: {0} - Y: {1} - Z: {2} - World: {3} - random: - rewards: Edit rewards - minMax: Edit min and max - checkpointActions: - name: Checkpoint actions - cancelActions: - name: Cancel actions - rewardsWithRequirements: - name: Rewards with requirements - listAllQuests: - name: Quests - listPlayerQuests: - name: '{player_name}''s quests' - listQuests: - notStarted: Not started quests - finished: Finished quests - inProgress: Quests in progress - loreDialogsHistoryClick: §7View the dialogs - loreCancelClick: §cCancel the quest - loreStart: §a§oClick to start the quest. - loreStartUnavailable: §c§oYou do not meet requirements to start the quest. - timeToWaitRedo: §3§oYou can restart this quest in {time_left}. - canRedo: §3§oYou can restart this quest! - timesFinished: §3Quest done {times_finished} times. - format: - normal: §6§l§o{quest_name} - withId: §6§l§o{quest_name}§r §e#{quest_id} - itemCreator: - name: Item creator - itemType: §bItem type - itemFlags: Toggle item flags - itemName: §bItem name - itemLore: §bItem lore - isQuestItem: '§bQuest item:' - command: - name: Command - value: §eCommand - console: Console - parse: Parse placeholders - delay: §bDelay - chooseAccount: - name: What account? - listBook: - questName: Name - questStarter: Starter - questRewards: Rewards - questMultiple: Several times - requirements: Requirements - questStages: Stages - noQuests: No quests have previously been created. - commandsList: - name: Command list - value: '§eCommand: {command_label}' - console: '§eConsole: {command_console}' - block: - name: Choose block - material: '§eMaterial: {block_type}' - materialNotItemLore: 'The block chosen cannot be displayed as an item. It is still correctly stored as {block_material}.' - blockName: '§bCustom block name' - blockData: '§dBlockdata (advanced)' - blockTag: '§dTag (advanced)' - blockTagLore: 'Choose a tag which describes a list of possible blocks. - Tags can be customized using datapacks. - You can find list of tags on the Minecraft wiki.' - blocksList: - name: Select blocks - addBlock: §aClick to add a block. - blockAction: - name: Select block action - location: §eSelect a precise location - material: §eSelect a block material - buckets: - name: Bucket type - permission: - name: Choose permission - perm: §aPermission - world: §aWorld - worldGlobal: §b§lGlobal - remove: Remove permission - removeLore: §7Permission will be taken off\n§7instead of given. - permissionList: - name: Permissions list - removed: '§eTaken off: §6{permission_removed}' - world: '§eWorld: §6{permission_world}' - classesRequired.name: Classes required - classesList.name: Classes list - factionsRequired.name: Factions required - factionsList.name: Factions list - poolsManage: - name: Quest Pools - itemName: '§aPool {pool}' - poolNPC: '§8NPC: §7{pool_npc_id}' - poolMaxQuests: '§8Max quests: §7{pool_max_quests}' - poolQuestsPerLaunch: '§8Quests given per launch: §7{pool_quests_per_launch}' - poolRedo: '§8Can redo completed quests: §7{pool_redo}' - poolTime: '§8Time between quests: §7{pool_time}' - poolHologram: '§8Hologram text: §7{pool_hologram}' - poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' - poolQuestsList: '§7{0} §8quest(s): §7{pool_quests}' - create: §aCreate a quest pool - edit: §e> §6§oEdit the pool... §e< - choose: §e> §6§oChoose this pool §e< - poolCreation: - name: Quest pool creation - hologramText: §ePool custom hologram - maxQuests: §aMax quests - questsPerLaunch: §aQuests started per launch - time: §bSet time between quests - redoAllowed: Is redo allowed - avoidDuplicates: Avoid duplicates - avoidDuplicatesLore: §8> §7Try to avoid doing\n the same quest over and over - requirements: §bRequirements to start a quest - poolsList.name: Quest pools - itemComparisons: - name: Item Comparisons - bukkit: Bukkit native comparison - bukkitLore: 'Uses Bukkit default item comparison system.\nCompares material, durability, nbt tags...' - customBukkit: Bukkit native comparison - NO NBT - customBukkitLore: 'Uses Bukkit default item comparison system, but wipes out NBT tags.\nCompares material, durability...' - material: Item material - materialLore: 'Compares item material (i. e. stone, iron sword...)' - itemName: Item name - itemNameLore: Compares items names - itemLore: Item lore - itemLoreLore: Compares items lores - enchants: Items enchants - enchantsLore: Compares items enchants - repairCost: Repair cost - repairCostLore: Compares repair cost for armors and swords - itemsAdder: ItemsAdder - itemsAdderLore: Compares ItemsAdder IDs - editTitle: - name: Edit Title - title: §6Title - subtitle: §eSubtitle - fadeIn: §aFade-in duration - stay: §bStay duration - fadeOut: §aFade-out duration - particleEffect: - name: Create particle effect - shape: §dParticle shape - type: §eParticle type - color: §bParticle color - particleList: - name: Particles list - colored: Colored particle - damageCause: - name: Damage cause - damageCausesList: - name: Damage causes list - visibility: - name: Quest visibility - notStarted: '"Not started" menu tab' - inProgress: '"In progress" menu tab' - finished: '"Finished" menu tab' - maps: 'Maps (such as dynmap or BlueMap)' - equipmentSlots: - name: Equipment slots - questObjects: - setCustomDescription: 'Set custom description' - description: '§8Description: §7{description}' - -scoreboard: - name: §6§lQuests - noLaunched: §cNo quests in progress. - noLaunchedName: §c§lLoading - noLaunchedDescription: §c§oLoading - textBetwteenBranch: §e or - asyncEnd: §ex - stage: - region: §eFind region §6{0} - npc: §eTalk with NPC §6{0} - items: '§eBring items to §6{0}§e:' - mobs: §eKill §6{0} - mine: §eMine {0} - placeBlocks: §ePlace {0} - chat: §eWrite §6{0} - interact: §eClick on the block at §6{0} - interactMaterial: §eClick on a §6{0}§e block - fish: §eFish §6{0} - melt: §eMelt §6{0} - enchant: §eEnchant §6{0} - craft: §eCraft §6{0} - bucket: §eFill §6{0} - location: §eGo to §6{0}§e, §6{1}§e, §6{2}§e in §6{3} - playTimeFormatted: §ePlay §6{0} - breed: §eBreed §6{0} - tame: §eTame §6{0} - die: §cDie - dealDamage: - any: §cDeal {0} damage - mobs: §cDeal {0} damage to {1} - eatDrink: §eConsume §6{0} -indication: - startQuest: §7Do you want to start the quest {quest_name}? - closeInventory: §7Are you sure you want to close the GUI? - cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? - removeQuest: §7Are you sure you want to remove the quest {quest_name}? -description: - requirement: - title: '§8§lRequirements:' - level: 'Level {short_level}' - jobLevel: 'Level {short_level} for {job_name}' - combatLevel: 'Combat level {short_level}' - skillLevel: 'Level {short_level} for {skill_name}' - class: 'Class {class_name}' - faction: 'Faction {faction_name}' - quest: 'Finish quest §e{quest_name}' - reward: - title: '§8§lRewards:' - -misc: - format: - prefix: §6<§e§lQuests§r§6> §r - npcText: §6[{2}/{3}] §e§l{0}:§r§e {1} - selfText: §6[{2}/{3}] §e§l{0}:§r§e {1} - offText: §r§e{0} - editorPrefix: §a - errorPrefix: §4✖ §c - successPrefix: §2✔ §a - requirementNotMetPrefix: §c - time: - weeks: '{0} weeks' - days: '{0} days' - hours: '{0} hours' - minutes: '{0} minutes' - lessThanAMinute: 'less than a minute' - stageType: - region: Find region - npc: Find NPC - items: Bring back items - mobs: Kill mobs - mine: Break blocks - placeBlocks: Place blocks - chat: Write in chat - interact: Interact with block - Fish: Catch fishes - Melt: Melt items - Enchant: Enchant items - Craft: Craft item - Bucket: Fill bucket - location: Find location - playTime: Play time - breedAnimals: Breed animals - tameAnimals: Tame animals - die: Die - dealDamage: Deal damage - eatDrink: Eat or drink - comparison: - equals: equal to {number} - different: different to {number} - less: strictly less than {number} - lessOrEquals: less than {number} - greater: strictly greater than {number} - greaterOrEquals: greater than {number} - requirement: - logicalOr: §dLogical OR (requirements) - skillAPILevel: §bSkillAPI level required - class: §bClass(es) required - faction: §bFaction(s) required - jobLevel: §bJob level required - combatLevel: §bCombat level required - experienceLevel: §bExperience levels required - permissions: §3Permission(s) required - scoreboard: §dScore required - region: §dRegion required - placeholder: §bPlaceholder value required - quest: §aQuest required - mcMMOSkillLevel: §dSkill level required - money: §dMoney required - equipment: §eEquipment required - bucket: - water: Water bucket - lava: Lava bucket - milk: Milk bucket - snow: Snow bucket - click: - right: Right click - left: Left click - shift-right: Shift-right click - shift-left: Shift-left click - middle: Middle click - amounts: - items: '{items_amount} item(s)' - comparisons: '{comparisons_amount} comparaison(s)' - dialogLines: '{lines_amount} line(s)' - permissions: '{permissions_amount} permission(s)' - mobs: '{mobs_amount} mob(s)' - xp: '{xp_amount} experience point(s)' - ticks: '{ticks} ticks' - questItemLore: §e§oQuest Item - hologramText: §8§lQuest NPC - poolHologramText: §eNew quest available! - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eEntity type: {0}' - entityTypeAny: §eAny entity - enabled: Enabled - disabled: Disabled - unknown: unknown - notSet: §cnot set - unused: §2§lUnused - used: §a§lUsed - remove: §7Middle-click to remove - removeRaw: Remove - reset: Reset - or: or - amount: '§eAmount: {amount}' - 'yes': 'Yes' - 'no': 'No' - and: and +msg: + quest: + finished: + base: §aCongratulations! You have finished the quest §e{quest_name}§a! + obtain: §aYou obtain {rewards}! + started: §aYou have started the quest §r§e{0}§o§6! + created: §aCongratulations! You have created the quest §e{quest}§a which includes + {quest_branches} branch(es)! + edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes + {quest_branches} branch(es)! + createCancelled: §cThe creation or edition has been cancelled by another plugin! + cancelling: §cProcess of quest creation cancelled. + editCancelling: §cProcess of quest edition cancelled. + invalidID: §cThe quest with the id {quest_id} doesn't exist. + invalidPoolID: §cThe pool {pool_id} does not exist. + alreadyStarted: §cYou have already started the quest! + notStarted: §cYou are not currently doing this quest. + quests: + maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same time... + nopStep: §cThis quest doesn't have any step. + updated: §7Quest §e{quest_name}§7 updated. + checkpoint: §7Quest checkpoint reached! + failed: §cYou have failed the quest {quest_name}... + pools: + noTime: §cYou must wait {time_left} before doing another quest. + allCompleted: §7You have completed all the quests! + noAvailable: §7There is no more quest available... + maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same time... + questItem: + drop: §cYou can't drop a quest item! + craft: §cYou can't use a quest item to craft! + eat: §cYou cannot eat a quest item! + stageMobs: + noMobs: §cThis stage doesn't need any mobs to kill. + listMobs: §aYou must kill {0}. + writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write + "help" to receive help.)' + writeRegionName: '§aWrite the name of the region required for the step:' + writeXPGain: '§aWrite the amount of experience points the player will obtain: (Last + value: {xp_amount})' + writeMobAmount: '§aWrite the amount of mobs to kill:' + writeMobName: '§aWrite the custom name of the mob to kill:' + writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if + you want a command.)' + writeMessage: '§aWrite the message that will be sent to the player' + writeStartMessage: '§aWrite the message that will be sent at the beginning of the quest, + "null" if you want the default one or "none" if you want none:' + writeEndMsg: '§aWrite the message that will be sent at the end of the quest, + "null" if you want the default one or "none" if you want none. You can use "{0}" which + will be replaced with the rewards obtained.' + writeEndSound: '§aWrite the sound name that will be played to the player at the end of + the quest, "null" if you want the default one or "none" if you want none:' + writeDescriptionText: '§aWrite the text which describes the goal of the stage:' + writeStageText: '§aWrite the text that will be sent to the player at the beginning + of the step:' + moveToTeleportPoint: §aGo to the wanted teleport location. + writeNpcName: '§aWrite the name of the NPC:' + writeNpcSkinName: '§aWrite the name of the skin of the NPC:' + writeQuestName: '§aWrite the name of your quest:' + writeCommand: '§aWrite the wanted command: (The command is without the "/" and the + placeholder "{PLAYER}" is supported. It will be replaced with the name of the + executor.)' + writeHologramText: '§aWrite text of the hologram: (Write "none" if you don''t want + a hologram and "null" if you want the default text.)' + writeQuestTimer: '§aWrite the required time (in minutes) before you can restart + the quest: (Write "null" if you want the default timer.)' + writeConfirmMessage: '§aWrite the confirmation message shown when a player is about + to start the quest: (Write "null" if you want the default message.)' + writeQuestDescription: '§aWrite the description of the quest, shown in the player''s quest GUI.' + writeQuestMaterial: '§aWrite the material of the quest item.' + requirements: + quest: §cYou must have finished the quest §e{quest_name}§c! + level: §cYour level must be {long_level}! + job: §cYour level for the job §e{job_name}§c must be {long_level}! + skill: §cYour level for the skill §e{skill_name}§c must be {long_level}! + combatLevel: §cYour combat level must be {long_level}! + money: §cYou must have {money}! + waitTime: §cYou must wait {time_left} before you can restart this quest! + experience: + edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} points. + selectNPCToKill: §aSelect the NPC to kill. + npc: + remove: §aNPC deleted. + talk: §aGo and talk to the NPC named §e{0}§a. + regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) + npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. + number: + negative: §cYou must enter a positive number! + zero: §cYou must enter a number other than 0! + invalid: §c{input} isn't a valid number. + notInBounds: §cYour number must be between {min} and {max}. + errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: {error}' + commandsDisabled: §cCurrently you aren't allowed to execute commands! + indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} and + {max}. + invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the block {block_material}. + invalidBlockTag: §cUnavailable block tag {block_tag}. + bringBackObjects: Bring me back {0}. + inventoryFull: §cYour inventory is full, the item has been dropped on the floor. + playerNeverConnected: §cUnable to find informations about the player {0}. + playerNotOnline: §cThe player {0} is offline. + playerDataNotFound: §cDatas of player {0} not found. + versionRequired: 'Version required: §l{version}' + restartServer: '§7Restart your server to see the modifications.' + dialogs: + skipped: '§8§o Dialog skipped.' + tooFar: '§7§oYou are too far away from {npc_name}...' + command: + downloadTranslations: + syntax: '§cYou must specify a language to download. Example: "/quests downloadTranslations en_US".' + notFound: '§cLanguage {lang} not found for version {version}.' + exists: '§cThe file {file_name} already exists. Append "-overwrite" to your command to overwrite it. (/quests downloadTranslations <lang> -overwrite)' + downloaded: '§aLanguage {lang} has been downloaded! §7You must now edit the + file "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 with {lang}, then restart the server.' + checkpoint: + noCheckpoint: §cNo checkpoint found for the quest {quest}. + questNotStarted: §cYou are not doing this quest. + setStage: + branchDoesntExist: §cThe branch with the id {branch_id} doesn't exist. + doesntExist: §cThe stage with the id {stage_id} doesn't exist. + next: §aThe stage has been skipped. + nextUnavailable: §cThe "skip" option is not available when the player is at + the end of a branch. + set: §aStage {stage_id} launched. + startDialog: + impossible: §cImpossible to start the dialog now. + noDialog: §cThe player has no pending dialog. + alreadyIn: §cThe player is already playing a dialog. + success: §aStarted dialog for player {player} in quest {quest}! + playerNeeded: §cYou must be a player to execute this command! + incorrectSyntax: §cIncorrect syntax. + noPermission: '§cYou haven''t enough permissions to execute this command! (Required: + {0})' + invalidCommand: + quests: §cThis command doesn't exist, write §e/quests help§c. + simple: §cThis command doesn't exist, write §ehelp§c. + needItem: §cYou must hold an item in your main hand! + itemChanged: §aThe item has been edited. The changes will affect after a restart. + itemRemoved: §aThe hologram item has been removed. + removed: §aThe quest {quest_name} has successfully been removed. + leaveAll: '§aYou have forced the end of {success} quest(s). Errors: {errors}' + resetPlayer: + player: §6All informations of your {quest_amount} quest(s) has/have been deleted by {deleter_name}. + remover: §6{quest_amount} quest information(s) (and {quest_pool} pools) of {player} has/have been deleted. + resetPlayerQuest: + player: §6All informations about the quest {quest} have been deleted by {deleter_name}. + remover: §6{player} informations of quest {quest} has/have been deleted. + resetQuest: §6Removed datas of the quest for {player_amount} players. + startQuest: '§6You have forced starting of quest {quest} for {player}.' + startQuestNoRequirements: '§cThe player does not meet the requirements for the quest {quest}... + Append "-overrideRequirements" at the end of your command to bypass the requirements check.' + cancelQuest: §6You have cancelled the quest {0}. + cancelQuestUnavailable: §cThe quest {0} can't be cancelled. + backupCreated: §6You have successfully created backups of all quests and player + informations. + backupPlayersFailed: §cCreating a backup for all the player informations has failed. + backupQuestsFailed: §cCreating a backup for all the quests has failed. + adminModeEntered: §aYou have entered the Admin Mode. + adminModeLeft: §aYou have left the Admin Mode. + resetPlayerPool: + timer: §aYou have reset the {pool} pool timer of {player}. + full: §aYou have reset the {pool} pool datas of {player}. + startPlayerPool: + error: 'Failed to start the pool {pool} for {player}.' + success: 'Started pool {pool} to {player}. Result: {result}' + scoreboard: + lineSet: §6You have successfully edited the line {line_id}. + lineReset: §6You have successfully reset the line {line_id}. + lineRemoved: §6You have successfully removed the line {line_id}. + lineInexistant: §cThe line {line_id} doesn't exist. + resetAll: §6You have successfully reset the scoreboard of the player {player_name}. + hidden: §6The scoreboard of the player {player_name} has been hidden. + shown: §6The scoreboard of the player {player_name} has been shown. + own: + hidden: §6Your scoreboard is now hidden. + shown: §6Your scoreboard is shown again. + help: + header: §6§lBeautyQuests — Help + create: '§6/{label} create: §eCreate a quest.' + edit: '§6/{label} edit: §eEdit a quest.' + remove: '§6/{label} remove <id>: §eDelete a quest with a specified id or click on + the NPC when not defined.' + finishAll: '§6/{label} finishAll <player>: §eFinish all quests of a player.' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eSkip the + current stage/start the branch/set a stage for a branch.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eStarts the pending dialog + for a NPC stage or the starting dialog for a quest.' + resetPlayer: '§6/{label} resetPlayer <player>: §eRemove all informations about a + player.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete informations + of a quest for a player.' + seePlayer: '§6/{label} seePlayer <player>: §eView informations about a player.' + reload: '§6/{label} reload: §eSave and reload all configurations and files. (§cdeprecated§e)' + start: '§6/{label} start <player> [id]: §eForce the starting of a quest.' + setItem: '§6/{label} setItem <talk|launch>: §eSave the hologram item.' + setFirework: '§6/{label} setFirework: §eEdit the default ending firework.' + adminMode: '§6/{label} adminMode: §eToggle the Admin Mode. (Useful for displaying + little log messages.)' + version: '§6/{label} version: §eSee the current plugin version.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownloads a vanilla translation file' + save: '§6/{label} save: §eMake a manual plugin save.' + list: '§6/{label} list: §eSee the quest list. (Only for supported versions.)' + typeCancel: §aWrite "cancel" to come back to the last text. + editor: + blockAmount: '§aWrite the amount of blocks:' + blockName: '§aWrite the name of the block:' + blockData: '§aWrite the blockdata (available blockdatas: §7{available_datas}§a):' + blockTag: '§aWrite the block tag (available tags: §7{available_tags}§a):' + typeBucketAmount: '§aWrite the amount of buckets to fill:' + typeDamageAmount: 'Write the amount of damage player have to deal:' + goToLocation: §aGo to the wanted location for the stage. + typeLocationRadius: '§aWrite the required distance from the location:' + typeGameTicks: '§aWrite the required game ticks:' + already: §cYou are already in the editor. + stage: + location: + typeWorldPattern: '§aWrite a regex for world names:' + enter: + title: §6~ Editor Mode ~ + subtitle: §6Write "/quests exitEditor" to force quit the editor. + list: '§c⚠ §7You have entered a "list" editor. Use "add" to add lines. Refer to "help" (without slash) for help. §e§lType "close" to exit editor.' + chat: §6You are currently in the Editor Mode. Write "/quests exitEditor" to force + leaving the editor. (Highly not recommended, consider using commands such as + "close" or "cancel" to come back to the previous inventory.) + npc: + enter: §aClick on a NPC, or write "cancel". + choseStarter: §aChoose the NPC which starts the quest. + notStarter: §cThis NPC isn't a quest starter. + text: + argNotSupported: §cThe argument {arg} not supported. + chooseLvlRequired: '§aWrite the required amount of levels:' + chooseJobRequired: '§aWrite name of the wanted job:' + choosePermissionRequired: '§aWrite the required permission to start the quest:' + choosePermissionMessage: §aYou can choose a rejection message if the player + doesn't have the required permission. (To skip this step, write "null".) + choosePlaceholderRequired: + identifier: '§aWrite the name of the required placeholder without the percent + characters:' + value: '§aWrite the required value for the placeholder §e%§e{placeholder}§e%§a:' + chooseSkillRequired: '§aWrite the name of the required skill:' + chooseMoneyRequired: '§aWrite the amount of required money:' + reward: + permissionName: §aWrite the permission name. + permissionWorld: §aWrite the world in which the permission will be edited, + or "null" if you want to be global. + money: '§aWrite the amount of the received money:' + wait: '§aWrite the amount of game ticks to wait: (1 second = 20 game ticks)' + random: + min: '§aWrite the minimum amount of rewards given to the player (inclusive).' + max: '§aWrite the maximum amount of rewards given to the player (inclusive).' + chooseObjectiveRequired: §aWrite the objective name. + chooseObjectiveTargetScore: §aWrite the target score for the objective. + chooseRegionRequired: §aWrite the name of the required region (you must be in the same world). + chooseRequirementCustomReason: 'Write the custom reason for this requirement. If the player does + not meet the requirement but tries to start the quest anyway, this message will appear in the chat.' + chooseRequirementCustomDescription: 'Write the custom description for this requirement. It will appear + in the description of the quest in the menu.' + chooseRewardCustomDescription: 'Write the custom description for this reward. It will appear + in the description of the quest in the menu.' + selectWantedBlock: §aClick with the stick on the wanted block for the stage. + itemCreator: + itemType: '§aWrite the name of the wanted item type:' + itemAmount: '§aWrite the amount of item(s):' + itemName: '§aWrite the item name:' + itemLore: '§aModify the item lore: (Write "help" for help.)' + unknownItemType: §cUnknown item type. + invalidItemType: §cInvalid item type. (The item can't be a block.) + unknownBlockType: §cUnknown block type. + invalidBlockType: §cInvalid block type. + dialog: + syntaxMessage: '§cCorrect syntax: {command} <message>' + syntaxRemove: '§cCorrect sytax: remove <id>' + player: §aMessage "§7{msg}§a" added for the player. + npc: §aMessage "§7{msg}§a" added for the NPC. + noSender: §aMessage "§7{msg}§a" added without a sender. + messageRemoved: §aMessage "§7{msg}§a" removed. + edited: §aMessage "§7{msg}§a" edited. + soundAdded: §aSound "§7{sound}§a" added for the message "§7{msg}§a". + cleared: §aRemoved §2§l{amount}§a message(s). + help: + header: §6§lBeautyQuests — Dialog editor help + npc: '§6npc <message>: §eAdd a message said by the NPC.' + player: '§6player <message>: §eAdd a message said by the player.' + nothing: '§6noSender <message>: §eAdd a message without a sender.' + remove: '§6remove <id>: §eRemove a message.' + list: '§6list: §eView all messages.' + npcInsert: '§6npcInsert <id> <message>: §eInsert a message said by the NPC.' + playerInsert: '§6playerInsert <id> <message>: §eInsert a message said by player.' + nothingInsert: '§6nothingInsert <id> <message>: §eInsert a message without + any prefix.' + edit: '§6edit <id> <message>: §eEdit a message.' + addSound: '§6addSound <id> <sound>: §eAdd a sound to a message.' + clear: '§6clear: §eRemove all messages.' + close: '§6close: §eValidate all messages.' + setTime: '§6setTime <id> <time>: §eSet the time (in ticks) before the next msg plays automatically.' + npcName: '§6npcName [custom NPC name]: §eSet (or reset to default) custom name of the NPC in the dialog' + skippable: '§6skippable [true|false]: §eSet if the dialog can be skipped or not' + timeSet: '§aTime has been edited for message {msg}: now {time} ticks.' + timeRemoved: '§aTime has been removed for message {msg}.' + npcName: + set: '§aCustom NPC name set to §7{new_name}§a (was §7{old_name}§a)' + unset: '§aCustom NPC name reset to default (was §7{old_name}§a)' + skippable: + set: '§aThe dialog skippable status is now set to §7{new_state}§a (was §7{old_state}§a)' + unset: '§aThe dialog skippable status is reset to default (was §7{old_state}§a)' + mythicmobs: + list: '§aA list of all Mythic Mobs:' + isntMythicMob: §cThis Mythic Mob doesn't exist. + disabled: §cMythicMob is disabled. + advancedSpawnersMob: 'Write the name of the custom spawner mob to kill:' + textList: + syntax: '§cCorrect syntax: {command}' + added: §aText "§7{msg}§a" added. + removed: §aText "§7{msg}§a" removed. + help: + header: §6§lBeautyQuests — List editor help + add: '§6add <message>: §eAdd a text.' + remove: '§6remove <id>: §eRemove a text.' + list: '§6list: §eView all added texts.' + close: '§6close: §eValidate the added texts.' + availableElements: 'Available elements: §e{available_elements}' + noSuchElement: '§cThere is no such element. Allowed elements are: §e{available_elements}' + invalidPattern: '§cInvalid regex pattern §4{input}§c.' + comparisonTypeDefault: '§aChoose the comparison type you want among {available}. Default comparison is: §e§l{default}§r§a. Type §onull§r§a to use it.' + scoreboardObjectiveNotFound: '§cUnknown scoreboard objective.' + pool: + hologramText: 'Write the custom hologram text for this pool (or "null" if you want the default one).' + maxQuests: 'Write the maximum amount of quests launcheable from this pool.' + questsPerLaunch: 'Write the amount of quests given when players click on the NPC.' + timeMsg: 'Write the time before players can take a new quest. (default unit: days)' + title: + title: 'Write the title text (or "null" if you want none).' + subtitle: 'Write the subtitle text (or "null" if you want none).' + fadeIn: 'Write the "fade-in" duration, in ticks (20 ticks = 1 second).' + stay: 'Write the "stay" duration, in ticks (20 ticks = 1 second).' + fadeOut: 'Write the "fade-out" duration, in ticks (20 ticks = 1 second).' + colorNamed: 'Enter the name of a color.' + color: 'Enter a color in the hexadecimal format (#XXXXX) or RGB format (RED GRE BLU).' + invalidColor: 'The color you entered is invalid. It must be either hexadecimal or RGB.' + firework: + invalid: 'This item is not a valid firework.' + invalidHand: 'You must hold a firework in your main hand.' + edited: 'Edited the quest firework!' + removed: 'Removed the quest firework!' + writeCommandDelay: '§aWrite the desired command delay, in ticks.' +advancement: + finished: Finished + notStarted: Not started +inv: + validate: §b§lValidate + cancel: §c§lCancel + search: §e§lSearch + addObject: §aAdd an object + confirm: + name: Are you sure? + 'yes': §aConfirm + 'no': §cCancel + create: + stageCreate: §aCreate new step + stageRemove: §cDelete this step + stageUp: Move up + stageDown: Move down + stageType: '§7Stage type: §e{stage_type}' + cantFinish: §7You must create at least one stage before finishing quest creation! + findNPC: §aFind NPC + bringBack: §aBring back items + findRegion: §aFind region + killMobs: §aKill mobs + mineBlocks: §aBreak blocks + placeBlocks: §aPlace blocks + talkChat: §aWrite in chat + interact: §aInteract with block + fish: §aCatch fishes + melt: §6Melt items + enchant: §dEnchant items + craft: §aCraft item + bucket: §aFill buckets + location: §aGo to location + playTime: §ePlay time + breedAnimals: §aBreed animals + tameAnimals: §aTame animals + death: §cDie + dealDamage: §cDeal damage to mobs + eatDrink: §aEat or drink food or potions + NPCText: §eEdit dialog + NPCSelect: §eChoose or create NPC + hideClues: Hide particles and holograms + gps: Displays a compass towards the objective + editMobsKill: §eEdit mobs to kill + mobsKillFromAFar: Needs to be killed with projectile + editBlocksMine: §eEdit blocks to break + preventBlockPlace: Prevent players to break their own blocks + editBlocksPlace: §eEdit blocks to place + editMessageType: §eEdit message to write + cancelMessage: Cancel sending + ignoreCase: Ignore the case of the message + replacePlaceholders: Replace {PLAYER} and placeholders from PAPI + selectItems: §eEdit required items + selectItemsMessage: §eEdit asking message + selectItemsComparisons: §eSelect items comparisons (ADVANCED) + selectRegion: §7Choose region + toggleRegionExit: On exit + stageStartMsg: §eEdit starting message + selectBlockLocation: §eSelect block location + selectBlockMaterial: §eSelect block material + leftClick: Click must be left-click + editFishes: §eEdit fishes to catch + editItemsToMelt: §eEdit items to melt + editItemsToEnchant: §eEdit items to enchant + editItem: §eEdit item to craft + editBucketType: §eEdit type of bucket to fill + editBucketAmount: §eEdit amount of buckets to fill + editLocation: §eEdit location + editRadius: §eEdit distance from location + currentRadius: '§eCurrent distance: §6{radius}' + changeTicksRequired: '§eChange played ticks required' + changeEntityType: '§eChange entity type' + stage: + location: + worldPattern: '§aSet world name pattern §d(ADVANCED)' + worldPatternLore: 'If you want the stage to be completed for any world matching a specific pattern, enter a regex (regular expression) here.' + death: + causes: '§aSet death causes §d(ADVANCED)' + anyCause: Any death cause + setCauses: '{causes_amount} death cause(s)' + dealDamage: + damage: '§eDamage to deal' + targetMobs: '§cMobs to damage' + eatDrink: + items: '§eEdit items to eat or drink' + stages: + name: Create stages + nextPage: §eNext page + laterPage: §ePrevious page + endingItem: §eEdit end rewards + descriptionTextItem: §eEdit description + regularPage: §aRegular stages + branchesPage: §dBranch stages + previousBranch: §eBack to previous branch + newBranch: §eGo to new branch + validationRequirements: §eValidation requirements + validationRequirementsLore: All the requirements must match the player that tries to complete the stage. If not, the stage can not be completed. + details: + hologramLaunch: §eEdit "launch" hologram item + hologramLaunchLore: Hologram displayed above Starter NPC's head when the player can start the quest. + hologramLaunchNo: §eEdit "launch unavailable" hologram item + hologramLaunchNoLore: Hologram displayed above Starter NPC's head when the player can NOT start the quest. + customConfirmMessage: §eEdit quest confirmation message + customConfirmMessageLore: Message displayed in the Confirmation GUI when a player is about to start the quest. + customDescription: §eEdit quest description + customDescriptionLore: Description shown below the name of the quest in GUIs. + name: Last quest details + multipleTime: + itemName: Toggle repeatable + itemLore: Can the quest be done several times? + cancellable: Cancellable by player + cancellableLore: Allows the player to cancel the quest through its Quests Menu. + startableFromGUI: Startable from GUI + startableFromGUILore: Allows the player to start the quest from the Quests Menu. + scoreboardItem: Enable scoreboard + scoreboardItemLore: If disabled, the quest will not be tracked through the scoreboard. + hideNoRequirementsItem: Hide when requirements not met + hideNoRequirementsItemLore: If enabled, the quest will not be displayed in the Quests Menu when the requirements are not met. + bypassLimit: Don't count quest limit + bypassLimitLore: If enabled, the quest will be startable even if the player has reached its maximum amount of started quests. + auto: Start automatically on first join + autoLore: If enabled, the quest will be started automatically when the player joins the server for the first time. + questName: §a§lEdit quest name + questNameLore: A name must be set to complete quest creation. + setItemsRewards: §eEdit reward items + removeItemsReward: §eRemove items from inventory + setXPRewards: §eEdit reward experience + setCheckpointReward: §eEdit checkpoint rewards + setRewardStopQuest: §cStop the quest + setRewardsWithRequirements: §eRewards with requirements + setRewardsRandom: §dRandom rewards + setPermReward: §eEdit permissions + setMoneyReward: §eEdit money reward + setWaitReward: '§eEdit "wait" reward' + setTitleReward: '§eEdit title reward' + selectStarterNPC: §e§lSelect NPC starter + selectStarterNPCLore: Clicking on the selected NPC will start the quest. + selectStarterNPCPool: §c⚠ A quest pool is selected + createQuestName: §lCreate quest + createQuestLore: You must define a quest name. + editQuestName: §lEdit quest + endMessage: §eEdit end message + endMessageLore: Message which will be sent to the player at the end of the quest. + endSound: §eEdit end sound + endSoundLore: Sound which will be played at the end of the quest. + startMessage: §eEdit start message + startMessageLore: Message which will be sent to the player at the beginning of the quest. + startDialog: §eEdit start dialog + startDialogLore: Dialog which will be played before the quests start when players click on the Starter NPC. + editRequirements: §eEdit requirements + editRequirementsLore: Every requirements must apply to the player before it can start the quest. + startRewards: §6Start rewards + startRewardsLore: Actions performed when the quest starts. + cancelRewards: §cCancel actions + cancelRewardsLore: Actions performed when players cancel this quest. + hologramText: §eHologram text + hologramTextLore: Text displayed on the hologram above the Starter NPC's head. + timer: §bRestart timer + timerLore: Time before the player can start the quest again. + requirements: '{amount} requirement(s)' + rewards: '{amount} reward(s)' + actions: '{amount} action(s)' + rewardsLore: Actions performed when the quest ends. + customMaterial: '§eEdit quest item material' + customMaterialLore: Item representative of this quest in the Quests Menu. + failOnDeath: Fail on death + failOnDeathLore: Will the quest be cancelled when the player dies? + questPool: §eQuest Pool + questPoolLore: Attach this quest to a quest pool + firework: §dEnding Firework + fireworkLore: Firework launched when the player finishes the quest + fireworkLoreDrop: Drop your custom firework here + visibility: §bQuest visibility + visibilityLore: Choose in which tabs of the menu will the quest be shown, and if + the quest is visible on dynamic maps. + keepDatas: Preserve players datas + keepDatasLore: |- + Force the plugin to preserve players datas, even though stages have been edited. + §c§lWARNING §c- enabling this option may break your players datas. + loreReset: '§e§lAll players'' advancement will be reset' + optionValue: '§8Value: §7{value}' + defaultValue: '§8(default value)' + requiredParameter: '§7Required parameter' + itemsSelect: + name: Edit items + none: |- + §aMove an item to here or + click to open the item editor. + itemSelect: + name: Choose item + npcCreate: + name: Create NPC + setName: §eEdit NPC name + setSkin: §eEdit NPC skin + setType: §eEdit NPC type + move: + itemName: §eMove + itemLore: §aChange the NPC location. + moveItem: §a§lValidate place + npcSelect: + name: Select or create? + selectStageNPC: §eSelect existing NPC + createStageNPC: §eCreate NPC + entityType: + name: Choose entity type + chooseQuest: + name: Which quest? + menu: §aQuests Menu + menuLore: Gets you to your Quests Menu. + mobs: + name: Select mobs + none: §aClick to add a mob. + clickLore: |- + §a§lLeft-click§a to edit amount. + §a§l§nShift§a§l + left-click§a to edit mob name. + §c§lRight-click§c to delete. + setLevel: Set minimum level + mobSelect: + name: Select mob type + bukkitEntityType: §eSelect entity type + mythicMob: §6Select Mythic Mob + epicBoss: §6Select Epic Boss + boss: §6Select a Boss + stageEnding: + locationTeleport: §eEdit teleport location + command: §eEdit executed command + requirements: + name: Requirements + setReason: Set custom reason + reason: '§8Custom reason: §7{reason}' + rewards: + name: Rewards + commands: 'Commands: {amount}' + teleportation: |- + §aSelected: + X: {0} + Y: {1} + Z: {2} + World: {3} + random: + rewards: Edit rewards + minMax: Edit min and max + checkpointActions: + name: Checkpoint actions + cancelActions: + name: Cancel actions + rewardsWithRequirements: + name: Rewards with requirements + listAllQuests: + name: Quests + listPlayerQuests: + name: '{player_name}''s quests' + listQuests: + notStarted: Not started quests + finished: Finished quests + inProgress: Quests in progress + loreDialogsHistoryClick: §7View the dialogs + loreCancelClick: §cCancel the quest + loreStart: §a§oClick to start the quest. + loreStartUnavailable: §c§oYou do not meet requirements to start the quest. + timeToWaitRedo: §3§oYou can restart this quest in {time_left}. + canRedo: §3§oYou can restart this quest! + timesFinished: §3Quest done {times_finished} times. + format: + normal: §6§l§o{quest_name} + withId: §6§l§o{quest_name}§r §e#{quest_id} + itemCreator: + name: Item creator + itemType: §bItem type + itemFlags: Toggle item flags + itemName: §bItem name + itemLore: §bItem lore + isQuestItem: '§bQuest item:' + command: + name: Command + value: §eCommand + console: Console + parse: Parse placeholders + delay: §bDelay + chooseAccount: + name: What account? + listBook: + questName: Name + questStarter: Starter + questRewards: Rewards + questMultiple: Several times + requirements: Requirements + questStages: Stages + noQuests: No quests have previously been created. + commandsList: + name: Command list + value: '§eCommand: {command_label}' + console: '§eConsole: {command_console}' + block: + name: Choose block + material: '§eMaterial: {block_type}' + materialNotItemLore: 'The block chosen cannot be displayed as an item. It is still correctly stored as {block_material}.' + blockName: '§bCustom block name' + blockData: '§dBlockdata (advanced)' + blockTag: '§dTag (advanced)' + blockTagLore: 'Choose a tag which describes a list of possible blocks. + Tags can be customized using datapacks. + You can find list of tags on the Minecraft wiki.' + blocksList: + name: Select blocks + addBlock: §aClick to add a block. + blockAction: + name: Select block action + location: §eSelect a precise location + material: §eSelect a block material + buckets: + name: Bucket type + permission: + name: Choose permission + perm: §aPermission + world: §aWorld + worldGlobal: §b§lGlobal + remove: Remove permission + removeLore: §7Permission will be taken off\n§7instead of given. + permissionList: + name: Permissions list + removed: '§eTaken off: §6{permission_removed}' + world: '§eWorld: §6{permission_world}' + classesRequired.name: Classes required + classesList.name: Classes list + factionsRequired.name: Factions required + factionsList.name: Factions list + poolsManage: + name: Quest Pools + itemName: '§aPool {pool}' + poolNPC: '§8NPC: §7{pool_npc_id}' + poolMaxQuests: '§8Max quests: §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Quests given per launch: §7{pool_quests_per_launch}' + poolRedo: '§8Can redo completed quests: §7{pool_redo}' + poolTime: '§8Time between quests: §7{pool_time}' + poolHologram: '§8Hologram text: §7{pool_hologram}' + poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' + poolQuestsList: '§7{0} §8quest(s): §7{pool_quests}' + create: §aCreate a quest pool + edit: §e> §6§oEdit the pool... §e< + choose: §e> §6§oChoose this pool §e< + poolCreation: + name: Quest pool creation + hologramText: §ePool custom hologram + maxQuests: §aMax quests + questsPerLaunch: §aQuests started per launch + time: §bSet time between quests + redoAllowed: Is redo allowed + avoidDuplicates: Avoid duplicates + avoidDuplicatesLore: §8> §7Try to avoid doing\n the same quest over and over + requirements: §bRequirements to start a quest + poolsList.name: Quest pools + itemComparisons: + name: Item Comparisons + bukkit: Bukkit native comparison + bukkitLore: 'Uses Bukkit default item comparison system.\nCompares material, durability, nbt tags...' + customBukkit: Bukkit native comparison - NO NBT + customBukkitLore: 'Uses Bukkit default item comparison system, but wipes out NBT tags.\nCompares material, durability...' + material: Item material + materialLore: 'Compares item material (i. e. stone, iron sword...)' + itemName: Item name + itemNameLore: Compares items names + itemLore: Item lore + itemLoreLore: Compares items lores + enchants: Items enchants + enchantsLore: Compares items enchants + repairCost: Repair cost + repairCostLore: Compares repair cost for armors and swords + itemsAdder: ItemsAdder + itemsAdderLore: Compares ItemsAdder IDs + editTitle: + name: Edit Title + title: §6Title + subtitle: §eSubtitle + fadeIn: §aFade-in duration + stay: §bStay duration + fadeOut: §aFade-out duration + particleEffect: + name: Create particle effect + shape: §dParticle shape + type: §eParticle type + color: §bParticle color + particleList: + name: Particles list + colored: Colored particle + damageCause: + name: Damage cause + damageCausesList: + name: Damage causes list + visibility: + name: Quest visibility + notStarted: '"Not started" menu tab' + inProgress: '"In progress" menu tab' + finished: '"Finished" menu tab' + maps: 'Maps (such as dynmap or BlueMap)' + equipmentSlots: + name: Equipment slots + questObjects: + setCustomDescription: 'Set custom description' + description: '§8Description: §7{description}' + +scoreboard: + name: §6§lQuests + noLaunched: §cNo quests in progress. + noLaunchedName: §c§lLoading + noLaunchedDescription: §c§oLoading + textBetwteenBranch: §e or + asyncEnd: §ex + stage: + region: §eFind region §6{region_id} + npc: §eTalk with NPC §6{dialog_npc_name} + items: '§eBring items to §6{dialog_npc_name}§e: {items}' + mobs: §eKill §6{mobs} + mine: §eMine {blocks} + placeBlocks: §ePlace {blocks} + chat: §eWrite §6{text} + interact: §eClick on the block at §6{0} + interactMaterial: §eClick on a §6{0}§e block + fish: §eFish §6{items} + melt: §eMelt §6{items} + enchant: §eEnchant §6{items} + craft: §eCraft §6{items} + bucket: §eFill §6{buckets} + location: §eGo to §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world} + playTimeFormatted: §ePlay §6{time_remaining_human} + breed: §eBreed §6{mobs} + tame: §eTame §6{mobs} + die: §cDie + dealDamage: + any: §cDeal {damage_remaining} damage + mobs: §cDeal {damage_remaining} damage to {target_mobs} + eatDrink: §eConsume §6{items} +indication: + startQuest: §7Do you want to start the quest {quest_name}? + closeInventory: §7Are you sure you want to close the GUI? + cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? + removeQuest: §7Are you sure you want to remove the quest {quest_name}? +description: + requirement: + title: '§8§lRequirements:' + level: 'Level {short_level}' + jobLevel: 'Level {short_level} for {job_name}' + combatLevel: 'Combat level {short_level}' + skillLevel: 'Level {short_level} for {skill_name}' + class: 'Class {class_name}' + faction: 'Faction {faction_name}' + quest: 'Finish quest §e{quest_name}' + reward: + title: '§8§lRewards:' + +misc: + format: + prefix: §6<§e§lQuests§r§6> §r + npcText: §6[{2}/{3}] §e§l{0}:§r§e {1} + selfText: §6[{2}/{3}] §e§l{0}:§r§e {1} + offText: §r§e{message} + editorPrefix: §a + errorPrefix: §4✖ §c + successPrefix: §2✔ §a + requirementNotMetPrefix: §c + time: + weeks: '{0} weeks' + days: '{0} days' + hours: '{0} hours' + minutes: '{0} minutes' + lessThanAMinute: 'less than a minute' + stageType: + region: Find region + npc: Find NPC + items: Bring back items + mobs: Kill mobs + mine: Break blocks + placeBlocks: Place blocks + chat: Write in chat + interact: Interact with block + Fish: Catch fishes + Melt: Melt items + Enchant: Enchant items + Craft: Craft item + Bucket: Fill bucket + location: Find location + playTime: Play time + breedAnimals: Breed animals + tameAnimals: Tame animals + die: Die + dealDamage: Deal damage + eatDrink: Eat or drink + comparison: + equals: equal to {number} + different: different to {number} + less: strictly less than {number} + lessOrEquals: less than {number} + greater: strictly greater than {number} + greaterOrEquals: greater than {number} + requirement: + logicalOr: §dLogical OR (requirements) + skillAPILevel: §bSkillAPI level required + class: §bClass(es) required + faction: §bFaction(s) required + jobLevel: §bJob level required + combatLevel: §bCombat level required + experienceLevel: §bExperience levels required + permissions: §3Permission(s) required + scoreboard: §dScore required + region: §dRegion required + placeholder: §bPlaceholder value required + quest: §aQuest required + mcMMOSkillLevel: §dSkill level required + money: §dMoney required + equipment: §eEquipment required + bucket: + water: Water bucket + lava: Lava bucket + milk: Milk bucket + snow: Snow bucket + click: + right: Right click + left: Left click + shift-right: Shift-right click + shift-left: Shift-left click + middle: Middle click + amounts: + items: '{items_amount} item(s)' + comparisons: '{comparisons_amount} comparaison(s)' + dialogLines: '{lines_amount} line(s)' + permissions: '{permissions_amount} permission(s)' + mobs: '{mobs_amount} mob(s)' + xp: '{xp_amount} experience point(s)' + ticks: '{ticks} ticks' + questItemLore: §e§oQuest Item + hologramText: §8§lQuest NPC + poolHologramText: §eNew quest available! + entityType: '§eEntity type: {0}' + entityTypeAny: §eAny entity + enabled: Enabled + disabled: Disabled + unknown: unknown + notSet: §cnot set + unused: §2§lUnused + used: §a§lUsed + remove: §7Middle-click to remove + removeRaw: Remove + reset: Reset + or: or + amount: '§eAmount: {amount}' + 'yes': 'Yes' + 'no': 'No' + and: and From 207db9445a96bc0e3534478b4c9d8d0480608a7a Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 6 Aug 2023 11:09:56 +0200 Subject: [PATCH 29/95] :construction: Finished progress placeholders and bar --- .../quests/api/QuestsConfiguration.java | 13 +- .../skytasul/quests/api/gui/GuiFactory.java | 5 + .../quests/api/stages/AbstractStage.java | 7 +- .../quests/api/stages/StageHandler.java | 15 +- .../quests/api/stages/StageTypeRegistry.java | 23 ++- .../options/StageOptionAutoRegister.java | 14 ++ .../stages/types/AbstractCountableStage.java | 135 +------------ .../api/stages/types/AbstractEntityStage.java | 15 +- .../utils/messaging/PlaceholderRegistry.java | 16 +- .../types => utils/progress}/HasProgress.java | 2 +- .../api/utils/progress/ProgressBarConfig.java | 11 + .../ProgressPlaceholders.java} | 100 +++++---- .../HasItemsDescriptionConfiguration.java | 40 +--- .../ItemsDescriptionConfiguration.java | 2 +- .../java/fr/skytasul/quests/BeautyQuests.java | 2 + .../skytasul/quests/DefaultQuestFeatures.java | 93 ++++++++- .../QuestsConfigurationImplementation.java | 56 +++--- .../quests/gui/DefaultGuiFactory.java | 9 + .../skytasul/quests/gui/npc/NpcCreateGUI.java | 5 +- .../quests/stages/StageBringBack.java | 8 +- .../skytasul/quests/stages/StageBucket.java | 8 +- .../fr/skytasul/quests/stages/StageCraft.java | 6 +- .../quests/stages/StageDealDamage.java | 15 +- .../skytasul/quests/stages/StagePlayTime.java | 17 +- .../options/StageOptionProgressBar.java | 189 ++++++++++++++++++ .../BranchesManagerImplementation.java | 2 +- .../structure/QuestBranchImplementation.java | 2 +- .../StageControllerImplementation.java | 4 +- .../compatibility/mobs/BQLevelledMobs.java | 5 +- .../mobs/BukkitEntityFactory.java | 4 +- core/src/main/resources/config.yml | 4 +- 31 files changed, 523 insertions(+), 304 deletions(-) create mode 100755 api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java rename api/src/main/java/fr/skytasul/quests/api/{stages/types => utils/progress}/HasProgress.java (81%) create mode 100755 api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressBarConfig.java rename api/src/main/java/fr/skytasul/quests/api/utils/{itemdescription/ItemsDescriptionPlaceholders.java => progress/ProgressPlaceholders.java} (57%) rename api/src/main/java/fr/skytasul/quests/api/utils/{ => progress}/itemdescription/HasItemsDescriptionConfiguration.java (63%) rename api/src/main/java/fr/skytasul/quests/api/utils/{ => progress}/itemdescription/ItemsDescriptionConfiguration.java (87%) create mode 100755 core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java index 983970e3..f08b1c84 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -8,7 +8,8 @@ import fr.skytasul.quests.api.npcs.NpcClickType; import fr.skytasul.quests.api.options.description.QuestDescription; import fr.skytasul.quests.api.utils.PlayerListCategory; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionConfiguration; +import fr.skytasul.quests.api.utils.progress.ProgressBarConfig; +import fr.skytasul.quests.api.utils.progress.itemdescription.ItemsDescriptionConfiguration; public interface QuestsConfiguration { @@ -53,10 +54,6 @@ interface Quests { boolean fireworks(); - boolean mobsProgressBar(); - - int progressBarTimeoutSeconds(); - Collection<NpcClickType> getNpcClicks(); boolean skipNpcGuiIfOnlyOneQuest(); @@ -109,14 +106,10 @@ interface QuestsMenu { } - interface StageDescription extends ItemsDescriptionConfiguration { + interface StageDescription extends ItemsDescriptionConfiguration, ProgressBarConfig { String getStageDescriptionFormat(); - boolean areBossBarsEnabled(); - - String getBossBarFormat(); - } } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java index 07e7cdf9..096b6b70 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java @@ -4,6 +4,8 @@ import java.util.Collection; import java.util.List; import java.util.function.Consumer; +import java.util.function.Predicate; +import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,4 +60,7 @@ default Gui createConfirmation(@Nullable Runnable yes, @Nullable Runnable no, @N Gui createConfirmation(@Nullable Runnable yes, @Nullable Runnable no, @NotNull String indication, @Nullable List<@Nullable String> lore); + @NotNull + Gui createEntityTypeSelection(@NotNull Consumer<EntityType> callback, @Nullable Predicate<@NotNull EntityType> filter); + } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 20bfcbc3..10b4d38d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -29,7 +29,7 @@ public abstract class AbstractStage implements HasPlaceholders { private @Nullable String customText = null; private @NotNull RewardList rewards = new RewardList(); private @NotNull RequirementList validationRequirements = new RequirementList(); - + private @NotNull List<@NotNull StageOption> options; private @Nullable PlaceholderRegistry placeholders; @@ -74,11 +74,11 @@ public void setValidationRequirements(@NotNull RequirementList validationRequire this.validationRequirements = validationRequirements; validationRequirements.attachQuest(getQuest()); } - + public @NotNull List<@NotNull StageOption> getOptions() { return options; } - + public void setOptions(@NotNull List<@NotNull StageOption> options) { this.options = options; } @@ -109,6 +109,7 @@ public boolean hasAsyncEnd() { } protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + placeholders.compose(false, controller.getBranch().getQuest()); placeholders.register("stage_type", controller.getStageType().getName()); placeholders.register("stage_rewards", rewards.getSizeString()); placeholders.register("stage_requirements", validationRequirements.getSizeString()); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java index 9eb3ff81..e209b8b7 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageHandler.java @@ -1,20 +1,23 @@ package fr.skytasul.quests.api.stages; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.players.PlayerAccount; public interface StageHandler { - default void stageStart(PlayerAccount acc, StageController stage) {} + default void stageStart(@NotNull PlayerAccount acc, @NotNull StageController stage) {} - default void stageEnd(PlayerAccount acc, StageController stage) {} + default void stageEnd(@NotNull PlayerAccount acc, @NotNull StageController stage) {} - default void stageJoin(Player p, StageController stage) {} + default void stageJoin(@NotNull Player p, @NotNull StageController stage) {} - default void stageLeave(Player p, StageController stage) {} + default void stageLeave(@NotNull Player p, @NotNull StageController stage) {} - default void stageLoad(StageController stage) {} + default void stageLoad(@NotNull StageController stage) {} - default void stageUnload(StageController stage) {} + default void stageUnload(@NotNull StageController stage) {} + default void stageUpdated(@NotNull Player player, @NotNull StageController stage) {} + } \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java index 4b15b130..b48fea72 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java @@ -1,16 +1,18 @@ package fr.skytasul.quests.api.stages; +import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; public class StageTypeRegistry implements Iterable<StageType<?>> { - private @NotNull List<@NotNull StageType<?>> types = new LinkedList<>(); + private final @NotNull List<@NotNull StageType<?>> types = new ArrayList<>(); + private final @NotNull List<@NotNull StageOptionAutoRegister> autoRegisteringOptions = new ArrayList<>(2); /** * Registers new stage type into the plugin. @@ -20,8 +22,25 @@ public void register(@NotNull StageType<? extends AbstractStage> type) { Validate.notNull(type); types.add(type); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Stage registered (" + type.getName() + ", " + (types.size() - 1) + ")"); + applyAutoregisteringOptions(type); } + private <T extends AbstractStage> void applyAutoregisteringOptions(@NotNull StageType<T> type) { + for (StageOptionAutoRegister autoRegister : autoRegisteringOptions) { + if (autoRegister.appliesTo(type)) + type.getOptionsRegistry().register(autoRegister.createOptionCreator(type)); + } + } + + public void autoRegisterOption(@NotNull StageOptionAutoRegister autoRegister) { + Validate.notNull(autoRegister); + autoRegisteringOptions.add(autoRegister); + + for (StageType<?> type : types) { + applyAutoregisteringOptions(type); + } + } + public @NotNull List<@NotNull StageType<?>> getTypes() { return types; } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java new file mode 100755 index 00000000..d389217c --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java @@ -0,0 +1,14 @@ +package fr.skytasul.quests.api.stages.options; + +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.serializable.SerializableCreator; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageType; + +public interface StageOptionAutoRegister { + + boolean appliesTo(@NotNull StageType<?> type); + + <T extends AbstractStage> SerializableCreator<StageOption<T>> createOptionCreator(@NotNull StageType<T> type); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index ad136a3e..60663a18 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -8,43 +8,30 @@ import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; -import org.bukkit.Bukkit; -import org.bukkit.boss.BarColor; -import org.bukkit.boss.BarStyle; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; -import fr.skytasul.quests.api.BossBarManager.BQBossBar; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasMultipleObjects; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasMultipleObjects; public abstract class AbstractCountableStage<T> extends AbstractStage implements HasMultipleObjects<T> { protected final @NotNull List<@NotNull CountableObject<T>> objects; - protected @NotNull Map<Player, BossBar> bars = new HashMap<>(); - private boolean barsEnabled = false; - private int cachedSize = 0; - protected AbstractCountableStage(@NotNull StageController controller, @NotNull List<@NotNull CountableObject<T>> objects) { super(controller); this.objects = objects; - calculateSize(); } @Override @@ -130,11 +117,16 @@ public int getPlayerAmount(@NotNull PlayerAccount account, CountableObject<T> ob } @Override - public int getTotalPlayerAmount(@NotNull PlayerAccount account) { + public int getPlayerAmount(@NotNull PlayerAccount account) { // same as in getPlayerAmount return getPlayerRemainings(account, false).values().stream().mapToInt(Integer::intValue).sum(); } + @Override + public int getTotalAmount() { + return objects.stream().mapToInt(CountableObject::getAmount).sum(); + } + @Override public @NotNull String getObjectName(CountableObject<T> object) { return getName(object.getObject()); @@ -145,15 +137,10 @@ protected void updatePlayerRemaining(@NotNull Player player, @NotNull Map<@NotNu .collect(Collectors.toMap(entry -> entry.getKey().toString(), Entry::getValue))); } - protected void calculateSize() { - cachedSize = objects.stream().mapToInt(CountableObject::getAmount).sum(); - barsEnabled = QuestsConfiguration.getConfig().getQuestsConfig().mobsProgressBar() && cachedSize > 0; - } - @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); - ItemsDescriptionPlaceholders.register(placeholders, getPlaceholderKey(), this); + ProgressPlaceholders.registerObjects(placeholders, getPlaceholderKey(), this); } @Override @@ -196,13 +183,6 @@ public boolean event(@NotNull Player p, @UnknownNullability Object object, int a finishStage(p); return true; }else { - if (barsEnabled) { - BossBar bar = bars.get(p); - if (bar == null) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning(p.getName() + " does not have boss bar for stage " + toString() + ". This is a bug!"); - }else bar.update(playerAmounts.values().stream().mapToInt(Integer::intValue).sum()); - } - updatePlayerRemaining(p, playerAmounts); return false; } @@ -211,52 +191,6 @@ public boolean event(@NotNull Player p, @UnknownNullability Object object, int a return false; } - @Override - public void started(@NotNull PlayerAccount acc) { - super.started(acc); - if (acc.isCurrent()) createBar(acc.getPlayer(), cachedSize); - } - - @Override - public void ended(@NotNull PlayerAccount acc) { - super.ended(acc); - if (acc.isCurrent()) removeBar(acc.getPlayer()); - } - - @Override - public void unload() { - super.unload(); - bars.values().forEach(BossBar::remove); - } - - @Override - public void joined(@NotNull Player p) { - super.joined(p); - Map<UUID, Integer> remainings = getPlayerRemainings(PlayersManager.getPlayerAccount(p), true); - if (remainings == null) return; - createBar(p, remainings.values().stream().mapToInt(Integer::intValue).sum()); - } - - @Override - public void left(@NotNull Player p) { - super.left(p); - removeBar(p); - } - - protected void createBar(@NotNull Player p, int amount) { - if (barsEnabled) { - if (bars.containsKey(p)) { // NOSONAR Map#computeIfAbsent cannot be used here as we should log the issue - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Trying to create an already existing bossbar for player " + p.getName()); - return; - } - bars.put(p, new BossBar(p, amount)); - } - } - - protected void removeBar(@NotNull Player p) { - if (bars.containsKey(p)) bars.remove(p).remove(); - } - protected boolean objectApplies(@NotNull T object, @UnknownNullability Object other) { return object.equals(other); } @@ -302,7 +236,6 @@ protected void deserialize(@NotNull ConfigurationSection section) { } if (objects.isEmpty()) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Stage with no content: " + toString()); - calculateSize(); } private static UUID uuidFromLegacyIndex(int index) { // useful for migration purpose @@ -311,54 +244,4 @@ private static UUID uuidFromLegacyIndex(int index) { // useful for migration pur // and I like the number 2478 } - class BossBar { - private Player p; - private BQBossBar bar; - private BukkitTask timer; - - public BossBar(Player p, int amount) { - this.p = p; - - BarStyle style = null; - if (cachedSize % 20 == 0) { - style = BarStyle.SEGMENTED_20; - }else if (cachedSize % 10 == 0) { - style = BarStyle.SEGMENTED_10; - }else if (cachedSize % 12 == 0) { - style = BarStyle.SEGMENTED_12; - }else if (cachedSize % 6 == 0) { - style = BarStyle.SEGMENTED_6; - }else style = BarStyle.SOLID; - bar = QuestsAPI.getAPI().getBossBarManager() - .buildBossBar(Lang.MobsProgression.format(getQuest().getName(), 100, 100), BarColor.YELLOW, style); - update(amount); - } - - public void remove() { - bar.removeAll(); - if (timer != null) timer.cancel(); - } - - public void update(int amount) { - if (amount >= 0 && amount <= cachedSize) { - bar.setProgress((double) (cachedSize - amount) / (double) cachedSize); - }else QuestsPlugin.getPlugin().getLoggerExpanded().warning("Amount of objects superior to max objects in " + AbstractCountableStage.this.toString() + " for player " + p.getName() + ": " + amount + " > " + cachedSize); - bar.setTitle(Lang.MobsProgression.format(getQuest().getName(), cachedSize - amount, cachedSize)); - bar.addPlayer(p); - timer(); - } - - private void timer() { - if (QuestsConfiguration.getConfig().getQuestsConfig().progressBarTimeoutSeconds() <= 0) - return; - if (timer != null) - timer.cancel(); - - timer = Bukkit.getScheduler().runTaskLater(QuestsPlugin.getPlugin(), () -> { - bar.removePlayer(p); - timer = null; - }, QuestsConfiguration.getConfig().getQuestsConfig().progressBarTimeoutSeconds() * 20L); - } - } - } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index 65e6e00a..534c10bf 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -29,9 +29,9 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.MinecraftNames; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; @LocatableType (types = LocatedType.ENTITY) public abstract class AbstractEntityStage extends AbstractStage implements Locatable.MultipleLocatable, HasSingleObject { @@ -96,7 +96,7 @@ protected void serialize(@NotNull ConfigurationSection section) { @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); - ItemsDescriptionPlaceholders.register(placeholders, "mobs", this); + ProgressPlaceholders.registerObject(placeholders, "mobs", this); } @Override @@ -135,13 +135,13 @@ public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); line.setItem(6, ItemUtils.item(XMaterial.CHICKEN_SPAWN_EGG, Lang.changeEntityType.toString()), event -> { - new EntityTypeGUI(x -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createEntityTypeSelection(x -> { setEntity(x); event.reopen(); }, x -> x == null ? canBeAnyEntity() : canUseEntity(x)).open(event.getPlayer()); }); - line.setItem(7, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.format(1)), event -> { + line.setItem(7, ItemUtils.item(XMaterial.REDSTONE, Lang.Amount.quickFormat("amount", 1)), event -> { new TextEditor<>(event.getPlayer(), event::reopen, x -> { setAmount(x); event.reopen(); @@ -151,13 +151,12 @@ public void setupLine(@NotNull StageGuiLine line) { public void setEntity(EntityType entity) { this.entity = entity; - getLine().refreshItemLore(6, - Lang.optionValue.format(entity == null ? Lang.EntityTypeAny.toString() : entity.name())); + getLine().refreshItemLoreOptionValue(6, entity == null ? Lang.EntityTypeAny.toString() : entity.name()); } public void setAmount(int amount) { this.amount = amount; - getLine().refreshItemName(7, Lang.Amount.format(amount)); + getLine().refreshItemName(7, Lang.Amount.quickFormat("amount", amount)); } @Override diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java index c624aa73..58d589ab 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java @@ -97,12 +97,26 @@ public boolean hasPlaceholder(@NotNull String key) { } /** - * Adds all the placeholders from the passed placeholders holders to this placeholders registry. + * Adds all the placeholders from the passed placeholders holders to this placeholders registry and + * keeps indexed placeholders. * * @param placeholdersHolders holders to get the placeholders from * @return this placeholder registry */ public @NotNull PlaceholderRegistry compose(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { + return compose(true, placeholdersHolders); + } + + /** + * Adds all the placeholders from the passed placeholders holders to this placeholders registry. + * + * @param withIndexes should the indexed placeholders of the passed placeholders holders be kept as + * indexed + * @param placeholdersHolders holders to get the placeholders from + * @return this placeholder registry + */ + public @NotNull PlaceholderRegistry compose(boolean withIndexes, + @NotNull HasPlaceholders @NotNull... placeholdersHolders) { for (HasPlaceholders holder : placeholdersHolders) { this.placeholders.addAll(holder.getPlaceholdersRegistry().placeholders); if (!holder.getPlaceholdersRegistry().indexed.isEmpty()) diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/HasProgress.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/HasProgress.java similarity index 81% rename from api/src/main/java/fr/skytasul/quests/api/stages/types/HasProgress.java rename to api/src/main/java/fr/skytasul/quests/api/utils/progress/HasProgress.java index e7444b4d..7813f3c5 100755 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/HasProgress.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/HasProgress.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.stages.types; +package fr.skytasul.quests.api.utils.progress; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.players.PlayerAccount; diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressBarConfig.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressBarConfig.java new file mode 100755 index 00000000..473c2cee --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressBarConfig.java @@ -0,0 +1,11 @@ +package fr.skytasul.quests.api.utils.progress; + +public interface ProgressBarConfig { + + boolean areBossBarsEnabled(); + + String getBossBarFormat(); + + int getBossBarTimeout(); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionPlaceholders.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java similarity index 57% rename from api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionPlaceholders.java rename to api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java index 88b7cf69..ae41dd6d 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionPlaceholders.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.utils.itemdescription; +package fr.skytasul.quests.api.utils.progress; import java.util.Map; import org.bukkit.entity.Player; @@ -8,45 +8,59 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.utils.CountableObject; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasMultipleObjects; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.Placeholder; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration; +import fr.skytasul.quests.api.utils.progress.itemdescription.ItemsDescriptionConfiguration; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasMultipleObjects; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; + +public final class ProgressPlaceholders { + + private static final PlaceholderRegistry PROGRESS_REGISTRY = new PlaceholderRegistry() + .registerIndexedContextual("remaining", ProgressPlaceholderContext.class, + context -> Integer.toString(context.getProgress().getPlayerAmount(context.getPlayerAccount()))) + .registerIndexedContextual("done", ProgressPlaceholderContext.class, + context -> Integer.toString(context.getProgress().getTotalAmount() + - context.getProgress().getPlayerAmount(context.getPlayerAccount()))) + .registerIndexedContextual("amount", ProgressPlaceholderContext.class, + context -> Integer.toString(context.getProgress().getTotalAmount())) + .registerIndexedContextual("percentage", ProgressPlaceholderContext.class, + context -> Integer.toString((int) (context.getProgress().getPlayerAmount(context.getPlayerAccount()) + * 100D / context.getProgress().getTotalAmount()))); + private static final PlaceholderRegistry DESCRIPTION_REGISTRY = PROGRESS_REGISTRY.with(new PlaceholderRegistry() + .registerIndexedContextual("name", ProgressObjectPlaceholderContext.class, + context -> context.getProgress().getObjectName())); + + private ProgressPlaceholders() {} + + public static void registerProgress(@NotNull PlaceholderRegistry placeholders, @NotNull String key, + @NotNull HasProgress progress) { + placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|amount|percentage)", + PlayerPlaceholdersContext.class, (matcher, context) -> { + return PROGRESS_REGISTRY.resolve(matcher.group(1), new ProgressPlaceholderContext( + context.getActor(), context.replacePluginPlaceholders(), progress)); + })); + } -public final class ItemsDescriptionPlaceholders { - - private static final PlaceholderRegistry DESCRIPTION_REGISTRY = new PlaceholderRegistry() - .registerIndexedContextual("remaining", DescriptionPlaceholderContext.class, - context -> Integer.toString(context.getItem().getPlayerAmount(context.getPlayerAccount()))) - .registerIndexedContextual("done", DescriptionPlaceholderContext.class, - context -> Integer.toString(context.getItem().getObjectAmount() - - context.getItem().getPlayerAmount(context.getPlayerAccount()))) - .registerIndexedContextual("amount", DescriptionPlaceholderContext.class, - context -> Integer.toString(context.getItem().getObjectAmount())) - .registerIndexedContextual("percentage", DescriptionPlaceholderContext.class, - context -> Integer.toString((int) (context.getItem().getPlayerAmount(context.getPlayerAccount()) * 100D - / context.getItem().getObjectAmount()))) - .registerIndexedContextual("name", DescriptionPlaceholderContext.class, - context -> context.getItem().getObjectName()); - - private ItemsDescriptionPlaceholders() {} - - public static void register(@NotNull PlaceholderRegistry placeholders, @NotNull String key, + public static void registerObject(@NotNull PlaceholderRegistry placeholders, @NotNull String key, @NotNull HasSingleObject object) { placeholders.registerIndexedContextual(key, PlayerPlaceholdersContext.class, context -> formatObject(object, context)); placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|amount|percentage|name)", PlayerPlaceholdersContext.class, (matcher, context) -> { - return DESCRIPTION_REGISTRY.resolve(matcher.group(1), new DescriptionPlaceholderContext( + return DESCRIPTION_REGISTRY.resolve(matcher.group(1), new ProgressObjectPlaceholderContext( context.getActor(), context.replacePluginPlaceholders(), object)); })); } - public static <T> void register(@NotNull PlaceholderRegistry placeholders, @NotNull String key, + public static <T> void registerObjects(@NotNull PlaceholderRegistry placeholders, @NotNull String key, @NotNull HasMultipleObjects<T> objects) { + registerProgress(placeholders, key, objects); + placeholders.registerIndexedContextual(key, StageDescriptionPlaceholdersContext.class, context -> { Map<CountableObject<T>, Integer> amounts = objects.getPlayerAmounts(context.getPlayerAccount()); String[] objectsDescription = amounts.entrySet().stream() @@ -56,12 +70,6 @@ public static <T> void register(@NotNull PlaceholderRegistry placeholders, @NotN objectsDescription); }); - placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|amount|percentage)", - PlayerPlaceholdersContext.class, (matcher, context) -> { - return DESCRIPTION_REGISTRY.resolve(matcher.group(1), new DescriptionPlaceholderContext( - context.getActor(), context.replacePluginPlaceholders(), objects.asTotalObject())); - })); - placeholders.register(Placeholder.ofPatternContextual(key + "_(\\d+)(?:_(remaining|done|amount|percentage))?", PlayerPlaceholdersContext.class, (matcher, context) -> { int index = Integer.parseInt(matcher.group(1)); @@ -75,7 +83,7 @@ public static <T> void register(@NotNull PlaceholderRegistry placeholders, @NotN if (operation == null) return formatObject(item, context); - return DESCRIPTION_REGISTRY.resolve(operation, new DescriptionPlaceholderContext(context.getActor(), + return DESCRIPTION_REGISTRY.resolve(operation, new ProgressObjectPlaceholderContext(context.getActor(), context.replacePluginPlaceholders(), item)); })); } @@ -110,7 +118,7 @@ public int getObjectAmount() { ? object.getItemsDescriptionConfiguration().getMultipleItemsFormat() : object.getItemsDescriptionConfiguration().getSingleItemFormat(); return MessageUtils.format(formatString, DESCRIPTION_REGISTRY, - new DescriptionPlaceholderContext(context.getActor(), context.replacePluginPlaceholders(), object)); + new ProgressObjectPlaceholderContext(context.getActor(), context.replacePluginPlaceholders(), object)); } public static @NotNull String formatObjectList(@NotNull DescriptionSource source, @@ -122,17 +130,17 @@ public int getObjectAmount() { return String.join(configuration.getSplitPrefix(), elements); } - private static class DescriptionPlaceholderContext implements PlayerPlaceholdersContext { + private static class ProgressPlaceholderContext implements PlayerPlaceholdersContext { private final @NotNull Player player; private final boolean replacePluginPlaceholders; - private final @NotNull HasSingleObject item; + private final @NotNull HasProgress progress; - public DescriptionPlaceholderContext(@NotNull Player player, boolean replacePluginPlaceholders, - @NotNull HasSingleObject item) { + public ProgressPlaceholderContext(@NotNull Player player, boolean replacePluginPlaceholders, + @NotNull HasProgress progress) { this.player = player; this.replacePluginPlaceholders = replacePluginPlaceholders; - this.item = item; + this.progress = progress; } @Override @@ -145,8 +153,22 @@ public boolean replacePluginPlaceholders() { return replacePluginPlaceholders; } - public @NotNull HasSingleObject getItem() { - return item; + public @NotNull HasProgress getProgress() { + return progress; + } + + } + + private static class ProgressObjectPlaceholderContext extends ProgressPlaceholderContext { + + public ProgressObjectPlaceholderContext(@NotNull Player player, boolean replacePluginPlaceholders, + @NotNull HasSingleObject object) { + super(player, replacePluginPlaceholders, object); + } + + @Override + public @NotNull HasSingleObject getProgress() { + return (@NotNull HasSingleObject) super.getProgress(); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/HasItemsDescriptionConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/HasItemsDescriptionConfiguration.java similarity index 63% rename from api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/HasItemsDescriptionConfiguration.java rename to api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/HasItemsDescriptionConfiguration.java index ebeb2976..ecad9e0b 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/HasItemsDescriptionConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/HasItemsDescriptionConfiguration.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.utils.itemdescription; +package fr.skytasul.quests.api.utils.progress.itemdescription; import java.util.Collection; import java.util.Map; @@ -6,8 +6,8 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.stages.types.HasProgress; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.progress.HasProgress; public interface HasItemsDescriptionConfiguration { @@ -33,7 +33,7 @@ default int getTotalAmount() { } - public interface HasMultipleObjects<T> extends HasItemsDescriptionConfiguration { + public interface HasMultipleObjects<T> extends HasItemsDescriptionConfiguration, HasProgress { @NotNull Collection<CountableObject<T>> getObjects(); @@ -48,36 +48,18 @@ public interface HasMultipleObjects<T> extends HasItemsDescriptionConfiguration @NotNull Map<CountableObject<T>, Integer> getPlayerAmounts(@NotNull PlayerAccount account); - default int getTotalPlayerAmount(@NotNull PlayerAccount account) { - return getPlayerAmounts(account).values().stream().mapToInt(Integer::intValue).sum(); - } - default int getPlayerAmount(@NotNull PlayerAccount account, CountableObject<T> object) { return getPlayerAmounts(account).get(object); } - default @NotNull HasSingleObject asTotalObject() { - return new HasSingleObject() { - @Override - public @NotNull ItemsDescriptionConfiguration getItemsDescriptionConfiguration() { - return getItemsDescriptionConfiguration(); - } - - @Override - public int getPlayerAmount(@NotNull PlayerAccount account) { - return getTotalPlayerAmount(account); - } - - @Override - public @NotNull String getObjectName() { - return "total"; - } - - @Override - public int getObjectAmount() { - return getObjects().stream().mapToInt(CountableObject::getAmount).sum(); - } - }; + @Override + default int getPlayerAmount(@NotNull PlayerAccount account) { + return getPlayerAmounts(account).values().stream().mapToInt(Integer::intValue).sum(); + } + + @Override + default int getTotalAmount() { + return getObjects().stream().mapToInt(CountableObject::getAmount).sum(); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/ItemsDescriptionConfiguration.java similarity index 87% rename from api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionConfiguration.java rename to api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/ItemsDescriptionConfiguration.java index f8778266..abc31e36 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/itemdescription/ItemsDescriptionConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/ItemsDescriptionConfiguration.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.utils.itemdescription; +package fr.skytasul.quests.api.utils.progress.itemdescription; import java.util.Set; import org.jetbrains.annotations.NotNull; diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index d0430ef4..15f079ab 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -409,6 +409,8 @@ private void loadConfigParameters(boolean init) throws LoadingException { DefaultQuestFeatures.registerRewards(); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default requirements."); DefaultQuestFeatures.registerRequirements(); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default stage options."); + DefaultQuestFeatures.registerStageOptions(); getServer().getPluginManager().registerEvents(guiManager = new GuiManagerImplementation(), this); getServer().getPluginManager().registerEvents(editorManager = new EditorManagerImplementation(), this); getAPI().registerMobFactory(new BukkitEntityFactory()); diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index 2c65d6a7..6fdc5d0c 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -5,6 +5,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.Repairable; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; @@ -17,19 +18,81 @@ import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.rewards.RewardCreator; import fr.skytasul.quests.api.rewards.RewardList; +import fr.skytasul.quests.api.serializable.SerializableCreator; +import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.stages.options.StageOption; +import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.options.*; +import fr.skytasul.quests.api.utils.progress.HasProgress; +import fr.skytasul.quests.options.OptionAutoQuest; +import fr.skytasul.quests.options.OptionBypassLimit; +import fr.skytasul.quests.options.OptionCancelRewards; +import fr.skytasul.quests.options.OptionCancellable; +import fr.skytasul.quests.options.OptionConfirmMessage; +import fr.skytasul.quests.options.OptionDescription; +import fr.skytasul.quests.options.OptionEndMessage; +import fr.skytasul.quests.options.OptionEndRewards; +import fr.skytasul.quests.options.OptionEndSound; +import fr.skytasul.quests.options.OptionFailOnDeath; +import fr.skytasul.quests.options.OptionFirework; +import fr.skytasul.quests.options.OptionHideNoRequirements; +import fr.skytasul.quests.options.OptionHologramLaunch; +import fr.skytasul.quests.options.OptionHologramLaunchNo; +import fr.skytasul.quests.options.OptionHologramText; +import fr.skytasul.quests.options.OptionName; +import fr.skytasul.quests.options.OptionQuestItem; +import fr.skytasul.quests.options.OptionQuestPool; +import fr.skytasul.quests.options.OptionRepeatable; +import fr.skytasul.quests.options.OptionRequirements; +import fr.skytasul.quests.options.OptionScoreboardEnabled; +import fr.skytasul.quests.options.OptionStartDialog; +import fr.skytasul.quests.options.OptionStartMessage; +import fr.skytasul.quests.options.OptionStartRewards; +import fr.skytasul.quests.options.OptionStartable; +import fr.skytasul.quests.options.OptionStarterNPC; +import fr.skytasul.quests.options.OptionTimer; +import fr.skytasul.quests.options.OptionVisibility; import fr.skytasul.quests.requirements.EquipmentRequirement; import fr.skytasul.quests.requirements.LevelRequirement; import fr.skytasul.quests.requirements.PermissionsRequirement; import fr.skytasul.quests.requirements.QuestRequirement; import fr.skytasul.quests.requirements.ScoreboardRequirement; import fr.skytasul.quests.requirements.logical.LogicalOrRequirement; -import fr.skytasul.quests.rewards.*; -import fr.skytasul.quests.stages.*; +import fr.skytasul.quests.rewards.CheckpointReward; +import fr.skytasul.quests.rewards.CommandReward; +import fr.skytasul.quests.rewards.ItemReward; +import fr.skytasul.quests.rewards.MessageReward; +import fr.skytasul.quests.rewards.QuestStopReward; +import fr.skytasul.quests.rewards.RandomReward; +import fr.skytasul.quests.rewards.RemoveItemsReward; +import fr.skytasul.quests.rewards.RequirementDependentReward; +import fr.skytasul.quests.rewards.TeleportationReward; +import fr.skytasul.quests.rewards.TitleReward; +import fr.skytasul.quests.rewards.WaitReward; +import fr.skytasul.quests.rewards.XPReward; +import fr.skytasul.quests.stages.StageBreed; +import fr.skytasul.quests.stages.StageBringBack; +import fr.skytasul.quests.stages.StageBucket; +import fr.skytasul.quests.stages.StageChat; +import fr.skytasul.quests.stages.StageCraft; +import fr.skytasul.quests.stages.StageDealDamage; +import fr.skytasul.quests.stages.StageDeath; +import fr.skytasul.quests.stages.StageEatDrink; +import fr.skytasul.quests.stages.StageEnchant; +import fr.skytasul.quests.stages.StageFish; +import fr.skytasul.quests.stages.StageInteract; +import fr.skytasul.quests.stages.StageLocation; +import fr.skytasul.quests.stages.StageMelt; +import fr.skytasul.quests.stages.StageMine; +import fr.skytasul.quests.stages.StageMobs; +import fr.skytasul.quests.stages.StageNPC; +import fr.skytasul.quests.stages.StagePlaceBlocks; +import fr.skytasul.quests.stages.StagePlayTime; +import fr.skytasul.quests.stages.StageTame; +import fr.skytasul.quests.stages.options.StageOptionProgressBar; public final class DefaultQuestFeatures { @@ -96,6 +159,30 @@ public static void registerStages() { StageEatDrink::new, stageEatDrink, StageEatDrink.Creator::new)); } + public static void registerStageOptions() { + QuestsAPI.getAPI().getStages().autoRegisterOption(new StageOptionAutoRegister() { + + @Override + public boolean appliesTo(@NotNull StageType<?> type) { + return HasProgress.class.isAssignableFrom(type.getStageClass()); + } + + @Override + public <T extends AbstractStage> SerializableCreator<StageOption<T>> createOptionCreator( + @NotNull StageType<T> type) { + return createCreator((StageType) type); + } + + public <T extends AbstractStage & HasProgress> SerializableCreator<StageOptionProgressBar<T>> createCreator( + @NotNull StageType<T> type) { + return new SerializableCreator<>("progressbar", StageOptionProgressBar.class, + () -> new StageOptionProgressBar<>(type.getStageClass())); + + } + + }); + } + public static void registerQuestOptions() { QuestsAPI.getAPI() .registerQuestOption(new QuestOptionCreator<>("pool", 9, OptionQuestPool.class, OptionQuestPool::new, null)); diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 9a0b3d23..ee2c2424 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -17,7 +17,6 @@ import org.bukkit.inventory.meta.FireworkMeta; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; @@ -203,10 +202,11 @@ private String loadSound(String key) { return sound; } - private boolean migrateEntry(ConfigurationSection config, ConfigurationSection migrateFrom, String key, String migrateKey) { - if (migrateFrom.contains(migrateKey)) { - config.set(key, migrateFrom.get(migrateKey)); - migrateFrom.set(migrateKey, null); + private boolean migrateEntry(ConfigurationSection oldConfig, String oldKey, ConfigurationSection newConfig, + String newKey) { + if (oldConfig.contains(oldKey)) { + newConfig.set(newKey, oldConfig.get(oldKey)); + oldConfig.set(oldKey, null); return true; } return false; @@ -351,8 +351,6 @@ public class QuestsConfig implements QuestsConfiguration.Quests { private boolean questConfirmGUI = false; private Collection<NpcClickType> npcClicks = Arrays.asList(NpcClickType.RIGHT, NpcClickType.SHIFT_RIGHT); private boolean skipNpcGuiIfOnlyOneQuest = true; - private boolean mobsProgressBar = false; - private int progressBarTimeoutSeconds = 15; private boolean requirementReasonOnMultipleQuests = true; private boolean stageEndRewardsMessage = true; @@ -397,8 +395,6 @@ private void init() { .warning("Unknown click type " + config.get("npcClick") + " for config entry \"npcClick\""); } skipNpcGuiIfOnlyOneQuest = config.getBoolean("skip npc gui if only one quest"); - mobsProgressBar = config.getBoolean("mobsProgressBar"); - progressBarTimeoutSeconds = config.getInt("progressBarTimeoutSeconds"); requirementReasonOnMultipleQuests = config.getBoolean("requirementReasonOnMultipleQuests"); stageEndRewardsMessage = config.getBoolean("stageEndRewardsMessage"); } @@ -453,16 +449,6 @@ public boolean fireworks() { return fireworks; } - @Override - public boolean mobsProgressBar() { - return mobsProgressBar && QuestsAPI.getAPI().hasBossBarManager(); - } - - @Override - public int progressBarTimeoutSeconds() { - return progressBarTimeoutSeconds; - } - @Override public Collection<NpcClickType> getNpcClicks() { return npcClicks; @@ -527,10 +513,10 @@ private DialogsConfig(ConfigurationSection config) { private boolean update() { boolean result = false; if (config.getParent() != null) { - result |= migrateEntry(config, config.getParent(), "inActionBar", "dialogsInActionBar"); - result |= migrateEntry(config, config.getParent(), "defaultTime", "dialogsDefaultTime"); - result |= migrateEntry(config, config.getParent(), "disableClick", "disableDialogClick"); - result |= migrateEntry(config, config.getParent(), "history", "dialogHistory"); + result |= migrateEntry(config.getParent(), "dialogsInActionBar", config, "inActionBar"); + result |= migrateEntry(config.getParent(), "dialogsDefaultTime", config, "defaultTime"); + result |= migrateEntry(config.getParent(), "disableDialogClick", config, "disableClick"); + result |= migrateEntry(config.getParent(), "dialogHistory", config, "history"); } return result; } @@ -616,8 +602,8 @@ private QuestsMenuConfig(ConfigurationSection config) { private boolean update() { boolean result = false; if (config.getParent() != null) { - result |= migrateEntry(config, config.getParent(), "openNotStartedTabWhenEmpty", "menuOpenNotStartedTabWhenEmpty"); - result |= migrateEntry(config, config.getParent(), "allowPlayerCancelQuest", "allowPlayerCancelQuest"); + result |= migrateEntry(config.getParent(), "menuOpenNotStartedTabWhenEmpty", config, "openNotStartedTabWhenEmpty"); + result |= migrateEntry(config.getParent(), "allowPlayerCancelQuest", config, "allowPlayerCancelQuest"); } return result; } @@ -658,6 +644,7 @@ public class StageDescriptionConfig implements QuestsConfiguration.StageDescript private Set<DescriptionSource> descSources = EnumSet.noneOf(DescriptionSource.class); private boolean bossBars = true; private String bossBarFormat; + private int bossBarTimeout = 15; private ConfigurationSection config; @@ -681,21 +668,22 @@ private void init() { } bossBars = config.getBoolean("boss bars"); bossBarFormat = config.getString("boss bar format"); + bossBarTimeout = config.getInt("boss bar timeout"); } private boolean update() { boolean result = false; if (config == null) { - migrateEntry(QuestsConfigurationImplementation.this.config, QuestsConfigurationImplementation.this.config, - "stageDescriptionItemsSplit", "stage description"); + migrateEntry(QuestsConfigurationImplementation.this.config, "stageDescriptionItemsSplit", + QuestsConfigurationImplementation.this.config, "stage description"); config = QuestsConfigurationImplementation.this.config.getConfigurationSection("stage description"); result = true; } - result |= migrateEntry(config, config.getParent(), "stageDescriptionFormat", "description format"); - result |= migrateEntry(config, config, "prefix", "line prefix"); - result |= migrateEntry(config, config, "sources", "split sources"); + result |= migrateEntry(config.getParent(), "stageDescriptionFormat", config, "description format"); + result |= migrateEntry(config, "prefix", config, "line prefix"); + result |= migrateEntry(config, "sources", config, "split sources"); if (config.contains("amountFormat")) { String amountFormat = config.getString("amountFormat"); boolean showXOne = config.getBoolean("showXOne"); @@ -714,7 +702,8 @@ private boolean update() { result = true; } - result |= migrateEntry(config, config.getParent(), "mobsProgressBar", "boss bars"); + result |= migrateEntry(config.getParent(), "mobsProgressBar", config, "boss bars"); + result |= migrateEntry(config.getParent(), "progressBarTimeoutSeconds", config, "boss bar timeout"); return result; } @@ -759,6 +748,11 @@ public String getBossBarFormat() { return bossBarFormat; } + @Override + public int getBossBarTimeout() { + return bossBarTimeout; + } + } public class QuestDescriptionConfig implements QuestDescription { diff --git a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java index 409471b4..3569d14c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java @@ -3,6 +3,8 @@ import java.util.Collection; import java.util.List; import java.util.function.Consumer; +import java.util.function.Predicate; +import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,6 +21,7 @@ import fr.skytasul.quests.gui.items.ItemCreatorGUI; import fr.skytasul.quests.gui.items.ItemGUI; import fr.skytasul.quests.gui.items.ItemsGUI; +import fr.skytasul.quests.gui.mobs.EntityTypeGUI; import fr.skytasul.quests.gui.npc.NpcSelectGUI; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.players.PlayerAccountImplementation; @@ -69,4 +72,10 @@ public class DefaultGuiFactory implements GuiFactory { return ConfirmGUI.confirm(yes, no, indication, lore); } + @Override + public @NotNull Gui createEntityTypeSelection(@NotNull Consumer<EntityType> callback, + @Nullable Predicate<@NotNull EntityType> filter) { + return new EntityTypeGUI(callback, filter); + } + } diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index c5c17932..59ef6664 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -22,7 +22,6 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.DefaultErrors; -import fr.skytasul.quests.gui.mobs.EntityTypeGUI; public class NpcCreateGUI extends AbstractGui { @@ -103,12 +102,12 @@ public void onClick(GuiClickEvent event) { break; case 5: - new EntityTypeGUI(en -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createEntityTypeSelection(en -> { setType(en); event.reopen(); }, x -> x != null && BeautyQuests.getInstance().getNpcManager().getInternalFactory().isValidEntityType(x)) - .open(event.getPlayer()); + .open(event.getPlayer()); break; case 7: diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 3a83eb2a..9fdc36b3 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -27,11 +27,11 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; import fr.skytasul.quests.gui.items.ItemComparisonGUI; import fr.skytasul.quests.gui.items.ItemsGUI; @@ -56,7 +56,7 @@ public StageBringBack(StageController controller, ItemStack[] items, String cust } itemsDescriptions = - Arrays.stream(items).map(item -> ItemsDescriptionPlaceholders.formatObject(new HasSingleObject() { + Arrays.stream(items).map(item -> ProgressPlaceholders.formatObject(new HasSingleObject() { @Override public int getPlayerAmount(@NotNull PlayerAccount account) { @@ -117,7 +117,7 @@ protected String getMessage() { protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); placeholders.registerIndexedContextual("items", StageDescriptionPlaceholdersContext.class, - context -> ItemsDescriptionPlaceholders.formatObjectList(context.getDescriptionSource(), + context -> ProgressPlaceholders.formatObjectList(context.getDescriptionSource(), QuestsConfiguration.getConfig().getStageDescriptionConfig(), itemsDescriptions)); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 0bd06782..14b46c29 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -24,10 +24,10 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionConfiguration; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.progress.itemdescription.ItemsDescriptionConfiguration; import fr.skytasul.quests.gui.misc.BucketTypeGUI; public class StageBucket extends AbstractStage implements HasSingleObject { @@ -93,7 +93,7 @@ public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); placeholders.register("bucket_type", bucket.getName()); - ItemsDescriptionPlaceholders.register(placeholders, "buckets", this); + ProgressPlaceholders.registerObject(placeholders, "buckets", this); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index 14df5bc1..2f9d8253 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -26,9 +26,9 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; +import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; import fr.skytasul.quests.gui.items.ItemComparisonGUI; /** @@ -148,7 +148,7 @@ public int getObjectAmount() { @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); - ItemsDescriptionPlaceholders.register(placeholders, "items", this); + ProgressPlaceholders.registerObject(placeholders, "items", this); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index 7d483b37..37a39689 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -30,14 +30,14 @@ import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.progress.HasProgress; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; import fr.skytasul.quests.gui.mobs.MobSelectionGUI; import fr.skytasul.quests.mobs.Mob; @SuppressWarnings ("rawtypes") -public class StageDealDamage extends AbstractStage implements HasSingleObject { +public class StageDealDamage extends AbstractStage implements HasProgress { private final double damage; private final List<Mob> targetMobs; @@ -92,19 +92,14 @@ public int getPlayerAmount(@NotNull PlayerAccount account) { } @Override - public int getObjectAmount() { + public int getTotalAmount() { return (int) damage; } - @Override - public @NotNull String getObjectName() { - return "damage"; - } - @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); - ItemsDescriptionPlaceholders.register(placeholders, "damage", this); + ProgressPlaceholders.registerProgress(placeholders, "damage", this); placeholders.registerIndexed("target_mobs", getTargetMobsString(targetMobs)); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index 5414e5b5..fb00e7f1 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -23,12 +23,12 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; -import fr.skytasul.quests.api.utils.itemdescription.ItemsDescriptionPlaceholders; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; +import fr.skytasul.quests.api.utils.progress.HasProgress; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; -public class StagePlayTime extends AbstractStage implements HasSingleObject { +public class StagePlayTime extends AbstractStage implements HasProgress { private final long playTicks; @@ -51,9 +51,9 @@ public long getTicksToPlay() { @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); - placeholders.registerContextual("time_remaining_human", PlayerPlaceholdersContext.class, + placeholders.registerIndexedContextual("time_remaining_human", PlayerPlaceholdersContext.class, context -> Utils.millisToHumanString(getPlayerAmount(context.getPlayerAccount()))); - ItemsDescriptionPlaceholders.register(placeholders, "time", this); + ProgressPlaceholders.registerProgress(placeholders, "time", this); } private long getRemaining(PlayerAccount acc) { @@ -74,15 +74,10 @@ public int getPlayerAmount(@NotNull PlayerAccount account) { } @Override - public int getObjectAmount() { + public int getTotalAmount() { return (int) (playTicks * 50L); } - @Override - public @NotNull String getObjectName() { - return "time"; - } - @Override public void joined(Player p) { super.joined(p); diff --git a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java new file mode 100755 index 00000000..cf7ab702 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java @@ -0,0 +1,189 @@ +package fr.skytasul.quests.stages.options; + +import java.util.HashMap; +import java.util.Map; +import org.bukkit.Bukkit; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.BossBarManager.BQBossBar; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.options.StageOption; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; +import fr.skytasul.quests.api.utils.progress.HasProgress; +import fr.skytasul.quests.api.utils.progress.ProgressBarConfig; +import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; + +public class StageOptionProgressBar<T extends AbstractStage & HasProgress> extends StageOption<T> { + + private final @NotNull Map<Player, ProgressBar> bars = new HashMap<>(); + + public StageOptionProgressBar(@NotNull Class<T> stageClass) { + super(stageClass); + } + + @Override + public @NotNull StageOption<T> clone() { + return new StageOptionProgressBar<>(getStageClass()); + } + + @Override + public void startEdition(@NotNull StageCreation<T> creation) { + // no data to save + } + + @Override + public boolean shouldSave() { + return false; + } + + @Override + public void save(@NotNull ConfigurationSection section) { + // no data to save + } + + @Override + public void load(@NotNull ConfigurationSection section) { + // no data to save + } + + @Override + public void stageStart(PlayerAccount acc, StageController stage) { + if (acc.isCurrent()) + createBar(acc.getPlayer(), (T) stage.getStage()); + } + + @Override + public void stageEnd(PlayerAccount acc, StageController stage) { + if (acc.isCurrent()) + removeBar(acc.getPlayer()); + } + + @Override + public void stageJoin(Player p, StageController stage) { + createBar(p, (T) stage.getStage()); + } + + @Override + public void stageLeave(Player p, StageController stage) { + removeBar(p); + } + + @Override + public void stageUpdated(@NotNull Player player, @NotNull StageController stage) { + ProgressBar bar = bars.get(player); + if (bar != null) + bar.update(); + } + + @Override + public void stageUnload(@NotNull StageController stage) { + bars.values().forEach(ProgressBar::remove); + bars.clear(); + } + + public ProgressBarConfig getProgressConfig() { + return QuestsConfiguration.getConfig().getStageDescriptionConfig(); + } + + public boolean areBarsEnabled() { + return getProgressConfig().areBossBarsEnabled() && QuestsAPI.getAPI().hasBossBarManager(); + } + + protected void createBar(@NotNull Player p, T progress) { + if (areBarsEnabled()) { + if (bars.containsKey(p)) { // NOSONAR Map#computeIfAbsent cannot be used here as we should log the issue + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Trying to create an already existing bossbar for player " + p.getName()); + return; + } + bars.put(p, new ProgressBar(p, progress)); + } + } + + protected void removeBar(@NotNull Player p) { + if (bars.containsKey(p)) + bars.remove(p).remove(); + } + + class ProgressBar { + private final PlayerAccount acc; + private final BQBossBar bar; + private final T progress; + private final int totalAmount; + private final PlaceholderRegistry placeholders; + + private BukkitTask timer; + + public ProgressBar(Player p, T progress) { + this.progress = progress; + this.acc = PlayersManager.getPlayerAccount(p); + this.totalAmount = progress.getTotalAmount(); + this.placeholders = PlaceholderRegistry.combine(progress); // to make a copy + ProgressPlaceholders.registerProgress(placeholders, "stage", progress); + + BarStyle style = null; + if (totalAmount % 20 == 0) { + style = BarStyle.SEGMENTED_20; + } else if (totalAmount % 10 == 0) { + style = BarStyle.SEGMENTED_10; + } else if (totalAmount % 12 == 0) { + style = BarStyle.SEGMENTED_12; + } else if (totalAmount % 6 == 0) { + style = BarStyle.SEGMENTED_6; + } else + style = BarStyle.SOLID; + + bar = QuestsAPI.getAPI().getBossBarManager().buildBossBar("tmp", BarColor.YELLOW, style); + update(); + bar.addPlayer(p); + } + + public void remove() { + bar.removeAll(); + if (timer != null) + timer.cancel(); + } + + public void update() { + timer(); + + int playerRemaining = progress.getPlayerAmount(acc); + if (playerRemaining >= 0 && playerRemaining <= totalAmount) { + bar.setProgress((totalAmount - playerRemaining) * 1D / totalAmount); + } else + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Amount of objects superior to max objects in " + progress.toString() + " for player " + + acc.getNameAndID() + ": " + playerRemaining + " > " + totalAmount); + + bar.setTitle(MessageUtils.format(getProgressConfig().getBossBarFormat(), placeholders, + PlaceholdersContext.of(acc.getPlayer(), true))); + } + + private void timer() { + if (getProgressConfig().getBossBarTimeout() <= 0) + return; + + if (timer != null) + timer.cancel(); + + timer = Bukkit.getScheduler().runTaskLater(QuestsPlugin.getPlugin(), () -> { + bar.removePlayer(acc.getPlayer()); + timer = null; + }, getProgressConfig().getBossBarTimeout() * 20L); + } + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java index 0ee6f66e..acc8c64d 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java @@ -78,7 +78,7 @@ public boolean hasBranchStarted(@NotNull PlayerAccount acc, @NotNull QuestBranch * * @param player Player */ - public final void objectiveUpdated(@NotNull Player player) { + public final void questUpdated(@NotNull Player player) { PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (quest.hasStarted(acc)) { QuestsAPI.getAPI().propagateQuestsHandlers(x -> x.questUpdated(acc, quest)); diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java index 3523191b..0e0720b2 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -233,7 +233,7 @@ public void finishStage(@NotNull Player p, @NotNull StageControllerImplementatio } branch.start(acc); } - manager.objectiveUpdated(p); + manager.questUpdated(p); }); } diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index 1551ab93..46070727 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -84,7 +84,9 @@ public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nu Validate.notNull(datas, "Account " + acc.debugName() + " does not have datas for " + toString()); datas.put(dataKey, dataValue); acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); - branch.getManager().objectiveUpdated(player); + + propagateStageHandlers(handler -> handler.stageUpdated(player, this)); + branch.getManager().questUpdated(player); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java index 49a621dc..e14fd769 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java @@ -9,9 +9,9 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.mobs.LeveledMobFactory; -import fr.skytasul.quests.gui.mobs.EntityTypeGUI; import me.lokka30.levelledmobs.LevelledMobs; public class BQLevelledMobs extends BukkitEntityFactory implements LeveledMobFactory<EntityType> { @@ -30,7 +30,8 @@ public ItemStack getFactoryItem() { @Override public void itemClick(Player p, Consumer<EntityType> run) { - new EntityTypeGUI(run, x -> x != null && x.isAlive()).open(p); + QuestsPlugin.getPlugin().getGuiManager().getFactory().createEntityTypeSelection(run, x -> x != null && x.isAlive()) + .open(p); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java index 1cdb5a7d..a763a8ff 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java @@ -13,11 +13,11 @@ import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; +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.gui.mobs.EntityTypeGUI; public class BukkitEntityFactory implements MobFactory<EntityType>, Listener { @@ -34,7 +34,7 @@ public ItemStack getFactoryItem() { @Override public void itemClick(Player p, Consumer<EntityType> run) { - new EntityTypeGUI(run, x -> x != null).open(p); + QuestsPlugin.getPlugin().getGuiManager().getFactory().createEntityTypeSelection(run, x -> x != null).open(p); } @Override diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 1e89b377..1556986a 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -49,8 +49,6 @@ finishSound: ENTITY_PLAYER_LEVELUP nextStageSound: ITEM_FIRECHARGE_USE # Enable or disable end fireworks fireworks: true -# Amount of seconds before the progress bar will disappear (set it to 0 to make it persistent) -progressBarTimeoutSeconds: 15 # Which clicks are acceptable for a player to do on the NPC in order to start a quest, follow a dialog... # (can be: RIGHT, LEFT, SHIFT_RIGHT, SHIFT_LEFT) npcClick: [RIGHT, SHIFT_RIGHT] @@ -165,6 +163,8 @@ stage description: # Format of the boss bar for stages with progress. # Available placeholders are: {quest_name}, {stage_done}, {stage_remaining}, {stage_total}, {stage_percentage} boss bar format: "§6{quest_name}: §e{stage_done}/{stage_total}" + # Seconds before the progress bar disappear (set it to 0 to make it persistent) + boss bar timeout: 15 # - Quest descriptions - # How is formatted the quest description in GUIs From f3a7fef0eaa4825e09c316ef7bcfed63e5213106 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 11 Aug 2023 21:58:51 +0200 Subject: [PATCH 30/95] :construction: Finished NPCs work --- .../fr/skytasul/quests/api/QuestsAPI.java | 2 +- .../quests/api/npcs/BqInternalNpc.java | 5 +- .../quests/api/npcs/BqInternalNpcFactory.java | 21 ++- .../fr/skytasul/quests/api/npcs/BqNpc.java | 2 + .../quests/api/npcs/BqNpcManager.java | 23 ++- .../quests/api/npcs/dialogs/Message.java | 31 +++- .../skytasul/quests/api/pools/QuestPool.java | 2 +- .../quests/api/pools/QuestPoolsManager.java | 2 +- .../fr/skytasul/quests/api/utils/Utils.java | 12 +- .../api/utils/messaging/MessageUtils.java | 1 + .../utils/messaging/PlaceholderRegistry.java | 27 +++ .../java/fr/skytasul/quests/BeautyQuests.java | 4 +- .../quests/QuestsAPIImplementation.java | 4 +- .../fr/skytasul/quests/QuestsListener.java | 2 +- .../CommandsManagerImplementation.java | 7 +- .../skytasul/quests/gui/npc/NpcCreateGUI.java | 18 +- .../quests/gui/npc/NpcFactoryGUI.java | 55 ++++++ .../skytasul/quests/gui/npc/NpcSelectGUI.java | 12 +- .../quests/gui/pools/PoolEditGUI.java | 9 +- .../quests/gui/quests/DialogHistoryGUI.java | 3 +- .../quests/npcs/BqNpcImplementation.java | 55 +++--- .../npcs/BqNpcManagerImplementation.java | 159 ++++++++++++++---- .../quests/options/OptionStarterNPC.java | 6 +- .../players/AbstractPlayersManager.java | 2 +- .../fr/skytasul/quests/stages/StageNPC.java | 4 +- .../pools/QuestPoolImplementation.java | 19 ++- .../QuestPoolsManagerImplementation.java | 5 +- .../utils/compatibility/npcs/BQCitizens.java | 26 ++- .../compatibility/npcs/BQServerNPCs.java | 18 +- .../types/DialogRunnerImplementation.java | 2 +- core/src/main/resources/locales/en_US.yml | 8 +- 31 files changed, 388 insertions(+), 158 deletions(-) create mode 100755 core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java index bf52459a..951b681a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -64,7 +64,7 @@ public interface QuestsAPI { @NotNull QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards(); - void setNpcFactory(@NotNull BqInternalNpcFactory factory); + void addNpcFactory(@NotNull String key, @NotNull BqInternalNpcFactory factory); boolean hasHologramsManager(); diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java index 540037b3..a3a0081c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java @@ -3,11 +3,10 @@ import org.bukkit.Location; import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public interface BqInternalNpc { - public abstract int getId(); + public int getInternalId(); public abstract @NotNull String getName(); @@ -17,8 +16,6 @@ public interface BqInternalNpc { public abstract @NotNull Location getLocation(); - public abstract void setSkin(@Nullable String skin); - /** * Sets the "paused" state of the NPC navigation * diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java index 0fd1d595..815c099c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java @@ -24,21 +24,26 @@ public interface BqInternalNpcFactory { @Nullable BqInternalNpc fetchNPC(int id); - @NotNull - BqInternalNpc create(@NotNull Location location, @NotNull EntityType type, @NotNull String name); - - boolean isValidEntityType(@NotNull EntityType type); - default void npcClicked(@Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click) { - QuestsPlugin.getPlugin().getNpcManager().npcClicked(event, npcID, p, click); + QuestsPlugin.getPlugin().getNpcManager().npcClicked(this, event, npcID, p, click); } default void npcRemoved(int id) { - QuestsPlugin.getPlugin().getNpcManager().npcRemoved(id); + QuestsPlugin.getPlugin().getNpcManager().npcRemoved(this, id); } default void npcsReloaded() { - QuestsPlugin.getPlugin().getNpcManager().reload(); + QuestsPlugin.getPlugin().getNpcManager().reload(this); + } + + public interface BqInternalNpcFactoryCreatable extends BqInternalNpcFactory { + + boolean isValidEntityType(@NotNull EntityType type); + + @NotNull + BqInternalNpc create(@NotNull Location location, @NotNull EntityType type, @NotNull String name, + @Nullable String skin); + } } diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java index 5974107e..f26d558d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpc.java @@ -10,6 +10,8 @@ public interface BqNpc extends Locatable.Located.LocatedEntity, HasPlaceholders { + String getId(); + BqInternalNpc getNpc(); Set<Quest> getQuests(); diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java index 016fb110..f963f21f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java @@ -1,29 +1,38 @@ package fr.skytasul.quests.api.npcs; +import java.util.Collection; import org.bukkit.Location; +import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; public interface BqNpcManager { boolean isEnabled(); - void setInternalFactory(BqInternalNpcFactory internalFactory); + void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactory internalFactory); @NotNull - BqNpc createNPC(@NotNull Location location, @NotNull EntityType type, @NotNull String name, - @Nullable String skin); + Collection<String> getAvailableIds(); + + boolean isNPC(@NotNull Entity entity); + + @NotNull + BqNpc createNPC(@NotNull BqInternalNpcFactoryCreatable internalFactory, @NotNull Location location, + @NotNull EntityType type, @NotNull String name, @Nullable String skin); @Nullable - BqNpc getById(int id); + BqNpc getById(String id); - void npcRemoved(int id); + void npcRemoved(@NotNull BqInternalNpcFactory internalFactory, int id); - void npcClicked(@Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click); + void npcClicked(@NotNull BqInternalNpcFactory internalFactory, @Nullable Cancellable event, int npcID, @NotNull Player p, + @NotNull NpcClickType click); - void reload(); + void reload(@NotNull BqInternalNpcFactory internalFactory); } diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java index b7b0e400..e2696df9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java @@ -6,10 +6,15 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.npcs.BqNpc; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; @@ -29,10 +34,10 @@ public int getWaitTime() { return wait == -1 ? QuestsConfiguration.getConfig().getDialogsConfig().getDefaultTime() : wait; } - public BukkitTask sendMessage(Player p, String npc, int id, int size) { + public BukkitTask sendMessage(@NotNull Player p, @Nullable BqNpc npc, @Nullable String npcCustomName, int id, int size) { BukkitTask task = null; - String sent = formatMessage(p, npc, id, size); + String sent = formatMessage(p, npc, npcCustomName, id, size); if (QuestsConfiguration.getConfig().getDialogsConfig().sendInActionBar()) { BaseComponent[] components = TextComponent.fromLegacyText(sent.replace("{nl}", " ")); p.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); @@ -78,17 +83,29 @@ private String getSound() { return sentSound; } - public String formatMessage(Player p, String npc, int id, int size) { + public String formatMessage(@NotNull Player p, @Nullable BqNpc npc, @Nullable String npcCustomName, int id, int size) { + PlaceholderRegistry registry = new PlaceholderRegistry() + .registerIndexed("player_name", p.getName()) + .registerIndexed("npc_name_message", npcCustomName) + .registerIndexed("text", text) + .registerIndexed("message_id", id + 1) + .registerIndexed("message_count", size); + if (npc != null) + registry.compose(npc); + String sent = null; switch (sender) { case PLAYER: - sent = Utils.finalFormat(p, Lang.SelfText.format(p.getName(), text, id + 1, size), true); + sent = MessageUtils.finalFormat(Lang.SelfText.toString(), registry.withoutIndexes("npc_name_message"), + PlaceholdersContext.of(p, true)); break; case NPC: - sent = Utils.finalFormat(p, Lang.NpcText.format(npc, text, id + 1, size), true); + sent = MessageUtils.finalFormat(Lang.NpcText.toString(), registry.withoutIndexes("player_name"), + PlaceholdersContext.of(p, true)); break; case NOSENDER: - sent = Utils.finalFormat(p, Utils.format(text, id + 1, size), true); + sent = MessageUtils.finalFormat(text, registry.withoutIndexes("npc_name_message", "player_name"), + PlaceholdersContext.of(p, true)); break; } return sent; 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 b49c08fb..46ea676c 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 @@ -14,7 +14,7 @@ public interface QuestPool extends HasPlaceholders { int getId(); - int getNpcId(); + String getNpcId(); String getHologram(); diff --git a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java index 5fc3b23a..cbe0a73c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java @@ -8,7 +8,7 @@ public interface QuestPoolsManager { - public @NotNull QuestPool createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, int maxQuests, + public @NotNull QuestPool createPool(@Nullable QuestPool editing, String npcID, @Nullable String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements); public void removePool(int id); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java index d87a7550..69648558 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java @@ -79,22 +79,26 @@ public static String millisToHumanString(long time) { StringBuilder sb = new StringBuilder(); long weeks = time / 604_800_000; - if (weeks != 0) sb.append(Lang.TimeWeeks.format(weeks)); + if (weeks != 0) + sb.append(Lang.TimeWeeks.quickFormat("weeks_amount", weeks)); time -= weeks * 604_800_000; long days = time / 86_400_000; if (sb.length() != 0) sb.append(' '); - if (days != 0) sb.append(Lang.TimeDays.format(days)); + if (days != 0) + sb.append(Lang.TimeDays.quickFormat("days_amount", days)); time -= days * 86_400_000; long hours = time / 3_600_000; if (sb.length() != 0) sb.append(' '); - if (hours != 0) sb.append(Lang.TimeHours.format(hours)); + if (hours != 0) + sb.append(Lang.TimeHours.quickFormat("hours_amount", hours)); time -= hours * 3_600_000; long minutes = time / 60_000; if (sb.length() != 0) sb.append(' '); - if (minutes != 0) sb.append(Lang.TimeMinutes.format(minutes)); + if (minutes != 0) + sb.append(Lang.TimeMinutes.quickFormat("minutes_amount", minutes)); time -= minutes * 60_000; if (sb.length() == 0) sb.append(Lang.TimeLessMinute.toString()); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java index 967d0909..677587b0 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -51,6 +51,7 @@ public static String finalFormat(@NotNull String text, @Nullable PlaceholderRegi text = QuestsPlaceholders.setPlaceholders((Player) context.getActor(), text); if (context.replacePluginPlaceholders()) { text = text + .replace("{player}", context.getActor().getName()) .replace("{PLAYER}", context.getActor().getName()) .replace("{PREFIX}", QuestsPlugin.getPlugin().getPrefix()); } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java index 58d589ab..398fea97 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java @@ -140,6 +140,33 @@ public boolean hasPlaceholder(@NotNull String key) { return combine(others); } + /** + * Creates a <i>new</i> placeholders registry containing the same placeholders as this instance but + * with the placeholers passed as parameter no longer being indexed. + * + * @param exceptedPlaceholders placeholders no longer being indexed + * @return a copy of this registry without some indexed placeholders + */ + public @NotNull PlaceholderRegistry withoutIndexes(@NotNull Placeholder @NotNull... exceptedPlaceholders) { + PlaceholderRegistry result = new PlaceholderRegistry(this.placeholders.toArray(Placeholder[]::new)); + + out: for (Placeholder placeholder : indexed) { // NOSONAR: very simple label use + for (Placeholder exceptedPlaceholder : exceptedPlaceholders) { + if (exceptedPlaceholder == placeholder) + continue out; + } + + result.indexed.add(placeholder); + } + + return result; + } + + public @NotNull PlaceholderRegistry withoutIndexes(@NotNull String @NotNull... exceptedPlaceholders) { + return withoutIndexes(Arrays.stream(exceptedPlaceholders).map(x -> Objects.requireNonNull(getPlaceholder(x))) + .toArray(Placeholder[]::new)); + } + /** * Creates a <i>new</i> placeholders registry containing the same placeholders as this instance but * with the indexed placeholers being shifted so that the passed placeholder is the first one. diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 15f079ab..5b82f34d 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -162,7 +162,7 @@ public void onEnable(){ logger.severe("An error occurred while initializing compatibilities. Consider restarting.", ex); } - if (npcManager.getInternalFactory() == null) { + if (!npcManager.isEnabled()) { throw new LoadingException("No NPC plugin installed - please install Citizens or znpcs"); } @@ -193,7 +193,7 @@ public void run() { logger.severe("An error occurred while loading plugin datas.", e); } } - }.runTaskLater(this, npcManager.getInternalFactory().getTimeToWaitForNPCs()); + }.runTaskLater(this, npcManager.getTimeToWaitForNPCs()); // Start of non-essential systems if (loggerHandler != null) loggerHandler.launchFlushTimer(); diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java index 33c86c42..57168897 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -119,8 +119,8 @@ public void registerMobStacker(@NotNull MobStacker stacker) { } @Override - public void setNpcFactory(@NotNull BqInternalNpcFactory factory) { - QuestsPlugin.getPlugin().getNpcManager().setInternalFactory(factory); + public void addNpcFactory(@NotNull String key, @NotNull BqInternalNpcFactory factory) { + QuestsPlugin.getPlugin().getNpcManager().addInternalFactory(key, factory); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 96dc0d55..3c174318 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -116,7 +116,7 @@ public void onNPCClick(BQNPCClickEvent e) { }else if (!startablePools.isEmpty()) { QuestPool pool = startablePools.iterator().next(); QuestsPlugin.getPlugin().getLoggerExpanded() - .debug("NPC " + npc.getNpc().getId() + ": " + startablePools.size() + " pools, result: " + pool.give(p)); + .debug("NPC " + npc.getId() + ": " + startablePools.size() + " pools, result: " + pool.give(p)); }else { if (!timer.isEmpty()) { timer.get(0).testTimer(acc, true); 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 d1189016..5a6d900b 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -66,17 +66,14 @@ public CommandsManagerImplementation() { .collect(Collectors.toList()))); handler.registerValueResolver(BqNpc.class, context -> { - int id = context.popInt(); + String id = context.pop(); BqNpc npc = QuestsPlugin.getPlugin().getNpcManager().getById(id); if (npc == null) throw new CommandErrorException(Lang.NPC_DOESNT_EXIST.quickFormat("npc_id", id)); return npc; }); handler.getAutoCompleter().registerParameterSuggestions(BqNpc.class, - SuggestionProvider.of(() -> BeautyQuests.getInstance().getNpcManager().getInternalFactory().getIDs() - .stream() - .map(String::valueOf) - .collect(Collectors.toList()))); + SuggestionProvider.of(() -> BeautyQuests.getInstance().getNpcManager().getAvailableIds())); handler.registerCondition((@NotNull CommandActor actor, @NotNull ExecutableCommand command, @NotNull @Unmodifiable List<String> arguments) -> { if (command.hasAnnotation(OutsideEditor.class)) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index 59ef6664..b82afd91 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -8,7 +8,6 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; @@ -18,6 +17,7 @@ import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.Utils; @@ -29,14 +29,17 @@ public class NpcCreateGUI extends AbstractGui { private static final ItemStack move = ItemUtils.item(XMaterial.MINECART, Lang.move.toString(), Lang.moveLore.toString()); public static ItemStack validMove = ItemUtils.item(XMaterial.EMERALD, Lang.moveItem.toString()); - private Consumer<BqNpc> end; - private Runnable cancel; + private final @NotNull BqInternalNpcFactoryCreatable factory; + private final @NotNull Consumer<@NotNull BqNpc> end; + private final @NotNull Runnable cancel; private EntityType en; private String name; private String skin; - public NpcCreateGUI(Consumer<BqNpc> end, Runnable cancel) { + public NpcCreateGUI(@NotNull BqInternalNpcFactoryCreatable factory, @NotNull Consumer<@NotNull BqNpc> end, + @NotNull Runnable cancel) { + this.factory = factory; this.end = end; this.cancel = cancel; } @@ -105,9 +108,7 @@ public void onClick(GuiClickEvent event) { QuestsPlugin.getPlugin().getGuiManager().getFactory().createEntityTypeSelection(en -> { setType(en); event.reopen(); - }, x -> x != null - && BeautyQuests.getInstance().getNpcManager().getInternalFactory().isValidEntityType(x)) - .open(event.getPlayer()); + }, x -> x != null && factory.isValidEntityType(x)).open(event.getPlayer()); break; case 7: @@ -118,7 +119,8 @@ public void onClick(GuiClickEvent event) { case 8: event.close(); try { - end.accept(QuestsPlugin.getPlugin().getNpcManager().createNPC(event.getPlayer().getLocation(), en, name, skin)); + end.accept(QuestsPlugin.getPlugin().getNpcManager().createNPC(factory, event.getPlayer().getLocation(), en, + name, skin)); }catch (Exception ex) { ex.printStackTrace(); DefaultErrors.sendGeneric(event.getPlayer(), "npc creation " + ex.getMessage()); diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java new file mode 100755 index 00000000..dba389aa --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java @@ -0,0 +1,55 @@ +package fr.skytasul.quests.gui.npc; + +import java.util.Collection; +import java.util.function.Consumer; +import org.bukkit.DyeColor; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; + +public class NpcFactoryGUI extends PagedGUI<BqInternalNpcFactory> { + + private final @NotNull Runnable cancel; + private final @NotNull Consumer<BqInternalNpcFactory> callback; + + public NpcFactoryGUI(@NotNull Collection<BqInternalNpcFactory> objects, @NotNull Runnable cancel, + @NotNull Consumer<BqInternalNpcFactory> callback) { + super(Lang.INVENTORY_SELECT.toString(), DyeColor.LIGHT_BLUE, objects); + this.cancel = cancel; + this.callback = callback; + } + + @Override + public void open(@NotNull Player player) { + if (objects.size() == 1) + callback.accept(objects.get(0)); + else + super.open(player); + } + + @Override + public @NotNull ItemStack getItemStack(@NotNull BqInternalNpcFactory object) { + return ItemUtils.item(XMaterial.FILLED_MAP, "§a" + BeautyQuests.getInstance().getNpcManager().getFactoryKey(object), + Lang.Amount.quickFormat("amount", object.getIDs().size())); + } + + @Override + public void click(@NotNull BqInternalNpcFactory existing, @NotNull ItemStack item, @NotNull ClickType clickType) { + callback.accept(existing); + } + + @Override + public @NotNull CloseBehavior onClose(@NotNull Player player) { + return new DelayCloseBehavior(cancel); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index 8c1cc52c..6b59ed0e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -1,10 +1,12 @@ package fr.skytasul.quests.gui.npc; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.editors.SelectNPC; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.ItemUtils; @@ -13,6 +15,7 @@ import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.gui.layout.LayoutedGUI.Builder; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.api.npcs.BqNpc; public final class NpcSelectGUI { @@ -25,7 +28,14 @@ private NpcSelectGUI() {} public static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BqNpc> end, boolean nullable) { Builder builder = LayoutedGUI.newBuilder().addButton(1, LayoutedButton.create(createNPC, event -> { - new NpcCreateGUI(end, event::reopen).open(event.getPlayer()); + new NpcFactoryGUI(BeautyQuests.getInstance().getNpcManager() + .getInternalFactories().stream() + .filter(BqInternalNpcFactoryCreatable.class::isInstance) + .map(BqInternalNpcFactoryCreatable.class::cast) + .collect(Collectors.toList()), event::reopen, factory -> { + new NpcCreateGUI((@NotNull BqInternalNpcFactoryCreatable) factory, end, event::reopen) + .open(event.getPlayer()); + }).open(event.getPlayer()); })).addButton(3, LayoutedButton.create(selectNPC, event -> { new SelectNPC(event.getPlayer(), event::reopen, end).start(); })); diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index a3e28a29..bb099d89 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -44,7 +44,7 @@ public class PoolEditGUI extends AbstractGui { private int questsPerLaunch = 1; private boolean redoAllowed = true; private long timeDiff = TimeUnit.DAYS.toMillis(1); - private int npcID = -1; + private String npcID = null; private boolean avoidDuplicates = true; private RequirementList requirements = new RequirementList(); @@ -67,7 +67,8 @@ public PoolEditGUI(Runnable end, QuestPool editing) { } private String[] getNPCLore() { - return new String[] { "§8> " + Lang.requiredParameter.toString(), "", QuestOption.formatNullableValue("NPC #" + npcID) }; + return new String[] {"§8> " + Lang.requiredParameter.toString(), "", + QuestOption.formatNullableValue("NPC " + npcID)}; } private String[] getHologramLore() { @@ -91,7 +92,7 @@ private String[] getRequirementsLore() { } private void handleDoneButton(Inventory inv) { - boolean newState = /*name != null &&*/ npcID != -1; + boolean newState = npcID != null; if (newState == canFinish) return; inv.getItem(SLOT_CREATE).setType((newState ? XMaterial.DIAMOND : XMaterial.CHARCOAL).parseMaterial()); canFinish = newState; @@ -123,7 +124,7 @@ public void onClick(GuiClickEvent event) { switch (event.getSlot()) { case SLOT_NPC: QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, npc -> { - npcID = npc.getNpc().getId(); + npcID = npc.getId(); ItemUtils.lore(event.getClicked(), getNPCLore()); handleDoneButton(getInventory()); reopen(event.getPlayer()); 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 10047a34..183c08fd 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 @@ -117,7 +117,8 @@ class WrappedDialogable { List<List<String>> lines = new ArrayList<>(messages.size()); for (int i = 0; i < messages.size(); i++) { Message msg = messages.get(i); - String formatted = msg.formatMessage(player, dialogable.getDialog().getNPCName(dialogable.getNPC()), i, messages.size()); + String formatted = msg.formatMessage(player, dialogable.getNPC(), + dialogable.getDialog().getNPCName(dialogable.getNPC()), i, messages.size()); lines.add(ChatColorUtils.wordWrap(formatted, 40, 100)); } 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 08f032dd..01d43bde 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java @@ -1,7 +1,17 @@ package fr.skytasul.quests.npcs; -import java.util.*; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.function.Predicate; import org.apache.commons.lang.StringUtils; import org.bukkit.Location; @@ -29,6 +39,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.Located; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.npcs.BqNpcManagerImplementation.WrappedInternalNpc; import fr.skytasul.quests.options.OptionHologramLaunch; import fr.skytasul.quests.options.OptionHologramLaunchNo; import fr.skytasul.quests.options.OptionHologramText; @@ -70,43 +81,48 @@ public double getYAdd() { } }; private final boolean holograms; - - private BqInternalNpc npc; + + private final @NotNull WrappedInternalNpc wrappedNpc; private @Nullable PlaceholderRegistry placeholders; - public BqNpcImplementation(BqInternalNpc npc) { - this.npc = npc; + public BqNpcImplementation(@NotNull WrappedInternalNpc wrappedNpc) { + this.wrappedNpc = wrappedNpc; holograms = hologramText.enabled || hologramLaunch.enabled || hologramLaunchNo.enabled || hologramPool.enabled; launcheableTask = startLauncheableTasks(); } + public @NotNull WrappedInternalNpc getWrappedNpc() { + return wrappedNpc; + } + @Override - public BqInternalNpc getNpc() { - return npc; + public String getId() { + return wrappedNpc.getId(); } - public void setNpc(BqInternalNpc npc) { - this.npc = npc; + @Override + public BqInternalNpc getNpc() { + return wrappedNpc.getNpc(); } @Override public @NotNull Entity getEntity() { - return npc.getEntity(); + return getNpc().getEntity(); } @Override public @NotNull Location getLocation() { - return npc.getLocation(); + return getNpc().getLocation(); } @Override public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { if (placeholders == null) { placeholders = new PlaceholderRegistry() - .register("npc_name", npc.getName()) - .register("npc_id", npc.getId()); + .register("npc_name", getNpc().getName()) + .register("npc_id", getId()); } return placeholders; } @@ -117,7 +133,7 @@ private BukkitTask startLauncheableTasks() { @Override public void run() { - if (!npc.isSpawned()) + if (!getNpc().isSpawned()) return; if (!(getEntity() instanceof LivingEntity)) return; LivingEntity en = (LivingEntity) getEntity(); @@ -207,7 +223,7 @@ private BukkitTask startHologramsTask() { @Override public void run() { LivingEntity en = null; // check if NPC is spawned and living - if (npc.isSpawned() && getEntity() instanceof LivingEntity) + if (getNpc().isSpawned() && getEntity() instanceof LivingEntity) en = (LivingEntity) getEntity(); if (en == null) { if (!hologramsRemoved) removeHolograms(false); // if the NPC is not living and holograms have not been already removed before @@ -352,15 +368,16 @@ public void unload() { } public void delete(String cause) { - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + npc.getId()); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + getId()); for (Quest qu : quests.keySet()) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Starter NPC #" + npc.getId() + " has been removed from quest " + qu.getId() + ". Reason: " + cause); + QuestsPlugin.getPlugin().getLoggerExpanded().warning( + "Starter NPC #" + getId() + " has been removed from quest " + qu.getId() + ". Reason: " + cause); qu.removeOption(OptionStarterNPC.class); } quests = null; for (QuestPool pool : pools) { QuestsPlugin.getPlugin().getLoggerExpanded() - .warning("NPC #" + npc.getId() + " has been removed from pool " + pool.getId() + ". Reason: " + cause); + .warning("NPC " + getId() + " has been removed from pool " + pool.getId() + ". Reason: " + cause); ((QuestPoolImplementation) pool).unloadStarter(); } unload(); @@ -374,7 +391,7 @@ public void toggleDebug() { @Override public String toString() { - String npcInfo = "NPC #" + npc.getId() + ", " + quests.size() + " quests, " + pools.size() + " pools"; + String npcInfo = "NPC " + getId() + ", " + quests.size() + " quests, " + pools.size() + " pools"; String hologramsInfo; if (!holograms) { hologramsInfo = "no holograms"; 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 49613715..785c85de 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -1,18 +1,24 @@ package fr.skytasul.quests.npcs; +import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; 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.api.QuestsPlugin; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.npcs.BqInternalNpc; import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.npcs.BqNpcManager; import fr.skytasul.quests.api.npcs.NpcClickType; @@ -20,82 +26,135 @@ public class BqNpcManagerImplementation implements BqNpcManager { - private final Map<Integer, BqNpcImplementation> npcs = new HashMap<>(); - private @Nullable BqInternalNpcFactory internalFactory = null; + private static final String SEPARATOR = "#"; + + private final BiMap<String, BqInternalNpcFactory> internalFactories = HashBiMap.create(); + private final Map<String, BqNpcImplementation> npcs = new HashMap<>(); - @Override - public boolean isEnabled() { - return internalFactory != null; + private BqInternalNpcFactory last = null; + + public @NotNull String getFactoryKey(@NotNull BqInternalNpcFactory internalFactory) { + return internalFactories.inverse().get(internalFactory); + } + + private String getNpcId(BqInternalNpcFactory factory, int id) { + return getFactoryKey(factory) + SEPARATOR + id; + } + + private BqInternalNpcFactory getMigrationFactory() { + return last; + } + + public Collection<BqInternalNpcFactory> getInternalFactories() { + return internalFactories.values(); } - public @Nullable BqInternalNpcFactory getInternalFactory() { - return internalFactory; + public long getTimeToWaitForNPCs() { + return internalFactories.values().stream().mapToInt(BqInternalNpcFactory::getTimeToWaitForNPCs).max().orElse(0); } @Override - public void setInternalFactory(BqInternalNpcFactory internalFactory) { - QuestsPlugin.getPlugin().getLoggerExpanded() - .info(internalFactory.getClass().getSimpleName() + " will replace " - + (this.internalFactory == null ? "none" : this.internalFactory.getClass().getSimpleName()) - + " as the new NPCs manager."); + public boolean isEnabled() { + return !internalFactories.isEmpty(); + } + + @Override + public void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactory internalFactory) { + if (internalFactories.containsKey(key)) + throw new IllegalArgumentException("Npc factory " + key + " is already registered"); + + QuestsPlugin.getPlugin().getLoggerExpanded().info("Adding " + key + " as a npc factory"); + internalFactories.put(key, internalFactory); - this.internalFactory = internalFactory; + last = internalFactory; QuestUtils.autoRegister(internalFactory); } @Override - public @NotNull BqNpc createNPC(@NotNull Location location, @NotNull EntityType type, @NotNull String name, - @Nullable String skin) { - BqInternalNpc internal = internalFactory.create(location, type, name); - try { - if (type == EntityType.PLAYER) - internal.setSkin(skin); - }catch (Exception ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("Failed to set NPC skin", ex); - } + public @NotNull Collection<String> getAvailableIds() { + return internalFactories.values() + .stream() + .flatMap(factory -> factory.getIDs() + .stream() + .map(String::valueOf)) + .collect(Collectors.toList()); + } + + @Override + public boolean isNPC(@NotNull Entity entity) { + return internalFactories.values().stream().anyMatch(factory -> factory.isNPC(entity)); + } - BqNpcImplementation npc = new BqNpcImplementation(internal); - npcs.put(internal.getId(), npc); + @Override + public @NotNull BqNpc createNPC(@NotNull BqInternalNpcFactoryCreatable internalFactory, @NotNull Location location, + @NotNull EntityType type, @NotNull String name, @Nullable String skin) { + BqInternalNpc internal = internalFactory.create(location, type, name, skin); + + BqNpcImplementation npc = new BqNpcImplementation(new WrappedInternalNpc(internalFactory, internal)); + npcs.put(npc.getId(), npc); return npc; } @Override - public @Nullable BqNpcImplementation getById(int id) { + public @Nullable BqNpcImplementation getById(String id) { return npcs.computeIfAbsent(id, this::registerNPC); } - private BqNpcImplementation registerNPC(int id) { - return new BqNpcImplementation(internalFactory.fetchNPC(id)); + public @Nullable BqNpcImplementation getById(BqInternalNpcFactory npcFactory, int id) { + return npcs.computeIfAbsent(getNpcId(npcFactory, id), this::registerNPC); + } + + private BqNpcImplementation registerNPC(String id) { + BqInternalNpcFactory factory; + int npcId; + + int separatorIndex = id.indexOf(SEPARATOR); + if (separatorIndex == -1) { // TODO remove, migration in 1.0 + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Loading NPC with id " + id + " from a previous version of the plugin."); + factory = getMigrationFactory(); + npcId = Integer.parseInt(id); + } else { + String factoryKey = id.substring(0, separatorIndex); + factory = internalFactories.get(factoryKey); + npcId = Integer.parseInt(id.substring(separatorIndex + SEPARATOR.length())); + } + + return new BqNpcImplementation(new WrappedInternalNpc(factory, npcId)); } @Override - public void npcRemoved(int id) { - BqNpcImplementation npc = npcs.get(id); + public void npcRemoved(BqInternalNpcFactory npcFactory, int id) { + String npcId = getNpcId(npcFactory, id); + BqNpcImplementation npc = npcs.get(npcId); if (npc == null) return; - npc.delete("NPC #" + id + " removed"); - npcs.remove(id); + npc.delete("NPC " + npcId + " removed"); + npcs.remove(npcId); } @Override - public void npcClicked(@Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click) { + public void npcClicked(BqInternalNpcFactory npcFactory, @Nullable Cancellable event, int npcID, @NotNull Player p, + @NotNull NpcClickType click) { if (event != null && event.isCancelled()) return; - BQNPCClickEvent newEvent = new BQNPCClickEvent(getById(npcID), p, click); + BQNPCClickEvent newEvent = new BQNPCClickEvent(getById(npcFactory, npcID), p, click); Bukkit.getPluginManager().callEvent(newEvent); if (event != null) event.setCancelled(newEvent.isCancelled()); } @Override - public void reload() { + public void reload(BqInternalNpcFactory npcFactory) { npcs.forEach((id, npc) -> { - BqInternalNpc newInternal = internalFactory.fetchNPC(id); + if (npc.getWrappedNpc().factory != npcFactory) + return; + BqInternalNpc newInternal = npcFactory.fetchNPC(npc.getWrappedNpc().id); if (newInternal == null) { QuestsPlugin.getPlugin().getLoggerExpanded() .warning("Unable to find NPC with ID " + id + " after a NPCs manager reload."); } else { - npc.setNpc(newInternal); + npc.getWrappedNpc().npc = newInternal; } }); } @@ -105,4 +164,32 @@ public void unload() { npcs.clear(); } + class WrappedInternalNpc { + + private final BqInternalNpcFactory factory; + private final int id; + private BqInternalNpc npc; + + public WrappedInternalNpc(BqInternalNpcFactory factory, int id) { + this.factory = factory; + this.id = id; + this.npc = factory.fetchNPC(id); + } + + public WrappedInternalNpc(BqInternalNpcFactory factory, BqInternalNpc npc) { + this.factory = factory; + this.npc = npc; + this.id = npc.getInternalId(); + } + + public @NotNull String getId() { + return getNpcId(factory, id); + } + + public @NotNull BqInternalNpc getNpc() { + return npc; + } + + } + } diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 4000d43e..3b80d43b 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -21,12 +21,12 @@ public OptionStarterNPC() { @Override public Object save() { - return getValue().getNpc().getId(); + return getValue().getId(); } @Override public void load(ConfigurationSection config, String key) { - setValue(QuestsPlugin.getPlugin().getNpcManager().getById(config.getInt(key))); + setValue(QuestsPlugin.getPlugin().getNpcManager().getById(config.getString(key))); } @Override @@ -40,7 +40,7 @@ private List<String> getLore(OptionSet options) { lore.add(null); if (options != null && options.hasOption(OptionQuestPool.class) && options.getOption(OptionQuestPool.class).hasCustomValue()) lore.add(Lang.questStarterSelectPool.toString()); lore.add(getValue() == null ? Lang.NotSet.toString() - : "§7" + getValue().getNpc().getName() + " §8(" + getValue().getNpc().getId() + ")"); + : "§7" + getValue().getNpc().getName() + " §8(" + getValue().getId() + ")"); return lore; } 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 8256302d..4c1db5b8 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -225,7 +225,7 @@ public synchronized void unloadPlayer(@NotNull Player p) { @Override public @UnknownNullability PlayerAccountImplementation getAccount(@NotNull Player p) { - if (BeautyQuests.getInstance().getNpcManager().getInternalFactory().isNPC(p)) + if (BeautyQuests.getInstance().getNpcManager().isNPC(p)) return null; if (!p.isOnline()) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Trying to fetch the account of an offline player (" + p.getName() + ")"); 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 25b87afe..6a819467 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -344,7 +344,7 @@ public void setupLine(@NotNull StageGuiLine line) { line.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString()), event -> { QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, newNPC -> { - setNPCId(newNPC.getNpc().getId()); + setNPCId(newNPC.getId()); event.reopen(); }, false).open(event.getPlayer()); }); @@ -386,7 +386,7 @@ public void setHidden(boolean hidden) { public void start(Player p) { super.start(p); QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(context::removeAndReopenGui, newNPC -> { - setNPCId(newNPC.getNpc().getId()); + setNPCId(newNPC.getId()); context.reopenGui(); }, false).open(p); } 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 9486bd11..ddd078e4 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 @@ -36,7 +36,7 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati private final int id; - private final int npcID; + private final String npcId; private final String hologram; private final int maxQuests; private final int questsPerLaunch; @@ -50,9 +50,10 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati private @Nullable PlaceholderRegistry placeholders; - QuestPoolImplementation(int id, int npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements) { + QuestPoolImplementation(int id, String npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, + long timeDiff, boolean avoidDuplicates, RequirementList requirements) { this.id = id; - this.npcID = npcID; + this.npcId = npcID; this.hologram = hologram; this.maxQuests = maxQuests; this.questsPerLaunch = questsPerLaunch; @@ -61,7 +62,7 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati this.avoidDuplicates = avoidDuplicates; this.requirements = requirements; - if (npcID >= 0) { + if (npcID != null) { npc = BeautyQuests.getInstance().getNpcManager().getById(npcID); if (npc != null) { npc.addPool(this); @@ -77,8 +78,8 @@ public int getId() { } @Override - public int getNpcId() { - return npcID; + public String getNpcId() { + return npcId; } @Override @@ -142,7 +143,7 @@ public int compareTo(QuestPoolImplementation o) { placeholders = new PlaceholderRegistry() .registerIndexed("pool", "#" + id) .register("pool_id", id) - .register("pool_npc", () -> npcID + " (" + (npc == null ? "unknown" : npc.getNpc().getName()) + ")") + .register("pool_npc", () -> npcId + " (" + (npc == null ? "unknown" : npc.getNpc().getName()) + ")") .register("pool_max_quests", maxQuests) .register("pool_quests_per_launch", questsPerLaunch) .register("pool_redo", MessageUtils.getYesNo(redoAllowed)) @@ -328,14 +329,14 @@ public void save(ConfigurationSection config) { if (questsPerLaunch != 1) config.set("questsPerLaunch", questsPerLaunch); config.set("redoAllowed", redoAllowed); config.set("timeDiff", timeDiff); - config.set("npcID", npcID); + config.set("npcID", npcId); config.set("avoidDuplicates", avoidDuplicates); if (!requirements.isEmpty()) config.set("requirements", requirements.serialize()); } public static QuestPoolImplementation deserialize(int id, ConfigurationSection config) { - return new QuestPoolImplementation(id, config.getInt("npcID"), config.getString("hologram"), + return new QuestPoolImplementation(id, config.getString("npcID"), config.getString("hologram"), config.getInt("maxQuests"), config.getInt("questsPerLaunch", 1), config.getBoolean("redoAllowed"), config.getLong("timeDiff"), config.getBoolean("avoidDuplicates", true), RequirementList.deserialize(config.getMapList("requirements"))); diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java index d769603a..cea587fc 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java @@ -57,9 +57,8 @@ public void save(@NotNull QuestPoolImplementation pool) { } @Override - public @NotNull QuestPoolImplementation createPool(@Nullable QuestPool editing, int npcID, @Nullable String hologram, - int maxQuests, - int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, + public @NotNull QuestPoolImplementation createPool(@Nullable QuestPool editing, String npcID, @Nullable String hologram, + int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, @NotNull RequirementList requirements) { if (editing != null) diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java index 4fbb57b7..7933228d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; 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.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.api.npcs.NpcClickType; import net.citizensnpcs.Settings; import net.citizensnpcs.api.CitizensAPI; @@ -24,7 +24,7 @@ import net.citizensnpcs.trait.LookClose; import net.citizensnpcs.trait.SkinTrait; -public class BQCitizens implements BqInternalNpcFactory { +public class BQCitizens implements BqInternalNpcFactoryCreatable { @Override public int getTimeToWaitForNPCs() { @@ -79,10 +79,18 @@ public boolean isValidEntityType(EntityType type) { } @Override - public BqInternalNpc create(Location location, EntityType type, String name) { + public BqInternalNpc create(Location location, EntityType type, String name, @Nullable String skin) { NPC npc = CitizensAPI.getNPCRegistry().createNPC(type, name); if (!Settings.Setting.DEFAULT_LOOK_CLOSE.asBoolean()) npc.getOrAddTrait(LookClose.class).toggle(); npc.spawn(location); + + if (skin == null) { + if (npc.hasTrait(SkinTrait.class)) + npc.getTraitNullable(SkinTrait.class).clearTexture(); + } else if (type == EntityType.PLAYER) { + npc.getOrAddTrait(SkinTrait.class).setSkinName(skin); + } + return new BQCitizensNPC(npc); } @@ -99,7 +107,7 @@ public NPC getCitizensNPC() { } @Override - public int getId() { + public int getInternalId() { return npc.getId(); } @@ -123,16 +131,6 @@ public boolean isSpawned() { return npc.getStoredLocation(); } - @Override - public void setSkin(@Nullable String skin) { - if (skin == null) { - if (npc.hasTrait(SkinTrait.class)) - npc.getTraitNullable(SkinTrait.class).clearTexture(); - } else { - npc.getOrAddTrait(SkinTrait.class).setSkinName(skin); - } - } - @Override public boolean setNavigationPaused(boolean paused) { boolean b = npc.getNavigator().isPaused(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java index d601b6e9..2523f8cd 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java @@ -10,10 +10,11 @@ import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import fr.skytasul.quests.api.npcs.BqInternalNpc; -import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.api.npcs.NpcClickType; import io.github.znetworkw.znpcservers.ServersNPC; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; @@ -23,7 +24,7 @@ import io.github.znetworkw.znpcservers.npc.NPCType; import io.github.znetworkw.znpcservers.npc.event.NPCInteractEvent; -public class BQServerNPCs implements BqInternalNpcFactory { +public class BQServerNPCs implements BqInternalNpcFactoryCreatable { private Cache<Integer, Boolean> cachedNpcs = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); @@ -59,12 +60,16 @@ public boolean isValidEntityType(EntityType type) { } @Override - public @NotNull BqInternalNpc create(Location location, EntityType type, String name) { + public @NotNull BqInternalNpc create(Location location, EntityType type, String name, @Nullable String skin) { List<Integer> ids = ConfigurationConstants.NPC_LIST.stream().map(NPCModel::getId).collect(Collectors.toList()); int id = ids.size(); while (ids.contains(id)) id++; NPC npc = ServersNPC.createNPC(id, NPCType.valueOf(type.name()), location, name); npc.getNpcPojo().getFunctions().put("look", true); + + if (type == EntityType.PLAYER) + NPCSkin.forName(skin, (values, exception) -> npc.changeSkin(NPCSkin.forValues(values))); + return new BQServerNPC(npc); } @@ -87,7 +92,7 @@ public NPC getServerNPC() { } @Override - public int getId() { + public int getInternalId() { return npc.getNpcPojo().getId(); } @@ -111,11 +116,6 @@ public Location getLocation() { return npc.getLocation(); } - @Override - public void setSkin(String skin) { - NPCSkin.forName(skin, (values, exception) -> npc.changeSkin(NPCSkin.forValues(values))); - } - @Override public boolean setNavigationPaused(boolean paused) { return true; diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java index 6bc1e5ff..8044776e 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java @@ -72,7 +72,7 @@ public boolean canContinue(Player p) { private void end(Player p) { if (test(p) != TestResult.ALLOW) { QuestsPlugin.getPlugin().getLoggerExpanded() - .warning("Dialog predicates not completed for NPC " + npc.getNpc().getId() + .warning("Dialog predicates not completed for NPC " + npc.getId() + " whereas the dialog should end. This is a bug."); return; } diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index d561c270..72a4e8fb 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -804,10 +804,10 @@ misc: successPrefix: §2✔ §a requirementNotMetPrefix: §c time: - weeks: '{0} weeks' - days: '{0} days' - hours: '{0} hours' - minutes: '{0} minutes' + weeks: '{weeks_amount} weeks' + days: '{days_amount} days' + hours: '{hours_amount} hours' + minutes: '{minutes_amount} minutes' lessThanAMinute: 'less than a minute' stageType: region: Find region From 245c853fb5a1f537607137d88d0fdbeb4a835391 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 11 Aug 2023 22:34:51 +0200 Subject: [PATCH 31/95] :construction: Cleanup up things --- .../skytasul/quests/api/blocks/BQBlock.java | 3 +- .../quests/api/editors/DialogEditor.java | 5 +- .../quests/api/localization/Lang.java | 5 +- .../api/objects/QuestObjectLoreBuilder.java | 2 +- .../fr/skytasul/quests/api/utils/Utils.java | 69 ------------------- .../skytasul/quests/DefaultQuestFeatures.java | 6 +- .../fr/skytasul/quests/gui/misc/ListBook.java | 4 +- .../quests/npcs/BqNpcImplementation.java | 4 +- .../quests/rewards/TeleportationReward.java | 4 +- .../quests/stages/StageBringBack.java | 3 +- .../skytasul/quests/stages/StageInteract.java | 12 ++-- .../skytasul/quests/stages/StageLocation.java | 3 +- .../fr/skytasul/quests/stages/StageNPC.java | 24 +++---- .../fr/skytasul/quests/utils/QuestUtils.java | 55 +++++++++++++++ .../quests/utils/types/BQLocation.java | 21 +++++- .../types/DialogRunnerImplementation.java | 2 +- core/src/main/resources/locales/en_US.yml | 3 + 17 files changed, 117 insertions(+), 108 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java index 94140e02..0f77b719 100644 --- a/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java +++ b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java @@ -69,7 +69,8 @@ public String toString() { if (placeholders == null) { placeholders = new PlaceholderRegistry() .registerIndexed("block_type", getAsString()) - .register("block_material", getMaterial().name()); + .register("block_material", getMaterial().name()) + .register("block", getName()); } return placeholders; } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java index 435a5640..de60c584 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java @@ -7,7 +7,6 @@ import fr.skytasul.quests.api.npcs.dialogs.Dialog; import fr.skytasul.quests.api.npcs.dialogs.Message; import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.DefaultErrors; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -88,7 +87,7 @@ public boolean chat(String coloredMessage, String strippedMessage){ break; } try{ - msg = Utils.buildFromArray(argsColored, 2, " "); + msg = Arrays.stream(argsColored).skip(2).collect(Collectors.joining(" ")); Sender sender = Sender.valueOf(cmd.name().replace("INSERT", "")); d.insert(msg, sender, Integer.parseInt(args[1])); Lang.valueOf("DIALOG_MSG_ADDED_" + cmd.name()).send(player, PlaceholderRegistry.of("msg", msg)); @@ -104,7 +103,7 @@ public boolean chat(String coloredMessage, String strippedMessage){ } try{ Message message = d.getMessages().get(Integer.parseInt(args[1])); - msg = Utils.buildFromArray(argsColored, 2, " "); + msg = Arrays.stream(argsColored).skip(2).collect(Collectors.joining(" ")); message.text = msg; Lang.DIALOG_MSG_EDITED.send(player, PlaceholderRegistry.of("msg", msg)); }catch (IllegalArgumentException ex){ 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 3d08ab2f..479fb2f4 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 @@ -8,6 +8,7 @@ /** * Stores all string paths and methods to format and send them to players. */ +@SuppressWarnings("squid:S115") public enum Lang implements Locale { /* Formats (must be first to be used after) */ @@ -551,7 +552,6 @@ public enum Lang implements Locale { INVENTORY_REWARDS("inv.rewards.name"), commands("inv.rewards.commands"), - teleportation("inv.rewards.teleportation"), rewardRandomRewards("inv.rewards.random.rewards"), rewardRandomMinMax("inv.rewards.random.minMax"), @@ -782,7 +782,7 @@ public enum Lang implements Locale { Enchant("misc.stageType.Enchant"), Craft("misc.stageType.Craft"), Bucket("misc.stageType.Bucket"), - Location("misc.stageType.location"), + StageLocation("misc.stageType.location"), PlayTime("misc.stageType.playTime"), Breed("misc.stageType.breedAnimals"), Tame("misc.stageType.tameAnimals"), @@ -837,6 +837,7 @@ public enum Lang implements Locale { EntityTypeAny("misc.entityTypeAny"), QuestItemLore("misc.questItemLore"), Ticks("misc.ticks"), + Location("misc.location"), Enabled("misc.enabled"), Disabled("misc.disabled"), Unknown("misc.unknown"), diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java index 6d397e06..58f96cc8 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java @@ -38,7 +38,7 @@ public void addDescription(@Nullable String line) { } public void addDescriptionAsValue(@Nullable Object value) { - addDescription(QuestOption.formatNullableValue(value == null ? null : value.toString())); + addDescription(QuestOption.formatNullableValue(value)); } public void addClick(@Nullable ClickType click, @NotNull String action) { diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java index 69648558..16a4130b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/Utils.java @@ -27,21 +27,13 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemoryConfiguration; import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.scoreboard.DisplaySlot; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsConfiguration; -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.utils.messaging.MessageUtils; -import fr.skytasul.quests.utils.nms.NMS; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; /** * A bunch of static methods who can be useful @@ -52,19 +44,6 @@ public class Utils{ public static Optional<String> getFilenameExtension(String filename) { return Optional.ofNullable(filename).filter(f -> f.contains(".")).map(f -> f.substring(filename.lastIndexOf(".") + 1)); } - - public static void openBook(Player p, ItemStack book){ - int slot = p.getInventory().getHeldItemSlot(); - ItemStack old = p.getInventory().getItem(slot); - p.getInventory().setItem(slot, book); - - ByteBuf buf = Unpooled.buffer(256); - buf.setByte(0, (byte) 0); - buf.writerIndex(1); - - NMS.getNMS().sendPacket(p, NMS.getNMS().bookPacket(buf)); - p.getInventory().setItem(slot, old); - } public static String ticksToElapsedTime(int ticks) { int i = ticks / 20; @@ -110,54 +89,6 @@ public static String getStringFromItemStack(ItemStack is, String amountColor, bo return ItemUtils.getName(is, true) + ((is.getAmount() > 1 || showXOne) ? "§r" + amountColor + " x" + is.getAmount() : ""); } - public static String getStringFromNameAndAmount(String name, String amountColor, int remaining, int total, boolean showXOne) { - int done = total - remaining; - int percentage = (int) (done / (double) total * 100); - String string = name; - if (remaining > 1 || showXOne) { - string += "§r" + amountColor + " " - + MessageUtils.format(QuestsConfiguration.getConfig().getStageDescriptionConfig().getSplitAmountFormat(), - remaining, done, total, percentage); - } - return string; - } - - public static String locationToString(Location lc){ - if (lc == null) return null; - return Lang.teleportation.format(lc.getBlockX(), lc.getBlockY(), lc.getBlockZ(), lc.getWorld() == null ? Lang.Unknown.toString() : lc.getWorld().getName()); - } - - private static boolean cachedScoreboardPresent = false; - private static long cachedScoreboardPresenceExp = 0; - public static Location upLocationForEntity(LivingEntity en, double value) { - double height = value; - height += QuestsConfiguration.getHologramsHeight(); - height += NMS.getNMS().entityNameplateHeight(en); - if (en instanceof Player) { - if (cachedScoreboardPresenceExp < System.currentTimeMillis()) { - cachedScoreboardPresenceExp = System.currentTimeMillis() + 60_000; - cachedScoreboardPresent = Bukkit.getScoreboardManager().getMainScoreboard().getObjective(DisplaySlot.BELOW_NAME) != null; - // as a new Objective object is allocated each time we check this, - // it is better to cache the boolean for memory consumption. - // scoreboards are not intended to change frequently, therefore it is - // not a problem to cache this value for a minute. - } - if (cachedScoreboardPresent) height += 0.24; - } - return en.getLocation().add(0, height, 0); - } - - public static boolean isSimilar(ItemStack item1, ItemStack item2) { - if (item2.getType() == item1.getType() && item2.getDurability() == item1.getDurability()) { - try { - return NMS.getNMS().equalsWithoutNBT(item1.getItemMeta(), item2.getItemMeta()); - }catch (ReflectiveOperationException ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while attempting to compare items using NMS", ex); - } - } - return false; - } - public static void giveItems(Player p, List<ItemStack> items) { HashMap<Integer, ItemStack> leftover = p.getInventory().addItem(items.stream().map(ItemStack::clone).toArray(ItemStack[]::new)); if (!leftover.isEmpty()) { diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index 6fdc5d0c..d6de0e28 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -25,7 +25,6 @@ import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.progress.HasProgress; import fr.skytasul.quests.options.OptionAutoQuest; import fr.skytasul.quests.options.OptionBypassLimit; @@ -93,6 +92,7 @@ import fr.skytasul.quests.stages.StagePlayTime; import fr.skytasul.quests.stages.StageTame; import fr.skytasul.quests.stages.options.StageOptionProgressBar; +import fr.skytasul.quests.utils.QuestUtils; public final class DefaultQuestFeatures { @@ -143,7 +143,7 @@ public static void registerStages() { StageCraft::deserialize, stageCraft, StageCraft.Creator::new)); QuestsAPI.getAPI().getStages().register(new StageType<>("BUCKET", StageBucket.class, Lang.Bucket.name(), StageBucket::deserialize, stageBucket, StageBucket.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("LOCATION", StageLocation.class, Lang.Location.name(), + QuestsAPI.getAPI().getStages().register(new StageType<>("LOCATION", StageLocation.class, Lang.StageLocation.name(), StageLocation::deserialize, stageLocation, StageLocation.Creator::new)); QuestsAPI.getAPI().getStages().register(new StageType<>("PLAY_TIME", StagePlayTime.class, Lang.PlayTime.name(), StagePlayTime::deserialize, stagePlayTime, StagePlayTime.Creator::new)); @@ -307,7 +307,7 @@ public static void registerItemComparisons() { QuestsAPI.getAPI().registerItemComparison(new ItemComparison("bukkit", Lang.comparisonBukkit.toString(), Lang.comparisonBukkitLore.toString(), ItemStack::isSimilar).setEnabledByDefault()); QuestsAPI.getAPI().registerItemComparison(new ItemComparison("customBukkit", Lang.comparisonCustomBukkit.toString(), - Lang.comparisonCustomBukkitLore.toString(), Utils::isSimilar)); + Lang.comparisonCustomBukkitLore.toString(), QuestUtils::isSimilar)); QuestsAPI.getAPI().registerItemComparison(new ItemComparison("material", Lang.comparisonMaterial.toString(), Lang.comparisonMaterialLore.toString(), (item1, item2) -> { if (item2.getType() != item1.getType()) diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java index 98462d56..c6a7fe3b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/ListBook.java @@ -7,9 +7,9 @@ import org.bukkit.inventory.meta.BookMeta; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.options.OptionRequirements; import fr.skytasul.quests.options.OptionStarterNPC; +import fr.skytasul.quests.utils.QuestUtils; public class ListBook{ @@ -42,7 +42,7 @@ public static void openQuestBook(Player p){ } is.setItemMeta(im); - Utils.openBook(p, is); + QuestUtils.openBook(p, is); } private static String formatLine(String title, String object){ 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 01d43bde..76d12ae2 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java @@ -37,7 +37,6 @@ import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.stages.types.Locatable.Located; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.npcs.BqNpcManagerImplementation.WrappedInternalNpc; import fr.skytasul.quests.options.OptionHologramLaunch; @@ -45,6 +44,7 @@ import fr.skytasul.quests.options.OptionHologramText; import fr.skytasul.quests.options.OptionStarterNPC; import fr.skytasul.quests.structure.pools.QuestPoolImplementation; +import fr.skytasul.quests.utils.QuestUtils; public class BqNpcImplementation implements Located.LocatedEntity, BqNpc { @@ -429,7 +429,7 @@ public Hologram(boolean visible, boolean enabled, ItemStack item) { } public void refresh(LivingEntity en) { - Location lc = Utils.upLocationForEntity(en, getYAdd()); + Location lc = QuestUtils.upLocationForEntity(en, getYAdd()); if (debug) System.out.println("refreshing " + toString() + " (hologram null: " + (hologram == null) + ")"); if (hologram == null) { create(lc); 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 b0d8e932..9200da50 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java @@ -9,9 +9,9 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.QuestUtils; +import fr.skytasul.quests.utils.types.BQLocation; public class TeleportationReward extends AbstractReward { @@ -38,7 +38,7 @@ public AbstractReward clone() { @Override protected void addLore(QuestObjectLoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescriptionAsValue(Utils.locationToString(teleportation)); + loreBuilder.addDescriptionAsValue(Lang.Location.format(new BQLocation(teleportation))); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 9fdc36b3..6e5204de 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -90,7 +90,8 @@ public boolean checkItems(Player p, boolean msg){ public void sendNeedMessage(Player p) { new Message(MessageUtils.format(getMessage(), getPlaceholdersRegistry(), StageDescriptionPlaceholdersContext.of(true, - PlayersManager.getPlayerAccount(p), DescriptionSource.FORCELINE)), Sender.NPC).sendMessage(p, npcName(), 1, 1); + PlayersManager.getPlayerAccount(p), DescriptionSource.FORCELINE)), Sender.NPC).sendMessage(p, getNPC(), + getNpcName(), 1, 1); } public void removeItems(Player p){ diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java index dea36c01..aae50384 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java @@ -22,7 +22,6 @@ import fr.skytasul.quests.api.gui.layout.LayoutedButton; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; @@ -34,7 +33,6 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.blocks.SelectBlockGUI; import fr.skytasul.quests.utils.types.BQLocation; @@ -182,7 +180,7 @@ public void setLocation(Location location) { }); } getLine().refreshItem(7, - item -> ItemUtils.lore(item, QuestOption.formatDescription(Utils.locationToString(location)))); + item -> ItemUtils.loreOptionValue(item, Lang.Location.format(getBQLocation()))); this.location = location; } @@ -195,7 +193,7 @@ public void setMaterial(BQBlock block) { }).open(event.getPlayer()); }); } - getLine().refreshItem(7, item -> ItemUtils.lore(item, Lang.optionValue.format(block.getName()))); + getLine().refreshItem(7, item -> ItemUtils.loreOptionValue(item, block.getName())); this.block = block; } @@ -225,6 +223,10 @@ public void start(Player p) { .build().open(p); } + private @NotNull BQLocation getBQLocation() { + return new BQLocation(location); + } + @Override public void edit(StageInteract stage) { super.edit(stage); @@ -237,7 +239,7 @@ public void edit(StageInteract stage) { @Override public StageInteract finishStage(StageController controller) { if (location != null) { - return new StageInteract(controller, leftClick, new BQLocation(location)); + return new StageInteract(controller, leftClick, getBQLocation()); }else return new StageInteract(controller, leftClick, block); } 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 94e44eec..7d1baef8 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -26,7 +26,6 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.compatibility.GPS; @@ -191,7 +190,7 @@ public void setupLine(@NotNull StageGuiLine line) { public void setLocation(Location location) { this.location = location; getLine().refreshItem(SLOT_LOCATION, - item -> ItemUtils.lore(item, QuestOption.formatDescription(Utils.locationToString(location)))); + item -> ItemUtils.loreOptionValue(item, Lang.Location.format(getBQLocation()))); } public void setRadius(int radius) { 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 6a819467..77a2b8e7 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -39,8 +39,8 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; @@ -48,7 +48,7 @@ public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable { private BqNpc npc; - private int npcID; + private String npcID; protected Dialog dialog = null; protected DialogRunnerImplementation dialogRunner = null; protected boolean hide = false; @@ -92,7 +92,7 @@ public void run() { if (hologram == null) createHoloLaunch(); hologram.setPlayersVisible(tmp); - hologram.teleport(Utils.upLocationForEntity((LivingEntity) en, 1)); + hologram.teleport(QuestUtils.upLocationForEntity((LivingEntity) en, 1)); } if (QuestsConfigurationImplementation.getConfiguration().showTalkParticles()) { @@ -125,14 +125,14 @@ public BqNpc getNPC() { return npc; } - public int getNPCID() { + public String getNPCID() { return npcID; } - public void setNPC(int npcID) { + public void setNPC(String npcID) { this.npcID = npcID; - if (npcID >= 0) - this.npc = QuestsPlugin.getPlugin().getNpcManager().getById(npcID); + if (npcID != null) + npc = QuestsPlugin.getPlugin().getNpcManager().getById(npcID); if (npc == null) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("The NPC " + npcID + " does not exist for " + toString()); } else { @@ -180,7 +180,7 @@ public Located getLocated() { @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); - placeholders.registerIndexed("dialog_npc_name", this::npcName); + placeholders.registerIndexed("dialog_npc_name", this::getNpcName); placeholders.compose(npc); } @@ -208,7 +208,7 @@ public void onClick(BQNPCClickEvent e) { e.setCancelled(dialogRunner.onClick(p).shouldCancel()); } - protected String npcName() { + protected String getNpcName() { if (npc == null) return "§c§lunknown NPC " + npcID; if (dialog != null && dialog.getNpcName() != null) @@ -302,7 +302,7 @@ protected void loadDatas(ConfigurationSection section) { if (section.contains("msg")) setDialog(Dialog.deserialize(section.getConfigurationSection("msg"))); if (section.contains("npcID")) { - setNPC(section.getInt("npcID")); + setNPC(section.getString("npcID")); } else QuestsPlugin.getPlugin().getLoggerExpanded().warning("No NPC specified for " + toString()); if (section.contains("hid")) @@ -330,7 +330,7 @@ public abstract static class AbstractCreator<T extends StageNPC> extends StageCr private static final int SLOT_NPC = 7; private static final int SLOT_DIALOG = 8; - private int npcID = -1; + private String npcID = null; private Dialog dialog = null; private boolean hidden = false; @@ -361,7 +361,7 @@ public void setupLine(@NotNull StageGuiLine line) { line.setItem(SLOT_HIDE, ItemUtils.itemSwitch(Lang.stageHide.toString(), hidden), event -> setHidden(!hidden)); } - public void setNPCId(int npcID) { + public void setNPCId(String npcID) { this.npcID = npcID; getLine().refreshItem(SLOT_NPC, item -> ItemUtils.lore(item, QuestOption.formatDescription("ID: §l" + npcID))); } 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 673c592a..dd87711b 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -6,19 +6,74 @@ import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.entity.Firework; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.scoreboard.DisplaySlot; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.utils.AutoRegistered; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.utils.nms.NMS; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; public class QuestUtils { + public static void openBook(Player p, ItemStack book) { + int slot = p.getInventory().getHeldItemSlot(); + ItemStack old = p.getInventory().getItem(slot); + p.getInventory().setItem(slot, book); + + ByteBuf buf = Unpooled.buffer(256); + buf.setByte(0, (byte) 0); + buf.writerIndex(1); + + NMS.getNMS().sendPacket(p, NMS.getNMS().bookPacket(buf)); + p.getInventory().setItem(slot, old); + } + + private static boolean cachedScoreboardPresent = false; + private static long cachedScoreboardPresenceExp = 0; + + public static Location upLocationForEntity(LivingEntity en, double value) { + double height = value; + height += QuestsConfigurationImplementation.getConfiguration().getHologramsHeight(); + height += NMS.getNMS().entityNameplateHeight(en); + if (en instanceof Player) { + if (cachedScoreboardPresenceExp < System.currentTimeMillis()) { + cachedScoreboardPresenceExp = System.currentTimeMillis() + 60_000; + cachedScoreboardPresent = + Bukkit.getScoreboardManager().getMainScoreboard().getObjective(DisplaySlot.BELOW_NAME) != null; + // as a new Objective object is allocated each time we check this, + // it is better to cache the boolean for memory consumption. + // scoreboards are not intended to change frequently, therefore it is + // not a problem to cache this value for a minute. + } + if (cachedScoreboardPresent) + height += 0.24; + } + return en.getLocation().add(0, height, 0); + } + + public static boolean isSimilar(ItemStack item1, ItemStack item2) { + if (item2.getType() == item1.getType() && item2.getDurability() == item1.getDurability()) { + try { + return NMS.getNMS().equalsWithoutNBT(item1.getItemMeta(), item2.getItemMeta()); + } catch (ReflectiveOperationException ex) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("An error occurred while attempting to compare items using NMS", ex); + } + } + return false; + } + public static void runOrSync(Runnable run) { if (Bukkit.isPrimaryThread()) { run.run(); 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 a4adc1b4..f5d7d32e 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 @@ -14,10 +14,14 @@ 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; -public class BQLocation extends Location implements Locatable.Located { +public class BQLocation extends Location implements Locatable.Located, HasPlaceholders { - private Pattern worldPattern; + private @Nullable Pattern worldPattern; + + private @Nullable PlaceholderRegistry placeholders; public BQLocation(Location bukkit) { this(bukkit.getWorld(), bukkit.getX(), bukkit.getY(), bukkit.getZ(), bukkit.getYaw(), bukkit.getPitch()); @@ -88,6 +92,19 @@ public Block getMatchingBlock() { .orElse(null); } + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) + placeholders = new PlaceholderRegistry() + .register("x", () -> Integer.toString(getBlockX())) + .register("y", () -> Integer.toString(getBlockY())) + .register("z", () -> Integer.toString(getBlockZ())) + .register("world", () -> getWorldName()) + .register("world_name", () -> getWorld() == null ? null : getWorld().getName()) + .register("world_pattern", () -> worldPattern.pattern()); + return placeholders; + } + @Override public double distanceSquared(Location o) { Validate.isTrue(isWorld(o.getWorld()), "World does not match"); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java index 8044776e..6b8b7853 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java @@ -173,7 +173,7 @@ private boolean send(Player p, PlayerStatus status, DialogNextReason reason) { DialogSendMessageEvent event = new DialogSendMessageEvent(dialog, msg, npc, p); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) - status.runningMsgTask = msg.sendMessage(p, dialog.getNPCName(npc), id, dialog.getMessages().size()); + status.runningMsgTask = msg.sendMessage(p, npc, dialog.getNPCName(npc), id, dialog.getMessages().size()); return false; } diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 72a4e8fb..53e213d9 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -872,6 +872,9 @@ misc: mobs: '{mobs_amount} mob(s)' xp: '{xp_amount} experience point(s)' ticks: '{ticks} ticks' + location: |- + Location: {x} {y} {z} + World: {world} questItemLore: §e§oQuest Item hologramText: §8§lQuest NPC poolHologramText: §eNew quest available! From f0187ded0a7fbf1da020ac3f076b1b598667320d Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 15 Aug 2023 16:30:42 +0200 Subject: [PATCH 32/95] :building_construction: Separated integrations into another project --- .../quests/api}/AbstractMapIntegration.java | 19 +- .../fr/skytasul/quests/api/QuestsAPI.java | 7 + .../fr/skytasul/quests/api/QuestsPlugin.java | 8 +- .../fr/skytasul/quests/api/quests/Quest.java | 3 + .../quests/api/utils/IntegrationManager.java | 162 ++++++++++ .../utils}/MissingDependencyException.java | 2 +- .../api/utils/logger/LoggerExpanded.java | 12 + .../api/utils/messaging/MessageProcessor.java | 24 ++ .../api/utils/messaging/MessageUtils.java | 15 +- core/pom.xml | 293 +++--------------- .../java/fr/skytasul/quests/BeautyQuests.java | 46 ++- .../skytasul/quests/DefaultQuestFeatures.java | 47 +++ .../quests/QuestsAPIImplementation.java | 14 + .../QuestsConfigurationImplementation.java | 37 +-- .../mobs/BukkitEntityFactory.java | 8 +- .../players/AbstractPlayersManager.java | 13 +- .../BqAccountsHook.java} | 4 +- .../skytasul/quests/stages/StageLocation.java | 57 +--- .../fr/skytasul/quests/stages/StageNPC.java | 11 - .../quests/structure/QuestImplementation.java | 29 +- .../fr/skytasul/quests/utils/DebugUtils.java | 13 - .../compatibility/DependenciesManager.java | 288 ----------------- .../quests/utils/compatibility/Factions.java | 21 -- .../quests/utils/compatibility/GPS.java | 27 -- .../compatibility/InternalIntegrations.java | 18 ++ .../quests/utils/compatibility/Jobs.java | 22 -- .../utils/compatibility/McCombatLevel.java | 16 - .../quests/utils/compatibility/McMMO.java | 12 - .../skytasul/quests/utils/types/Command.java | 12 +- core/src/main/resources/config.yml | 6 +- core/src/main/resources/locales/en_US.yml | 2 +- dist/pom.xml | 7 + integrations/pom.xml | 275 ++++++++++++++++ .../skytasul/quests/integrations}/BQCMI.java | 2 +- .../integrations}/BQDecentHolograms.java | 4 +- .../integrations}/BQHolographicDisplays2.java | 6 +- .../integrations}/BQHolographicDisplays3.java | 2 +- .../quests/integrations}/BQItemsAdder.java | 4 +- .../quests/integrations}/BQTokenEnchant.java | 2 +- .../integrations}/BQUltimateTimber.java | 2 +- .../IntegrationsConfiguration.java | 43 +++ .../integrations/IntegrationsLoader.java | 222 +++++++++++++ .../factions}/FactionRequirement.java | 5 +- .../jobs}/JobLevelRequirement.java | 14 +- .../quests/integrations}/maps/BQBlueMap.java | 21 +- .../quests/integrations}/maps/BQDynmap.java | 18 +- .../mcmmo}/McCombatLevelRequirement.java | 6 +- .../mcmmo}/McMMOSkillRequirement.java | 11 +- .../mobs/BQAdvancedSpawners.java | 2 +- .../quests/integrations}/mobs/BQBoss.java | 4 +- .../integrations}/mobs/BQLevelledMobs.java | 34 +- .../integrations}/mobs/BQWildStacker.java | 2 +- .../integrations}/mobs/CitizensFactory.java | 9 +- .../quests/integrations}/mobs/EpicBosses.java | 2 +- .../quests/integrations}/mobs/MythicMobs.java | 12 +- .../integrations}/mobs/MythicMobs5.java | 12 +- .../quests/integrations}/npcs/BQCitizens.java | 2 +- .../quests/integrations}/npcs/BQSentinel.java | 2 +- .../integrations}/npcs/BQServerNPCs.java | 2 +- .../placeholders/PapiMessageProcessor.java | 26 ++ .../placeholders}/PlaceholderRequirement.java | 3 +- .../placeholders}/QuestsPlaceholders.java | 18 +- .../skillapi}/ClassRequirement.java | 3 +- .../integrations/skillapi}/SkillAPI.java | 2 +- .../skillapi}/SkillAPILevelRequirement.java | 3 +- .../quests/integrations/vault}/Vault.java | 2 +- .../vault/economy}/MoneyRequirement.java | 4 +- .../vault/economy}/MoneyReward.java | 4 +- .../vault/permission}/Permission.java | 4 +- .../vault/permission}/PermissionGUI.java | 3 +- .../vault/permission}/PermissionListGUI.java | 3 +- .../vault/permission}/PermissionReward.java | 4 +- .../worldguard/BQWorldGuard.java | 6 +- .../worldguard}/RegionRequirement.java | 3 +- .../integrations/worldguard}/StageArea.java | 11 +- .../worldguard/WorldGuardEntryEvent.java | 2 +- .../worldguard/WorldGuardEntryHandler.java | 6 +- .../worldguard/WorldGuardExitEvent.java | 2 +- pom.xml | 1 + 79 files changed, 1136 insertions(+), 949 deletions(-) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility/maps => api/src/main/java/fr/skytasul/quests/api}/AbstractMapIntegration.java (65%) create mode 100755 api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => api/src/main/java/fr/skytasul/quests/api/utils}/MissingDependencyException.java (80%) create mode 100755 api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java rename core/src/main/java/fr/skytasul/quests/{utils/compatibility => }/mobs/BukkitEntityFactory.java (85%) rename core/src/main/java/fr/skytasul/quests/{utils/compatibility/Accounts.java => players/BqAccountsHook.java} (91%) delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java create mode 100755 core/src/main/java/fr/skytasul/quests/utils/compatibility/InternalIntegrations.java delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java delete mode 100644 core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java create mode 100644 integrations/pom.xml rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/BQCMI.java (94%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/BQDecentHolograms.java (98%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/BQHolographicDisplays2.java (91%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/BQHolographicDisplays3.java (98%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/BQItemsAdder.java (96%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/BQTokenEnchant.java (92%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/BQUltimateTimber.java (94%) create mode 100644 integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java create mode 100644 integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/factions}/FactionRequirement.java (93%) rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/jobs}/JobLevelRequirement.java (83%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/maps/BQBlueMap.java (81%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/maps/BQDynmap.java (69%) rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo}/McCombatLevelRequirement.java (85%) rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo}/McMMOSkillRequirement.java (87%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/BQAdvancedSpawners.java (96%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/BQBoss.java (91%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/BQLevelledMobs.java (55%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/BQWildStacker.java (90%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/CitizensFactory.java (87%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/EpicBosses.java (92%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/MythicMobs.java (88%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/mobs/MythicMobs5.java (91%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/npcs/BQCitizens.java (98%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/npcs/BQSentinel.java (97%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/npcs/BQServerNPCs.java (98%) create mode 100644 integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/placeholders}/PlaceholderRequirement.java (95%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations/placeholders}/QuestsPlaceholders.java (93%) rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/skillapi}/ClassRequirement.java (94%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations/skillapi}/SkillAPI.java (90%) rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/skillapi}/SkillAPILevelRequirement.java (93%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations/vault}/Vault.java (94%) rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy}/MoneyRequirement.java (92%) rename {core/src/main/java/fr/skytasul/quests/rewards => integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy}/MoneyReward.java (91%) rename {core/src/main/java/fr/skytasul/quests/utils/types => integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission}/Permission.java (90%) rename {core/src/main/java/fr/skytasul/quests/gui/permissions => integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission}/PermissionGUI.java (94%) rename {core/src/main/java/fr/skytasul/quests/gui/permissions => integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission}/PermissionListGUI.java (90%) rename {core/src/main/java/fr/skytasul/quests/rewards => integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission}/PermissionReward.java (90%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/worldguard/BQWorldGuard.java (92%) rename {core/src/main/java/fr/skytasul/quests/requirements => integrations/src/main/java/fr/skytasul/quests/integrations/worldguard}/RegionRequirement.java (93%) rename {core/src/main/java/fr/skytasul/quests/stages => integrations/src/main/java/fr/skytasul/quests/integrations/worldguard}/StageArea.java (91%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/worldguard/WorldGuardEntryEvent.java (92%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/worldguard/WorldGuardEntryHandler.java (91%) rename {core/src/main/java/fr/skytasul/quests/utils/compatibility => integrations/src/main/java/fr/skytasul/quests/integrations}/worldguard/WorldGuardExitEvent.java (92%) diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/AbstractMapIntegration.java b/api/src/main/java/fr/skytasul/quests/api/AbstractMapIntegration.java similarity index 65% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/AbstractMapIntegration.java rename to api/src/main/java/fr/skytasul/quests/api/AbstractMapIntegration.java index 0d97b31d..0928483a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/AbstractMapIntegration.java +++ b/api/src/main/java/fr/skytasul/quests/api/AbstractMapIntegration.java @@ -1,12 +1,9 @@ -package fr.skytasul.quests.utils.compatibility.maps; +package fr.skytasul.quests.api; import org.bukkit.Location; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsHandler; -import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; -import fr.skytasul.quests.options.OptionStarterNPC; public abstract class AbstractMapIntegration implements QuestsHandler { @@ -17,22 +14,23 @@ public final void load() { } private void initializeQuests() { - if (QuestsAPI.getAPI().getQuestsManager() != null) - QuestsAPI.getAPI().getQuestsManager().getQuests().forEach(this::questLoaded); + QuestsAPI.getAPI().getQuestsManager().getQuests().forEach(this::questLoaded); } @Override public void questLoaded(Quest quest) { if (!isEnabled()) return; - if (!quest.hasOption(OptionStarterNPC.class)) + + BqNpc starter = quest.getStarterNpc(); + if (starter == null) return; if (quest.isHidden(QuestVisibilityLocation.MAPS)) { QuestsPlugin.getPlugin().getLoggerExpanded().debug("No marker created for quest " + quest.getId() + ": quest is hidden"); return; } - Location lc = quest.getOptionValueOrDef(OptionStarterNPC.class).getLocation(); + Location lc = starter.getLocation(); if (lc == null) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot create map marker for quest #" + quest.getId() + " (" + quest.getName() + ")"); }else { @@ -42,7 +40,8 @@ public void questLoaded(Quest quest) { @Override public void questUnload(Quest quest) { - if (!quest.isHidden(QuestVisibilityLocation.MAPS) && quest.hasOption(OptionStarterNPC.class)) removeMarker(quest); + if (!quest.isHidden(QuestVisibilityLocation.MAPS) && quest.getStarterNpc() != null) + removeMarker(quest); } public abstract boolean isEnabled(); diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java index 951b681a..d8f35551 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -2,6 +2,7 @@ import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,6 +20,7 @@ import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.RewardCreator; import fr.skytasul.quests.api.stages.StageTypeRegistry; +import fr.skytasul.quests.api.utils.messaging.MessageProcessor; /** * This class contains most of the useful accessors to fetch data from BeautyQuests and methods to @@ -92,6 +94,11 @@ public interface QuestsAPI { void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> consumer); + @NotNull + Set<MessageProcessor> getMessageProcessors(); + + void registerMessageProcessor(@NotNull MessageProcessor processor); + public static @NotNull QuestsAPI getAPI() { return QuestsAPIProvider.getAPI(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java index a6accd9c..703080d0 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java @@ -7,6 +7,7 @@ import fr.skytasul.quests.api.gui.GuiManager; import fr.skytasul.quests.api.npcs.BqNpcManager; import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.utils.IntegrationManager; import fr.skytasul.quests.api.utils.logger.LoggerExpanded; public interface QuestsPlugin extends Plugin { @@ -25,15 +26,16 @@ public interface QuestsPlugin extends Plugin { public @NotNull EditorManager getEditorManager(); + public @NotNull BqNpcManager getNpcManager(); + + public @NotNull IntegrationManager getIntegrationManager(); + public @NotNull String getPrefix(); // TODO maybe not necessary public void notifyLoadingFailure(); public void noticeSavingFailure(); - @NotNull - BqNpcManager getNpcManager(); - public static @NotNull QuestsPlugin getPlugin() { return QuestsAPIProvider.getAPI().getPlugin(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java index 9c135e6b..cdcdafbb 100644 --- a/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java +++ b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java @@ -6,6 +6,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.description.DescriptionSource; @@ -38,6 +39,8 @@ public interface Quest extends OptionSet, Comparable<Quest>, HasPlaceholders { public @NotNull ItemStack getQuestItem(); + public @Nullable BqNpc getStarterNpc(); + public boolean isScoreboardEnabled(); public boolean isCancellable(); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java b/api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java new file mode 100755 index 00000000..7a0e4468 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java @@ -0,0 +1,162 @@ +package fr.skytasul.quests.api.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.plugin.Plugin; +import fr.skytasul.quests.api.QuestsPlugin; + +public class IntegrationManager implements Listener { + + private List<BQDependency> dependencies; + private boolean dependenciesTested = false; + private boolean dependenciesInitialized = false; + private boolean lockDependencies = false; + + public List<BQDependency> getDependencies() { + return dependencies; + } + + public void addDependency(BQDependency dependency) { + if (lockDependencies) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("Trying to add a BQ dependency for plugin " + dependency.pluginNames + " after final locking."); + return; + } + dependencies.add(dependency); + if (dependenciesTested) { + if (dependency.testCompatibility(true) && dependenciesInitialized) + dependency.initialize(); + } + } + + public void testCompatibilities() { + if (dependenciesTested) + return; + dependencies.forEach(x -> x.testCompatibility(false)); + dependenciesTested = true; + } + + public void initializeCompatibilities() { + if (dependenciesInitialized) + return; + dependencies.stream().filter(BQDependency::isEnabled).forEach(BQDependency::initialize); + dependenciesInitialized = true; + } + + public void disableCompatibilities() { + dependencies.forEach(BQDependency::disable); + } + + public void lockDependencies() { + lockDependencies = true; + } + + @EventHandler + public void onPluginEnable(PluginEnableEvent e) { + if (lockDependencies) + return; + // if (dependenciesTested) return; + dependencies.stream().filter(x -> !x.enabled && x.isPlugin(e.getPlugin())).findAny().ifPresent(dependency -> { + if (dependency.testCompatibility(true) && dependenciesInitialized) + dependency.initialize(); + }); + } + + public static class BQDependency { + private final List<String> pluginNames; + private final Runnable initialize; + private final Runnable disable; + private final Predicate<Plugin> isValid; + private boolean enabled = false; + private boolean forceDisable = false; + private boolean initialized = false; + private Plugin foundPlugin; + + public BQDependency(String pluginName) { + this(pluginName, null); + } + + public BQDependency(String pluginName, Runnable initialize) { + this(pluginName, initialize, null, null); + } + + public BQDependency(String pluginName, Runnable initialize, Runnable disable) { + this(pluginName, initialize, disable, null); + } + + public BQDependency(String pluginName, Runnable initialize, Runnable disable, Predicate<Plugin> isValid) { + Validate.notNull(pluginName); + this.pluginNames = new ArrayList<>(); + this.pluginNames.add(pluginName); + this.initialize = initialize; + this.disable = disable; + this.isValid = isValid; + } + + public BQDependency addPluginName(String name) { + pluginNames.add(name); + return this; + } + + boolean isPlugin(Plugin plugin) { + return pluginNames.contains(plugin.getName()); + } + + boolean testCompatibility(boolean after) { + if (forceDisable) + return false; + Plugin plugin = pluginNames.stream().map(Bukkit.getPluginManager()::getPlugin) + .filter(x -> x != null && x.isEnabled()).findAny().orElse(null); + if (plugin == null) + return false; + if (isValid != null && !isValid.test(plugin)) + return false; + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Hooked into " + pluginNames + " v" + + plugin.getDescription().getVersion() + (after ? " after primary initialization" : "")); + enabled = true; + foundPlugin = plugin; + return true; + } + + void initialize() { + try { + if (initialize != null) + initialize.run(); + initialized = true; + } catch (Throwable ex) { + QuestsPlugin.getPlugin().getLoggerExpanded() + .severe("An error occurred while initializing " + pluginNames.toString() + " integration", ex); + enabled = false; + } + } + + public void disable() { + forceDisable = true; + if (enabled) { + enabled = false; + if (disable != null && initialized) + disable.run(); + initialized = false; + } + } + + public boolean isEnabled() { + return enabled; + } + + public Plugin getFoundPlugin() { + if (!enabled) + throw new IllegalStateException( + "The dependency " + pluginNames + " is not enabled"); + return foundPlugin; + } + + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/MissingDependencyException.java b/api/src/main/java/fr/skytasul/quests/api/utils/MissingDependencyException.java similarity index 80% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/MissingDependencyException.java rename to api/src/main/java/fr/skytasul/quests/api/utils/MissingDependencyException.java index a4526671..b259dbf4 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/MissingDependencyException.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/MissingDependencyException.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.api.utils; public class MissingDependencyException extends RuntimeException{ diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java b/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java index dd70a883..13e61072 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/logger/LoggerExpanded.java @@ -1,5 +1,7 @@ package fr.skytasul.quests.api.utils.logger; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CompletionException; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -15,6 +17,8 @@ public class LoggerExpanded { private final @NotNull Logger logger; private final @NotNull ILoggerHandler handler; + private final Map<Object, Long> times = new HashMap<>(); + public LoggerExpanded(@NotNull Logger logger, @Nullable ILoggerHandler handler) { this.logger = logger; this.handler = handler == null ? ILoggerHandler.EMPTY_LOGGER : handler; @@ -36,6 +40,14 @@ public void warning(@Nullable String msg, @Nullable Throwable throwable) { logger.log(Level.WARNING, msg, throwable); } + public void warning(@Nullable String msg, @NotNull Object type, int seconds) { + Long time = times.get(type); + if (time == null || time.longValue() + seconds * 1000 < System.currentTimeMillis()) { + logger.warning(msg); + times.put(type, System.currentTimeMillis()); + } + } + public void severe(@Nullable String msg) { logger.log(Level.SEVERE, msg); } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java new file mode 100755 index 00000000..a9c08f69 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java @@ -0,0 +1,24 @@ +package fr.skytasul.quests.api.utils.messaging; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface MessageProcessor extends Comparable<MessageProcessor> { + + default @Nullable PlaceholderRegistry processPlaceholders(@Nullable PlaceholderRegistry placeholders, + @NotNull PlaceholdersContext context) { + return placeholders; + } + + default @NotNull String processString(@NotNull String string, @NotNull PlaceholdersContext context) { + return string; + } + + int getPriority(); + + @Override + default int compareTo(MessageProcessor o) { + return Integer.compare(getPriority(), o.getPriority()); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java index 677587b0..1a4d65d9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -3,13 +3,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.ChatColorUtils; -import net.md_5.bungee.api.ChatColor; public class MessageUtils { @@ -47,15 +45,10 @@ public static void sendRawMessage(@NotNull CommandSender sender, @Nullable Strin public static String finalFormat(@NotNull String text, @Nullable PlaceholderRegistry placeholders, @NotNull PlaceholdersContext context) { - if (DependenciesManager.papi.isEnabled() && context.getActor() instanceof Player) - text = QuestsPlaceholders.setPlaceholders((Player) context.getActor(), text); - if (context.replacePluginPlaceholders()) { - text = text - .replace("{player}", context.getActor().getName()) - .replace("{PLAYER}", context.getActor().getName()) - .replace("{PREFIX}", QuestsPlugin.getPlugin().getPrefix()); + for (MessageProcessor processor : QuestsAPI.getAPI().getMessageProcessors()) { + placeholders = processor.processPlaceholders(placeholders, context); + text = processor.processString(text, context); } - text = ChatColor.translateAlternateColorCodes('&', text); return format(text, placeholders, context); } diff --git a/core/pom.xml b/core/pom.xml index 7d0a8840..52f3d890 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -41,11 +41,13 @@ </relocation> <relocation> <pattern>com.tchristofferson.configupdater</pattern> - <shadedPattern>fr.skytasul.quests.utils.configupdater</shadedPattern> + <shadedPattern> + fr.skytasul.quests.utils.configupdater</shadedPattern> </relocation> <relocation> <pattern>com.jeff_media.updatechecker</pattern> - <shadedPattern>fr.skytasul.quests.utils.updatechecker</shadedPattern> + <shadedPattern> + fr.skytasul.quests.utils.updatechecker</shadedPattern> </relocation> <relocation> <pattern>com.zaxxer.hikari</pattern> @@ -85,155 +87,73 @@ <url>https://repo.papermc.io/repository/maven-public/</url> </repository> <repository> - <id>placeholderapi</id> - <url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url> - </repository> - <repository> - <id>dynmap</id> - <url>https://repo.mikeprimm.com/</url> - </repository> - <repository> - <id>sk89q-repo</id> - <url>https://maven.enginehub.org/repo/</url> + <id>jeff-media-public</id> + <url>https://hub.jeff-media.com/nexus/repository/jeff-media-public/</url> </repository> <repository> <id>codemc-repo</id> <url>https://repo.codemc.io/repository/maven-public/</url> </repository> - <repository> - <id>mineacademy-repo</id> - <url>https://bitbucket.org/kangarko/libraries/raw/master</url> - </repository> <repository> <id>jitpack.io</id> <url>https://jitpack.io</url> </repository> - <repository> - <id>maven-central</id> - <url>https://oss.sonatype.org/content/groups/public</url> - </repository> - <repository> - <id>teamvk-repo</id> - <url>https://raw.githubusercontent.com/TeamVK/maven-repository/master/release/</url> - </repository> - <repository> - <id>lumine</id> - <url>https://mvn.lumine.io/repository/maven-public/</url> - <releases> - <updatePolicy>interval:10080</updatePolicy> - </releases> - <snapshots> - <updatePolicy>interval:10080</updatePolicy> - </snapshots> - </repository> - <repository> - <id>citizens</id> - <url>http://repo.citizensnpcs.co/</url> <!-- really slow repo --> - <releases> - <updatePolicy>interval:10080</updatePolicy> - </releases> - <snapshots> - <updatePolicy>interval:10080</updatePolicy> - </snapshots> - </repository> - <repository> - <id>jeff-media-public</id> - <url>https://hub.jeff-media.com/nexus/repository/jeff-media-public/</url> - </repository> - <repository> - <id>bg-repo</id> - <url>https://repo.bg-software.com/repository/api/</url> - </repository> </repositories> <dependencies> - <dependency> - <groupId>fr.skytasul</groupId> - <artifactId>beautyquests-api</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.jetbrains</groupId> - <artifactId>annotations</artifactId> - <version>24.0.0</version> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-api</artifactId> + <version>${project.version}</version> <scope>provided</scope> </dependency> - - <dependency> - <groupId>com.zaxxer</groupId> - <artifactId>HikariCP</artifactId> - <version>4.0.3</version> <!-- For Java 8 compatibility --> - </dependency> + <!-- Development dependencies --> <dependency> - <groupId>io.papermc.paper</groupId> - <artifactId>paper-api</artifactId> - <version>1.19.4-R0.1-SNAPSHOT</version> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>net.citizensnpcs</groupId> - <artifactId>citizens-main</artifactId> - <version>2.0.31-SNAPSHOT</version> - <type>jar</type> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.mcmonkey</groupId> - <artifactId>sentinel</artifactId> - <version>2.7.3-SNAPSHOT</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>io.github.znetworkw.znpcservers</groupId> - <artifactId>znpcservers</artifactId> - <version>3.6</version> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>24.0.0</version> <scope>provided</scope> </dependency> <dependency> - <groupId>com.github.MilkBowl</groupId> - <artifactId>VaultAPI</artifactId> - <version>1.7</version> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> <scope>provided</scope> </dependency> <dependency> - <groupId>me.clip</groupId> - <artifactId>placeholderapi</artifactId> - <version>2.11.3</version> + <groupId>io.papermc.paper</groupId> + <artifactId>paper-api</artifactId> + <version>1.19.4-R0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> - <groupId>com.gmail.filoghost.holographicdisplays</groupId> - <artifactId>holographicdisplays-api</artifactId> - <version>2.4.9</version> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <version>4.1.68.Final</version> <scope>provided</scope> </dependency> + + <!-- Integrations that must be in core --> <dependency> - <groupId>me.filoghost.holographicdisplays</groupId> - <artifactId>holographicdisplays-api</artifactId> - <version>3.0.1</version> + <groupId>fr.skytasul</groupId> + <artifactId>accountshook</artifactId> + <version>1.4.0</version> <scope>provided</scope> </dependency> <dependency> - <groupId>com.sk89q.worldguard</groupId> - <artifactId>worldguard-bukkit</artifactId> - <version>7.0.7</version> + <groupId>com.github.Flo0</groupId> + <artifactId>PlayerBlockTracker</artifactId> + <version>1.0.2</version> <scope>provided</scope> - <exclusions> - <exclusion> - <groupId>net.java.truevfs</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> </dependency> + + <!-- Included libraries --> <dependency> - <groupId>fr.skytasul</groupId> - <artifactId>accountshook</artifactId> - <version>1.4.0</version> - <scope>provided</scope> + <groupId>com.zaxxer</groupId> + <artifactId>HikariCP</artifactId> + <version>4.0.3</version> <!-- For Java 8 compatibility --> + <scope>compile</scope> </dependency> <dependency> <groupId>org.bstats</groupId> @@ -251,30 +171,7 @@ <groupId>com.tchristofferson</groupId> <artifactId>ConfigUpdater</artifactId> <version>2.0-SNAPSHOT</version> - </dependency> - <dependency> - <groupId>io.lumine.xikage</groupId> - <artifactId>MythicMobs</artifactId> - <version>4.12.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>io.lumine</groupId> - <artifactId>Mythic-Dist</artifactId> - <version>5.2.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.github.promcteam</groupId> - <artifactId>proskillapi</artifactId> - <version>1.1.7.0.3</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.github.BlueMap-Minecraft</groupId> - <artifactId>BlueMapAPI</artifactId> - <version>v2.5.0</version> - <scope>provided</scope> + <scope>compile</scope> </dependency> <dependency> <groupId>com.jeff_media</groupId> @@ -282,121 +179,5 @@ <version>3.0.0</version> <scope>compile</scope> </dependency> - <dependency> - <groupId>com.vk2gpz.tokenenchant</groupId> - <artifactId>TokenEnchantAPI</artifactId> - <version>18.37.1</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.github.decentsoftware-eu</groupId> - <artifactId>decentholograms</artifactId> - <version>2.8.1</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.github.Flo0</groupId> - <artifactId>PlayerBlockTracker</artifactId> - <version>1.0.2</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.github.lokka30</groupId> - <artifactId>LevelledMobs</artifactId> - <version>3.2.6</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.bgsoftware</groupId> - <artifactId>WildStackerAPI</artifactId> - <version>2022.6</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.github.LoneDev6</groupId> - <artifactId>api-itemsadder</artifactId> - <version>3.2.5</version> - <scope>provided</scope> - </dependency> - - <!-- Local JARs --> - <dependency> - <groupId>org.mineacademy</groupId> - <artifactId>boss</artifactId> - <version>4.2.1</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.songoda</groupId> - <artifactId>UltimateTimber</artifactId> - <version>2.3.5</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.dynmap</groupId> - <artifactId>dynmap</artifactId> - <version>1.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.massivecraft</groupId> - <artifactId>factions</artifactId> - <version>1.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.massivecraft</groupId> - <artifactId>massivecore</artifactId> - <version>1.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.live.bemmamin</groupId> - <artifactId>gps</artifactId> - <version>1.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.gamingmesh</groupId> - <artifactId>jobs</artifactId> - <version>5.1.0.1</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.gmail.mrphpfan</groupId> - <artifactId>mccombatlevel</artifactId> - <version>1.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.gmail.nossr50</groupId> - <artifactId>mcmmo</artifactId> - <version>1.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.suxy</groupId> - <artifactId>skillapi</artifactId> - <version>1.0</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.zrips</groupId> - <artifactId>cmi</artifactId> - <version>9.0.2.1</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.zrips</groupId> - <artifactId>cmilib</artifactId> - <version>1.2.3.3</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>gcspawners</groupId> - <artifactId>gcspawners</artifactId> - <version>3.3.0</version> - <scope>provided</scope> - </dependency> </dependencies> </project> diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 5b82f34d..3b25ba2e 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -41,6 +41,7 @@ import fr.skytasul.quests.api.gui.GuiManager; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.localization.Locale; +import fr.skytasul.quests.api.utils.IntegrationManager; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.logger.LoggerExpanded; import fr.skytasul.quests.commands.CommandsManagerImplementation; @@ -56,10 +57,8 @@ import fr.skytasul.quests.structure.QuestsManagerImplementation; import fr.skytasul.quests.structure.pools.QuestPoolsManagerImplementation; import fr.skytasul.quests.utils.Database; -import fr.skytasul.quests.utils.compatibility.BQBossBarImplementation; -import fr.skytasul.quests.utils.compatibility.DependenciesManager; +import fr.skytasul.quests.utils.compatibility.InternalIntegrations; import fr.skytasul.quests.utils.compatibility.Post1_16; -import fr.skytasul.quests.utils.compatibility.mobs.BukkitEntityFactory; import fr.skytasul.quests.utils.logger.LoggerHandler; import fr.skytasul.quests.utils.nms.NMS; @@ -99,7 +98,7 @@ public class BeautyQuests extends JavaPlugin implements QuestsPlugin { protected boolean savingFailure = false; protected boolean loaded = false; - private @NotNull DependenciesManager dependencies = new DependenciesManager(); + private @NotNull IntegrationManager integrations = new IntegrationManager(); private @Nullable CommandsManagerImplementation command; private @Nullable LoggerExpanded logger; private @Nullable LoggerHandler loggerHandler; @@ -143,8 +142,9 @@ public void onEnable(){ checkPaper(); - dependencies.testCompatibilities(); - Bukkit.getPluginManager().registerEvents(dependencies, this); + loadDefaultIntegrations(); + integrations.testCompatibilities(); + Bukkit.getPluginManager().registerEvents(integrations, this); saveDefaultConfig(); NMS.isValid(); // to force initialization @@ -157,7 +157,7 @@ public void onEnable(){ registerCommands(); try { - dependencies.initializeCompatibilities(); + integrations.initializeCompatibilities(); }catch (Exception ex) { logger.severe("An error occurred while initializing compatibilities. Consider restarting.", ex); } @@ -216,7 +216,7 @@ public void run() { setEnabled(false); } } - + @Override public void onDisable(){ try { @@ -240,7 +240,7 @@ public void onDisable(){ logger.severe("An error occurred while saving config.", e); } try { - dependencies.disableCompatibilities(); + integrations.disableCompatibilities(); }catch (Exception e) { logger.severe("An error occurred while disabling plugin integrations.", e); } @@ -331,7 +331,7 @@ private void launchMetrics(String pluginVersion) { return "0 - 5"; })); metrics.addCustomChart(new AdvancedPie("hooks", () -> { // replace with bar chart when bStats add them back - return dependencies.getDependencies() + return integrations.getDependencies() .stream() .filter(dep -> dep.isEnabled()) .map(dep -> dep.getFoundPlugin().getName()) @@ -411,11 +411,11 @@ private void loadConfigParameters(boolean init) throws LoadingException { DefaultQuestFeatures.registerRequirements(); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default stage options."); DefaultQuestFeatures.registerStageOptions(); + QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default miscellenaeous."); + DefaultQuestFeatures.registerMisc(); + DefaultQuestFeatures.registerMessageProcessors(); getServer().getPluginManager().registerEvents(guiManager = new GuiManagerImplementation(), this); getServer().getPluginManager().registerEvents(editorManager = new EditorManagerImplementation(), this); - getAPI().registerMobFactory(new BukkitEntityFactory()); - if (MinecraftVersion.MAJOR >= 9) - getAPI().setBossBarManager(new BQBossBarImplementation()); } }catch (LoadingException ex) { throw ex; @@ -423,6 +423,19 @@ private void loadConfigParameters(boolean init) throws LoadingException { throw new LoadingException("Error while loading configuration and initializing values", ex); } } + + + private void loadDefaultIntegrations() { + try { + Class<?> loaderClass = Class.forName("fr.skytasul.quests.integrations.IntegrationsLoader"); + loaderClass.getDeclaredConstructor().newInstance(); + } catch (ClassNotFoundException ex) { + logger.warning("Could not find integrations loader class."); + } catch (ReflectiveOperationException ex) { + logger.severe("Cannot load default integrations.", ex); + } + InternalIntegrations.AccountsHook.isEnabled(); // to initialize the class + } private YamlConfiguration loadLang() throws LoadingException { try { @@ -461,7 +474,7 @@ private void loadDataFile() throws LoadingException { private void loadAllDatas() throws Throwable { if (disable) return; - dependencies.lockDependencies(); + integrations.lockDependencies(); // command.lockCommands(); we cannot register Brigadier after plugin initialization... if (scoreboards == null && config.getQuestsConfig().scoreboards()) { @@ -784,6 +797,11 @@ public boolean hasSavingFailed() { return npcManager; } + @Override + public @NotNull IntegrationManager getIntegrationManager() { + return integrations; + } + @Override public @NotNull QuestsAPIImplementation getAPI() { return QuestsAPIImplementation.INSTANCE; diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index d6de0e28..7c2ada84 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -9,6 +9,7 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -25,7 +26,11 @@ import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.api.utils.messaging.MessageProcessor; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.api.utils.progress.HasProgress; +import fr.skytasul.quests.mobs.BukkitEntityFactory; import fr.skytasul.quests.options.OptionAutoQuest; import fr.skytasul.quests.options.OptionBypassLimit; import fr.skytasul.quests.options.OptionCancelRewards; @@ -93,6 +98,8 @@ import fr.skytasul.quests.stages.StageTame; import fr.skytasul.quests.stages.options.StageOptionProgressBar; import fr.skytasul.quests.utils.QuestUtils; +import fr.skytasul.quests.utils.compatibility.BQBossBarImplementation; +import net.md_5.bungee.api.ChatColor; public final class DefaultQuestFeatures { @@ -348,4 +355,44 @@ public static void registerItemComparisons() { }).setMetaNeeded()); } + public static void registerMisc() { + QuestsAPI.getAPI().registerMobFactory(new BukkitEntityFactory()); + if (MinecraftVersion.MAJOR >= 9) + QuestsAPI.getAPI().setBossBarManager(new BQBossBarImplementation()); + } + + public static void registerMessageProcessors() { + PlaceholderRegistry defaultPlaceholders = new PlaceholderRegistry() + .registerContextual("player", PlaceholdersContext.class, context -> context.getActor().getName()) + .registerContextual("PLAYER", PlaceholdersContext.class, context -> context.getActor().getName()) + .register("prefix", () -> QuestsPlugin.getPlugin().getPrefix()); + + QuestsAPI.getAPI().registerMessageProcessor(new MessageProcessor() { + @Override + public PlaceholderRegistry processPlaceholders(PlaceholderRegistry placeholders, PlaceholdersContext context) { + if (context.replacePluginPlaceholders()) + return placeholders == null ? defaultPlaceholders : placeholders.with(defaultPlaceholders); + else + return placeholders; + } + + @Override + public int getPriority() { + return 1; + } + }); + + QuestsAPI.getAPI().registerMessageProcessor(new MessageProcessor() { + @Override + public String processString(String string, PlaceholdersContext context) { + return ChatColor.translateAlternateColorCodes('&', string); + } + + @Override + public int getPriority() { + return 10; + } + }); + } + } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java index 57168897..e0f17690 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -6,6 +6,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.TreeSet; import java.util.function.Consumer; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; @@ -29,6 +30,7 @@ import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.RewardCreator; import fr.skytasul.quests.api.stages.StageTypeRegistry; +import fr.skytasul.quests.api.utils.messaging.MessageProcessor; import fr.skytasul.quests.blocks.BQBlocksManagerImplementation; import fr.skytasul.quests.utils.QuestUtils; @@ -50,6 +52,8 @@ public class QuestsAPIImplementation implements QuestsAPI { private final Set<QuestsHandler> handlers = new HashSet<>(); + private final Set<MessageProcessor> processors = new TreeSet<>(); + private QuestsAPIImplementation() {} @Override @@ -199,6 +203,16 @@ public void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> co }); } + @Override + public @NotNull Set<MessageProcessor> getMessageProcessors() { + return processors; + } + + @Override + public void registerMessageProcessor(@NotNull MessageProcessor processor) { + processors.add(processor); + } + @Override public @NotNull QuestsManager getQuestsManager() { return BeautyQuests.getInstance().getQuestsManager(); diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index ee2c2424..2bb4381b 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -28,9 +28,9 @@ import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.PlayerListCategory; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.players.BqAccountsHook; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; -import fr.skytasul.quests.utils.compatibility.Accounts; import fr.skytasul.quests.utils.compatibility.DependenciesManager; public class QuestsConfigurationImplementation implements QuestsConfiguration { @@ -40,8 +40,6 @@ public static QuestsConfigurationImplementation getConfiguration() { } private String minecraftTranslationsFile = null; - private boolean gps = false; - private boolean skillAPIoverride = true; private boolean enablePrefix = true; private double hologramsHeight = 0.0; private boolean disableTextHologram = false; @@ -51,9 +49,6 @@ public static QuestsConfigurationImplementation getConfiguration() { private ParticleEffect particleStart; private ParticleEffect particleTalk; private ParticleEffect particleNext; - private String dSetName = "Quests"; - private String dIcon = "bookshelf"; - private int dMinZoom = 0; private ItemStack holoLaunchItem = null; private ItemStack holoLaunchNoItem = null; @@ -67,7 +62,7 @@ public static QuestsConfigurationImplementation getConfiguration() { int saveCycle = 15; int firstQuestID = -1; // changed in 0.19, TODO - private FileConfiguration config; + private final FileConfiguration config; private QuestsConfig quests; private DialogsConfig dialogs; private QuestsMenuConfig menu; @@ -108,22 +103,16 @@ void init() { saveCycle = config.getInt("saveCycle"); saveCycleMessage = config.getBoolean("saveCycleMessage"); firstQuestID = config.getInt("firstQuest", -1); - gps = DependenciesManager.gps.isEnabled() && config.getBoolean("gps"); - skillAPIoverride = config.getBoolean("skillAPIoverride"); enablePrefix = config.getBoolean("enablePrefix"); disableTextHologram = config.getBoolean("disableTextHologram"); showCustomHologramName = config.getBoolean("showCustomHologramName"); hologramsHeight = 0.28 + config.getDouble("hologramsHeight"); hookAcounts = DependenciesManager.acc.isEnabled() && config.getBoolean("accountsHook"); if (hookAcounts) { - Bukkit.getPluginManager().registerEvents(new Accounts(), BeautyQuests.getInstance()); + Bukkit.getPluginManager().registerEvents(new BqAccountsHook(), BeautyQuests.getInstance()); QuestsPlugin.getPlugin().getLoggerExpanded().info("AccountsHook is now managing player datas for quests !"); } usePlayerBlockTracker = DependenciesManager.PlayerBlockTracker.isEnabled() && config.getBoolean("usePlayerBlockTracker"); - dSetName = config.getString("dynmap.markerSetName"); - if (dSetName == null || dSetName.isEmpty()) DependenciesManager.dyn.disable(); - dIcon = config.getString("dynmap.markerIcon"); - dMinZoom = config.getInt("dynmap.minZoom"); if (MinecraftVersion.MAJOR >= 9) { particleStart = loadParticles("start", new ParticleEffect(Particle.REDSTONE, ParticleShape.POINT, Color.YELLOW)); @@ -244,14 +233,6 @@ public FileConfiguration getConfig() { public String getPrefix() { return (enablePrefix) ? Lang.Prefix.toString() : "§6"; } - - public boolean handleGPS() { - return gps; - } - - public boolean xpOverridedSkillAPI() { - return skillAPIoverride; - } public boolean isTextHologramDisabled() { return disableTextHologram; @@ -312,18 +293,6 @@ public boolean hookAccounts() { public boolean usePlayerBlockTracker() { return usePlayerBlockTracker; } - - public String dynmapSetName() { - return dSetName; - } - - public String dynmapMarkerIcon() { - return dIcon; - } - - public int dynmapMinimumZoom() { - return dMinZoom; - } public boolean isMinecraftTranslationsEnabled() { return minecraftTranslationsFile != null && !minecraftTranslationsFile.isEmpty(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java b/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java similarity index 85% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java rename to core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java index a763a8ff..981eed65 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BukkitEntityFactory.java +++ b/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.mobs; import java.util.Arrays; import java.util.List; @@ -12,7 +12,6 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -64,14 +63,15 @@ public EntityType getEntityType(EntityType data) { @Override public List<String> getDescriptiveLore(EntityType data) { - return Arrays.asList(Lang.EntityType.format(MinecraftNames.getEntityName(data))); + return Arrays.asList(Lang.EntityType.quickFormat("entity_type", MinecraftNames.getEntityName(data))); } @EventHandler public void onEntityKilled(EntityDeathEvent e) { LivingEntity en = e.getEntity(); if (en.getKiller() == null) return; - if (QuestsAPI.getAPI().getNPCsManager().isNPC(en)) return; + if (QuestsPlugin.getPlugin().getNpcManager().isNPC(en)) + return; callEvent(e, en.getType(), en, en.getKiller()); } 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 4c1db5b8..72765d50 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -29,11 +29,10 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.MissingDependencyException; import fr.skytasul.quests.players.accounts.AbstractAccount; import fr.skytasul.quests.players.accounts.UUIDAccount; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.compatibility.Accounts; -import fr.skytasul.quests.utils.compatibility.MissingDependencyException; +import fr.skytasul.quests.utils.DebugUtils; public abstract class AbstractPlayersManager implements PlayersManager { @@ -95,7 +94,7 @@ public void addAccountData(@NotNull SavableData<?> data) { } protected @NotNull AbstractAccount createAbstractAccount(@NotNull Player p) { - return QuestsConfigurationImplementation.getConfiguration().hookAccounts() ? Accounts.getPlayerAccount(p) + return QuestsConfigurationImplementation.getConfiguration().hookAccounts() ? BqAccountsHook.getPlayerAccount(p) : new UUIDAccount(p.getUniqueId()); } @@ -103,7 +102,7 @@ public void addAccountData(@NotNull SavableData<?> data) { if (QuestsConfigurationImplementation.getConfiguration().hookAccounts()) { if (!p.isOnline()) throw new IllegalArgumentException("Cannot fetch player identifier of an offline player with AccountsHook"); - return "Hooked|" + Accounts.getPlayerCurrentIdentifier(p.getPlayer()); + return "Hooked|" + BqAccountsHook.getPlayerCurrentIdentifier(p.getPlayer()); } return p.getUniqueId().toString(); } @@ -115,7 +114,7 @@ public void addAccountData(@NotNull SavableData<?> data) { "AccountsHook is not enabled or config parameter is disabled, but saved datas need it."); String nidentifier = identifier.substring(7); try{ - return Accounts.getAccountFromIdentifier(nidentifier); + return BqAccountsHook.getAccountFromIdentifier(nidentifier); }catch (Exception ex){ ex.printStackTrace(); } @@ -124,7 +123,7 @@ public void addAccountData(@NotNull SavableData<?> data) { UUID uuid = UUID.fromString(identifier); if (QuestsConfigurationImplementation.getConfiguration().hookAccounts()) { try{ - return Accounts.createAccountFromUUID(uuid); + return BqAccountsHook.createAccountFromUUID(uuid); }catch (UnsupportedOperationException ex){ QuestsPlugin.getPlugin().getLoggerExpanded().warning("Can't migrate an UUID account to a hooked one."); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Accounts.java b/core/src/main/java/fr/skytasul/quests/players/BqAccountsHook.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/Accounts.java rename to core/src/main/java/fr/skytasul/quests/players/BqAccountsHook.java index ae2ab048..3c23413a 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Accounts.java +++ b/core/src/main/java/fr/skytasul/quests/players/BqAccountsHook.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.players; import java.util.UUID; import org.bukkit.Bukkit; @@ -12,7 +12,7 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.players.accounts.HookedAccount; -public class Accounts implements Listener { +public class BqAccountsHook implements Listener { public static final AccountService service = Bukkit.getServicesManager().getRegistration(AccountService.class).getProvider(); 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 7d1baef8..fc63f5da 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -16,7 +16,6 @@ import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; -import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; @@ -28,7 +27,6 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.npc.NpcCreateGUI; -import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.BQLocation; @LocatableType (types = LocatedType.OTHER) @@ -37,25 +35,18 @@ public class StageLocation extends AbstractStage implements Locatable.PreciseLoc private final BQLocation lc; private final int radius; private final int radiusSquared; - private final boolean gps; - public StageLocation(StageController controller, BQLocation lc, int radius, boolean gps) { + public StageLocation(StageController controller, BQLocation lc, int radius) { super(controller); this.lc = lc; this.radius = radius; this.radiusSquared = radius * radius; - this.gps = gps; } public BQLocation getLocation() { return lc; } - @Override - public boolean isShown(Player player) { - return isGPSEnabled(); - } - @Override public Located getLocated() { return lc; @@ -65,10 +56,6 @@ public int getRadius(){ return radius; } - public boolean isGPSEnabled() { - return gps; - } - @EventHandler public void onPlayerMove(PlayerMoveEvent e){ if (e.getFrom().getBlockX() == e.getTo().getBlockX() && e.getFrom().getBlockY() == e.getTo().getBlockY() @@ -82,40 +69,6 @@ public void onPlayerMove(PlayerMoveEvent e){ } } - @Override - public void joined(Player p) { - super.joined(p); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) - GPS.launchCompass(p, lc); - } - - @Override - public void left(Player p) { - super.left(p); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) - GPS.stopCompass(p); - } - - @Override - public void started(PlayerAccount acc) { - super.started(acc); - if (acc.isCurrent()) { - Player p = acc.getPlayer(); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) - GPS.launchCompass(p, lc); - } - } - - @Override - public void ended(PlayerAccount acc) { - super.ended(acc); - if (acc.isCurrent()) { - Player p = acc.getPlayer(); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && gps) - GPS.stopCompass(p); - } - } - @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); @@ -134,11 +87,12 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol protected void serialize(ConfigurationSection section) { section.set("location", lc.serialize()); section.set("radius", radius); - if (!gps) section.set("gps", false); } public static StageLocation deserialize(ConfigurationSection section, StageController controller) { - return new StageLocation(controller, BQLocation.deserialize(section.getConfigurationSection("location").getValues(false)), section.getInt("radius"), section.getBoolean("gps", true)); + return new StageLocation(controller, + BQLocation.deserialize(section.getConfigurationSection("location").getValues(false)), + section.getInt("radius")); } public static class Creator extends StageCreation<StageLocation> { @@ -238,12 +192,11 @@ public void edit(StageLocation stage) { setLocation(stage.getLocation()); setRadius(stage.getRadius()); setPattern(stage.getLocation().getWorldPattern()); - setGPS(stage.isGPSEnabled()); } @Override public StageLocation finishStage(StageController controller) { - return new StageLocation(controller, getBQLocation(), radius, gps); + return new StageLocation(controller, getBQLocation(), radius); } } 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 77a2b8e7..176de9c7 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -41,7 +41,6 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.QuestUtils; -import fr.skytasul.quests.utils.compatibility.GPS; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; @LocatableType(types = LocatedType.ENTITY) @@ -220,8 +219,6 @@ protected String getNpcName() { public void joined(Player p) { super.joined(p); cachePlayer(p); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) - GPS.launchCompass(p, npc.getLocation()); } private void cachePlayer(Player p) { @@ -237,8 +234,6 @@ private void uncachePlayer(Player p) { } private void uncacheAll() { - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) - cached.forEach(GPS::stopCompass); if (npc != null) cached.forEach(p -> npc.removeHiddenForPlayer(p, this)); } @@ -247,8 +242,6 @@ private void uncacheAll() { public void left(Player p) { super.left(p); uncachePlayer(p); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) - GPS.stopCompass(p); if (dialogRunner != null) dialogRunner.removePlayer(p); } @@ -259,8 +252,6 @@ public void started(PlayerAccount acc) { if (acc.isCurrent()) { Player p = acc.getPlayer(); cachePlayer(p); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && npc != null) - GPS.launchCompass(p, npc.getLocation()); } } @@ -272,8 +263,6 @@ public void ended(PlayerAccount acc) { if (dialogRunner != null) dialogRunner.removePlayer(p); uncachePlayer(p); - if (QuestsConfigurationImplementation.getConfiguration().handleGPS() && !hide) - GPS.stopCompass(p); } } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index ee681320..1d4e1a91 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -31,6 +31,7 @@ import fr.skytasul.quests.api.events.QuestPreLaunchEvent; import fr.skytasul.quests.api.events.QuestRemoveEvent; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.options.QuestOptionCreator; import fr.skytasul.quests.api.options.description.DescriptionSource; @@ -51,7 +52,28 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.npcs.BqNpcImplementation; -import fr.skytasul.quests.options.*; +import fr.skytasul.quests.options.OptionBypassLimit; +import fr.skytasul.quests.options.OptionCancelRewards; +import fr.skytasul.quests.options.OptionCancellable; +import fr.skytasul.quests.options.OptionConfirmMessage; +import fr.skytasul.quests.options.OptionDescription; +import fr.skytasul.quests.options.OptionEndMessage; +import fr.skytasul.quests.options.OptionEndRewards; +import fr.skytasul.quests.options.OptionEndSound; +import fr.skytasul.quests.options.OptionFirework; +import fr.skytasul.quests.options.OptionHideNoRequirements; +import fr.skytasul.quests.options.OptionName; +import fr.skytasul.quests.options.OptionQuestItem; +import fr.skytasul.quests.options.OptionQuestPool; +import fr.skytasul.quests.options.OptionRepeatable; +import fr.skytasul.quests.options.OptionRequirements; +import fr.skytasul.quests.options.OptionScoreboardEnabled; +import fr.skytasul.quests.options.OptionStartDialog; +import fr.skytasul.quests.options.OptionStartMessage; +import fr.skytasul.quests.options.OptionStartRewards; +import fr.skytasul.quests.options.OptionStarterNPC; +import fr.skytasul.quests.options.OptionTimer; +import fr.skytasul.quests.options.OptionVisibility; import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.rewards.MessageReward; import fr.skytasul.quests.structure.pools.QuestPoolImplementation; @@ -207,6 +229,11 @@ public boolean canBypassLimit() { return getOptionValueOrDef(OptionBypassLimit.class); } + @Override + public @Nullable BqNpc getStarterNpc() { + return getOptionValueOrDef(OptionStarterNPC.class); + } + public boolean hasAsyncStart() { return getOptionValueOrDef(OptionStartRewards.class).hasAsync(); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java b/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java index e5161e0b..d9e02172 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/DebugUtils.java @@ -1,16 +1,11 @@ package fr.skytasul.quests.utils; -import java.util.HashMap; -import java.util.Map; import java.util.StringJoiner; -import fr.skytasul.quests.api.QuestsPlugin; public class DebugUtils { private DebugUtils() {} - private static Map<String, Long> errors = new HashMap<>(); - public static String stackTraces(int from, int to){ StringJoiner joiner = new StringJoiner(" -> "); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); @@ -20,13 +15,5 @@ public static String stackTraces(int from, int to){ } return joiner.toString(); } - - public static void printError(String errorMsg, String typeID, int seconds) { - Long time = errors.get(typeID); - if (time == null || time.longValue() + seconds * 1000 < System.currentTimeMillis()) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning(errorMsg); - errors.put(typeID, System.currentTimeMillis()); - } - } } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java deleted file mode 100644 index 94eb28b6..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/DependenciesManager.java +++ /dev/null @@ -1,288 +0,0 @@ -package fr.skytasul.quests.utils.compatibility; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Predicate; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.server.PluginEnableEvent; -import org.bukkit.plugin.Plugin; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.api.QuestsAPI; -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.requirements.RequirementCreator; -import fr.skytasul.quests.api.rewards.RewardCreator; -import fr.skytasul.quests.requirements.ClassRequirement; -import fr.skytasul.quests.requirements.FactionRequirement; -import fr.skytasul.quests.requirements.JobLevelRequirement; -import fr.skytasul.quests.requirements.McCombatLevelRequirement; -import fr.skytasul.quests.requirements.McMMOSkillRequirement; -import fr.skytasul.quests.requirements.MoneyRequirement; -import fr.skytasul.quests.requirements.PlaceholderRequirement; -import fr.skytasul.quests.requirements.SkillAPILevelRequirement; -import fr.skytasul.quests.rewards.MoneyReward; -import fr.skytasul.quests.rewards.PermissionReward; -import fr.skytasul.quests.utils.compatibility.maps.BQBlueMap; -import fr.skytasul.quests.utils.compatibility.maps.BQDynmap; -import fr.skytasul.quests.utils.compatibility.mobs.BQAdvancedSpawners; -import fr.skytasul.quests.utils.compatibility.mobs.BQBoss; -import fr.skytasul.quests.utils.compatibility.mobs.BQLevelledMobs; -import fr.skytasul.quests.utils.compatibility.mobs.BQWildStacker; -import fr.skytasul.quests.utils.compatibility.mobs.CitizensFactory; -import fr.skytasul.quests.utils.compatibility.mobs.MythicMobs; -import fr.skytasul.quests.utils.compatibility.mobs.MythicMobs5; -import fr.skytasul.quests.utils.compatibility.npcs.BQCitizens; -import fr.skytasul.quests.utils.compatibility.npcs.BQSentinel; -import fr.skytasul.quests.utils.compatibility.npcs.BQServerNPCs; -import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; - -public class DependenciesManager implements Listener { - - public static final BQDependency znpcs = - new BQDependency("ServersNPC", () -> QuestsAPI.getAPI().setNpcFactory(new BQServerNPCs()), null, plugin -> { - if (plugin.getClass().getName().equals("io.github.znetworkw.znpcservers.ServersNPC")) // NOSONAR - return true; - - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of znpcs (" + plugin.getDescription().getVersion() + ") is not supported by BeautyQuests."); - return false; - }); - - public static final BQDependency citizens = new BQDependency("Citizens", () -> { - QuestsAPI.getAPI().setNpcFactory(new BQCitizens()); - QuestsAPI.getAPI().registerMobFactory(new CitizensFactory()); - }); - - public static final BQDependency vault = new BQDependency("Vault", () -> { - QuestsAPI.getAPI().getRewards().register(new RewardCreator("moneyReward", MoneyReward.class, ItemUtils.item(XMaterial.EMERALD, Lang.rewardMoney.toString()), MoneyReward::new)); - QuestsAPI.getAPI().getRewards().register(new RewardCreator("permReward", PermissionReward.class, ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.rewardPerm.toString()), PermissionReward::new)); - QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("moneyRequired", MoneyRequirement.class, ItemUtils.item(XMaterial.EMERALD, Lang.RMoney.toString()), MoneyRequirement::new)); - }); - - public static final BQDependency papi = new BQDependency("PlaceholderAPI", () -> { - QuestsPlaceholders.registerPlaceholders(BeautyQuests.getInstance().getConfig().getConfigurationSection("startedQuestsPlaceholder")); - QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("placeholderRequired", PlaceholderRequirement.class, ItemUtils.item(XMaterial.NAME_TAG, Lang.RPlaceholder.toString()), PlaceholderRequirement::new)); - }); - - public static final BQDependency skapi = new BQDependency("SkillAPI", () -> { - QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("classRequired", ClassRequirement.class, ItemUtils.item(XMaterial.GHAST_TEAR, Lang.RClass.toString()), ClassRequirement::new)); - QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("skillAPILevelRequired", SkillAPILevelRequirement.class, ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RSkillAPILevel.toString()), SkillAPILevelRequirement::new)); - }).addPluginName("ProSkillAPI"); - - public static final BQDependency cmi = new BQDependency("CMI", () -> { - if (BQCMI.areHologramsEnabled()) QuestsAPI.getAPI().setHologramsManager(new BQCMI()); - }); - - public static final BQDependency boss = new BQDependency("Boss", () -> QuestsAPI.getAPI().registerMobFactory(new BQBoss()), null, plugin -> { - try { - Class.forName("org.mineacademy.boss.model.Boss"); - }catch (ClassNotFoundException ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of Boss (" + plugin.getDescription().getVersion() + ") is not compatible with BeautyQuests."); - return false; - } - return true; - }); - - public static final BQDependency mm = new BQDependency("MythicMobs", () -> { - try { - Class.forName("io.lumine.mythic.api.MythicPlugin"); - QuestsAPI.getAPI().registerMobFactory(new MythicMobs5()); - }catch (ClassNotFoundException ex) { - QuestsAPI.getAPI().registerMobFactory(new MythicMobs()); - } - }); - - public static final BQDependency advancedspawners = new BQDependency("AdvancedSpawners", () -> QuestsAPI.getAPI().registerMobFactory(new BQAdvancedSpawners())); - public static final BQDependency LevelledMobs = - new BQDependency("LevelledMobs", () -> QuestsAPI.getAPI().registerMobFactory(new BQLevelledMobs())); - - public static final BQDependency holod2 = new BQDependency("HolographicDisplays", () -> QuestsAPI.getAPI().setHologramsManager(new BQHolographicDisplays2()), null, plugin -> plugin.getClass().getName().equals("com.gmail.filoghost.holographicdisplays.HolographicDisplays")); - public static final BQDependency holod3 = new BQDependency("HolographicDisplays", () -> QuestsAPI.getAPI().setHologramsManager(new BQHolographicDisplays3()), null, plugin -> { - if (!plugin.getClass().getName().equals("me.filoghost.holographicdisplays.plugin.HolographicDisplays")) // NOSONAR - return false; - - try { - Class.forName("me.filoghost.holographicdisplays.api.HolographicDisplaysAPI"); - return true; - }catch (ClassNotFoundException ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of HolographicDisplays is unsupported. Please make sure you are running the LATEST dev build of HolographicDisplays."); - return false; - } - }); - public static final BQDependency decentholograms = new BQDependency("DecentHolograms", () -> QuestsAPI.getAPI().setHologramsManager(new BQDecentHolograms())); - - public static final BQDependency sentinel = new BQDependency("Sentinel", BQSentinel::initialize); - - public static final BQDependency wg = - new BQDependency("WorldGuard", BQWorldGuard::initialize, BQWorldGuard::unload); - public static final BQDependency jobs = new BQDependency("Jobs", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("jobLevelRequired", JobLevelRequirement.class, ItemUtils.item(XMaterial.LEATHER_CHESTPLATE, Lang.RJobLvl.toString()), JobLevelRequirement::new))); - public static final BQDependency fac = new BQDependency("Factions", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("factionRequired", FactionRequirement.class, ItemUtils.item(XMaterial.WITHER_SKELETON_SKULL, Lang.RFaction.toString()), FactionRequirement::new))); - public static final BQDependency acc = new BQDependency("AccountsHook"); - public static final BQDependency dyn = new BQDependency("dynmap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQDynmap())); - public static final BQDependency BlueMap = new BQDependency("BlueMap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQBlueMap())); - public static final BQDependency gps = new BQDependency("GPS", GPS::init); - public static final BQDependency mmo = new BQDependency("mcMMO", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("mcmmoSklillLevelRequired", McMMOSkillRequirement.class, ItemUtils.item(XMaterial.IRON_CHESTPLATE, Lang.RSkillLvl.toString()), McMMOSkillRequirement::new))); - public static final BQDependency mclvl = new BQDependency("McCombatLevel", () -> QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("mcmmoCombatLevelRequirement", McCombatLevelRequirement.class, ItemUtils.item(XMaterial.IRON_SWORD, Lang.RCombatLvl.toString()), McCombatLevelRequirement::new))); - public static final BQDependency tokenEnchant = new BQDependency("TokenEnchant", () -> Bukkit.getPluginManager().registerEvents(new BQTokenEnchant(), BeautyQuests.getInstance())); - public static final BQDependency ultimateTimber = new BQDependency("UltimateTimber", () -> Bukkit.getPluginManager().registerEvents(new BQUltimateTimber(), BeautyQuests.getInstance())); - public static final BQDependency PlayerBlockTracker = new BQDependency("PlayerBlockTracker"); - public static final BQDependency WildStacker = new BQDependency("WildStacker", BQWildStacker::initialize); - public static final BQDependency ItemsAdder = - new BQDependency("ItemsAdder", BQItemsAdder::initialize, BQItemsAdder::unload); - - //public static final BQDependency par = new BQDependency("Parties"); - //public static final BQDependency eboss = new BQDependency("EpicBosses", () -> Bukkit.getPluginManager().registerEvents(new EpicBosses(), BeautyQuests.getInstance())); - //public static final BQDependency interactions = new BQDependency("Interactions", () -> InteractionsAPI.); TODO - - private List<BQDependency> dependencies; - private boolean dependenciesTested = false; - private boolean dependenciesInitialized = false; - private boolean lockDependencies = false; - - public DependenciesManager() { - dependencies = new ArrayList<>(Arrays.asList( - /*par, eboss, */ - znpcs, citizens, // npcs - wg, gps, tokenEnchant, ultimateTimber, sentinel, PlayerBlockTracker, // other - mm, boss, advancedspawners, LevelledMobs, WildStacker, // mobs - vault, papi, acc, // hooks - skapi, jobs, fac, mmo, mclvl, // rewards and requirements - dyn, BlueMap, // maps - cmi, holod2, holod3, decentholograms, // holograms - ItemsAdder // items - )); - } - - public List<BQDependency> getDependencies() { - return dependencies; - } - - public void addDependency(BQDependency dependency) { - if (lockDependencies) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("Trying to add a BQ dependency for plugin " + dependency.pluginNames + " after final locking."); - return; - } - dependencies.add(dependency); - if (dependenciesTested) { - if (dependency.testCompatibility(true) && dependenciesInitialized) dependency.initialize(); - } - } - - public void testCompatibilities() { - if (dependenciesTested) return; - dependencies.forEach(x -> x.testCompatibility(false)); - dependenciesTested = true; - } - - public void initializeCompatibilities() { - if (dependenciesInitialized) return; - dependencies.stream().filter(BQDependency::isEnabled).forEach(BQDependency::initialize); - dependenciesInitialized = true; - } - - public void disableCompatibilities() { - dependencies.forEach(BQDependency::disable); - } - - public void lockDependencies() { - lockDependencies = true; - } - - @EventHandler - public void onPluginEnable(PluginEnableEvent e) { - if (lockDependencies) return; - //if (dependenciesTested) return; - dependencies.stream().filter(x -> !x.enabled && x.isPlugin(e.getPlugin())).findAny().ifPresent(dependency -> { - if (dependency.testCompatibility(true) && dependenciesInitialized) dependency.initialize(); - }); - } - - public static class BQDependency { - private final List<String> pluginNames; - private final Runnable initialize; - private final Runnable disable; - private final Predicate<Plugin> isValid; - private boolean enabled = false; - private boolean forceDisable = false; - private boolean initialized = false; - private Plugin foundPlugin; - - public BQDependency(String pluginName) { - this(pluginName, null); - } - - public BQDependency(String pluginName, Runnable initialize) { - this(pluginName, initialize, null, null); - } - - public BQDependency(String pluginName, Runnable initialize, Runnable disable) { - this(pluginName, initialize, disable, null); - } - - public BQDependency(String pluginName, Runnable initialize, Runnable disable, Predicate<Plugin> isValid) { - Validate.notNull(pluginName); - this.pluginNames = new ArrayList<>(); - this.pluginNames.add(pluginName); - this.initialize = initialize; - this.disable = disable; - this.isValid = isValid; - } - - public BQDependency addPluginName(String name) { - pluginNames.add(name); - return this; - } - - boolean isPlugin(Plugin plugin) { - return pluginNames.contains(plugin.getName()); - } - - boolean testCompatibility(boolean after) { - if (forceDisable) return false; - Plugin plugin = pluginNames.stream().map(Bukkit.getPluginManager()::getPlugin).filter(x -> x != null && x.isEnabled()).findAny().orElse(null); - if (plugin == null) return false; - if (isValid != null && !isValid.test(plugin)) return false; - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Hooked into " + pluginNames + " v" + plugin.getDescription().getVersion() + (after ? " after primary initialization" : "")); - enabled = true; - foundPlugin = plugin; - return true; - } - - void initialize() { - try { - if (initialize != null) initialize.run(); - initialized = true; - }catch (Throwable ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while initializing " + pluginNames.toString() + " integration", ex); - enabled = false; - } - } - - public void disable() { - forceDisable = true; - if (enabled) { - enabled = false; - if (disable != null && initialized) disable.run(); - initialized = false; - } - } - - public boolean isEnabled() { - return enabled; - } - - public Plugin getFoundPlugin() { - if (!enabled) - throw new IllegalStateException( - "The dependency " + pluginNames + " is not enabled"); - return foundPlugin; - } - - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java deleted file mode 100644 index 218aab03..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Factions.java +++ /dev/null @@ -1,21 +0,0 @@ -package fr.skytasul.quests.utils.compatibility; - -import java.util.Collection; -import com.massivecraft.factions.entity.Faction; -import com.massivecraft.factions.entity.FactionColl; - -public class Factions { - - public static boolean factionExists(String name){ - return getFaction(name) != null; - } - - public static Object getFaction(String name){ - return FactionColl.get().getByName(name); - } - - public static Collection<Faction> getFactions() { - return FactionColl.get().getAll(); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java deleted file mode 100644 index 11afebdd..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/GPS.java +++ /dev/null @@ -1,27 +0,0 @@ -package fr.skytasul.quests.utils.compatibility; - -import org.bukkit.Location; -import org.bukkit.entity.Player; -import com.live.bemmamin.gps.api.GPSAPI; -import fr.skytasul.quests.BeautyQuests; - -public class GPS { - - private static GPSAPI api; - - static void init(){ - api = new GPSAPI(BeautyQuests.getInstance()); - } - - public static boolean launchCompass(Player p, Location location) { - if (api.gpsIsActive(p)) return false; - if (location == null) return false; - api.startCompass(p, location); - return true; - } - - public static void stopCompass(Player p){ - api.stopGPS(p); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/InternalIntegrations.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/InternalIntegrations.java new file mode 100755 index 00000000..7b9e596a --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/InternalIntegrations.java @@ -0,0 +1,18 @@ +package fr.skytasul.quests.utils.compatibility; + +import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.utils.IntegrationManager.BQDependency; + +public final class InternalIntegrations { + + public static final BQDependency PlayerBlockTracker = new BQDependency("PlayerBlockTracker"); + public static final BQDependency AccountsHook = new BQDependency("AccountsHook"); + + static { + BeautyQuests.getInstance().getIntegrationManager().addDependency(PlayerBlockTracker); + BeautyQuests.getInstance().getIntegrationManager().addDependency(AccountsHook); + } + + private InternalIntegrations() {} + +} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java deleted file mode 100644 index 234864be..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Jobs.java +++ /dev/null @@ -1,22 +0,0 @@ -package fr.skytasul.quests.utils.compatibility; - -import org.bukkit.entity.Player; -import com.gamingmesh.jobs.container.Job; -import com.gamingmesh.jobs.container.JobProgression; -import com.gamingmesh.jobs.container.JobsPlayer; - -public class Jobs { - - public static int getLevel(Player p, String jobName){ - JobsPlayer player = com.gamingmesh.jobs.Jobs.getPlayerManager().getJobsPlayer(p); - if (player == null) return -1; - JobProgression prog = player.getJobProgression((Job) getJob(jobName)); - if (prog == null) return 0; - return prog.getLevel(); - } - - public static Object getJob(String jobName){ - return com.gamingmesh.jobs.Jobs.getJob(jobName); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java deleted file mode 100644 index 616150c7..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McCombatLevel.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.skytasul.quests.utils.compatibility; - -import java.util.OptionalInt; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -public class McCombatLevel { - - private static com.gmail.mrphpfan.mccombatlevel.McCombatLevel plugin = (com.gmail.mrphpfan.mccombatlevel.McCombatLevel) Bukkit.getPluginManager().getPlugin("McCombatLevel"); - - public static int getCombatLevel(Player p){ - OptionalInt lvl = plugin.getLevel(p); - return lvl.isPresent() ? lvl.getAsInt() : 0; - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java deleted file mode 100644 index 6fbb69a0..00000000 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/McMMO.java +++ /dev/null @@ -1,12 +0,0 @@ -package fr.skytasul.quests.utils.compatibility; - -import org.bukkit.entity.Player; -import com.gmail.nossr50.api.ExperienceAPI; - -public class McMMO { - - public static int getLevel(Player p, String jobName){ - return ExperienceAPI.getLevel(p, jobName); - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java index 41487ae9..cd34d16b 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java @@ -11,9 +11,9 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.DependenciesManager; -import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; public class Command implements HasPlaceholders { @@ -33,11 +33,11 @@ public Command(String label, boolean console, boolean parse, int delay) { public void execute(Player o){ Runnable run = () -> { - String formattedcmd = label.replace("{PLAYER}", o.getName()); - if (parse && DependenciesManager.papi.isEnabled()) formattedcmd = QuestsPlaceholders.setPlaceholders(o, formattedcmd); + String formattedCommand = MessageUtils.finalFormat(label, null, PlaceholdersContext.of(o, parse)); + CommandSender sender = console ? Bukkit.getConsoleSender() : o; - Bukkit.dispatchCommand(sender, formattedcmd); - QuestsPlugin.getPlugin().getLoggerExpanded().debug(sender.getName() + " performed command " + formattedcmd); + Bukkit.dispatchCommand(sender, formattedCommand); + QuestsPlugin.getPlugin().getLoggerExpanded().debug(sender.getName() + " performed command " + formattedCommand); }; if (delay == 0 && Bukkit.isPrimaryThread()) { run.run(); diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 1556986a..20275d60 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -101,8 +101,6 @@ questsMenu: allowPlayerCancelQuest: true # - Integrations - -# Enable GPS integration -gps: false # Enable or disable SkillAPI experience overriding in xp reward/requirement skillAPIoverride: true # Enable or disable AccountsHook managing player accounts @@ -130,9 +128,9 @@ startedQuestsPlaceholder: splitPlaceholderFormat: "§6{questName}\n{questDescription}" # Format of the empty placeholder %beautyquests_started_ordered%. Available placeholders: {questName} and {questDescription} inlinePlaceholderFormat: "§6{questName}§e: §o{questDescription}" -# dynmap integration options +# dynmap and BlueMap integration options dynmap: - # Name of the marker set. To disable dynmap integration, put an empty string + # Name of the marker set. To disable dynmap or BlueMap integration, put an empty string markerSetName: "" # Icon for quest markers markerIcon: "bookshelf" diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 53e213d9..3e55902d 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -878,7 +878,7 @@ misc: questItemLore: §e§oQuest Item hologramText: §8§lQuest NPC poolHologramText: §eNew quest available! - entityType: '§eEntity type: {0}' + entityType: '§eEntity type: {entity_type}' entityTypeAny: §eAny entity enabled: Enabled disabled: Disabled diff --git a/dist/pom.xml b/dist/pom.xml index 2d23b703..29878f69 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -44,6 +44,13 @@ <type>jar</type> <scope>compile</scope> </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>beautyquests-integrations</artifactId> + <version>${project.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>beautyquests-v1_9_R1</artifactId> diff --git a/integrations/pom.xml b/integrations/pom.xml new file mode 100644 index 00000000..b338362b --- /dev/null +++ b/integrations/pom.xml @@ -0,0 +1,275 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <packaging>jar</packaging> + <artifactId>beautyquests-integrations</artifactId> + <parent> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-parent</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + + <repositories> + <repository> + <id>placeholderapi</id> + <url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url> + </repository> + <repository> + <id>dynmap</id> + <url>https://repo.mikeprimm.com/</url> + </repository> + <repository> + <id>sk89q-repo</id> + <url>https://maven.enginehub.org/repo/</url> + </repository> + <repository> + <id>codemc-repo</id> + <url>https://repo.codemc.io/repository/maven-public/</url> + </repository> + <repository> + <id>mineacademy-repo</id> + <url>https://bitbucket.org/kangarko/libraries/raw/master</url> + </repository> + <repository> + <id>jitpack.io</id> + <url>https://jitpack.io</url> + </repository> + <repository> + <id>teamvk-repo</id> + <url>https://raw.githubusercontent.com/TeamVK/maven-repository/master/release/</url> + </repository> + <repository> + <id>lumine</id> + <url>https://mvn.lumine.io/repository/maven-public/</url> + <releases> + <updatePolicy>interval:10080</updatePolicy> + </releases> + <snapshots> + <updatePolicy>interval:10080</updatePolicy> + </snapshots> + </repository> + <repository> + <id>citizens</id> + <url>http://repo.citizensnpcs.co/</url> <!-- really slow repo --> + <releases> + <updatePolicy>interval:10080</updatePolicy> + </releases> + <snapshots> + <updatePolicy>interval:10080</updatePolicy> + </snapshots> + </repository> + <repository> + <id>bg-repo</id> + <url>https://repo.bg-software.com/repository/api/</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>24.0.0</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>io.papermc.paper</groupId> + <artifactId>paper-api</artifactId> + <version>1.19.4-R0.1-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>net.citizensnpcs</groupId> + <artifactId>citizens-main</artifactId> + <version>2.0.31-SNAPSHOT</version> + <type>jar</type> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.mcmonkey</groupId> + <artifactId>sentinel</artifactId> + <version>2.7.3-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>io.github.znetworkw.znpcservers</groupId> + <artifactId>znpcservers</artifactId> + <version>3.6</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.github.MilkBowl</groupId> + <artifactId>VaultAPI</artifactId> + <version>1.7</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>me.clip</groupId> + <artifactId>placeholderapi</artifactId> + <version>2.11.3</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.gmail.filoghost.holographicdisplays</groupId> + <artifactId>holographicdisplays-api</artifactId> + <version>2.4.9</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>me.filoghost.holographicdisplays</groupId> + <artifactId>holographicdisplays-api</artifactId> + <version>3.0.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.sk89q.worldguard</groupId> + <artifactId>worldguard-bukkit</artifactId> + <version>7.0.7</version> + <scope>provided</scope> + <exclusions> + <exclusion> + <groupId>net.java.truevfs</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>io.lumine.xikage</groupId> + <artifactId>MythicMobs</artifactId> + <version>4.12.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>io.lumine</groupId> + <artifactId>Mythic-Dist</artifactId> + <version>5.2.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.github.promcteam</groupId> + <artifactId>proskillapi</artifactId> + <version>1.1.7.0.3</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.github.BlueMap-Minecraft</groupId> + <artifactId>BlueMapAPI</artifactId> + <version>v2.5.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.vk2gpz.tokenenchant</groupId> + <artifactId>TokenEnchantAPI</artifactId> + <version>18.37.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.github.decentsoftware-eu</groupId> + <artifactId>decentholograms</artifactId> + <version>2.8.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.github.lokka30</groupId> + <artifactId>LevelledMobs</artifactId> + <version>3.2.6</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.bgsoftware</groupId> + <artifactId>WildStackerAPI</artifactId> + <version>2022.6</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.github.LoneDev6</groupId> + <artifactId>api-itemsadder</artifactId> + <version>3.2.5</version> + <scope>provided</scope> + </dependency> + + <!-- Local JARs --> + <dependency> + <groupId>org.mineacademy</groupId> + <artifactId>boss</artifactId> + <version>4.2.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.songoda</groupId> + <artifactId>UltimateTimber</artifactId> + <version>2.3.5</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.dynmap</groupId> + <artifactId>dynmap</artifactId> + <version>1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.massivecraft</groupId> + <artifactId>factions</artifactId> + <version>1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.massivecraft</groupId> + <artifactId>massivecore</artifactId> + <version>1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.gamingmesh</groupId> + <artifactId>jobs</artifactId> + <version>5.1.0.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.gmail.mrphpfan</groupId> + <artifactId>mccombatlevel</artifactId> + <version>1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.gmail.nossr50</groupId> + <artifactId>mcmmo</artifactId> + <version>1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.suxy</groupId> + <artifactId>skillapi</artifactId> + <version>1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.zrips</groupId> + <artifactId>cmi</artifactId> + <version>9.0.2.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.zrips</groupId> + <artifactId>cmilib</artifactId> + <version>1.2.3.3</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>gcspawners</groupId> + <artifactId>gcspawners</artifactId> + <version>3.3.0</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQCMI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/BQCMI.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/BQCMI.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/BQCMI.java index 1c811395..ad5364e1 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQCMI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/BQCMI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations; import java.lang.reflect.Constructor; import org.bukkit.Location; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQDecentHolograms.java b/integrations/src/main/java/fr/skytasul/quests/integrations/BQDecentHolograms.java similarity index 98% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/BQDecentHolograms.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/BQDecentHolograms.java index ad0d5623..a2f2d786 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQDecentHolograms.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/BQDecentHolograms.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations; import java.util.ArrayList; import java.util.Iterator; @@ -9,9 +9,9 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.api.AbstractHolograms; import eu.decentsoftware.holograms.api.DHAPI; import eu.decentsoftware.holograms.api.holograms.Hologram; +import fr.skytasul.quests.api.AbstractHolograms; public class BQDecentHolograms extends AbstractHolograms<Hologram> { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays2.java b/integrations/src/main/java/fr/skytasul/quests/integrations/BQHolographicDisplays2.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays2.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/BQHolographicDisplays2.java index 2b8e00bf..bdece452 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays2.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/BQHolographicDisplays2.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations; import java.lang.reflect.Field; import java.util.Iterator; @@ -14,8 +14,8 @@ import com.gmail.filoghost.holographicdisplays.api.Hologram; import com.gmail.filoghost.holographicdisplays.api.HologramsAPI; import com.gmail.filoghost.holographicdisplays.api.VisibilityManager; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.AbstractHolograms; +import fr.skytasul.quests.api.QuestsPlugin; public class BQHolographicDisplays2 extends AbstractHolograms<Hologram> { @@ -35,7 +35,7 @@ public boolean supportItems() { @Override public HD2Hologram createHologram(Location lc, boolean visible) { - Hologram holo = HologramsAPI.createHologram(BeautyQuests.getInstance(), lc); + Hologram holo = HologramsAPI.createHologram(QuestsPlugin.getPlugin(), lc); if (protocolLib) holo.getVisibilityManager().setVisibleByDefault(visible); return new HD2Hologram(holo); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays3.java b/integrations/src/main/java/fr/skytasul/quests/integrations/BQHolographicDisplays3.java similarity index 98% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays3.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/BQHolographicDisplays3.java index 98dd47f0..45e62d15 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQHolographicDisplays3.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/BQHolographicDisplays3.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations; import java.lang.reflect.Field; import java.util.List; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQItemsAdder.java b/integrations/src/main/java/fr/skytasul/quests/integrations/BQItemsAdder.java similarity index 96% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/BQItemsAdder.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/BQItemsAdder.java index 7f966131..bb249563 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQItemsAdder.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/BQItemsAdder.java @@ -1,10 +1,10 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations; import org.bukkit.inventory.ItemStack; +import dev.lone.itemsadder.api.CustomStack; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.localization.Lang; -import dev.lone.itemsadder.api.CustomStack; public final class BQItemsAdder { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java b/integrations/src/main/java/fr/skytasul/quests/integrations/BQTokenEnchant.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/BQTokenEnchant.java index 8e7babdb..37c2e02e 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQTokenEnchant.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/BQTokenEnchant.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java b/integrations/src/main/java/fr/skytasul/quests/integrations/BQUltimateTimber.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/BQUltimateTimber.java index d9cc0ca5..92e71b36 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQUltimateTimber.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/BQUltimateTimber.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations; import java.util.stream.Collectors; import org.bukkit.Bukkit; diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java new file mode 100644 index 00000000..8747b616 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java @@ -0,0 +1,43 @@ +package fr.skytasul.quests.integrations; + +import org.bukkit.configuration.file.FileConfiguration; + +public class IntegrationsConfiguration { + + private final FileConfiguration config; + + private String dSetName = "Quests"; + private String dIcon = "bookshelf"; + private int dMinZoom = 0; + + public IntegrationsConfiguration(FileConfiguration config) { + this.config = config; + } + + public void load() { + if (config.getBoolean("skillAPIoverride")) { + + } + + dSetName = config.getString("dynmap.markerSetName"); + dIcon = config.getString("dynmap.markerIcon"); + dMinZoom = config.getInt("dynmap.minZoom"); + } + + public String dynmapSetName() { + return dSetName; + } + + public String dynmapMarkerIcon() { + return dIcon; + } + + public int dynmapMinimumZoom() { + return dMinZoom; + } + + public static IntegrationsConfiguration getConfiguration() { + return IntegrationsLoader.getInstance().getConfig(); + } + +} diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java new file mode 100644 index 00000000..b8386ab4 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java @@ -0,0 +1,222 @@ +package fr.skytasul.quests.integrations; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.AbstractHolograms; +import fr.skytasul.quests.api.QuestsAPI; +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.requirements.RequirementCreator; +import fr.skytasul.quests.api.rewards.RewardCreator; +import fr.skytasul.quests.api.utils.IntegrationManager; +import fr.skytasul.quests.api.utils.IntegrationManager.BQDependency; +import fr.skytasul.quests.integrations.factions.FactionRequirement; +import fr.skytasul.quests.integrations.jobs.JobLevelRequirement; +import fr.skytasul.quests.integrations.maps.BQBlueMap; +import fr.skytasul.quests.integrations.maps.BQDynmap; +import fr.skytasul.quests.integrations.mcmmo.McCombatLevelRequirement; +import fr.skytasul.quests.integrations.mcmmo.McMMOSkillRequirement; +import fr.skytasul.quests.integrations.mobs.BQAdvancedSpawners; +import fr.skytasul.quests.integrations.mobs.BQBoss; +import fr.skytasul.quests.integrations.mobs.BQLevelledMobs; +import fr.skytasul.quests.integrations.mobs.BQWildStacker; +import fr.skytasul.quests.integrations.mobs.CitizensFactory; +import fr.skytasul.quests.integrations.mobs.MythicMobs; +import fr.skytasul.quests.integrations.mobs.MythicMobs5; +import fr.skytasul.quests.integrations.npcs.BQCitizens; +import fr.skytasul.quests.integrations.npcs.BQSentinel; +import fr.skytasul.quests.integrations.npcs.BQServerNPCs; +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.vault.economy.MoneyRequirement; +import fr.skytasul.quests.integrations.vault.economy.MoneyReward; +import fr.skytasul.quests.integrations.vault.permission.PermissionReward; +import fr.skytasul.quests.integrations.worldguard.BQWorldGuard; + +public class IntegrationsLoader { + + private static IntegrationsLoader instance; + + public static IntegrationsLoader getInstance() { + return instance; + } + + //public static final BQDependency par = new BQDependency("Parties"); + //public static final BQDependency eboss = new BQDependency("EpicBosses", () -> Bukkit.getPluginManager().registerEvents(new EpicBosses(), BeautyQuests.getInstance())); + //public static final BQDependency interactions = new BQDependency("Interactions", () -> InteractionsAPI.); TODO + + private IntegrationsConfiguration config; + + public IntegrationsLoader() { + instance = this; + + config = new IntegrationsConfiguration(QuestsPlugin.getPlugin().getConfig()); + config.load(); + + IntegrationManager manager = QuestsPlugin.getPlugin().getIntegrationManager(); + + // NPCS + manager.addDependency(new BQDependency("ServersNPC", + () -> QuestsAPI.getAPI().addNpcFactory("znpcs", new BQServerNPCs()), null, this::isZnpcsVersionValid)); + + manager.addDependency(new BQDependency("Citizens", () -> { + QuestsAPI.getAPI().addNpcFactory("citizens", new BQCitizens()); + QuestsAPI.getAPI().registerMobFactory(new CitizensFactory()); + })); + + + // MOBS + manager.addDependency(new BQDependency("MythicMobs", this::registerMythicMobs)); + + manager.addDependency(new BQDependency("Boss", () -> QuestsAPI.getAPI().registerMobFactory(new BQBoss()), null, + this::isBossVersionValid)); + + manager.addDependency( + new BQDependency("AdvancedSpawners", () -> QuestsAPI.getAPI().registerMobFactory(new BQAdvancedSpawners()))); + + manager.addDependency( + new BQDependency("LevelledMobs", () -> QuestsAPI.getAPI().registerMobFactory(new BQLevelledMobs()))); + + manager.addDependency(new BQDependency("WildStacker", BQWildStacker::initialize)); + + + // REWARDS / REQUIREMENTS + manager.addDependency(new BQDependency("SkillAPI", this::registerSkillApi).addPluginName("ProSkillAPI")); + manager.addDependency(new BQDependency("Jobs", this::registerJobs)); + manager.addDependency(new BQDependency("Factions", this::registerFactions)); + manager.addDependency(new BQDependency("mcMMO", this::registerMcMmo)); + manager.addDependency(new BQDependency("McCombatLevel", this::registerMcCombatLevel)); + manager.addDependency(new BQDependency("Vault", this::registerVault)); + + + // MAPS + manager.addDependency(new BQDependency("dynmap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQDynmap()))); + manager.addDependency(new BQDependency("BlueMap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQBlueMap()))); + + + // HOLOGRAMS + manager.addDependency(new BQDependency("CMI", () -> { + if (BQCMI.areHologramsEnabled()) + QuestsAPI.getAPI().setHologramsManager(new BQCMI()); + })); + manager.addDependency(new BQDependency("HolographicDisplays", this::registerHolographicDisplays)); + manager.addDependency( + new BQDependency("DecentHolograms", () -> QuestsAPI.getAPI().setHologramsManager(new BQDecentHolograms()))); + + + // OTHERS + manager.addDependency(new BQDependency("PlaceholderAPI", this::registerPapi)); + manager.addDependency(new BQDependency("WorldGuard", BQWorldGuard::initialize, BQWorldGuard::unload)); + manager.addDependency(new BQDependency("Sentinel", BQSentinel::initialize)); + manager.addDependency(new BQDependency("TokenEnchant", + () -> Bukkit.getPluginManager().registerEvents(new BQTokenEnchant(), QuestsPlugin.getPlugin()))); + manager.addDependency(new BQDependency("UltimateTimber", + () -> Bukkit.getPluginManager().registerEvents(new BQUltimateTimber(), QuestsPlugin.getPlugin()))); + manager.addDependency(new BQDependency("ItemsAdder", BQItemsAdder::initialize, BQItemsAdder::unload)); + } + + private void registerPapi() { + QuestsPlaceholders.registerPlaceholders( + QuestsPlugin.getPlugin().getConfig().getConfigurationSection("startedQuestsPlaceholder")); + QuestsAPI.getAPI().getRequirements() + .register(new RequirementCreator("placeholderRequired", PlaceholderRequirement.class, + ItemUtils.item(XMaterial.NAME_TAG, Lang.RPlaceholder.toString()), PlaceholderRequirement::new)); + QuestsAPI.getAPI().registerMessageProcessor(new PapiMessageProcessor()); + } + + private void registerVault() { + QuestsAPI.getAPI().getRewards().register(new RewardCreator("moneyReward", MoneyReward.class, + ItemUtils.item(XMaterial.EMERALD, Lang.rewardMoney.toString()), MoneyReward::new)); + QuestsAPI.getAPI().getRewards().register(new RewardCreator("permReward", PermissionReward.class, + ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.rewardPerm.toString()), PermissionReward::new)); + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("moneyRequired", MoneyRequirement.class, + ItemUtils.item(XMaterial.EMERALD, Lang.RMoney.toString()), MoneyRequirement::new)); + } + + private void registerHolographicDisplays() { + AbstractHolograms<?> holograms; + try { + Class.forName("com.gmail.filoghost.holographicdisplays.HolographicDisplays"); // v2 + holograms = new BQHolographicDisplays2(); + } catch (ClassNotFoundException ex) { + try { + Class.forName("me.filoghost.holographicdisplays.plugin.HolographicDisplays"); // v3 + holograms = new BQHolographicDisplays3(); + } catch (ClassNotFoundException ex1) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning( + "Your version of HolographicDisplays is unsupported. Please make sure you are running the LATEST dev build of HolographicDisplays."); + return; + } + } + QuestsAPI.getAPI().setHologramsManager(holograms); + } + + private void registerMcCombatLevel() { + QuestsAPI.getAPI().getRequirements() + .register(new RequirementCreator("mcmmoCombatLevelRequirement", McCombatLevelRequirement.class, + ItemUtils.item(XMaterial.IRON_SWORD, Lang.RCombatLvl.toString()), McCombatLevelRequirement::new)); + } + + private void registerMcMmo() { + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("mcmmoSklillLevelRequired", McMMOSkillRequirement.class, ItemUtils.item(XMaterial.IRON_CHESTPLATE, Lang.RSkillLvl.toString()), McMMOSkillRequirement::new)); + } + + private void registerFactions() { + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("factionRequired", FactionRequirement.class, + ItemUtils.item(XMaterial.WITHER_SKELETON_SKULL, Lang.RFaction.toString()), FactionRequirement::new)); + } + + private void registerJobs() { + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("jobLevelRequired", JobLevelRequirement.class, + ItemUtils.item(XMaterial.LEATHER_CHESTPLATE, Lang.RJobLvl.toString()), + JobLevelRequirement::new)); + } + + private void registerSkillApi() { + QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("classRequired", ClassRequirement.class, + ItemUtils.item(XMaterial.GHAST_TEAR, Lang.RClass.toString()), ClassRequirement::new)); + QuestsAPI.getAPI().getRequirements() + .register(new RequirementCreator("skillAPILevelRequired", SkillAPILevelRequirement.class, + ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RSkillAPILevel.toString()), + SkillAPILevelRequirement::new)); + } + + private boolean isBossVersionValid(Plugin plugin) { + try { + Class.forName("org.mineacademy.boss.model.Boss"); + } catch (ClassNotFoundException ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of Boss (" + + plugin.getDescription().getVersion() + ") is not compatible with BeautyQuests."); + return false; + } + return true; + } + + private void registerMythicMobs() { + try { + Class.forName("io.lumine.mythic.api.MythicPlugin"); + QuestsAPI.getAPI().registerMobFactory(new MythicMobs5()); + } catch (ClassNotFoundException ex) { + QuestsAPI.getAPI().registerMobFactory(new MythicMobs()); + } + } + + private boolean isZnpcsVersionValid(Plugin plugin) { + if (plugin.getClass().getName().equals("io.github.znetworkw.znpcservers.ServersNPC")) // NOSONAR + return true; + + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Your version of znpcs (" + + plugin.getDescription().getVersion() + ") is not supported by BeautyQuests."); + return false; + } + + public IntegrationsConfiguration getConfig() { + return config; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java similarity index 93% rename from core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java index bbf53a32..81fcc07e 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/FactionRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.factions; import java.util.ArrayList; import java.util.List; @@ -22,7 +22,6 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.utils.compatibility.Factions; public class FactionRequirement extends AbstractRequirement { @@ -73,7 +72,7 @@ public ItemStack getObjectItemStack(Faction object) { @Override public void createObject(Function<Faction, ItemStack> callback) { - new PagedGUI<Faction>(Lang.INVENTORY_FACTIONS_LIST.toString(), DyeColor.PURPLE, Factions.getFactions()) { + new PagedGUI<Faction>(Lang.INVENTORY_FACTIONS_LIST.toString(), DyeColor.PURPLE, FactionColl.get().getAll()) { @Override public ItemStack getItemStack(Faction object) { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/jobs/JobLevelRequirement.java similarity index 83% rename from core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/jobs/JobLevelRequirement.java index 41c540cd..bc641c2f 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/JobLevelRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/jobs/JobLevelRequirement.java @@ -1,8 +1,11 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.jobs; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import com.gamingmesh.jobs.Jobs; +import com.gamingmesh.jobs.container.JobProgression; +import com.gamingmesh.jobs.container.JobsPlayer; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -11,7 +14,6 @@ import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.Jobs; public class JobLevelRequirement extends TargetNumberRequirement { @@ -29,7 +31,13 @@ public JobLevelRequirement(String customDescription, String customReason, String @Override public double getPlayerTarget(Player p) { - return Jobs.getLevel(p, jobName); + JobsPlayer player = Jobs.getPlayerManager().getJobsPlayer(p); + if (player == null) + return -1; + JobProgression prog = player.getJobProgression(Jobs.getJob(jobName)); + if (prog == null) + return 0; + return prog.getLevel(); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java b/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQBlueMap.java similarity index 81% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQBlueMap.java index 9b335395..d4cccc45 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQBlueMap.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQBlueMap.java @@ -1,17 +1,17 @@ -package fr.skytasul.quests.utils.compatibility.maps; +package fr.skytasul.quests.integrations.maps; import java.util.function.Consumer; import org.bukkit.Location; -import fr.skytasul.quests.QuestsConfigurationImplementation; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.options.OptionStarterNPC; import de.bluecolored.bluemap.api.BlueMapAPI; import de.bluecolored.bluemap.api.BlueMapMap; import de.bluecolored.bluemap.api.BlueMapWorld; import de.bluecolored.bluemap.api.markers.MarkerSet; import de.bluecolored.bluemap.api.markers.POIMarker; +import fr.skytasul.quests.api.AbstractMapIntegration; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.integrations.IntegrationsConfiguration; public class BQBlueMap extends AbstractMapIntegration { @@ -22,7 +22,8 @@ public class BQBlueMap extends AbstractMapIntegration { @Override public boolean isEnabled() { - return QuestsConfigurationImplementation.dynmapMarkerIcon() != null && !QuestsConfigurationImplementation.dynmapMarkerIcon().isEmpty(); + return IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon() != null + && !IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon().isEmpty(); } @Override @@ -30,7 +31,7 @@ protected void initializeMarkers(Runnable initializeQuests) { BlueMapAPI.onEnable(enableConsumer = api -> { try { set = MarkerSet.builder() - .label(QuestsConfigurationImplementation.dynmapSetName()) + .label(IntegrationsConfiguration.getConfiguration().dynmapSetName()) .defaultHidden(false) .toggleable(true) .build(); @@ -60,7 +61,7 @@ protected void addMarker(Quest quest, Location lc) { for (BlueMapMap map : maps) { POIMarker marker = POIMarker.toBuilder() .label(quest.getName()) - .icon(QuestsConfigurationImplementation.dynmapMarkerIcon(), 0, 0) + .icon(IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon(), 0, 0) .position(lc.getBlockX(), lc.getBlockY(), lc.getBlockZ()) .build(); set.getMarkers().put("qu_" + quest.getId() + "_" + i++, marker); @@ -74,7 +75,7 @@ protected void addMarker(Quest quest, Location lc) { @Override public void removeMarker(Quest quest) { BlueMapAPI.getInstance().ifPresent(api -> { - Location lc = quest.getOptionValueOrDef(OptionStarterNPC.class).getLocation(); + 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); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java b/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQDynmap.java similarity index 69% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQDynmap.java index 1db90f41..09b9fb33 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/maps/BQDynmap.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/maps/BQDynmap.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.maps; +package fr.skytasul.quests.integrations.maps; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -7,9 +7,10 @@ import org.dynmap.markers.MarkerAPI; import org.dynmap.markers.MarkerIcon; import org.dynmap.markers.MarkerSet; -import fr.skytasul.quests.QuestsConfigurationImplementation; +import fr.skytasul.quests.api.AbstractMapIntegration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.integrations.IntegrationsConfiguration; import net.md_5.bungee.api.ChatColor; public class BQDynmap extends AbstractMapIntegration { @@ -19,21 +20,24 @@ public class BQDynmap extends AbstractMapIntegration { @Override public boolean isEnabled() { - return QuestsConfigurationImplementation.dynmapMarkerIcon() != null && !QuestsConfigurationImplementation.dynmapMarkerIcon().isEmpty(); + return IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon() != null + && !IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon().isEmpty(); } @Override protected void initializeMarkers(Runnable initializeQuests) { DynmapAPI dynmap = (DynmapAPI) Bukkit.getPluginManager().getPlugin("dynmap"); MarkerAPI api = dynmap.getMarkerAPI(); - icon = api.getMarkerIcon(QuestsConfigurationImplementation.dynmapMarkerIcon()); + icon = api.getMarkerIcon(IntegrationsConfiguration.getConfiguration().dynmapMarkerIcon()); markers = api.getMarkerSet("beautyquests.markerset"); if (markers == null){ - markers = api.createMarkerSet("beautyquests.markerset", QuestsConfigurationImplementation.dynmapSetName(), null, false); - }else markers.setMarkerSetLabel(QuestsConfigurationImplementation.dynmapSetName()); + markers = api.createMarkerSet("beautyquests.markerset", + IntegrationsConfiguration.getConfiguration().dynmapSetName(), null, false); + } else + markers.setMarkerSetLabel(IntegrationsConfiguration.getConfiguration().dynmapSetName()); - markers.setMinZoom(QuestsConfigurationImplementation.dynmapMinimumZoom()); + markers.setMinZoom(IntegrationsConfiguration.getConfiguration().dynmapMinimumZoom()); markers.setHideByDefault(false); markers.setDefaultMarkerIcon(icon); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McCombatLevelRequirement.java similarity index 85% rename from core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McCombatLevelRequirement.java index d5ff759d..3f83cfe4 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McCombatLevelRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McCombatLevelRequirement.java @@ -1,11 +1,11 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.mcmmo; import org.bukkit.entity.Player; +import com.gmail.mrphpfan.mccombatlevel.McCombatLevel; 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 fr.skytasul.quests.utils.compatibility.McCombatLevel; public class McCombatLevelRequirement extends TargetNumberRequirement { @@ -20,7 +20,7 @@ public McCombatLevelRequirement(String customDescription, String customReason, d @Override public double getPlayerTarget(Player p) { - return McCombatLevel.getCombatLevel(p); + return McCombatLevel.getPlugin(McCombatLevel.class).getLevel(p).orElse(0); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McMMOSkillRequirement.java similarity index 87% rename from core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McMMOSkillRequirement.java index f9576529..ba4c5f0b 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/McMMOSkillRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McMMOSkillRequirement.java @@ -1,8 +1,9 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.mcmmo; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import com.gmail.nossr50.api.ExperienceAPI; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -11,7 +12,6 @@ import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.McMMO; public class McMMOSkillRequirement extends TargetNumberRequirement { @@ -27,7 +27,7 @@ public McMMOSkillRequirement(String customDescription, String customReason, doub @Override public double getPlayerTarget(Player p) { - return McMMO.getLevel(p, skillName); + return ExperienceAPI.getLevel(p, skillName); } @Override @@ -70,10 +70,7 @@ protected void addLore(QuestObjectLoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { Lang.CHOOSE_SKILL_REQUIRED.send(event.getPlayer()); - new TextEditor<String>(event.getPlayer(), () -> { - if (skillName == null) event.getGUI().remove(this); - event.reopenGUI(); - }, (obj) -> { + new TextEditor<String>(event.getPlayer(), event::cancel, obj -> { this.skillName = obj; super.itemClick(event); }).useStrippedMessage().start(); diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQAdvancedSpawners.java similarity index 96% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQAdvancedSpawners.java index 619ddf7f..23d71281 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQAdvancedSpawners.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQAdvancedSpawners.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.integrations.mobs; import java.util.function.Consumer; import org.bukkit.entity.Entity; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQBoss.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQBoss.java index 660da625..9c43a11e 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQBoss.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQBoss.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.integrations.mobs; import java.util.Arrays; import java.util.List; @@ -80,7 +80,7 @@ public EntityType getEntityType(Boss data) { @Override public List<String> getDescriptiveLore(Boss data) { return Arrays.asList( - Lang.EntityType.format(MinecraftNames.getEntityName(data.getType())), + Lang.EntityType.quickFormat("entity_type", MinecraftNames.getEntityName(data.getType())), "§8Health: §7§l" + data.getDefaultHealth()); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQLevelledMobs.java similarity index 55% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQLevelledMobs.java index e14fd769..985c1f5f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQLevelledMobs.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQLevelledMobs.java @@ -1,20 +1,21 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +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.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; 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 me.lokka30.levelledmobs.LevelledMobs; -public class BQLevelledMobs extends BukkitEntityFactory implements LeveledMobFactory<EntityType> { +public class BQLevelledMobs implements LeveledMobFactory<EntityType> { @Override public String getID() { @@ -40,8 +41,31 @@ public double getMobLevel(EntityType type, Entity entity) { } @Override - public void onEntityKilled(EntityDeathEvent e) { - // do nothing as the original BukkitEntityFactory will manage the event itself + public EntityType fromValue(String value) { + return EntityType.valueOf(value); } + @Override + public String getValue(EntityType data) { + return data.name(); + } + + @Override + public String getName(EntityType data) { + return MinecraftNames.getEntityName(data); + } + + @Override + public EntityType getEntityType(EntityType data) { + return data; + } + + @Override + public boolean bukkitMobApplies(@NotNull EntityType first, @NotNull Entity entity) { + return entity.getType() == first; + } + + // we do not have to bother about listening to EntityDeathEvent as the integrated + // BukkitEntityFactory will manage the event by itself + } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQWildStacker.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQWildStacker.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQWildStacker.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQWildStacker.java index 044b7463..76f7458f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/BQWildStacker.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQWildStacker.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.integrations.mobs; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java similarity index 87% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java index 97e6affe..1f504308 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/CitizensFactory.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.integrations.mobs; import java.util.Arrays; import java.util.List; @@ -11,10 +11,11 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; +import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.CancellableEditor; +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.gui.npc.NpcSelectGUI; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.NPCDeathEvent; import net.citizensnpcs.api.event.NPCRightClickEvent; @@ -23,6 +24,8 @@ public class CitizensFactory implements MobFactory<NPC>, Listener { + private final ItemStack item = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); + @Override public String getID() { return "citizensNPC"; @@ -30,7 +33,7 @@ public String getID() { @Override public ItemStack getFactoryItem() { - return NpcSelectGUI.selectNPC; + return item; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/EpicBosses.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/EpicBosses.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/EpicBosses.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/EpicBosses.java index 307477ee..9b5f1c34 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/EpicBosses.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/EpicBosses.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.integrations.mobs; import org.bukkit.entity.EntityType; import org.bukkit.event.Listener; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs.java similarity index 88% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs.java index 279de6cc..5ca5580d 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.integrations.mobs; import java.util.Arrays; import java.util.List; @@ -20,7 +20,6 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.messaging.MessageUtils; import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; import io.lumine.xikage.mythicmobs.mobs.MythicMob; import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderString; @@ -132,13 +131,4 @@ public void onMythicDeath(MythicMobDeathEvent e) { callEvent(e, e.getMob().getType(), e.getEntity(), (Player) e.getKiller()); } - public static void sendMythicMobsList(Player p){ - Lang.MYTHICMOB_LIST.send(p); - StringBuilder stb = new StringBuilder("§a"); - for (MythicMob mm : io.lumine.xikage.mythicmobs.MythicMobs.inst().getMobManager().getMobTypes()) { - stb.append(mm.getInternalName() + "; "); - } - MessageUtils.sendUnprefixedMessage(p, stb.toString()); - } - } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs5.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs5.java index e0595820..2444d958 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/mobs/MythicMobs5.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs5.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.mobs; +package fr.skytasul.quests.integrations.mobs; import java.util.Arrays; import java.util.List; @@ -21,7 +21,6 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.messaging.MessageUtils; import io.lumine.mythic.api.mobs.MythicMob; import io.lumine.mythic.api.skills.placeholders.PlaceholderString; import io.lumine.mythic.bukkit.MythicBukkit; @@ -135,13 +134,4 @@ public void onMythicDeath(MythicMobDeathEvent e) { callEvent(e, e.getMob().getType(), e.getEntity(), (Player) e.getKiller()); } - public static void sendMythicMobsList(Player p){ - Lang.MYTHICMOB_LIST.send(p); - StringBuilder stb = new StringBuilder("§a"); - for (MythicMob mm : MythicBukkit.inst().getMobManager().getMobTypes()) { - stb.append(mm.getInternalName() + "; "); - } - MessageUtils.sendUnprefixedMessage(p, stb.toString()); - } - } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java similarity index 98% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java index 7933228d..6ebaf390 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQCitizens.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.npcs; +package fr.skytasul.quests.integrations.npcs; import java.util.Collection; import java.util.stream.Collectors; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQSentinel.java similarity index 97% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQSentinel.java index b5acb583..77d8f3d9 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQSentinel.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQSentinel.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.npcs; +package fr.skytasul.quests.integrations.npcs; import java.util.function.BiPredicate; import org.bukkit.entity.LivingEntity; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java similarity index 98% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java index 2523f8cd..bd80836f 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/npcs/BQServerNPCs.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.npcs; +package fr.skytasul.quests.integrations.npcs; import java.util.Arrays; import java.util.Collection; diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java new file mode 100644 index 00000000..78ffd0a7 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java @@ -0,0 +1,26 @@ +package fr.skytasul.quests.integrations.placeholders; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.utils.messaging.MessageProcessor; +import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; +import me.clip.placeholderapi.PlaceholderAPI; + +public class PapiMessageProcessor implements MessageProcessor { + + @Override + public int getPriority() { + return 5; + } + + @Override + public @NotNull String processString(@NotNull String string, @NotNull PlaceholdersContext context) { + if (context.replacePluginPlaceholders() && context.getActor() instanceof Player) { + Player player = (Player) context.getActor(); + return PlaceholderAPI.setPlaceholders(player, string); + } + + return string; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java similarity index 95% rename from core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java index 91ee97e6..99397ebf 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PlaceholderRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.placeholders; import java.math.BigDecimal; import org.bukkit.configuration.ConfigurationSection; @@ -15,7 +15,6 @@ import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; -import fr.skytasul.quests.utils.compatibility.QuestsPlaceholders; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/QuestsPlaceholders.java similarity index 93% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/QuestsPlaceholders.java index 26c15dc2..2ce413db 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/QuestsPlaceholders.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/QuestsPlaceholders.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations.placeholders; import java.util.AbstractMap; import java.util.ArrayList; @@ -20,7 +20,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; -import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.localization.Lang; @@ -30,7 +29,6 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.ChatColorUtils; -import me.clip.placeholderapi.PlaceholderAPI; import me.clip.placeholderapi.events.ExpansionRegisterEvent; import me.clip.placeholderapi.expansion.PlaceholderExpansion; @@ -56,14 +54,10 @@ private QuestsPlaceholders(ConfigurationSection placeholderConfig) { inlineFormat = placeholderConfig.getString("inlinePlaceholderFormat"); } - public static String setPlaceholders(OfflinePlayer p, String text) { - return PlaceholderAPI.setPlaceholders(p, text); - } - - static void registerPlaceholders(ConfigurationSection placeholderConfig) { + public static void registerPlaceholders(ConfigurationSection placeholderConfig) { placeholders = new QuestsPlaceholders(placeholderConfig); placeholders.register(); - Bukkit.getPluginManager().registerEvents(placeholders, BeautyQuests.getInstance()); + Bukkit.getPluginManager().registerEvents(placeholders, QuestsPlugin.getPlugin()); QuestsPlugin.getPlugin().getLoggerExpanded().info("Placeholders registered !"); } @@ -73,7 +67,7 @@ public static void waitForExpansion(String identifier, Consumer<PlaceholderExpan @Override public String getAuthor() { - return BeautyQuests.getInstance().getDescription().getAuthors().toString(); + return QuestsPlugin.getPlugin().getDescription().getAuthors().toString(); } @Override @@ -83,7 +77,7 @@ public String getIdentifier() { @Override public String getVersion() { - return BeautyQuests.getInstance().getDescription().getVersion(); + return QuestsPlugin.getPlugin().getDescription().getVersion(); } @Override @@ -227,7 +221,7 @@ public String onRequest(OfflinePlayer off, String identifier) { } private void launchTask() { - task = Bukkit.getScheduler().runTaskTimerAsynchronously(BeautyQuests.getInstance(), () -> { + task = Bukkit.getScheduler().runTaskTimerAsynchronously(QuestsPlugin.getPlugin(), () -> { playersLock.lock(); try { for (Iterator<Entry<Player, PlayerPlaceholderData>> iterator = players.entrySet().iterator(); iterator.hasNext();) { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java index 5592e886..68e48919 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ClassRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.skillapi; import java.util.ArrayList; import java.util.List; @@ -19,7 +19,6 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; -import fr.skytasul.quests.utils.compatibility.SkillAPI; public class ClassRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/SkillAPI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPI.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/SkillAPI.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPI.java index e67d536b..71440af4 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/SkillAPI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations.skillapi; import java.util.Collection; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPILevelRequirement.java similarity index 93% rename from core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPILevelRequirement.java index cec669c5..bc1b3aee 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/SkillAPILevelRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPILevelRequirement.java @@ -1,11 +1,10 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.skillapi; 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 fr.skytasul.quests.utils.compatibility.SkillAPI; public class SkillAPILevelRequirement extends TargetNumberRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Vault.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/Vault.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/Vault.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/vault/Vault.java index fcdd0a39..fd11df4c 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Vault.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/Vault.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility; +package fr.skytasul.quests.integrations.vault; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyRequirement.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyRequirement.java index 18b85baf..0c28bd80 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/MoneyRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyRequirement.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.vault.economy; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -12,7 +12,7 @@ import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.Actionnable; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.Vault; +import fr.skytasul.quests.integrations.vault.Vault; public class MoneyRequirement extends AbstractRequirement implements Actionnable { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyReward.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyReward.java index 6b8c40cb..732ad8ad 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MoneyReward.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyReward.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.rewards; +package fr.skytasul.quests.integrations.vault.economy; import java.util.Arrays; import java.util.List; @@ -12,7 +12,7 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.Vault; +import fr.skytasul.quests.integrations.vault.Vault; public class MoneyReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/Permission.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/utils/types/Permission.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/Permission.java index 0e8b90ac..b34ae9aa 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Permission.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/Permission.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.types; +package fr.skytasul.quests.integrations.vault.permission; import java.util.HashMap; import java.util.Map; @@ -8,7 +8,7 @@ import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.Vault; +import fr.skytasul.quests.integrations.vault.Vault; public class Permission implements Cloneable, HasPlaceholders { diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java similarity index 94% rename from core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java index ec973fca..9d2c9175 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionGUI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.permissions; +package fr.skytasul.quests.integrations.vault.permission; import java.util.function.Consumer; import org.bukkit.Bukkit; @@ -17,7 +17,6 @@ import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.utils.types.Permission; public class PermissionGUI extends AbstractGui { diff --git a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java index c3dc9f04..5e17c4ce 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/permissions/PermissionListGUI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.gui.permissions; +package fr.skytasul.quests.integrations.vault.permission; import java.util.List; import java.util.function.Consumer; @@ -10,7 +10,6 @@ import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.utils.types.Permission; public class PermissionListGUI extends ListGUI<Permission> { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionReward.java similarity index 90% rename from core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionReward.java index e67ee30c..53698ac4 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/PermissionReward.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionReward.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.rewards; +package fr.skytasul.quests.integrations.vault.permission; import java.util.ArrayList; import java.util.List; @@ -11,8 +11,6 @@ import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.gui.permissions.PermissionListGUI; -import fr.skytasul.quests.utils.types.Permission; public class PermissionReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/BQWorldGuard.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/BQWorldGuard.java index e8c27248..9a8ddcdd 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/BQWorldGuard.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/BQWorldGuard.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.worldguard; +package fr.skytasul.quests.integrations.worldguard; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -17,9 +17,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.requirements.RequirementCreator; import fr.skytasul.quests.api.stages.StageType; -import fr.skytasul.quests.requirements.RegionRequirement; -import fr.skytasul.quests.stages.StageArea; -import fr.skytasul.quests.utils.compatibility.MissingDependencyException; +import fr.skytasul.quests.api.utils.MissingDependencyException; public class BQWorldGuard { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/RegionRequirement.java similarity index 93% rename from core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/RegionRequirement.java index cdce3546..32dde177 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/RegionRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/RegionRequirement.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.requirements; +package fr.skytasul.quests.integrations.worldguard; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; @@ -13,7 +13,6 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; public class RegionRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/stages/StageArea.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java index 30dffdb5..1d6a8b3b 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageArea.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.stages; +package fr.skytasul.quests.integrations.worldguard; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; @@ -13,6 +13,7 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -29,10 +30,6 @@ import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.DebugUtils; -import fr.skytasul.quests.utils.compatibility.worldguard.BQWorldGuard; -import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardEntryEvent; -import fr.skytasul.quests.utils.compatibility.worldguard.WorldGuardExitEvent; @LocatableType (types = LocatedType.OTHER) public class StageArea extends AbstractStage implements Locatable.PreciseLocatable { @@ -76,7 +73,7 @@ public void onRegionEntry(WorldGuardEntryEvent e) { if (exit) return; if (region == null) { - DebugUtils.printError("No region for " + toString(), "area" + toString(), 5); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("No region for " + toString(), this, 15); return; } if (e.getRegionsEntered().stream().anyMatch(eventRegion -> eventRegion.getId().equals(region.getId()))) { @@ -89,7 +86,7 @@ public void onRegionExit(WorldGuardExitEvent e) { if (!exit) return; if (region == null) { - DebugUtils.printError("No region for " + toString(), "area" + toString(), 5); + QuestsPlugin.getPlugin().getLoggerExpanded().warning("No region for " + toString(), this, 15); return; } if (e.getRegionsExited().stream().anyMatch(eventRegion -> eventRegion.getId().equals(region.getId()))) { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryEvent.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardEntryEvent.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryEvent.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardEntryEvent.java index 8327cc08..fabc6bf4 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryEvent.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardEntryEvent.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.worldguard; +package fr.skytasul.quests.integrations.worldguard; import java.util.Set; import org.bukkit.entity.Player; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardEntryHandler.java similarity index 91% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardEntryHandler.java index 067c11e8..79a7a3d5 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardEntryHandler.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardEntryHandler.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.worldguard; +package fr.skytasul.quests.integrations.worldguard; import java.util.Set; import org.bukkit.Bukkit; @@ -14,7 +14,7 @@ import com.sk89q.worldguard.session.Session; import com.sk89q.worldguard.session.SessionManager; import com.sk89q.worldguard.session.handler.Handler; -import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.QuestsPlugin; public class WorldGuardEntryHandler extends Handler { @@ -53,7 +53,7 @@ public WorldGuardEntryHandler(Session session) { @Override public boolean onCrossBoundary(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) { Player bukkitPlayer = BukkitAdapter.adapt(player); - if (!BeautyQuests.getInstance().getNpcManager().getInternalFactory().isNPC(bukkitPlayer)) { + if (!QuestsPlugin.getPlugin().getNpcManager().isNPC(bukkitPlayer)) { Bukkit.getPluginManager().callEvent(new WorldGuardEntryEvent(bukkitPlayer, entered)); Bukkit.getPluginManager().callEvent(new WorldGuardExitEvent(bukkitPlayer, exited)); } diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardExitEvent.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardExitEvent.java similarity index 92% rename from core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardExitEvent.java rename to integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardExitEvent.java index ba64685c..3f0d1ddc 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/worldguard/WorldGuardExitEvent.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/WorldGuardExitEvent.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.utils.compatibility.worldguard; +package fr.skytasul.quests.integrations.worldguard; import java.util.Set; import org.bukkit.entity.Player; diff --git a/pom.xml b/pom.xml index c5ac71c7..e8775cdb 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ <modules> <module>api</module> <module>core</module> + <module>integrations</module> <module>v1_9_R1</module> <module>v1_9_R2</module> <module>v1_12_R1</module> From db8d045be877374fdfda195b20c5abbfc2490dd8 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 15 Aug 2023 22:06:04 +0200 Subject: [PATCH 33/95] :construction: Completed work on integrations separation --- .../quests/api/localization/Lang.java | 2 + .../QuestsConfigurationImplementation.java | 10 +-- .../skytasul/quests/gui/misc/CommandGUI.java | 6 +- .../fr/skytasul/quests/rewards/XPReward.java | 8 +- core/src/main/resources/config.yml | 12 ++- core/src/main/resources/locales/en_US.yml | 4 +- .../IntegrationsConfiguration.java | 7 +- .../integrations/IntegrationsLoader.java | 11 ++- .../skillapi/SkillAPIXpReward.java | 82 +++++++++++++++++++ 9 files changed, 114 insertions(+), 28 deletions(-) create mode 100755 integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java 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 479fb2f4..8ef4023c 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 @@ -813,6 +813,8 @@ public enum Lang implements Locale { RMoney("misc.requirement.money"), REquipment("misc.requirement.equipment"), + RWSkillApiXp("misc.reward.skillApiXp"), + BucketWater("misc.bucket.water"), BucketLava("misc.bucket.lava"), BucketMilk("misc.bucket.milk"), diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 2bb4381b..bd98d46f 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -31,7 +31,7 @@ import fr.skytasul.quests.players.BqAccountsHook; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; -import fr.skytasul.quests.utils.compatibility.DependenciesManager; +import fr.skytasul.quests.utils.compatibility.InternalIntegrations; public class QuestsConfigurationImplementation implements QuestsConfiguration { @@ -107,12 +107,12 @@ void init() { disableTextHologram = config.getBoolean("disableTextHologram"); showCustomHologramName = config.getBoolean("showCustomHologramName"); hologramsHeight = 0.28 + config.getDouble("hologramsHeight"); - hookAcounts = DependenciesManager.acc.isEnabled() && config.getBoolean("accountsHook"); + hookAcounts = config.getBoolean("accountsHook"); if (hookAcounts) { Bukkit.getPluginManager().registerEvents(new BqAccountsHook(), BeautyQuests.getInstance()); QuestsPlugin.getPlugin().getLoggerExpanded().info("AccountsHook is now managing player datas for quests !"); } - usePlayerBlockTracker = DependenciesManager.PlayerBlockTracker.isEnabled() && config.getBoolean("usePlayerBlockTracker"); + usePlayerBlockTracker = config.getBoolean("usePlayerBlockTracker"); if (MinecraftVersion.MAJOR >= 9) { particleStart = loadParticles("start", new ParticleEffect(Particle.REDSTONE, ParticleShape.POINT, Color.YELLOW)); @@ -287,11 +287,11 @@ public FireworkMeta getDefaultFirework() { } public boolean hookAccounts() { - return hookAcounts; + return hookAcounts && InternalIntegrations.AccountsHook.isEnabled(); } public boolean usePlayerBlockTracker() { - return usePlayerBlockTracker; + return usePlayerBlockTracker && InternalIntegrations.PlayerBlockTracker.isEnabled(); } public boolean isMinecraftTranslationsEnabled() { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java index fc8091e3..9c1644c3 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java @@ -13,7 +13,6 @@ import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.utils.compatibility.DependenciesManager; import fr.skytasul.quests.utils.types.Command; public class CommandGUI extends LayoutedGUI.LayoutedRowsGUI { @@ -36,9 +35,8 @@ public CommandGUI(Consumer<Command> end, Runnable cancel) { this::commandClick)); buttons.put(3, LayoutedButton.create(() -> ItemUtils.itemSwitch(Lang.commandConsole.toString(), console), this::consoleClick)); - if (DependenciesManager.papi.isEnabled()) - buttons.put(4, LayoutedButton.create(() -> ItemUtils.itemSwitch(Lang.commandParse.toString(), parse), - this::parseClick)); + buttons.put(4, LayoutedButton.create(() -> ItemUtils.itemSwitch(Lang.commandParse.toString(), parse), + this::parseClick)); buttons.put(5, LayoutedButton.createLoreValue(XMaterial.CLOCK, Lang.commandDelay.toString(), () -> delay, this::delayClick)); buttons.put(8, diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index bd4bf3c8..cf52b3ce 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -5,7 +5,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.localization.Lang; @@ -13,8 +12,6 @@ import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.utils.compatibility.DependenciesManager; -import fr.skytasul.quests.utils.compatibility.SkillAPI; public class XPReward extends AbstractReward { @@ -29,10 +26,7 @@ public XPReward(String customDescription, int exp) { @Override public List<String> give(Player p) { - if (DependenciesManager.skapi.isEnabled() - && QuestsConfigurationImplementation.getConfiguration().xpOverridedSkillAPI()) { - SkillAPI.giveExp(p, exp); - }else p.giveExp(exp); + p.giveExp(exp); return Arrays.asList(getXpAmountString()); } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 20275d60..dd6960cc 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -101,22 +101,20 @@ questsMenu: allowPlayerCancelQuest: true # - Integrations - -# Enable or disable SkillAPI experience overriding in xp reward/requirement -skillAPIoverride: true # Enable or disable AccountsHook managing player accounts accountsHook: false # If set to "true" and the PlayerBlockTracker plugin is enabled on this server, then player-placed blocks will be tracked # using PlayerBlockTracker: it allows for persistence after restart, piston tracking, and more. usePlayerBlockTracker: true -# (HolographicDisplays) Disable the hologram above NPC's head +# (Holograms) Disable the hologram above NPC's head disableTextHologram: false -# (HolographicDisplays) Value added to the hologram height (decimal value) +# (Holograms) Value added to the hologram height (decimal value) hologramsHeight: 0.0 -# (HolographicDisplays) Material name of the hologram showed above head of Quests starter. If ProtocolLib is enabled, holograms will be visible only by players who can start the quest +# (Holograms) Material name of the hologram showed above head of Quests starter. If ProtocolLib is enabled, holograms will be visible only by players who can start the quest holoLaunchItemName: BOOK -# (HolographicDisplays) Material name of the hologram showed above head of Stage NPC. If ProtocolLib is enabled, holograms will be visible only by players who has to talk with this NPC +# (Holograms) Material name of the hologram showed above head of Stage NPC. If ProtocolLib is enabled, holograms will be visible only by players who has to talk with this NPC holoTalkItemName: COAL -# (HolographicDisplays) Is the custom name of the hologram in datas.yml shown +# (Holograms) Is the custom name of the hologram in datas.yml shown showCustomHologramName: true # (PlaceholdersAPI) Configuration for %beautyquests_started_ordered_X% placeholder startedQuestsPlaceholder: diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 3e55902d..8760bcf3 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -808,7 +808,7 @@ misc: days: '{days_amount} days' hours: '{hours_amount} hours' minutes: '{minutes_amount} minutes' - lessThanAMinute: 'less than a minute' + lessThanAMinute: 'a few seconds' stageType: region: Find region npc: Find NPC @@ -853,6 +853,8 @@ misc: mcMMOSkillLevel: §dSkill level required money: §dMoney required equipment: §eEquipment required + reward: + skillApiXp: SkillAPI XP reward bucket: water: Water bucket lava: Lava bucket diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java index 8747b616..5114a8ef 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsConfiguration.java @@ -1,6 +1,7 @@ package fr.skytasul.quests.integrations; import org.bukkit.configuration.file.FileConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; public class IntegrationsConfiguration { @@ -15,8 +16,10 @@ public IntegrationsConfiguration(FileConfiguration config) { } public void load() { - if (config.getBoolean("skillAPIoverride")) { - + if (config.getBoolean("skillAPIoverride", false)) { + config.set("skillAPIoverride", null); + QuestsPlugin.getPlugin().getLogger().warning("The config option \"skillAPIoverride\" is no longer supported." + + " You must change your vanilla XP rewards to specialized SkillAPI XP rewards."); } dSetName = config.getString("dynmap.markerSetName"); 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 b8386ab4..60f9a19c 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java @@ -33,6 +33,7 @@ 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; @@ -95,8 +96,12 @@ public IntegrationsLoader() { // MAPS - manager.addDependency(new BQDependency("dynmap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQDynmap()))); - manager.addDependency(new BQDependency("BlueMap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQBlueMap()))); + if (config.dynmapSetName() != null && !config.dynmapSetName().isEmpty()) { + manager.addDependency( + new BQDependency("dynmap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQDynmap()))); + manager.addDependency( + new BQDependency("BlueMap", () -> QuestsAPI.getAPI().registerQuestsHandler(new BQBlueMap()))); + } // HOLOGRAMS @@ -184,6 +189,8 @@ private void registerSkillApi() { .register(new RequirementCreator("skillAPILevelRequired", SkillAPILevelRequirement.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)); } private boolean isBossVersionValid(Plugin plugin) { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java new file mode 100755 index 00000000..71535505 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java @@ -0,0 +1,82 @@ +package fr.skytasul.quests.integrations.skillapi; + +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.localization.Lang; +import fr.skytasul.quests.api.objects.QuestObjectClickEvent; +import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; +import fr.skytasul.quests.api.rewards.AbstractReward; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; + +public class SkillAPIXpReward extends AbstractReward { + + public int exp = 0; + + public SkillAPIXpReward() {} + + public SkillAPIXpReward(String customDescription, int exp) { + super(customDescription); + this.exp = exp; + } + + @Override + public List<String> give(Player p) { + SkillAPI.giveExp(p, exp); + return Arrays.asList(getXpAmountString()); + } + + @Override + public AbstractReward clone() { + return new SkillAPIXpReward(getCustomDescription(), exp); + } + + @Override + public String getDefaultDescription(Player p) { + return getXpAmountString(); + } + + @Override + protected void addLore(QuestObjectLoreBuilder loreBuilder) { + super.addLore(loreBuilder); + loreBuilder.addDescriptionAsValue(getXpAmountString()); + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexed("xp_amount", this::getXpAmountString); + } + + private @NotNull String getXpAmountString() { + return Lang.AmountXp.quickFormat("xp_amount", exp); + } + + @Override + public void itemClick(QuestObjectClickEvent event) { + Lang.XP_GAIN.send(event.getPlayer(), this); + new TextEditor<>(event.getPlayer(), event::cancel, obj -> { + int old = exp; + exp = obj; + Lang.XP_EDITED.send(event.getPlayer(), PlaceholderRegistry.of("old_xp_amount", old).with(this)); + event.reopenGUI(); + }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); + } + + @Override + public void save(ConfigurationSection section) { + super.save(section); + section.set("xp", exp); + } + + @Override + public void load(ConfigurationSection section) { + super.load(section); + exp = section.getInt("xp"); + } + +} From 8b10b4f9b8da20df796f42691af9f9f3d3cff459 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 21 Aug 2023 22:30:04 +0200 Subject: [PATCH 34/95] :construction: Split interaction stage --- .../quests/api/localization/Lang.java | 8 +- .../skytasul/quests/DefaultQuestFeatures.java | 158 +++++------ .../skytasul/quests/stages/StageInteract.java | 248 ------------------ .../quests/stages/StageInteractBlock.java | 163 ++++++++++++ .../quests/stages/StageInteractLocation.java | 172 ++++++++++++ .../skytasul/quests/stages/StageLocation.java | 14 - .../StageControllerImplementation.java | 10 +- .../utils/compatibility/BQBackwardCompat.java | 23 ++ core/src/main/resources/locales/en_US.yml | 6 +- 9 files changed, 455 insertions(+), 347 deletions(-) delete mode 100644 core/src/main/java/fr/skytasul/quests/stages/StageInteract.java create mode 100755 core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java create mode 100644 core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java create mode 100755 core/src/main/java/fr/skytasul/quests/utils/compatibility/BQBackwardCompat.java 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 8ef4023c..fd5d2185 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 @@ -357,7 +357,8 @@ public enum Lang implements Locale { stageMine("inv.create.mineBlocks"), stagePlace("inv.create.placeBlocks"), stageChat("inv.create.talkChat"), - stageInteract("inv.create.interact"), + stageInteractBlock("inv.create.interact"), + stageInteractLocation("inv.create.interactLocation"), stageFish("inv.create.fish"), stageMelt("inv.create.melt"), stageEnchant("inv.create.enchant"), @@ -725,7 +726,7 @@ public enum Lang implements Locale { SCOREBOARD_MINE("scoreboard.stage.mine"), SCOREBOARD_PLACE("scoreboard.stage.placeBlocks"), SCOREBOARD_CHAT("scoreboard.stage.chat"), - SCOREBOARD_INTERACT("scoreboard.stage.interact"), + SCOREBOARD_INTERACT_LOCATION("scoreboard.stage.interact"), SCOREBOARD_INTERACT_MATERIAL("scoreboard.stage.interactMaterial"), SCOREBOARD_FISH("scoreboard.stage.fish"), SCOREBOARD_MELT("scoreboard.stage.melt"), @@ -776,7 +777,8 @@ public enum Lang implements Locale { Mine("misc.stageType.mine"), Place("misc.stageType.placeBlocks"), Chat("misc.stageType.chat"), - Interact("misc.stageType.interact"), + InteractBlock("misc.stageType.interact"), + InteractLocation("misc.stageType.interactLocation"), Fish("misc.stageType.Fish"), Melt("misc.stageType.Melt"), Enchant("misc.stageType.Enchant"), diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index 7c2ada84..8e8a7516 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -1,5 +1,6 @@ package fr.skytasul.quests; +import static fr.skytasul.quests.api.gui.ItemUtils.item; import java.util.Arrays; import java.util.Objects; import org.bukkit.inventory.ItemStack; @@ -11,7 +12,6 @@ import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparison; -import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectLocation; import fr.skytasul.quests.api.options.QuestOptionCreator; @@ -22,6 +22,7 @@ import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.stages.StageTypeRegistry; import fr.skytasul.quests.api.stages.options.StageOption; import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; import fr.skytasul.quests.api.utils.MinecraftVersion; @@ -87,7 +88,8 @@ import fr.skytasul.quests.stages.StageEatDrink; import fr.skytasul.quests.stages.StageEnchant; import fr.skytasul.quests.stages.StageFish; -import fr.skytasul.quests.stages.StageInteract; +import fr.skytasul.quests.stages.StageInteractBlock; +import fr.skytasul.quests.stages.StageInteractLocation; import fr.skytasul.quests.stages.StageLocation; import fr.skytasul.quests.stages.StageMelt; import fr.skytasul.quests.stages.StageMine; @@ -105,65 +107,67 @@ public final class DefaultQuestFeatures { private DefaultQuestFeatures() {} - private static final ItemStack stageNPC = ItemUtils.item(XMaterial.OAK_SIGN, Lang.stageNPC.toString()); - private static final ItemStack stageItems = ItemUtils.item(XMaterial.CHEST, Lang.stageBring.toString()); - private static final ItemStack stageMobs = ItemUtils.item(XMaterial.WOODEN_SWORD, Lang.stageMobs.toString()); - private static final ItemStack stageMine = ItemUtils.item(XMaterial.WOODEN_PICKAXE, Lang.stageMine.toString()); - private static final ItemStack stagePlace = ItemUtils.item(XMaterial.OAK_STAIRS, Lang.stagePlace.toString()); - private static final ItemStack stageChat = ItemUtils.item(XMaterial.PLAYER_HEAD, Lang.stageChat.toString()); - private static final ItemStack stageInteract = ItemUtils.item(XMaterial.STICK, Lang.stageInteract.toString()); - private static final ItemStack stageFish = ItemUtils.item(XMaterial.COD, Lang.stageFish.toString()); - private static final ItemStack stageMelt = ItemUtils.item(XMaterial.FURNACE, Lang.stageMelt.toString()); - private static final ItemStack stageEnchant = ItemUtils.item(XMaterial.ENCHANTING_TABLE, Lang.stageEnchant.toString()); - private static final ItemStack stageCraft = ItemUtils.item(XMaterial.CRAFTING_TABLE, Lang.stageCraft.toString()); - private static final ItemStack stageBucket = ItemUtils.item(XMaterial.BUCKET, Lang.stageBucket.toString()); - private static final ItemStack stageLocation = ItemUtils.item(XMaterial.MINECART, Lang.stageLocation.toString()); - private static final ItemStack stagePlayTime = ItemUtils.item(XMaterial.CLOCK, Lang.stagePlayTime.toString()); - private static final ItemStack stageBreed = ItemUtils.item(XMaterial.WHEAT, Lang.stageBreedAnimals.toString()); - private static final ItemStack stageTame = ItemUtils.item(XMaterial.CARROT, Lang.stageTameAnimals.toString()); - private static final ItemStack stageDeath = ItemUtils.item(XMaterial.SKELETON_SKULL, Lang.stageDeath.toString()); - private static final ItemStack stageDealDamage = ItemUtils.item(XMaterial.REDSTONE, Lang.stageDealDamage.toString()); - private static final ItemStack stageEatDrink = ItemUtils.item(XMaterial.COOKED_PORKCHOP, Lang.stageEatDrink.toString()); public static void registerStages() { - QuestsAPI.getAPI().getStages().register(new StageType<>("NPC", StageNPC.class, Lang.Talk.name(), - StageNPC::deserialize, stageNPC, StageNPC.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("ITEMS", StageBringBack.class, Lang.Items.name(), - StageBringBack::deserialize, stageItems, StageBringBack.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("MOBS", StageMobs.class, Lang.Mobs.name(), - StageMobs::deserialize, stageMobs, StageMobs.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("MINE", StageMine.class, Lang.Mine.name(), - StageMine::deserialize, stageMine, StageMine.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("PLACE_BLOCKS", StagePlaceBlocks.class, Lang.Place.name(), - StagePlaceBlocks::deserialize, stagePlace, StagePlaceBlocks.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("CHAT", StageChat.class, Lang.Chat.name(), - StageChat::deserialize, stageChat, StageChat.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("INTERACT", StageInteract.class, Lang.Interact.name(), - StageInteract::deserialize, stageInteract, StageInteract.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("FISH", StageFish.class, Lang.Fish.name(), - StageFish::deserialize, stageFish, StageFish.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("MELT", StageMelt.class, Lang.Melt.name(), - StageMelt::deserialize, stageMelt, StageMelt.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("ENCHANT", StageEnchant.class, Lang.Enchant.name(), - StageEnchant::deserialize, stageEnchant, StageEnchant.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("CRAFT", StageCraft.class, Lang.Craft.name(), - StageCraft::deserialize, stageCraft, StageCraft.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("BUCKET", StageBucket.class, Lang.Bucket.name(), - StageBucket::deserialize, stageBucket, StageBucket.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("LOCATION", StageLocation.class, Lang.StageLocation.name(), - StageLocation::deserialize, stageLocation, StageLocation.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("PLAY_TIME", StagePlayTime.class, Lang.PlayTime.name(), - StagePlayTime::deserialize, stagePlayTime, StagePlayTime.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("BREED", StageBreed.class, Lang.Breed.name(), - StageBreed::deserialize, stageBreed, StageBreed.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("TAME", StageTame.class, Lang.Tame.name(), - StageTame::deserialize, stageTame, StageTame.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("DEATH", StageDeath.class, Lang.Death.name(), - StageDeath::deserialize, stageDeath, StageDeath.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("DEAL_DAMAGE", StageDealDamage.class, Lang.DealDamage.name(), - StageDealDamage::deserialize, stageDealDamage, StageDealDamage.Creator::new)); - QuestsAPI.getAPI().getStages().register(new StageType<>("EAT_DRINK", StageEatDrink.class, Lang.EatDrink.name(), - StageEatDrink::new, stageEatDrink, StageEatDrink.Creator::new)); + StageTypeRegistry stages = QuestsAPI.getAPI().getStages(); + stages.register(new StageType<>("NPC", StageNPC.class, Lang.Talk.name(), + StageNPC::deserialize, item(XMaterial.OAK_SIGN, Lang.stageNPC.toString()), StageNPC.Creator::new)); + stages.register(new StageType<>("ITEMS", StageBringBack.class, Lang.Items.name(), + StageBringBack::deserialize, item(XMaterial.CHEST, Lang.stageBring.toString()), + StageBringBack.Creator::new)); + stages.register(new StageType<>("MOBS", StageMobs.class, Lang.Mobs.name(), + StageMobs::deserialize, item(XMaterial.WOODEN_SWORD, Lang.stageMobs.toString()), + StageMobs.Creator::new)); + stages.register(new StageType<>("MINE", StageMine.class, Lang.Mine.name(), + StageMine::deserialize, item(XMaterial.WOODEN_PICKAXE, Lang.stageMine.toString()), + StageMine.Creator::new)); + stages.register(new StageType<>("PLACE_BLOCKS", StagePlaceBlocks.class, Lang.Place.name(), + StagePlaceBlocks::deserialize, item(XMaterial.OAK_STAIRS, Lang.stagePlace.toString()), + StagePlaceBlocks.Creator::new)); + stages.register(new StageType<>("CHAT", StageChat.class, Lang.Chat.name(), + StageChat::deserialize, item(XMaterial.PLAYER_HEAD, Lang.stageChat.toString()), + StageChat.Creator::new)); + stages.register(new StageType<>("INTERACT_BLOCK", StageInteractBlock.class, Lang.InteractBlock.name(), + StageInteractBlock::deserialize, item(XMaterial.STICK, Lang.stageInteractBlock.toString()), + StageInteractBlock.Creator::new)); + stages.register(new StageType<>("INTERACT_LOCATION", StageInteractLocation.class, Lang.InteractLocation.name(), + StageInteractLocation::deserialize, item(XMaterial.BEACON, Lang.stageInteractLocation.toString()), + StageInteractLocation.Creator::new)); + stages.register(new StageType<>("FISH", StageFish.class, Lang.Fish.name(), + StageFish::deserialize, item(XMaterial.COD, Lang.stageFish.toString()), StageFish.Creator::new)); + stages.register(new StageType<>("MELT", StageMelt.class, Lang.Melt.name(), + StageMelt::deserialize, item(XMaterial.FURNACE, Lang.stageMelt.toString()), + StageMelt.Creator::new)); + stages.register(new StageType<>("ENCHANT", StageEnchant.class, Lang.Enchant.name(), + StageEnchant::deserialize, item(XMaterial.ENCHANTING_TABLE, Lang.stageEnchant.toString()), + StageEnchant.Creator::new)); + stages.register(new StageType<>("CRAFT", StageCraft.class, Lang.Craft.name(), + StageCraft::deserialize, item(XMaterial.CRAFTING_TABLE, Lang.stageCraft.toString()), + StageCraft.Creator::new)); + stages.register(new StageType<>("BUCKET", StageBucket.class, Lang.Bucket.name(), + StageBucket::deserialize, item(XMaterial.BUCKET, Lang.stageBucket.toString()), + StageBucket.Creator::new)); + stages.register(new StageType<>("LOCATION", StageLocation.class, Lang.StageLocation.name(), + StageLocation::deserialize, item(XMaterial.MINECART, Lang.stageLocation.toString()), + StageLocation.Creator::new)); + stages.register(new StageType<>("PLAY_TIME", StagePlayTime.class, Lang.PlayTime.name(), + StagePlayTime::deserialize, item(XMaterial.CLOCK, Lang.stagePlayTime.toString()), + StagePlayTime.Creator::new)); + stages.register(new StageType<>("BREED", StageBreed.class, Lang.Breed.name(), + StageBreed::deserialize, item(XMaterial.WHEAT, Lang.stageBreedAnimals.toString()), + StageBreed.Creator::new)); + stages.register(new StageType<>("TAME", StageTame.class, Lang.Tame.name(), + StageTame::deserialize, item(XMaterial.CARROT, Lang.stageTameAnimals.toString()), + StageTame.Creator::new)); + stages.register(new StageType<>("DEATH", StageDeath.class, Lang.Death.name(), + StageDeath::deserialize, item(XMaterial.SKELETON_SKULL, Lang.stageDeath.toString()), + StageDeath.Creator::new)); + stages.register(new StageType<>("DEAL_DAMAGE", StageDealDamage.class, Lang.DealDamage.name(), + StageDealDamage::deserialize, item(XMaterial.REDSTONE, Lang.stageDealDamage.toString()), + StageDealDamage.Creator::new)); + stages.register(new StageType<>("EAT_DRINK", StageEatDrink.class, Lang.EatDrink.name(), + StageEatDrink::new, item(XMaterial.COOKED_PORKCHOP, Lang.stageEatDrink.toString()), + StageEatDrink.Creator::new)); } public static void registerStageOptions() { @@ -254,59 +258,59 @@ public static void registerQuestOptions() { public static void registerRewards() { QuestsAPI.getAPI().getRewards().register(new RewardCreator("commandReward", CommandReward.class, - ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.command.toString()), CommandReward::new)); + item(XMaterial.COMMAND_BLOCK, Lang.command.toString()), CommandReward::new)); QuestsAPI.getAPI().getRewards().register(new RewardCreator("itemReward", ItemReward.class, - ItemUtils.item(XMaterial.STONE_SWORD, Lang.rewardItems.toString()), ItemReward::new)); + item(XMaterial.STONE_SWORD, Lang.rewardItems.toString()), ItemReward::new)); QuestsAPI.getAPI().getRewards().register(new RewardCreator("removeItemsReward", RemoveItemsReward.class, - ItemUtils.item(XMaterial.CHEST, Lang.rewardRemoveItems.toString()), RemoveItemsReward::new)); + item(XMaterial.CHEST, Lang.rewardRemoveItems.toString()), RemoveItemsReward::new)); QuestsAPI.getAPI().getRewards().register(new RewardCreator("textReward", MessageReward.class, - ItemUtils.item(XMaterial.WRITABLE_BOOK, Lang.endMessage.toString()), MessageReward::new)); + item(XMaterial.WRITABLE_BOOK, Lang.endMessage.toString()), MessageReward::new)); QuestsAPI.getAPI().getRewards().register(new RewardCreator("tpReward", TeleportationReward.class, - ItemUtils.item(XMaterial.ENDER_PEARL, Lang.location.toString()), TeleportationReward::new, false)); + item(XMaterial.ENDER_PEARL, Lang.location.toString()), TeleportationReward::new, false)); QuestsAPI.getAPI().getRewards().register(new RewardCreator("expReward", XPReward.class, - ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.rewardXP.toString()), XPReward::new)); + item(XMaterial.EXPERIENCE_BOTTLE, Lang.rewardXP.toString()), XPReward::new)); QuestsAPI.getAPI().getRewards() .register(new RewardCreator("checkpointReward", CheckpointReward.class, - ItemUtils.item(XMaterial.NETHER_STAR, Lang.rewardCheckpoint.toString()), CheckpointReward::new, + item(XMaterial.NETHER_STAR, Lang.rewardCheckpoint.toString()), CheckpointReward::new, false, QuestObjectLocation.STAGE)); QuestsAPI.getAPI().getRewards() .register(new RewardCreator("questStopReward", QuestStopReward.class, - ItemUtils.item(XMaterial.BARRIER, Lang.rewardStopQuest.toString()), QuestStopReward::new, false, + item(XMaterial.BARRIER, Lang.rewardStopQuest.toString()), QuestStopReward::new, false, QuestObjectLocation.STAGE)); QuestsAPI.getAPI().getRewards() .register(new RewardCreator("requirementDependentReward", RequirementDependentReward.class, - ItemUtils.item(XMaterial.REDSTONE, Lang.rewardWithRequirements.toString()), + item(XMaterial.REDSTONE, Lang.rewardWithRequirements.toString()), RequirementDependentReward::new, true).setCanBeAsync(true)); QuestsAPI.getAPI().getRewards() .register(new RewardCreator("randomReward", RandomReward.class, - ItemUtils.item(XMaterial.EMERALD, Lang.rewardRandom.toString()), RandomReward::new, true) + item(XMaterial.EMERALD, Lang.rewardRandom.toString()), RandomReward::new, true) .setCanBeAsync(true)); QuestsAPI.getAPI().getRewards() .register(new RewardCreator("wait", WaitReward.class, - ItemUtils.item(XMaterial.CLOCK, Lang.rewardWait.toString()), WaitReward::new, true) + item(XMaterial.CLOCK, Lang.rewardWait.toString()), WaitReward::new, true) .setCanBeAsync(true)); if (MinecraftVersion.MAJOR >= 9) QuestsAPI.getAPI().getRewards().register(new RewardCreator("titleReward", TitleReward.class, - ItemUtils.item(XMaterial.NAME_TAG, Lang.rewardTitle.toString()), TitleReward::new, false)); + item(XMaterial.NAME_TAG, Lang.rewardTitle.toString()), TitleReward::new, false)); } public static void registerRequirements() { QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("logicalOr", LogicalOrRequirement.class, - ItemUtils.item(XMaterial.REDSTONE_TORCH, Lang.RLOR.toString()), LogicalOrRequirement::new)); + item(XMaterial.REDSTONE_TORCH, Lang.RLOR.toString()), LogicalOrRequirement::new)); QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("questRequired", QuestRequirement.class, - ItemUtils.item(XMaterial.ARMOR_STAND, Lang.RQuest.toString()), QuestRequirement::new)); + item(XMaterial.ARMOR_STAND, Lang.RQuest.toString()), QuestRequirement::new)); QuestsAPI.getAPI().getRequirements().register(new RequirementCreator("levelRequired", LevelRequirement.class, - ItemUtils.item(XMaterial.EXPERIENCE_BOTTLE, Lang.RLevel.toString()), LevelRequirement::new)); + item(XMaterial.EXPERIENCE_BOTTLE, Lang.RLevel.toString()), LevelRequirement::new)); QuestsAPI.getAPI().getRequirements() .register(new RequirementCreator("permissionRequired", PermissionsRequirement.class, - ItemUtils.item(XMaterial.PAPER, Lang.RPermissions.toString()), PermissionsRequirement::new)); + item(XMaterial.PAPER, Lang.RPermissions.toString()), PermissionsRequirement::new)); QuestsAPI.getAPI().getRequirements() .register(new RequirementCreator("scoreboardRequired", ScoreboardRequirement.class, - ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.RScoreboard.toString()), ScoreboardRequirement::new)); + item(XMaterial.COMMAND_BLOCK, Lang.RScoreboard.toString()), ScoreboardRequirement::new)); if (MinecraftVersion.MAJOR >= 9) QuestsAPI.getAPI().getRequirements() .register(new RequirementCreator("equipmentRequired", EquipmentRequirement.class, - ItemUtils.item(XMaterial.CHAINMAIL_HELMET, Lang.REquipment.toString()), + item(XMaterial.CHAINMAIL_HELMET, Lang.REquipment.toString()), EquipmentRequirement::new)); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java deleted file mode 100644 index aae50384..00000000 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteract.java +++ /dev/null @@ -1,248 +0,0 @@ -package fr.skytasul.quests.stages; - -import java.util.Collections; -import java.util.Spliterator; -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.block.Action; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.blocks.BQBlock; -import fr.skytasul.quests.api.editors.WaitBlockClick; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.gui.layout.LayoutedButton; -import fr.skytasul.quests.api.gui.layout.LayoutedGUI; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.players.PlayerAccount; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.creation.StageCreation; -import fr.skytasul.quests.api.stages.creation.StageCreationContext; -import fr.skytasul.quests.api.stages.creation.StageGuiLine; -import fr.skytasul.quests.api.stages.types.Locatable; -import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; -import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; -import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.gui.blocks.SelectBlockGUI; -import fr.skytasul.quests.utils.types.BQLocation; - -@LocatableType (types = { LocatedType.BLOCK, LocatedType.OTHER }) -public class StageInteract extends AbstractStage implements Locatable.MultipleLocatable, Locatable.PreciseLocatable { - - private final boolean left; - private final BQLocation lc; - private final BQBlock block; - - private Located.LocatedBlock locatedBlock; - - public StageInteract(StageController controller, boolean leftClick, BQLocation location) { - super(controller); - this.left = leftClick; - this.lc = new BQLocation(location.getWorldName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); - - this.block = null; - } - - public StageInteract(StageController controller, boolean leftClick, BQBlock block) { - super(controller); - this.left = leftClick; - this.block = block; - - this.lc = null; - } - - public BQLocation getLocation() { - return lc; - } - - public BQBlock getBlockType() { - return block; - } - - public boolean needLeftClick(){ - return left; - } - - @Override - public Located getLocated() { - if (lc == null) - return null; - if (locatedBlock == null) { - Block realBlock = lc.getMatchingBlock(); - if (realBlock != null) - locatedBlock = Located.LocatedBlock.create(realBlock); - } - return locatedBlock; - } - - @Override - public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { - if (block == null) return null; - - return QuestsAPI.getAPI().getBlocksManager().getNearbyBlocks(fetcher, Collections.singleton(block)); - } - - @EventHandler - public void onInteract(PlayerInteractEvent e){ - if (e.getClickedBlock() == null) return; - if (MinecraftVersion.MAJOR >= 9 && e.getHand() != EquipmentSlot.HAND) return; - - if (left){ - if (e.getAction() != Action.LEFT_CLICK_BLOCK) return; - }else if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; - - if (lc != null) { - if (!lc.equals(e.getClickedBlock().getLocation())) return; - }else if (block != null) { - if (!block.applies(e.getClickedBlock())) return; - }else { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("No block nor location set for " + toString()); - return; - } - - Player p = e.getPlayer(); - if (hasStarted(p) && canUpdate(p)) { - if (left) e.setCancelled(true); - finishStage(p); - } - } - - @Override - public String descriptionLine(PlayerAccount acc, DescriptionSource source) { - return lc == null ? Lang.SCOREBOARD_INTERACT_MATERIAL.format(block.getName()) : Lang.SCOREBOARD_INTERACT.format(lc.getBlockX() + " " + lc.getBlockY() + " " + lc.getBlockZ()); - } - - @Override - protected void serialize(ConfigurationSection section) { - section.set("leftClick", left); - if (lc == null) { - section.set("block", block.getAsString()); - }else section.set("location", lc.serialize()); - } - - public static StageInteract deserialize(ConfigurationSection section, StageController controller) { - if (section.contains("location")) { - return new StageInteract(controller, section.getBoolean("leftClick"), BQLocation.deserialize(section.getConfigurationSection("location").getValues(false))); - }else { - BQBlock block; - if (section.contains("material")) { - block = QuestsAPI.getAPI().getBlocksManager().createSimple(XMaterial.valueOf(section.getString("material")), - null); - }else { - block = QuestsAPI.getAPI().getBlocksManager().deserialize(section.getString("block")); - } - return new StageInteract(controller, section.getBoolean("leftClick"), block); - } - } - - public static class Creator extends StageCreation<StageInteract> { - - private boolean leftClick = false; - private Location location; - private BQBlock block; - - public Creator(@NotNull StageCreationContext<StageInteract> context) { - super(context); - } - - @Override - public void setupLine(@NotNull StageGuiLine line) { - super.setupLine(line); - - line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); - } - - public void setLeftClick(boolean leftClick) { - if (this.leftClick != leftClick) { - this.leftClick = leftClick; - getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, leftClick)); - } - } - - public void setLocation(Location location) { - if (this.location == null) { - getLine().setItem(7, ItemUtils.item(XMaterial.COMPASS, Lang.blockLocation.toString()), event -> { - Lang.CLICK_BLOCK.send(event.getPlayer()); - new WaitBlockClick(event.getPlayer(), event::reopen, obj -> { - setLocation(obj); - event.reopen(); - }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); - }); - } - getLine().refreshItem(7, - item -> ItemUtils.loreOptionValue(item, Lang.Location.format(getBQLocation()))); - this.location = location; - } - - public void setMaterial(BQBlock block) { - if (this.block == null) { - getLine().setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), event -> { - new SelectBlockGUI(false, (newBlock, __) -> { - setMaterial(newBlock); - event.reopen(); - }).open(event.getPlayer()); - }); - } - getLine().refreshItem(7, item -> ItemUtils.loreOptionValue(item, block.getName())); - this.block = block; - } - - @Override - public void start(Player p) { - super.start(p); - LayoutedGUI.newBuilder() - .setInventoryType(InventoryType.HOPPER) - .addButton(0, LayoutedButton.create(ItemUtils.item(XMaterial.COMPASS, Lang.clickLocation.toString()), - event -> { - Lang.CLICK_BLOCK.send(p); - new WaitBlockClick(p, context::removeAndReopenGui, obj -> { - setLocation(obj); - context.reopenGui(); - }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); - })) - .addButton(1, - LayoutedButton.create(ItemUtils.item(XMaterial.STICK, Lang.clickMaterial.toString()), event -> { - new SelectBlockGUI(false, (newBlock, __) -> { - setMaterial(newBlock); - context.reopenGui(); - }).open(p); - })) - .addButton(4, LayoutedButton.create(ItemUtils.itemCancel, __ -> context.removeAndReopenGui())) - .setCloseBehavior(StandardCloseBehavior.REOPEN) - .setName(Lang.INVENTORY_BLOCK_ACTION.toString()) - .build().open(p); - } - - private @NotNull BQLocation getBQLocation() { - return new BQLocation(location); - } - - @Override - public void edit(StageInteract stage) { - super.edit(stage); - if (stage.lc != null) { - setLocation(stage.getLocation()); - }else setMaterial(stage.getBlockType()); - setLeftClick(stage.needLeftClick()); - } - - @Override - public StageInteract finishStage(StageController controller) { - if (location != null) { - return new StageInteract(controller, leftClick, getBQLocation()); - }else return new StageInteract(controller, leftClick, block); - } - - } - -} diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java new file mode 100755 index 00000000..527c6d2d --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java @@ -0,0 +1,163 @@ +package fr.skytasul.quests.stages; + +import java.util.Collections; +import java.util.Spliterator; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.blocks.BQBlock; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.stages.types.Locatable; +import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; +import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.gui.blocks.SelectBlockGUI; + +@LocatableType(types = LocatedType.BLOCK) +public class StageInteractBlock extends AbstractStage implements Locatable.MultipleLocatable { + + private final boolean left; + private final @NotNull BQBlock block; + + public StageInteractBlock(StageController controller, boolean leftClick, BQBlock block) { + super(controller); + this.left = leftClick; + this.block = block; + } + + public BQBlock getBlockType() { + return block; + } + + public boolean needLeftClick(){ + return left; + } + + @Override + public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { + if (block == null) return null; + + return QuestsAPI.getAPI().getBlocksManager().getNearbyBlocks(fetcher, Collections.singleton(block)); + } + + @EventHandler + public void onInteract(PlayerInteractEvent e){ + if (e.getClickedBlock() == null) return; + if (MinecraftVersion.MAJOR >= 9 && e.getHand() != EquipmentSlot.HAND) return; + + if (left){ + if (e.getAction() != Action.LEFT_CLICK_BLOCK) return; + }else if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; + + if (!block.applies(e.getClickedBlock())) + return; + + Player p = e.getPlayer(); + if (hasStarted(p) && canUpdate(p)) { + if (left) e.setCancelled(true); + finishStage(p); + } + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.compose(block); + } + + @Override + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_INTERACT_MATERIAL.toString(); + } + + @Override + protected void serialize(ConfigurationSection section) { + section.set("leftClick", left); + section.set("block", block.getAsString()); + } + + public static StageInteractBlock deserialize(ConfigurationSection section, StageController controller) { + BQBlock block; + if (section.contains("material")) { + block = QuestsAPI.getAPI().getBlocksManager().createSimple(XMaterial.valueOf(section.getString("material")), + null); + }else { + block = QuestsAPI.getAPI().getBlocksManager().deserialize(section.getString("block")); + } + return new StageInteractBlock(controller, section.getBoolean("leftClick"), block); + } + + public static class Creator extends StageCreation<StageInteractBlock> { + + private boolean leftClick = false; + private BQBlock block; + + public Creator(@NotNull StageCreationContext<StageInteractBlock> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); + + line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); + } + + public void setLeftClick(boolean leftClick) { + if (this.leftClick != leftClick) { + this.leftClick = leftClick; + getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, leftClick)); + } + } + + public void setMaterial(BQBlock block) { + if (this.block == null) { + getLine().setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), event -> { + new SelectBlockGUI(false, (newBlock, __) -> { + setMaterial(newBlock); + event.reopen(); + }).open(event.getPlayer()); + }); + } + getLine().refreshItem(7, item -> ItemUtils.loreOptionValue(item, block.getName())); + this.block = block; + } + + @Override + public void start(Player p) { + super.start(p); + new SelectBlockGUI(false, (newBlock, __) -> { + setMaterial(newBlock); + context.reopenGui(); + }).open(p); + } + + @Override + public void edit(StageInteractBlock stage) { + super.edit(stage); + setMaterial(stage.getBlockType()); + setLeftClick(stage.needLeftClick()); + } + + @Override + public StageInteractBlock finishStage(StageController controller) { + return new StageInteractBlock(controller, leftClick, block); + } + + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java new file mode 100644 index 00000000..92fb5702 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java @@ -0,0 +1,172 @@ +package fr.skytasul.quests.stages; + +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.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.jetbrains.annotations.NotNull; +import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.editors.WaitBlockClick; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.stages.AbstractStage; +import fr.skytasul.quests.api.stages.StageController; +import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; +import fr.skytasul.quests.api.stages.creation.StageCreation; +import fr.skytasul.quests.api.stages.creation.StageCreationContext; +import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.stages.types.Locatable; +import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; +import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.utils.types.BQLocation; + +@LocatableType (types = { LocatedType.BLOCK, LocatedType.OTHER }) +public class StageInteractLocation extends AbstractStage implements Locatable.PreciseLocatable { + + private final boolean left; + private final BQLocation lc; + + private Located.LocatedBlock locatedBlock; + + public StageInteractLocation(StageController controller, boolean leftClick, BQLocation location) { + super(controller); + this.left = leftClick; + this.lc = new BQLocation(location.getWorldName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + + public BQLocation getLocation() { + return lc; + } + + public boolean needLeftClick(){ + return left; + } + + @Override + public Located getLocated() { + if (lc == null) + return null; + if (locatedBlock == null) { + Block realBlock = lc.getMatchingBlock(); + if (realBlock != null) + locatedBlock = Located.LocatedBlock.create(realBlock); + } + return locatedBlock; + } + + @EventHandler + public void onInteract(PlayerInteractEvent e){ + if (e.getClickedBlock() == null) return; + if (MinecraftVersion.MAJOR >= 9 && e.getHand() != EquipmentSlot.HAND) return; + + if (left){ + if (e.getAction() != Action.LEFT_CLICK_BLOCK) return; + }else if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; + + if (!lc.equals(e.getClickedBlock().getLocation())) + return; + + Player p = e.getPlayer(); + if (hasStarted(p) && canUpdate(p)) { + if (left) e.setCancelled(true); + finishStage(p); + } + } + + @Override + protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { + super.createdPlaceholdersRegistry(placeholders); + placeholders.compose(lc); + // TODO remove following, for migration only + placeholders.registerIndexed("location", lc.getBlockX() + " " + lc.getBlockY() + " " + lc.getBlockZ()); + } + + @Override + public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { + return Lang.SCOREBOARD_INTERACT_LOCATION.toString(); + } + + @Override + protected void serialize(ConfigurationSection section) { + section.set("leftClick", left); + section.set("location", lc.serialize()); + } + + public static StageInteractLocation deserialize(ConfigurationSection section, StageController controller) { + return new StageInteractLocation(controller, section.getBoolean("leftClick"), + BQLocation.deserialize(section.getConfigurationSection("location").getValues(false))); + } + + public static class Creator extends StageCreation<StageInteractLocation> { + + private boolean leftClick = false; + private Location location; + + public Creator(@NotNull StageCreationContext<StageInteractLocation> context) { + super(context); + } + + @Override + public void setupLine(@NotNull StageGuiLine line) { + super.setupLine(line); + + line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); + } + + public void setLeftClick(boolean leftClick) { + if (this.leftClick != leftClick) { + this.leftClick = leftClick; + getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, leftClick)); + } + } + + public void setLocation(Location location) { + if (this.location == null) { + getLine().setItem(7, ItemUtils.item(XMaterial.COMPASS, Lang.blockLocation.toString()), event -> { + Lang.CLICK_BLOCK.send(event.getPlayer()); + new WaitBlockClick(event.getPlayer(), event::reopen, obj -> { + setLocation(obj); + event.reopen(); + }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); + }); + } + getLine().refreshItem(7, + item -> ItemUtils.loreOptionValue(item, Lang.Location.format(getBQLocation()))); + this.location = location; + } + + @Override + public void start(Player p) { + super.start(p); + Lang.CLICK_BLOCK.send(p); + new WaitBlockClick(p, context::removeAndReopenGui, obj -> { + setLocation(obj); + context.reopenGui(); + }, 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); + setLocation(stage.getLocation()); + setLeftClick(stage.needLeftClick()); + } + + @Override + public StageInteractLocation finishStage(StageController controller) { + return new StageInteractLocation(controller, leftClick, getBQLocation()); + } + + } + +} 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 fc63f5da..daeb18e2 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -8,7 +8,6 @@ import org.bukkit.event.player.PlayerMoveEvent; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; import fr.skytasul.quests.api.editors.parsers.NumberParser; @@ -100,12 +99,10 @@ public static class Creator extends StageCreation<StageLocation> { private static final int SLOT_RADIUS = 6; private static final int SLOT_LOCATION = 7; private static final int SLOT_WORLD_PATTERN = 8; - private static final int SLOT_GPS = 9; private Location location; private Pattern pattern; private int radius; - private boolean gps = true; public Creator(@NotNull StageCreationContext<StageLocation> context) { super(context); @@ -136,9 +133,6 @@ public void setupLine(@NotNull StageGuiLine line) { event.reopen(); }, PatternParser.PARSER).passNullIntoEndConsumer().start(); }); - - if (QuestsConfigurationImplementation.getConfiguration().handleGPS()) - line.setItem(SLOT_GPS, ItemUtils.itemSwitch(Lang.stageGPS.toString(), gps), event -> setGPS(!gps)); } public void setLocation(Location location) { @@ -161,14 +155,6 @@ public void setPattern(Pattern pattern) { pattern == null ? Lang.NotSet.toString() : QuestOption.formatNullableValue(pattern.pattern()))); } - public void setGPS(boolean gps) { - if (this.gps != gps) { - this.gps = gps; - if (QuestsConfigurationImplementation.getConfiguration().handleGPS()) - getLine().refreshItem(SLOT_GPS, item -> ItemUtils.setSwitch(item, gps)); - } - } - private BQLocation getBQLocation() { BQLocation loc = new BQLocation(location); if (pattern != null) loc.setWorldPattern(pattern); diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index 46070727..c1c802fd 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -3,6 +3,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.function.Consumer; import org.apache.commons.lang.Validate; import org.bukkit.configuration.ConfigurationSection; @@ -26,6 +27,7 @@ import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.utils.QuestUtils; +import fr.skytasul.quests.utils.compatibility.BQBackwardCompat; public class StageControllerImplementation<T extends AbstractStage> implements StageController, Listener { @@ -196,10 +198,12 @@ public String toString() { @NotNull ConfigurationSection section) { String typeID = section.getString("stageType"); - StageType<?> stageType = QuestsAPI.getAPI().getStages().getType(typeID) - .orElseThrow(() -> new IllegalArgumentException("Unknown stage type " + typeID)); + Optional<StageType<?>> stageType = QuestsAPI.getAPI().getStages().getType(typeID); - return loadFromConfig(branch, section, stageType); + if (!stageType.isPresent()) + stageType = BQBackwardCompat.loadStageFromConfig(typeID, section); + + return loadFromConfig(branch, section, stageType.orElseThrow(() -> new IllegalArgumentException("Unknown stage type " + typeID))); } private static <T extends AbstractStage> @NotNull StageControllerImplementation<T> loadFromConfig( diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQBackwardCompat.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQBackwardCompat.java new file mode 100755 index 00000000..a5295d77 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/BQBackwardCompat.java @@ -0,0 +1,23 @@ +package fr.skytasul.quests.utils.compatibility; + +import java.util.Optional; +import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.stages.StageType; + +public class BQBackwardCompat { + + public static @NotNull Optional<StageType<?>> loadStageFromConfig(@Nullable String stageType, + @NotNull ConfigurationSection config) { + + if ("INTERACT".equals(stageType)) { + stageType = config.contains("location") ? "INTERACT_LOCATION" : "INTERACT_BLOCK"; + return QuestsAPI.getAPI().getStages().getType(stageType); + } + + return Optional.empty(); + } + +} diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 8760bcf3..04629431 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -370,6 +370,7 @@ inv: placeBlocks: §aPlace blocks talkChat: §aWrite in chat interact: §aInteract with block + interactBlock: §aInteract with block at location fish: §aCatch fishes melt: §6Melt items enchant: §dEnchant items @@ -759,8 +760,8 @@ scoreboard: mine: §eMine {blocks} placeBlocks: §ePlace {blocks} chat: §eWrite §6{text} - interact: §eClick on the block at §6{0} - interactMaterial: §eClick on a §6{0}§e block + interact: §eClick on the block at §6{x} {y} {z} + interactMaterial: §eClick on a §6{block}§e block fish: §eFish §6{items} melt: §eMelt §6{items} enchant: §eEnchant §6{items} @@ -818,6 +819,7 @@ misc: placeBlocks: Place blocks chat: Write in chat interact: Interact with block + interactLocation: Interact with block at location Fish: Catch fishes Melt: Melt items Enchant: Enchant items From 79d7d7a5068aa4fcdd6fa290ce978f43de307ce3 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 22 Aug 2023 19:29:13 +0200 Subject: [PATCH 35/95] :globe_with_meridians: Updated strings and deleted some useless ones --- api/pom.xml | 4 +- .../quests/api/localization/Lang.java | 18 --------- .../pools/QuestPoolImplementation.java | 3 +- core/src/main/resources/locales/en_US.yml | 40 ++++--------------- 4 files changed, 12 insertions(+), 53 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index dde2b738..9a604c23 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -21,11 +21,11 @@ <relocations> <relocation> <pattern>revxrsal.commands</pattern> - <shadedPattern>fr.skytasul.quests.commands.revxrsal</shadedPattern> + <shadedPattern>fr.skytasul.quests.api.commands.revxrsal</shadedPattern> </relocation> <relocation> <pattern>com.cryptomorin.xseries</pattern> - <shadedPattern>fr.skytasul.quests.utils</shadedPattern> + <shadedPattern>fr.skytasul.quests.api.utils</shadedPattern> </relocation> </relocations> <filters> 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 fd5d2185..ddeac918 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 @@ -36,7 +36,6 @@ public enum Lang implements Locale { QUEST_NOT_STARTED("msg.quest.notStarted"), QUESTS_MAX_LAUNCHED("msg.quests.maxLaunched"), // 0: max quests - QUEST_NOSTEPS("msg.quests.nopStep"), QUEST_UPDATED("msg.quests.updated"), QUEST_CHECKPOINT("msg.quests.checkpoint"), QUEST_FAILED("msg.quests.failed"), @@ -53,7 +52,6 @@ public enum Lang implements Locale { QUEST_ITEM_CRAFT("msg.questItem.craft"), QUEST_ITEM_EAT("msg.questItem.eat"), - STAGE_NOMOBS("msg.stageMobs.noMobs"), STAGE_MOBSLIST("msg.stageMobs.listMobs"), TYPE_CANCEL("msg.typeCancel"), @@ -92,9 +90,6 @@ public enum Lang implements Locale { XP_EDITED("msg.experience.edited"), SELECT_KILL_NPC("msg.selectNPCToKill"), - NPC_REMOVE("msg.npc.remove"), - TALK_NPC("msg.npc.talk"), - REGION_DOESNT_EXIST("msg.regionDoesntExists"), NPC_DOESNT_EXIST("msg.npcDoesntExist"), NUMBER_NEGATIVE("msg.number.negative"), @@ -102,7 +97,6 @@ public enum Lang implements Locale { NUMBER_INVALID("msg.number.invalid"), NUMBER_NOT_IN_BOUNDS("msg.number.notInBounds"), // 0: min, 1: max ERROR_OCCURED("msg.errorOccurred"), - CANT_COMMAND("msg.commandsDisabled"), OUT_OF_BOUNDS("msg.indexOutOfBounds"), INVALID_BLOCK_DATA("msg.invalidBlockData"), // 0: blockdata, 1: material INVALID_BLOCK_TAG("msg.invalidBlockTag"), // 0: tag @@ -110,22 +104,13 @@ public enum Lang implements Locale { NEED_OBJECTS("msg.bringBackObjects"), ITEM_DROPPED("msg.inventoryFull"), - PLAYER_NEVER_CONNECTED("msg.playerNeverConnected"), - PLAYER_NOT_ONLINE("msg.playerNotOnline"), - PLAYER_DATA_NOT_FOUND("msg.playerDataNotFound"), // 0: player name - VERSION_REQUIRED("msg.versionRequired", ErrorPrefix), // 0: version RESTART_SERVER("msg.restartServer"), // * Commands * - MUST_PLAYER("msg.command.playerNeeded"), - INCORRECT_SYNTAX("msg.command.incorrectSyntax"), - PERMISSION_REQUIRED("msg.command.noPermission"), - COMMAND_DOESNT_EXIST("msg.command.invalidCommand.quests"), COMMAND_DOESNT_EXIST_NOSLASH("msg.command.invalidCommand.simple"), - MUST_HOLD_ITEM("msg.command.needItem"), ITEM_CHANGED("msg.command.itemChanged"), ITEM_REMOVED("msg.command.itemRemoved"), SUCCESFULLY_REMOVED("msg.command.removed"), @@ -374,7 +359,6 @@ public enum Lang implements Locale { stageText("inv.create.NPCText"), stageNPCSelect("inv.create.NPCSelect"), stageHide("inv.create.hideClues"), - stageGPS("inv.create.gps"), editMobs("inv.create.editMobsKill"), mobsKillType("inv.create.mobsKillFromAFar"), editBlocksMine("inv.create.editBlocksMine"), @@ -846,8 +830,6 @@ public enum Lang implements Locale { Disabled("misc.disabled"), Unknown("misc.unknown"), NotSet("misc.notSet"), - Unused("misc.unused"), - Used("misc.used"), RemoveMid("misc.remove"), Remove("misc.removeRaw"), Reset("misc.reset"), 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 ddd078e4..a4cd56fa 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 @@ -151,7 +151,8 @@ public int compareTo(QuestPoolImplementation o) { .register("pool_time", Utils.millisToHumanString(timeDiff)) .register("pool_hologram", QuestOption.formatNullableValue(hologram, Lang.PoolHologramText)) .register("pool_quests", - () -> quests.stream().map(x -> "#" + x.getId()).collect(Collectors.joining(", "))); + () -> quests.stream().map(x -> "#" + x.getId()).collect(Collectors.joining(", "))) + .register("pool_quests_amount", () -> Integer.toString(quests.size())); } return placeholders; } diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 04629431..7c816049 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -3,7 +3,7 @@ msg: finished: base: §aCongratulations! You have finished the quest §e{quest_name}§a! obtain: §aYou obtain {rewards}! - started: §aYou have started the quest §r§e{0}§o§6! + started: §aYou have started the quest §r§e{quest_name}§o§6! created: §aCongratulations! You have created the quest §e{quest}§a which includes {quest_branches} branch(es)! edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes @@ -17,7 +17,6 @@ msg: notStarted: §cYou are not currently doing this quest. quests: maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same time... - nopStep: §cThis quest doesn't have any step. updated: §7Quest §e{quest_name}§7 updated. checkpoint: §7Quest checkpoint reached! failed: §cYou have failed the quest {quest_name}... @@ -31,8 +30,7 @@ msg: craft: §cYou can't use a quest item to craft! eat: §cYou cannot eat a quest item! stageMobs: - noMobs: §cThis stage doesn't need any mobs to kill. - listMobs: §aYou must kill {0}. + listMobs: §aYou must kill {mobs}. writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write "help" to receive help.)' writeRegionName: '§aWrite the name of the region required for the step:' @@ -79,9 +77,6 @@ msg: experience: edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} points. selectNPCToKill: §aSelect the NPC to kill. - npc: - remove: §aNPC deleted. - talk: §aGo and talk to the NPC named §e{0}§a. regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. number: @@ -90,16 +85,12 @@ msg: invalid: §c{input} isn't a valid number. notInBounds: §cYour number must be between {min} and {max}. errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: {error}' - commandsDisabled: §cCurrently you aren't allowed to execute commands! indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} and {max}. invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the block {block_material}. invalidBlockTag: §cUnavailable block tag {block_tag}. - bringBackObjects: Bring me back {0}. + bringBackObjects: Bring me back {items}. inventoryFull: §cYour inventory is full, the item has been dropped on the floor. - playerNeverConnected: §cUnable to find informations about the player {0}. - playerNotOnline: §cThe player {0} is offline. - playerDataNotFound: §cDatas of player {0} not found. versionRequired: 'Version required: §l{version}' restartServer: '§7Restart your server to see the modifications.' dialogs: @@ -127,14 +118,8 @@ msg: noDialog: §cThe player has no pending dialog. alreadyIn: §cThe player is already playing a dialog. success: §aStarted dialog for player {player} in quest {quest}! - playerNeeded: §cYou must be a player to execute this command! - incorrectSyntax: §cIncorrect syntax. - noPermission: '§cYou haven''t enough permissions to execute this command! (Required: - {0})' invalidCommand: - quests: §cThis command doesn't exist, write §e/quests help§c. simple: §cThis command doesn't exist, write §ehelp§c. - needItem: §cYou must hold an item in your main hand! itemChanged: §aThe item has been edited. The changes will affect after a restart. itemRemoved: §aThe hologram item has been removed. removed: §aThe quest {quest_name} has successfully been removed. @@ -149,8 +134,8 @@ msg: startQuest: '§6You have forced starting of quest {quest} for {player}.' startQuestNoRequirements: '§cThe player does not meet the requirements for the quest {quest}... Append "-overrideRequirements" at the end of your command to bypass the requirements check.' - cancelQuest: §6You have cancelled the quest {0}. - cancelQuestUnavailable: §cThe quest {0} can't be cancelled. + cancelQuest: §6You have cancelled the quest {quest}. + cancelQuestUnavailable: §cThe quest {quest} can't be cancelled. backupCreated: §6You have successfully created backups of all quests and player informations. backupPlayersFailed: §cCreating a backup for all the player informations has failed. @@ -386,7 +371,6 @@ inv: NPCText: §eEdit dialog NPCSelect: §eChoose or create NPC hideClues: Hide particles and holograms - gps: Displays a compass towards the objective editMobsKill: §eEdit mobs to kill mobsKillFromAFar: Needs to be killed with projectile editBlocksMine: §eEdit blocks to break @@ -577,12 +561,6 @@ inv: rewards: name: Rewards commands: 'Commands: {amount}' - teleportation: |- - §aSelected: - X: {0} - Y: {1} - Z: {2} - World: {3} random: rewards: Edit rewards minMax: Edit min and max @@ -681,7 +659,7 @@ inv: poolTime: '§8Time between quests: §7{pool_time}' poolHologram: '§8Hologram text: §7{pool_hologram}' poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' - poolQuestsList: '§7{0} §8quest(s): §7{pool_quests}' + poolQuestsList: '§7{pool_quests_amount} §8quest(s): §7{pool_quests}' create: §aCreate a quest pool edit: §e> §6§oEdit the pool... §e< choose: §e> §6§oChoose this pool §e< @@ -797,8 +775,8 @@ description: misc: format: prefix: §6<§e§lQuests§r§6> §r - npcText: §6[{2}/{3}] §e§l{0}:§r§e {1} - selfText: §6[{2}/{3}] §e§l{0}:§r§e {1} + npcText: §6[{message_id}/{message_count}] §e§l{npc_name_message}:§r§e {text} + selfText: §6[{message_id}/{message_count}] §e§l{player_name}:§r§e {text} offText: §r§e{message} editorPrefix: §a errorPrefix: §4✖ §c @@ -888,8 +866,6 @@ misc: disabled: Disabled unknown: unknown notSet: §cnot set - unused: §2§lUnused - used: §a§lUsed remove: §7Middle-click to remove removeRaw: Remove reset: Reset From af976508f72ef2e5a2b184cadf20957265da8827 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 22 Aug 2023 21:17:58 +0200 Subject: [PATCH 36/95] :children_crossing: Changed remove click from middle click to shift left click --- .../LoreBuilder.java} | 23 +++++++++--------- .../quests/api/gui/templates/ListGUI.java | 10 ++++++-- .../quests/api/localization/Lang.java | 4 +++- .../quests/api/objects/QuestObject.java | 5 ++-- .../quests/api/objects/QuestObjectGUI.java | 2 +- .../api/requirements/AbstractRequirement.java | 4 ++-- .../requirements/TargetNumberRequirement.java | 4 ++-- .../quests/commands/CommandsAdmin.java | 6 ++--- .../skytasul/quests/gui/blocks/BlocksGUI.java | 5 ++-- .../skytasul/quests/gui/mobs/MobsListGUI.java | 24 +++++++------------ .../quests/gui/pools/PoolsManageGUI.java | 8 ++++--- .../requirements/EquipmentRequirement.java | 4 ++-- .../requirements/PermissionsRequirement.java | 6 ++--- .../quests/requirements/QuestRequirement.java | 4 ++-- .../requirements/ScoreboardRequirement.java | 4 ++-- .../logical/LogicalOrRequirement.java | 4 ++-- .../quests/rewards/CheckpointReward.java | 4 ++-- .../quests/rewards/CommandReward.java | 9 ++++--- .../skytasul/quests/rewards/ItemReward.java | 4 ++-- .../quests/rewards/MessageReward.java | 4 ++-- .../skytasul/quests/rewards/RandomReward.java | 4 ++-- .../quests/rewards/RemoveItemsReward.java | 4 ++-- .../rewards/RequirementDependentReward.java | 4 ++-- .../quests/rewards/TeleportationReward.java | 4 ++-- .../skytasul/quests/rewards/TitleReward.java | 4 ++-- .../skytasul/quests/rewards/WaitReward.java | 4 ++-- .../fr/skytasul/quests/rewards/XPReward.java | 4 ++-- .../quests/stages/StageDealDamage.java | 3 ++- core/src/main/resources/locales/en_US.yml | 10 ++++---- .../factions/FactionRequirement.java | 6 ++--- .../jobs/JobLevelRequirement.java | 4 ++-- .../mcmmo/McMMOSkillRequirement.java | 4 ++-- .../placeholders/PlaceholderRequirement.java | 4 ++-- .../skillapi/ClassRequirement.java | 6 ++--- .../skillapi/SkillAPIXpReward.java | 4 ++-- .../vault/economy/MoneyRequirement.java | 4 ++-- .../vault/economy/MoneyReward.java | 4 ++-- .../vault/permission/PermissionListGUI.java | 5 ++-- .../vault/permission/PermissionReward.java | 4 ++-- .../worldguard/RegionRequirement.java | 4 ++-- 40 files changed, 119 insertions(+), 109 deletions(-) rename api/src/main/java/fr/skytasul/quests/api/{objects/QuestObjectLoreBuilder.java => gui/LoreBuilder.java} (76%) diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java b/api/src/main/java/fr/skytasul/quests/api/gui/LoreBuilder.java similarity index 76% rename from api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java rename to api/src/main/java/fr/skytasul/quests/api/gui/LoreBuilder.java index 58f96cc8..9cfdbfac 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectLoreBuilder.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/LoreBuilder.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.objects; +package fr.skytasul.quests.api.gui; import java.util.ArrayList; import java.util.Arrays; @@ -13,7 +13,7 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.Utils; -public class QuestObjectLoreBuilder { +public class LoreBuilder { private static final List<ClickType> ORDERED_CLICKS = Arrays.asList(ClickType.RIGHT, ClickType.LEFT, ClickType.SHIFT_RIGHT, ClickType.SHIFT_LEFT); @@ -27,25 +27,26 @@ public class QuestObjectLoreBuilder { private List<String> description = new ArrayList<>(5); private Map<ClickType, String> clicks = new TreeMap<>(CLICKS_COMPARATOR); - public QuestObjectLoreBuilder() {} - - public void addDescriptionRaw(@Nullable String line) { + public @NotNull LoreBuilder addDescriptionRaw(@Nullable String line) { description.add(line); + return this; } - public void addDescription(@Nullable String line) { + public @NotNull LoreBuilder addDescription(@Nullable String line) { addDescriptionRaw(QuestOption.formatDescription(line)); + return this; } - public void addDescriptionAsValue(@Nullable Object value) { + public @NotNull LoreBuilder addDescriptionAsValue(@Nullable Object value) { addDescription(QuestOption.formatNullableValue(value)); + return this; } - public void addClick(@Nullable ClickType click, @NotNull String action) { - if (click == null) - return; + public @NotNull LoreBuilder addClick(@Nullable ClickType click, @NotNull String action) { + if (click != null) + clicks.put(click, action); - clicks.put(click, action); + return this; } public @NotNull String @Nullable [] toLoreArray() { diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ListGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ListGUI.java index 75d74778..ca948ee0 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/ListGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/ListGUI.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; @@ -53,8 +54,13 @@ public final void click(T existing, ItemStack item, ClickType clickType) { } } - protected ClickType getRemoveClick(T object) { - return ClickType.MIDDLE; + protected ClickType getRemoveClick(@NotNull T object) { + return ClickType.SHIFT_LEFT; + } + + protected @NotNull LoreBuilder createLoreBuilder(@NotNull T object) { + return new LoreBuilder() + .addClick(getRemoveClick(object), "§c" + Lang.Remove.toString()); } public boolean remove(T object) { 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 ddeac918..30497965 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 @@ -519,6 +519,8 @@ public enum Lang implements Locale { INVENTORY_MOBS("inv.mobs.name"), click("inv.mobs.clickLore"), + editAmount("inv.mobs.editAmount"), + editMobName("inv.mobs.editMobName"), setLevel("inv.mobs.setLevel"), INVENTORY_MOBSELECT("inv.mobSelect.name"), @@ -732,6 +734,7 @@ public enum Lang implements Locale { INDICATION_CLOSE("indication.closeInventory"), INDICATION_CANCEL("indication.cancelQuest"), // 0: quest name INDICATION_REMOVE("indication.removeQuest"), // 0: quest name + INDICATION_REMOVE_POOL("indication.removePool"), /* Description */ @@ -830,7 +833,6 @@ public enum Lang implements Locale { Disabled("misc.disabled"), Unknown("misc.unknown"), NotSet("misc.notSet"), - RemoveMid("misc.remove"), Remove("misc.removeRaw"), Reset("misc.reset"), Or("misc.or"), diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index 12f52f32..28d26545 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -9,6 +9,7 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.serializable.SerializableObject; @@ -109,12 +110,12 @@ public void load(@NotNull ConfigurationSection section) { } public @NotNull String @Nullable [] getItemLore() { - QuestObjectLoreBuilder lore = new QuestObjectLoreBuilder(); + LoreBuilder lore = new LoreBuilder(); addLore(lore); return lore.toLoreArray(); } - protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { + protected void addLore(@NotNull LoreBuilder loreBuilder) { loreBuilder.addClick(getRemoveClick(), "§c" + Lang.Remove.toString()); loreBuilder.addClick(getCustomDescriptionClick(), Lang.object_description_set.toString()); diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java index b382b549..468a2dc2 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectGUI.java @@ -40,7 +40,7 @@ public ItemStack getObjectItemStack(QuestObject object) { } @Override - protected ClickType getRemoveClick(T object) { + protected ClickType getRemoveClick(@NotNull T object) { return object.getRemoveClick(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index ba15a1cc..d4bf8a7a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -8,10 +8,10 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObject; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.serializable.SerializableObject; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; @@ -119,7 +119,7 @@ protected final void clickInternal(@NotNull QuestObjectClickEvent event) { protected abstract void itemClick(@NotNull QuestObjectClickEvent event); @Override - protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { + protected void addLore(@NotNull LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(Lang.requirementReason.format( PlaceholderRegistry.of("reason", customReason == null ? Lang.NotSet.toString() : customReason))); diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java index ffab707b..e9132a78 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/TargetNumberRequirement.java @@ -8,9 +8,9 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.ComparisonMethod; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -65,7 +65,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol } @Override - protected void addLore(@NotNull QuestObjectLoreBuilder loreBuilder) { + protected void addLore(@NotNull LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(getFormattedValue())); } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 830ca453..887b1bac 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -111,11 +111,11 @@ private void doRemove(BukkitCommandActor sender, Quest quest) { if (sender.isPlayer()) { QuestsPlugin.getPlugin().getGuiManager().getFactory().createConfirmation(() -> { quest.delete(false, false); - Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getPlaceholdersRegistry()); - }, null, Lang.INDICATION_REMOVE.format(quest.getPlaceholdersRegistry())).open(sender.getAsPlayer()); + Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest); + }, null, Lang.INDICATION_REMOVE.format(quest)).open(sender.getAsPlayer()); }else { quest.delete(false, false); - Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest.getPlaceholdersRegistry()); + Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java index c799a54c..b545b123 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/blocks/BlocksGUI.java @@ -38,8 +38,9 @@ public void createObject(Function<MutableCountableObject<BQBlock>, ItemStack> ca @Override public ItemStack getObjectItemStack(MutableCountableObject<BQBlock> object) { - return item(object.getObject().getMaterial(), Lang.materialName.format(object.getObject()), - Lang.Amount.format(object)); + return item(object.getObject().getMaterial(), Lang.materialName.format(object.getObject()), createLoreBuilder(object) + .addDescription(Lang.Amount.format(object)) + .toLoreArray()); } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java index 4424d922..128b797c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java @@ -1,6 +1,5 @@ package fr.skytasul.quests.gui.mobs; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.UUID; @@ -12,6 +11,7 @@ import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.LeveledMobFactory; @@ -38,7 +38,7 @@ public void finish(List<MutableCountableObject<Mob<?>>> objects) { @Override public void clickObject(MutableCountableObject<Mob<?>> mob, ItemStack item, ClickType click) { super.clickObject(mob, item, click); - if (click == ClickType.SHIFT_LEFT) { + if (click == ClickType.RIGHT) { Lang.MOB_NAME.send(player); new TextEditor<>(player, super::reopen, name -> { mob.getObject().setCustomName((String) name); @@ -62,8 +62,6 @@ public void clickObject(MutableCountableObject<Mob<?>> mob, ItemStack item, Clic } else { QuestUtils.playPluginSound(player.getLocation(), "ENTITY_VILLAGER_NO", 0.6f); } - } else if (click == ClickType.RIGHT) { - remove(mob); } } @@ -79,17 +77,13 @@ public void createObject(Function<MutableCountableObject<Mob<?>>, ItemStack> cal @Override public ItemStack getObjectItemStack(MutableCountableObject<Mob<?>> mob) { - List<String> lore = new ArrayList<>(); - lore.add(Lang.Amount.format(mob)); - lore.addAll(mob.getObject().getDescriptiveLore()); - lore.add(""); - lore.add(Lang.click.toString()); - if (mob.getObject().getFactory() instanceof LeveledMobFactory) { - lore.add("§7" + Lang.ClickShiftRight + " > §e" + Lang.setLevel); - } else { - lore.add("§8§n" + Lang.ClickShiftRight + " > " + Lang.setLevel); - } - ItemStack item = ItemUtils.item(mob.getObject().getMobItem(), mob.getObject().getName(), lore); + LoreBuilder loreBuilder = createLoreBuilder(mob) + .addDescription(Lang.Amount.format(mob)) + .addClick(ClickType.LEFT, Lang.editAmount.toString()) + .addClick(ClickType.RIGHT, Lang.editMobName.toString()) + .addClick(ClickType.SHIFT_RIGHT, (mob.getObject().getFactory() instanceof LeveledMobFactory ? "" : "§8§n") + + Lang.setLevel.toString()); + ItemStack item = ItemUtils.item(mob.getObject().getMobItem(), mob.getObject().getName(), loreBuilder.toLoreArray()); item.setAmount(Math.min(mob.getAmount(), 64)); return item; } diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java index 379607ab..3b02836f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java @@ -31,10 +31,12 @@ public ItemStack getItemStack(QuestPool object) { @Override public void click(QuestPool existing, ItemStack clicked, ClickType click) { - if (click == ClickType.MIDDLE) { + if (click == ClickType.SHIFT_LEFT) { if (existing != null) { - BeautyQuests.getInstance().getPoolsManager().removePool(existing.getId()); - get().open(player); + BeautyQuests.getInstance().getGuiManager().getFactory().createConfirmation(() -> { + BeautyQuests.getInstance().getPoolsManager().removePool(existing.getId()); + get().open(player); + }, this::reopen, Lang.INDICATION_REMOVE_POOL.format(existing)).open(player); } }else { new PoolEditGUI(() -> get().open(player), existing).open(player); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java index c78ab52b..3dd3965c 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java @@ -12,10 +12,10 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.templates.StaticPagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.gui.items.ItemComparisonGUI; @@ -47,7 +47,7 @@ public AbstractRequirement clone() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); if (slot != null) { loreBuilder.addDescription(slot.name() + ": " + ItemUtils.getName(item)); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java index a81e525f..a8ac78ec 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java @@ -12,10 +12,10 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -47,7 +47,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(Lang.AmountPermissions.format(this)); } @@ -63,7 +63,7 @@ public void itemClick(QuestObjectClickEvent event) { @Override public ItemStack getObjectItemStack(Permission object) { - return ItemUtils.item(XMaterial.PAPER, object.toString(), "", Lang.RemoveMid.toString()); + return ItemUtils.item(XMaterial.PAPER, object.toString(), createLoreBuilder(object).toLoreArray()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java index 817625fc..159dfe86 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java @@ -4,9 +4,9 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.Quest; @@ -57,7 +57,7 @@ private boolean exists(){ } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(exists() ? cached.getName() : null)); } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java index 1179ccc1..d700a8a9 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java @@ -6,9 +6,9 @@ import org.bukkit.scoreboard.Objective; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.ScoreboardObjectiveParser; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; @@ -54,7 +54,7 @@ public void sendHelpString(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription("§8Objective name: §7" + objectiveName); } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java index df79c2c0..9d91b16f 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java @@ -3,9 +3,9 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementList; @@ -36,7 +36,7 @@ public void detach() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(requirements.getSizeString()); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java index 7b1ac28a..d935dc72 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CheckpointReward.java @@ -6,10 +6,10 @@ import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; @@ -71,7 +71,7 @@ public AbstractReward clone() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(getActionsSizeString()); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index 0452a93c..281b6c3a 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -11,10 +11,10 @@ import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.misc.CommandGUI; @@ -46,7 +46,7 @@ public AbstractReward clone() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(getCommandsSizeString()); } @@ -75,7 +75,10 @@ public void clickObject(Command object, ItemStack item, ClickType clickType) { @Override public ItemStack getObjectItemStack(Command cmd) { return ItemUtils.item(XMaterial.CHAIN_COMMAND_BLOCK, Lang.commandsListValue.format(cmd), - Lang.commandsListConsole.format(cmd.getPlaceholdersRegistry().shifted("command_console"))); + createLoreBuilder(cmd) + .addDescription(Lang.commandsListConsole + .format(cmd.getPlaceholdersRegistry().shifted("command_console"))) + .toLoreArray()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java index cfc103fa..637ebc10 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java @@ -8,9 +8,9 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -58,7 +58,7 @@ private String getItemsSizeString() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(getItemsSizeString()); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java index 46416020..6ea8aba0 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java @@ -6,9 +6,9 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; @@ -43,7 +43,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(text); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java index c6f0e810..d4cbc645 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RandomReward.java @@ -13,10 +13,10 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; @@ -111,7 +111,7 @@ public String getDefaultDescription(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(Lang.actions.quickFormat("amount", rewards.size())); loreBuilder.addDescriptionRaw("§8 | min: §7" + min + "§8 | max: §7" + max); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java index fc858e5b..e0af17af 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RemoveItemsReward.java @@ -10,9 +10,9 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.comparison.ItemComparisonMap; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -71,7 +71,7 @@ private String getItemsSizeString() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(getItemsSizeString()); loreBuilder.addDescription(getComparisonsSizeString()); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 687d03d6..09e39f7c 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -9,6 +9,7 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.gui.layout.LayoutedButton; import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; @@ -16,7 +17,6 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.objects.QuestObjectLocation; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementList; @@ -84,7 +84,7 @@ public String getDefaultDescription(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(rewards.getSizeString()); loreBuilder.addDescription(requirements.getSizeString()); 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 9200da50..fb02b4d2 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java @@ -5,9 +5,9 @@ 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; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.QuestUtils; @@ -36,7 +36,7 @@ public AbstractReward clone() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(Lang.Location.format(new BQLocation(teleportation))); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java index c6b98353..5a7be231 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TitleReward.java @@ -3,8 +3,8 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.gui.misc.TitleGUI; import fr.skytasul.quests.utils.types.Title; @@ -21,7 +21,7 @@ public TitleReward(String customDescription, Title title) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(title); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java index c87dbac6..bf4ff9c0 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/WaitReward.java @@ -6,9 +6,9 @@ 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; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -29,7 +29,7 @@ public boolean isAsync() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(getTicksString()); } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java index cf52b3ce..6b0c46b7 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/XPReward.java @@ -7,9 +7,9 @@ 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; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -41,7 +41,7 @@ public String getDefaultDescription(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(getXpAmountString()); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index 37a39689..aff82892 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -163,7 +163,8 @@ public void finish(List<Mob> objects) { @Override public ItemStack getObjectItemStack(Mob object) { - return ItemUtils.item(object.getMobItem(), object.getName(), Lang.RemoveMid.toString()); + return ItemUtils.item(object.getMobItem(), object.getName(), + createLoreBuilder(object).toLoreArray()); } @Override diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 7c816049..9a444b88 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -540,10 +540,8 @@ inv: mobs: name: Select mobs none: §aClick to add a mob. - clickLore: |- - §a§lLeft-click§a to edit amount. - §a§l§nShift§a§l + left-click§a to edit mob name. - §c§lRight-click§c to delete. + editAmount: Edit amount + editMobName: Edit mob name setLevel: Set minimum level mobSelect: name: Select mob type @@ -758,7 +756,8 @@ indication: startQuest: §7Do you want to start the quest {quest_name}? closeInventory: §7Are you sure you want to close the GUI? cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? - removeQuest: §7Are you sure you want to remove the quest {quest_name}? + removeQuest: §7Are you sure you want to remove the quest {quest}? + removePool: §7Are you sure you want to remove the pool {quest}? description: requirement: title: '§8§lRequirements:' @@ -866,7 +865,6 @@ misc: disabled: Disabled unknown: unknown notSet: §cnot set - remove: §7Middle-click to remove removeRaw: Remove reset: Reset or: or diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java index 81fcc07e..62ffb708 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java @@ -16,11 +16,11 @@ import com.massivecraft.factions.entity.MPlayer; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; public class FactionRequirement extends AbstractRequirement { @@ -56,7 +56,7 @@ public boolean test(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(factions.size() + " factions"); } @@ -67,7 +67,7 @@ public void itemClick(QuestObjectClickEvent event) { @Override public ItemStack getObjectItemStack(Faction object) { - return ItemUtils.item(XMaterial.IRON_SWORD, object.getName(), "", Lang.RemoveMid.toString()); + return ItemUtils.item(XMaterial.IRON_SWORD, object.getName(), createLoreBuilder(object).toLoreArray()); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/jobs/JobLevelRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/jobs/JobLevelRequirement.java index bc641c2f..03959275 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/jobs/JobLevelRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/jobs/JobLevelRequirement.java @@ -7,9 +7,9 @@ import com.gamingmesh.jobs.container.JobProgression; import com.gamingmesh.jobs.container.JobsPlayer; import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; @@ -77,7 +77,7 @@ public AbstractRequirement clone() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription("§8Job name: §7" + jobName); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McMMOSkillRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McMMOSkillRequirement.java index ba4c5f0b..8a78111c 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McMMOSkillRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mcmmo/McMMOSkillRequirement.java @@ -5,9 +5,9 @@ import org.jetbrains.annotations.NotNull; import com.gmail.nossr50.api.ExperienceAPI; import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.TargetNumberRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; @@ -62,7 +62,7 @@ public void sendHelpString(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription("§8Skill name: §7" + skillName); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java index 99397ebf..946bed7d 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java @@ -6,9 +6,9 @@ import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.utils.ComparisonMethod; @@ -136,7 +136,7 @@ public void load(ConfigurationSection section){ } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(rawPlaceholder)); loreBuilder.addDescription(comparison.getTitle().quickFormat("number", value)); diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java index 68e48919..9c7c5b63 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/ClassRequirement.java @@ -13,11 +13,11 @@ 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; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.requirements.AbstractRequirement; public class ClassRequirement extends AbstractRequirement { @@ -60,7 +60,7 @@ public String getDefaultDescription(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(classes.size() + " classes"); } @@ -71,7 +71,7 @@ public void itemClick(QuestObjectClickEvent event) { @Override public ItemStack getObjectItemStack(RPGClass object) { - return ItemUtils.loreAdd(object.getIcon(), "", Lang.RemoveMid.toString()); + return ItemUtils.loreAdd(object.getIcon(), createLoreBuilder(object).toLoreArray()); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java index 71535505..d23a96cc 100755 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/skillapi/SkillAPIXpReward.java @@ -7,9 +7,9 @@ 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; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -41,7 +41,7 @@ public String getDefaultDescription(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(getXpAmountString()); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyRequirement.java index 0c28bd80..852c463d 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyRequirement.java @@ -5,9 +5,9 @@ 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; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.Actionnable; @@ -58,7 +58,7 @@ public AbstractRequirement clone() { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(money)); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyReward.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyReward.java index 732ad8ad..a0c2235f 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyReward.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/economy/MoneyReward.java @@ -7,9 +7,9 @@ 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; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.integrations.vault.Vault; @@ -51,7 +51,7 @@ public String getDefaultDescription(Player p) { } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(money); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java index 5e17c4ce..5824f014 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java @@ -22,8 +22,9 @@ public PermissionListGUI(List<Permission> list, Consumer<List<Permission>> end) @Override public ItemStack getObjectItemStack(Permission object) { - return ItemUtils.item(XMaterial.PAPER, "§e" + object.permission, Lang.permRemoved.format(object), - Lang.permWorld.format(object)); + return ItemUtils.item(XMaterial.PAPER, "§e" + object.permission, createLoreBuilder(object) + .addDescription(Lang.permRemoved.format(object)) + .addDescription(Lang.permWorld.format(object)).toLoreArray()); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionReward.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionReward.java index 53698ac4..4921f259 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionReward.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionReward.java @@ -5,9 +5,9 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -45,7 +45,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescriptionAsValue(Lang.AmountPermissions.format(this)); } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/RegionRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/RegionRequirement.java index 32dde177..e179da7d 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/RegionRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/RegionRequirement.java @@ -7,9 +7,9 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; +import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; -import fr.skytasul.quests.api.objects.QuestObjectLoreBuilder; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -46,7 +46,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol } @Override - protected void addLore(QuestObjectLoreBuilder loreBuilder) { + protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(QuestOption.formatNullableValue(regionName)); } From 5b2e8e487bc8ae9f6204714a3cbb18ade02deffa Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 22 Aug 2023 21:37:16 +0200 Subject: [PATCH 37/95] :zap: Improved performances on quickformat --- .../java/fr/skytasul/quests/api/localization/Locale.java | 8 ++++++-- .../main/java/fr/skytasul/quests/stages/StageDeath.java | 6 ++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java index 5937963c..47e63d08 100644 --- a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java +++ b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java @@ -7,6 +7,7 @@ import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.util.Objects; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; @@ -44,8 +45,11 @@ public interface Locale { } default @NotNull String quickFormat(@NotNull String key1, @Nullable Object value1) { - // TODO maybe simplify this for optimization? - return format(PlaceholderRegistry.of(key1, value1)); + // for performance reason: no need to allocate a new placeholder registry with a new placeholder + String replacement = Objects.toString(value1); + return getValue() + .replace("{0}", replacement) // TODO remove, migration + .replace("{" + key1 + "}", replacement); } default void send(@NotNull CommandSender sender) { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java index 4fee91e4..ac0834db 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java @@ -13,7 +13,6 @@ import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; @@ -89,9 +88,8 @@ public void setupLine(@NotNull StageGuiLine line) { public void setCauses(List<DamageCause> causes) { this.causes = causes; - getLine().refreshItem(CAUSES_SLOT, - item -> ItemUtils.lore(item, QuestOption.formatNullableValue(causes.isEmpty() ? Lang.stageDeathCauseAny - : Lang.stageDeathCausesSet.quickFormat("causes_amount", causes.size())))); + getLine().refreshItemLoreOptionValue(CAUSES_SLOT, causes.isEmpty() ? Lang.stageDeathCauseAny + : Lang.stageDeathCausesSet.quickFormat("causes_amount", causes.size())); } @Override From aa3ebca584a6023317bf994f87bf3a9280b15633 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 23 Aug 2023 15:57:44 +0200 Subject: [PATCH 38/95] :truck: Moved all dependencies --- api/dependency-reduced-pom.xml | 163 ++++++++++++++++++ .../skytasul/quests/DefaultQuestFeatures.java | 71 +------- .../QuestsConfigurationImplementation.java | 2 +- .../fr/skytasul/quests/QuestsListener.java | 2 +- .../quests/blocks/BQBlockMaterial.java | 4 +- .../blocks/BQBlocksManagerImplementation.java | 2 +- .../quests/commands/CommandsAdmin.java | 18 +- .../CommandsManagerImplementation.java | 16 +- .../quests/commands/CommandsPlayer.java | 21 ++- .../commands/CommandsPlayerManagement.java | 24 +-- .../quests/commands/CommandsPools.java | 12 +- .../quests/commands/CommandsRoot.java | 12 +- .../quests/commands/CommandsScoreboard.java | 20 ++- .../quests/editor/DefaultEditorFactory.java | 2 +- .../quests/editor/parsers/MaterialParser.java | 2 +- .../quests/gui/blocks/SelectBlockGUI.java | 2 +- .../quest/QuestCreationGuiImplementation.java | 2 +- .../quests/gui/creation/stages/StagesGUI.java | 2 +- .../quests/gui/items/ItemCreatorGUI.java | 2 +- .../skytasul/quests/gui/items/ItemsGUI.java | 2 +- .../skytasul/quests/gui/misc/CommandGUI.java | 2 +- .../quests/gui/misc/DamageCausesGUI.java | 2 +- .../fr/skytasul/quests/gui/misc/TitleGUI.java | 2 +- .../quests/gui/mobs/EntityTypeGUI.java | 2 +- .../skytasul/quests/gui/npc/NpcCreateGUI.java | 2 +- .../quests/gui/npc/NpcFactoryGUI.java | 2 +- .../skytasul/quests/gui/npc/NpcSelectGUI.java | 2 +- .../gui/particles/ParticleEffectGUI.java | 2 +- .../quests/gui/particles/ParticleListGUI.java | 2 +- .../quests/gui/pools/PoolEditGUI.java | 2 +- .../quests/gui/pools/PoolsManageGUI.java | 2 +- .../quests/gui/quests/DialogHistoryGUI.java | 2 +- .../quests/gui/quests/PlayerListGUI.java | 2 +- .../quests/mobs/BukkitEntityFactory.java | 2 +- .../java/fr/skytasul/quests/mobs/Mob.java | 2 +- .../quests/options/OptionCancelRewards.java | 2 +- .../quests/options/OptionConfirmMessage.java | 2 +- .../quests/options/OptionDescription.java | 2 +- .../quests/options/OptionEndMessage.java | 2 +- .../quests/options/OptionEndRewards.java | 2 +- .../quests/options/OptionEndSound.java | 2 +- .../quests/options/OptionFirework.java | 2 +- .../quests/options/OptionHologramLaunch.java | 2 +- .../options/OptionHologramLaunchNo.java | 2 +- .../quests/options/OptionHologramText.java | 2 +- .../skytasul/quests/options/OptionName.java | 2 +- .../quests/options/OptionQuestItem.java | 2 +- .../quests/options/OptionQuestPool.java | 2 +- .../quests/options/OptionRequirements.java | 2 +- .../quests/options/OptionStartDialog.java | 2 +- .../quests/options/OptionStartMessage.java | 2 +- .../quests/options/OptionStartRewards.java | 2 +- .../quests/options/OptionStarterNPC.java | 2 +- .../skytasul/quests/options/OptionTimer.java | 2 +- .../quests/options/OptionVisibility.java | 2 +- .../requirements/EquipmentRequirement.java | 2 +- .../requirements/PermissionsRequirement.java | 2 +- .../quests/rewards/CommandReward.java | 2 +- .../rewards/RequirementDependentReward.java | 2 +- .../quests/stages/StageBringBack.java | 2 +- .../skytasul/quests/stages/StageBucket.java | 2 +- .../fr/skytasul/quests/stages/StageChat.java | 2 +- .../fr/skytasul/quests/stages/StageCraft.java | 2 +- .../quests/stages/StageDealDamage.java | 2 +- .../fr/skytasul/quests/stages/StageDeath.java | 2 +- .../skytasul/quests/stages/StageEatDrink.java | 2 +- .../skytasul/quests/stages/StageEnchant.java | 2 +- .../fr/skytasul/quests/stages/StageFish.java | 2 +- .../quests/stages/StageInteractBlock.java | 2 +- .../quests/stages/StageInteractLocation.java | 2 +- .../skytasul/quests/stages/StageLocation.java | 2 +- .../fr/skytasul/quests/stages/StageMelt.java | 2 +- .../fr/skytasul/quests/stages/StageMine.java | 2 +- .../fr/skytasul/quests/stages/StageMobs.java | 2 +- .../fr/skytasul/quests/stages/StageNPC.java | 2 +- .../quests/stages/StagePlaceBlocks.java | 2 +- .../skytasul/quests/stages/StagePlayTime.java | 2 +- .../options/StageOptionProgressBar.java | 16 +- .../pools/QuestPoolImplementation.java | 2 +- .../quests/utils/compatibility/Post1_13.java | 2 +- .../integrations/IntegrationsLoader.java | 2 +- .../factions/FactionRequirement.java | 2 +- .../integrations/mobs/BQAdvancedSpawners.java | 2 +- .../quests/integrations/mobs/BQBoss.java | 2 +- .../integrations/mobs/BQLevelledMobs.java | 2 +- .../integrations/mobs/CitizensFactory.java | 2 +- .../quests/integrations/mobs/MythicMobs.java | 2 +- .../quests/integrations/mobs/MythicMobs5.java | 2 +- .../vault/permission/PermissionGUI.java | 2 +- .../vault/permission/PermissionListGUI.java | 2 +- .../integrations/worldguard/BQWorldGuard.java | 2 +- .../integrations/worldguard/StageArea.java | 2 +- 92 files changed, 323 insertions(+), 216 deletions(-) create mode 100755 api/dependency-reduced-pom.xml diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml new file mode 100755 index 00000000..6b97e5d6 --- /dev/null +++ b/api/dependency-reduced-pom.xml @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>beautyquests-parent</artifactId> + <groupId>fr.skytasul</groupId> + <version>1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>beautyquests-api</artifactId> + <build> + <plugins> + <plugin> + <artifactId>maven-shade-plugin</artifactId> + <version>3.2.1</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + </execution> + </executions> + <configuration> + <relocations> + <relocation> + <pattern>revxrsal.commands</pattern> + <shadedPattern>fr.skytasul.quests.api.commands.revxrsal</shadedPattern> + </relocation> + <relocation> + <pattern>com.cryptomorin.xseries</pattern> + <shadedPattern>fr.skytasul.quests.api.utils</shadedPattern> + </relocation> + </relocations> + <filters> + <filter> + <artifact>com.github.cryptomorin:XSeries</artifact> + <includes> + <include>com/cryptomorin/xseries/XMaterial*</include> + <include>com/cryptomorin/xseries/XBlock*</include> + <include>com/cryptomorin/xseries/XPotion*</include> + </includes> + </filter> + </filters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.4.1</version> + <configuration> + <skip>false</skip> + </configuration> + </plugin> + </plugins> + </build> + <repositories> + <repository> + <id>papermc</id> + <url>https://repo.papermc.io/repository/maven-public/</url> + </repository> + <repository> + <id>jitpack.io</id> + <url>https://jitpack.io</url> + </repository> + </repositories> + <dependencies> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>24.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>io.papermc.paper</groupId> + <artifactId>paper-api</artifactId> + <version>1.19.4-R0.1-SNAPSHOT</version> + <scope>provided</scope> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + <exclusion> + <artifactId>gson</artifactId> + <groupId>com.google.code.gson</groupId> + </exclusion> + <exclusion> + <artifactId>bungeecord-chat</artifactId> + <groupId>net.md-5</groupId> + </exclusion> + <exclusion> + <artifactId>snakeyaml</artifactId> + <groupId>org.yaml</groupId> + </exclusion> + <exclusion> + <artifactId>joml</artifactId> + <groupId>org.joml</groupId> + </exclusion> + <exclusion> + <artifactId>json-simple</artifactId> + <groupId>com.googlecode.json-simple</groupId> + </exclusion> + <exclusion> + <artifactId>fastutil</artifactId> + <groupId>it.unimi.dsi</groupId> + </exclusion> + <exclusion> + <artifactId>log4j-api</artifactId> + <groupId>org.apache.logging.log4j</groupId> + </exclusion> + <exclusion> + <artifactId>slf4j-api</artifactId> + <groupId>org.slf4j</groupId> + </exclusion> + <exclusion> + <artifactId>maven-resolver-provider</artifactId> + <groupId>org.apache.maven</groupId> + </exclusion> + <exclusion> + <artifactId>adventure-api</artifactId> + <groupId>net.kyori</groupId> + </exclusion> + <exclusion> + <artifactId>adventure-text-minimessage</artifactId> + <groupId>net.kyori</groupId> + </exclusion> + <exclusion> + <artifactId>adventure-text-serializer-gson</artifactId> + <groupId>net.kyori</groupId> + </exclusion> + <exclusion> + <artifactId>adventure-text-serializer-legacy</artifactId> + <groupId>net.kyori</groupId> + </exclusion> + <exclusion> + <artifactId>adventure-text-serializer-plain</artifactId> + <groupId>net.kyori</groupId> + </exclusion> + <exclusion> + <artifactId>adventure-text-logger-slf4j</artifactId> + <groupId>net.kyori</groupId> + </exclusion> + <exclusion> + <artifactId>checker-qual</artifactId> + <groupId>org.checkerframework</groupId> + </exclusion> + <exclusion> + <artifactId>asm</artifactId> + <groupId>org.ow2.asm</groupId> + </exclusion> + <exclusion> + <artifactId>asm-commons</artifactId> + <groupId>org.ow2.asm</groupId> + </exclusion> + </exclusions> + </dependency> + </dependencies> +</project> diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index 8e8a7516..b3c9e705 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -7,7 +7,6 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.Repairable; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; @@ -27,77 +26,17 @@ import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageProcessor; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.api.utils.progress.HasProgress; import fr.skytasul.quests.mobs.BukkitEntityFactory; -import fr.skytasul.quests.options.OptionAutoQuest; -import fr.skytasul.quests.options.OptionBypassLimit; -import fr.skytasul.quests.options.OptionCancelRewards; -import fr.skytasul.quests.options.OptionCancellable; -import fr.skytasul.quests.options.OptionConfirmMessage; -import fr.skytasul.quests.options.OptionDescription; -import fr.skytasul.quests.options.OptionEndMessage; -import fr.skytasul.quests.options.OptionEndRewards; -import fr.skytasul.quests.options.OptionEndSound; -import fr.skytasul.quests.options.OptionFailOnDeath; -import fr.skytasul.quests.options.OptionFirework; -import fr.skytasul.quests.options.OptionHideNoRequirements; -import fr.skytasul.quests.options.OptionHologramLaunch; -import fr.skytasul.quests.options.OptionHologramLaunchNo; -import fr.skytasul.quests.options.OptionHologramText; -import fr.skytasul.quests.options.OptionName; -import fr.skytasul.quests.options.OptionQuestItem; -import fr.skytasul.quests.options.OptionQuestPool; -import fr.skytasul.quests.options.OptionRepeatable; -import fr.skytasul.quests.options.OptionRequirements; -import fr.skytasul.quests.options.OptionScoreboardEnabled; -import fr.skytasul.quests.options.OptionStartDialog; -import fr.skytasul.quests.options.OptionStartMessage; -import fr.skytasul.quests.options.OptionStartRewards; -import fr.skytasul.quests.options.OptionStartable; -import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.options.OptionTimer; -import fr.skytasul.quests.options.OptionVisibility; -import fr.skytasul.quests.requirements.EquipmentRequirement; -import fr.skytasul.quests.requirements.LevelRequirement; -import fr.skytasul.quests.requirements.PermissionsRequirement; -import fr.skytasul.quests.requirements.QuestRequirement; -import fr.skytasul.quests.requirements.ScoreboardRequirement; +import fr.skytasul.quests.options.*; +import fr.skytasul.quests.requirements.*; import fr.skytasul.quests.requirements.logical.LogicalOrRequirement; -import fr.skytasul.quests.rewards.CheckpointReward; -import fr.skytasul.quests.rewards.CommandReward; -import fr.skytasul.quests.rewards.ItemReward; -import fr.skytasul.quests.rewards.MessageReward; -import fr.skytasul.quests.rewards.QuestStopReward; -import fr.skytasul.quests.rewards.RandomReward; -import fr.skytasul.quests.rewards.RemoveItemsReward; -import fr.skytasul.quests.rewards.RequirementDependentReward; -import fr.skytasul.quests.rewards.TeleportationReward; -import fr.skytasul.quests.rewards.TitleReward; -import fr.skytasul.quests.rewards.WaitReward; -import fr.skytasul.quests.rewards.XPReward; -import fr.skytasul.quests.stages.StageBreed; -import fr.skytasul.quests.stages.StageBringBack; -import fr.skytasul.quests.stages.StageBucket; -import fr.skytasul.quests.stages.StageChat; -import fr.skytasul.quests.stages.StageCraft; -import fr.skytasul.quests.stages.StageDealDamage; -import fr.skytasul.quests.stages.StageDeath; -import fr.skytasul.quests.stages.StageEatDrink; -import fr.skytasul.quests.stages.StageEnchant; -import fr.skytasul.quests.stages.StageFish; -import fr.skytasul.quests.stages.StageInteractBlock; -import fr.skytasul.quests.stages.StageInteractLocation; -import fr.skytasul.quests.stages.StageLocation; -import fr.skytasul.quests.stages.StageMelt; -import fr.skytasul.quests.stages.StageMine; -import fr.skytasul.quests.stages.StageMobs; -import fr.skytasul.quests.stages.StageNPC; -import fr.skytasul.quests.stages.StagePlaceBlocks; -import fr.skytasul.quests.stages.StagePlayTime; -import fr.skytasul.quests.stages.StageTame; +import fr.skytasul.quests.rewards.*; +import fr.skytasul.quests.stages.*; import fr.skytasul.quests.stages.options.StageOptionProgressBar; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.compatibility.BQBossBarImplementation; diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index bd98d46f..7b7b2da5 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -16,7 +16,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; @@ -28,6 +27,7 @@ import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.PlayerListCategory; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.players.BqAccountsHook; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 3c174318..47d84fd3 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -21,7 +21,6 @@ import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ComplexRecipe; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; @@ -37,6 +36,7 @@ import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java index a1630caf..226f4a4e 100644 --- a/core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlockMaterial.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.blocks; import org.bukkit.block.Block; -import com.cryptomorin.xseries.XBlock; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.blocks.BQBlockOptions; +import fr.skytasul.quests.api.utils.XBlock; +import fr.skytasul.quests.api.utils.XMaterial; public class BQBlockMaterial extends BQBlock { diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java index e914eae0..cfdb5c35 100644 --- a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java @@ -8,7 +8,6 @@ import org.bukkit.block.Block; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import fr.skytasul.quests.api.blocks.BQBlock; @@ -20,6 +19,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.Located.LocatedBlock; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Post1_13; public class BQBlocksManagerImplementation implements BQBlocksManager { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 887b1bac..2735564e 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -18,6 +18,15 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.commands.OutsideEditor; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Flag; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Optional; +import fr.skytasul.quests.api.commands.revxrsal.annotation.SecretCommand; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Subcommand; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Switch; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.BukkitCommandActor; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.annotation.CommandPermission; +import fr.skytasul.quests.api.commands.revxrsal.exception.CommandErrorException; +import fr.skytasul.quests.api.commands.revxrsal.orphan.OrphanCommand; import fr.skytasul.quests.api.editors.SelectNPC; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; @@ -38,15 +47,6 @@ import fr.skytasul.quests.utils.Database; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.nms.NMS; -import revxrsal.commands.annotation.Flag; -import revxrsal.commands.annotation.Optional; -import revxrsal.commands.annotation.SecretCommand; -import revxrsal.commands.annotation.Subcommand; -import revxrsal.commands.annotation.Switch; -import revxrsal.commands.bukkit.BukkitCommandActor; -import revxrsal.commands.bukkit.annotation.CommandPermission; -import revxrsal.commands.exception.CommandErrorException; -import revxrsal.commands.orphan.OrphanCommand; public class CommandsAdmin implements OrphanCommand { 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 5a6d900b..ccd55ecd 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -11,6 +11,14 @@ import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.commands.CommandsManager; import fr.skytasul.quests.api.commands.OutsideEditor; +import fr.skytasul.quests.api.commands.revxrsal.autocomplete.SuggestionProvider; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.BukkitCommandActor; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.BukkitCommandHandler; +import fr.skytasul.quests.api.commands.revxrsal.command.CommandActor; +import fr.skytasul.quests.api.commands.revxrsal.command.ExecutableCommand; +import fr.skytasul.quests.api.commands.revxrsal.exception.CommandErrorException; +import fr.skytasul.quests.api.commands.revxrsal.orphan.OrphanCommand; +import fr.skytasul.quests.api.commands.revxrsal.orphan.Orphans; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.pools.QuestPool; @@ -18,14 +26,6 @@ import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.scoreboards.Scoreboard; -import revxrsal.commands.autocomplete.SuggestionProvider; -import revxrsal.commands.bukkit.BukkitCommandActor; -import revxrsal.commands.bukkit.BukkitCommandHandler; -import revxrsal.commands.command.CommandActor; -import revxrsal.commands.command.ExecutableCommand; -import revxrsal.commands.exception.CommandErrorException; -import revxrsal.commands.orphan.OrphanCommand; -import revxrsal.commands.orphan.Orphans; public class CommandsManagerImplementation implements CommandsManager { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java index 0d6790bb..c77c3202 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java @@ -3,6 +3,14 @@ import java.util.Optional; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Default; +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.annotation.CommandPermission; +import fr.skytasul.quests.api.commands.revxrsal.command.ExecutableCommand; +import fr.skytasul.quests.api.commands.revxrsal.exception.CommandErrorException; +import fr.skytasul.quests.api.commands.revxrsal.exception.InvalidSubcommandException; +import fr.skytasul.quests.api.commands.revxrsal.orphan.OrphanCommand; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayerQuestDatas; @@ -11,20 +19,15 @@ import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.rewards.CheckpointReward; -import revxrsal.commands.annotation.Default; -import revxrsal.commands.annotation.Subcommand; -import revxrsal.commands.bukkit.BukkitCommandActor; -import revxrsal.commands.bukkit.annotation.CommandPermission; -import revxrsal.commands.command.ExecutableCommand; -import revxrsal.commands.exception.CommandErrorException; -import revxrsal.commands.orphan.OrphanCommand; public class CommandsPlayer implements OrphanCommand { @Default @CommandPermission ("beautyquests.command.listPlayer") - public void menu(BukkitCommandActor actor, ExecutableCommand command, @revxrsal.commands.annotation.Optional String subcommand) { - if (subcommand != null) throw new revxrsal.commands.exception.InvalidSubcommandException(command.getPath(), subcommand); + public void menu(BukkitCommandActor actor, ExecutableCommand command, + @fr.skytasul.quests.api.commands.revxrsal.annotation.Optional String subcommand) { + if (subcommand != null) + throw new InvalidSubcommandException(command.getPath(), subcommand); PlayerAccount acc = PlayersManager.getPlayerAccount(actor.requirePlayer()); if (acc == null) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Player " + actor.getName() + " has got no account. This is a CRITICAL issue."); 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 bc8ca6f0..8b6fb81e 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayerManagement.java @@ -13,6 +13,18 @@ import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; +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.annotation.Switch; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.BukkitCommandActor; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.BukkitCommandPermission; +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.CommandErrorException; +import fr.skytasul.quests.api.commands.revxrsal.exception.NoPermissionException; +import fr.skytasul.quests.api.commands.revxrsal.orphan.OrphanCommand; import fr.skytasul.quests.api.events.accounts.PlayerAccountResetEvent; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; @@ -35,18 +47,6 @@ import fr.skytasul.quests.structure.EndingStageImplementation; import fr.skytasul.quests.structure.QuestBranchImplementation; import fr.skytasul.quests.utils.QuestUtils; -import revxrsal.commands.annotation.Optional; -import revxrsal.commands.annotation.Range; -import revxrsal.commands.annotation.Subcommand; -import revxrsal.commands.annotation.Switch; -import revxrsal.commands.bukkit.BukkitCommandActor; -import revxrsal.commands.bukkit.BukkitCommandPermission; -import revxrsal.commands.bukkit.EntitySelector; -import revxrsal.commands.bukkit.annotation.CommandPermission; -import revxrsal.commands.command.ExecutableCommand; -import revxrsal.commands.exception.CommandErrorException; -import revxrsal.commands.exception.NoPermissionException; -import revxrsal.commands.orphan.OrphanCommand; public class CommandsPlayerManagement implements OrphanCommand { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index 9642de0a..c26178a0 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java @@ -2,18 +2,18 @@ import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Default; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Subcommand; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Switch; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.BukkitCommandActor; +import fr.skytasul.quests.api.commands.revxrsal.bukkit.annotation.CommandPermission; +import fr.skytasul.quests.api.commands.revxrsal.orphan.OrphanCommand; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.pools.PoolsManageGUI; import fr.skytasul.quests.structure.pools.QuestPoolImplementation; -import revxrsal.commands.annotation.Default; -import revxrsal.commands.annotation.Subcommand; -import revxrsal.commands.annotation.Switch; -import revxrsal.commands.bukkit.BukkitCommandActor; -import revxrsal.commands.bukkit.annotation.CommandPermission; -import revxrsal.commands.orphan.OrphanCommand; public class CommandsPools implements OrphanCommand { diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java index e4baf9e5..b0574c0c 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java @@ -1,15 +1,15 @@ package fr.skytasul.quests.commands; import fr.skytasul.quests.BeautyQuests; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Command; +import fr.skytasul.quests.api.commands.revxrsal.annotation.Description; +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.annotation.CommandPermission; +import fr.skytasul.quests.api.commands.revxrsal.help.CommandHelp; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; -import revxrsal.commands.annotation.Command; -import revxrsal.commands.annotation.Description; -import revxrsal.commands.annotation.Subcommand; -import revxrsal.commands.bukkit.BukkitCommandActor; -import revxrsal.commands.bukkit.annotation.CommandPermission; -import revxrsal.commands.help.CommandHelp; @Command ({ "quests", "quest", "bq", "beautyquests", "bquests" }) @Description ("Main command for quests") 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 0dc5df81..2f6c866a 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsScoreboard.java @@ -2,24 +2,26 @@ 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.annotation.CommandPermission; +import fr.skytasul.quests.api.commands.revxrsal.command.ExecutableCommand; +import fr.skytasul.quests.api.commands.revxrsal.exception.InvalidSubcommandException; +import fr.skytasul.quests.api.commands.revxrsal.orphan.OrphanCommand; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.scoreboards.Scoreboard; -import revxrsal.commands.annotation.Default; -import revxrsal.commands.annotation.Optional; -import revxrsal.commands.annotation.Range; -import revxrsal.commands.annotation.Subcommand; -import revxrsal.commands.bukkit.BukkitCommandActor; -import revxrsal.commands.bukkit.annotation.CommandPermission; -import revxrsal.commands.command.ExecutableCommand; -import revxrsal.commands.orphan.OrphanCommand; public class CommandsScoreboard implements OrphanCommand { @Default @CommandPermission ("beautyquests.command.scoreboard.toggle") public void scoreboardToggle(Player player, ExecutableCommand command, Scoreboard scoreboard, @Optional String subcommand) { - if (subcommand != null) throw new revxrsal.commands.exception.InvalidSubcommandException(command.getPath(), subcommand); + if (subcommand != null) + throw new InvalidSubcommandException(command.getPath(), subcommand); if (scoreboard.isForceHidden()) { scoreboard.show(true); Lang.COMMAND_SCOREBOARD_OWN_SHOWN.send(player); diff --git a/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java b/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java index deb9fdb7..b555d814 100644 --- a/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java +++ b/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.editor; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.EditorFactory; import fr.skytasul.quests.api.editors.parsers.AbstractParser; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.editor.parsers.MaterialParser; public class DefaultEditorFactory implements EditorFactory { diff --git a/core/src/main/java/fr/skytasul/quests/editor/parsers/MaterialParser.java b/core/src/main/java/fr/skytasul/quests/editor/parsers/MaterialParser.java index 2664ceee..05e30e0c 100644 --- a/core/src/main/java/fr/skytasul/quests/editor/parsers/MaterialParser.java +++ b/core/src/main/java/fr/skytasul/quests/editor/parsers/MaterialParser.java @@ -2,10 +2,10 @@ import org.bukkit.Material; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.parsers.AbstractParser; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.compatibility.Post1_13; public class MaterialParser implements AbstractParser<XMaterial> { 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 57f811d5..61007060 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 @@ -11,7 +11,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.blocks.BQBlock; @@ -25,6 +24,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; 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.nms.NMS; 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 73354140..d0e80143 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 @@ -10,7 +10,6 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; @@ -31,6 +30,7 @@ import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.DefaultErrors; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.creation.QuestCreationSession; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 6042647d..f0ae5f0b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -10,7 +10,6 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; @@ -27,6 +26,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiClickEvent; import fr.skytasul.quests.api.stages.creation.StageGuiClickHandler; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.structure.QuestBranchImplementation; import fr.skytasul.quests.utils.QuestUtils; diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java index 35e4e528..d022d64a 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java @@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.TextListEditor; @@ -20,6 +19,7 @@ import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.XMaterial; public class ItemCreatorGUI extends AbstractGui { diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java index 3250d006..6b25ea23 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java @@ -10,7 +10,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; @@ -19,6 +18,7 @@ import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.QuestUtils; public class ItemsGUI extends AbstractGui { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java index 9c1644c3..e2a78eff 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java @@ -4,7 +4,6 @@ import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; @@ -13,6 +12,7 @@ import fr.skytasul.quests.api.gui.layout.LayoutedClickEvent; import fr.skytasul.quests.api.gui.layout.LayoutedGUI; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.types.Command; public class CommandGUI extends LayoutedGUI.LayoutedRowsGUI { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java index 10e4dc54..51aa0b21 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/DamageCausesGUI.java @@ -8,11 +8,11 @@ import org.bukkit.DyeColor; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.gui.templates.StaticPagedGUI; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.XMaterial; public class DamageCausesGUI extends ListGUI<DamageCause> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index 9f38fa9e..ac13d4a7 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -7,7 +7,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.AbstractGui; @@ -17,6 +16,7 @@ import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.types.Title; public class TitleGUI extends AbstractGui { diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java index b05618ce..2f467a1f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/EntityTypeGUI.java @@ -10,13 +10,13 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; public class EntityTypeGUI extends PagedGUI<EntityType>{ diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index b82afd91..f4bcbc3f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -7,7 +7,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; @@ -21,6 +20,7 @@ import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.DefaultErrors; public class NpcCreateGUI extends AbstractGui { diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java index dba389aa..c4d1745a 100755 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java @@ -7,7 +7,6 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -15,6 +14,7 @@ import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; +import fr.skytasul.quests.api.utils.XMaterial; public class NpcFactoryGUI extends PagedGUI<BqInternalNpcFactory> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index 6b59ed0e..bfdf8f36 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -5,7 +5,6 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.editors.SelectNPC; import fr.skytasul.quests.api.gui.AbstractGui; @@ -17,6 +16,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.api.npcs.BqNpc; +import fr.skytasul.quests.api.utils.XMaterial; public final class NpcSelectGUI { diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index f36442a7..9186af7d 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -10,7 +10,6 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.ColorParser; import fr.skytasul.quests.api.gui.ItemUtils; @@ -21,6 +20,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; import fr.skytasul.quests.utils.compatibility.Post1_13; diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java index b9218cbb..1ada8a12 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleListGUI.java @@ -7,11 +7,11 @@ import org.bukkit.DyeColor; import org.bukkit.Particle; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.StaticPagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.ParticleEffect; public class ParticleListGUI extends StaticPagedGUI<Particle> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index bb099d89..4a9ea525 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -6,7 +6,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; @@ -23,6 +22,7 @@ import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; public class PoolEditGUI extends AbstractGui { diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java index 3b02836f..f23eb26c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolsManageGUI.java @@ -7,7 +7,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -15,6 +14,7 @@ import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.pools.QuestPool; +import fr.skytasul.quests.api.utils.XMaterial; public class PoolsManageGUI extends PagedGUI<QuestPool> { 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 183c08fd..5d040c07 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 @@ -13,7 +13,6 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; @@ -26,6 +25,7 @@ import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.api.utils.ChatColorUtils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.gui.quests.DialogHistoryGUI.WrappedDialogable; import fr.skytasul.quests.options.OptionStartDialog; import fr.skytasul.quests.utils.QuestUtils; 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 1a1160d3..de369289 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 @@ -12,7 +12,6 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; @@ -26,6 +25,7 @@ import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.options.OptionStartable; import fr.skytasul.quests.players.PlayerAccountImplementation; import fr.skytasul.quests.utils.QuestUtils; 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 981eed65..41b18aac 100644 --- a/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java +++ b/core/src/main/java/fr/skytasul/quests/mobs/BukkitEntityFactory.java @@ -11,12 +11,12 @@ import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; 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; public class BukkitEntityFactory implements MobFactory<EntityType>, Listener { diff --git a/core/src/main/java/fr/skytasul/quests/mobs/Mob.java b/core/src/main/java/fr/skytasul/quests/mobs/Mob.java index 2ad3ec9a..c5ddce46 100644 --- a/core/src/main/java/fr/skytasul/quests/mobs/Mob.java +++ b/core/src/main/java/fr/skytasul/quests/mobs/Mob.java @@ -9,11 +9,11 @@ import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.mobs.LeveledMobFactory; import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; public class Mob<D> implements Cloneable { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java index bea95d69..23b55afa 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionCancelRewards.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.options; import java.util.stream.Collectors; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -10,6 +9,7 @@ import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.rewards.RewardList; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionCancelRewards extends QuestOptionRewards { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java index f1cb427a..40bfb1a4 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionConfirmMessage.java @@ -1,11 +1,11 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionConfirmMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java index e535046e..5c38653e 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java @@ -4,13 +4,13 @@ import java.util.List; import java.util.concurrent.TimeUnit; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java index e4c64314..c2261a2e 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndMessage.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionEndMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java index 7a85d720..e5f8a666 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndRewards.java @@ -4,12 +4,12 @@ import java.util.Objects; import java.util.regex.Pattern; import java.util.stream.Collectors; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionRewards; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; import fr.skytasul.quests.api.options.description.QuestDescriptionProvider; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java b/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java index 54d124c3..210068ee 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionEndSound.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionEndSound extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java index 6f51efcf..e0215684 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionFirework.java @@ -7,13 +7,13 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.QuestUtils; public class OptionFirework extends QuestOption<FireworkMeta> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java index 70d9b54a..f141a36c 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunch.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.options; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionItem; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionHologramLaunch extends QuestOptionItem { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java index fd0715ca..701b00e4 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramLaunchNo.java @@ -1,10 +1,10 @@ package fr.skytasul.quests.options; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionItem; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionHologramLaunchNo extends QuestOptionItem { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java index 38f4ac06..914a0868 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionHologramText.java @@ -1,12 +1,12 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOptionString; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionHologramText extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionName.java b/core/src/main/java/fr/skytasul/quests/options/OptionName.java index 118faff7..5be0907f 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionName.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionName.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionName extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java index ed2fa4db..d83ad3f6 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestItem.java @@ -3,7 +3,6 @@ import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; @@ -11,6 +10,7 @@ import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.QuestUtils; public class OptionQuestItem extends QuestOption<ItemStack> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java index af14717d..35060c9a 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionQuestPool.java @@ -7,7 +7,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; @@ -19,6 +18,7 @@ import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionQuestPool extends QuestOption<QuestPool> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java index 58a00f7a..4cf65fb8 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java @@ -5,7 +5,6 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; @@ -16,6 +15,7 @@ import fr.skytasul.quests.api.requirements.RequirementCreator; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java index 990782de..d70c8890 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartDialog.java @@ -3,7 +3,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemoryConfiguration; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.DialogEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -14,6 +13,7 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.stages.types.Dialogable; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; public class OptionStartDialog extends QuestOption<Dialog> implements Dialogable { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java index ccf8db51..f103f4d1 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartMessage.java @@ -1,9 +1,9 @@ package fr.skytasul.quests.options; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionString; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionStartMessage extends QuestOptionString { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java index 8a8ea663..2f54728b 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStartRewards.java @@ -1,8 +1,8 @@ package fr.skytasul.quests.options; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOptionRewards; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionStartRewards extends QuestOptionRewards { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 3b80d43b..3fef152f 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -4,7 +4,6 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -12,6 +11,7 @@ import fr.skytasul.quests.api.options.OptionSet; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionStarterNPC extends QuestOption<BqNpc> { 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 71b8616a..6de3bed3 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionTimer.java @@ -2,7 +2,6 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.gui.ItemUtils; @@ -11,6 +10,7 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionTimer extends QuestOption<Integer> { diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java index ca6a8f2f..2d5968db 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java @@ -13,7 +13,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -24,6 +23,7 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; +import fr.skytasul.quests.api.utils.XMaterial; public class OptionVisibility extends QuestOption<List<QuestVisibilityLocation>> { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java index 3dd3965c..10b9ef83 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/EquipmentRequirement.java @@ -7,7 +7,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import com.google.common.collect.ImmutableMap; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparisonMap; @@ -17,6 +16,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.gui.items.ItemComparisonGUI; public class EquipmentRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java index a8ac78ec..73776bfc 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java @@ -9,7 +9,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.LoreBuilder; @@ -17,6 +16,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class PermissionsRequirement extends AbstractRequirement { diff --git a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java index 281b6c3a..9601ab46 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/CommandReward.java @@ -9,7 +9,6 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.templates.ListGUI; @@ -17,6 +16,7 @@ import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.gui.misc.CommandGUI; import fr.skytasul.quests.utils.types.Command; diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 09e39f7c..98eecff2 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -6,7 +6,6 @@ import java.util.stream.Collectors; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.LoreBuilder; @@ -23,6 +22,7 @@ import fr.skytasul.quests.api.rewards.AbstractReward; import fr.skytasul.quests.api.rewards.InterruptingBranchException; import fr.skytasul.quests.api.rewards.RewardList; +import fr.skytasul.quests.api.utils.XMaterial; public class RequirementDependentReward extends AbstractReward { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 6e5204de..b4ebf536 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -10,7 +10,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.editors.TextEditor; @@ -27,6 +26,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index 14b46c29..d7a14092 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -8,7 +8,6 @@ import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; @@ -24,6 +23,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; 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.api.utils.progress.ProgressPlaceholders; import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index f2a6490e..cd0252ba 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -7,7 +7,6 @@ import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -18,6 +17,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index 2f9d8253..0c6082c7 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -10,7 +10,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.events.internal.BQCraftEvent; @@ -26,6 +25,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index aff82892..ae3a4d2f 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -15,7 +15,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.projectiles.ProjectileSource; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; @@ -30,6 +29,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.progress.HasProgress; import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java index ac0834db..7736ed88 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java @@ -10,7 +10,6 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.PlayerDeathEvent; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.stages.AbstractStage; @@ -19,6 +18,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.gui.misc.DamageCausesGUI; public class StageDeath extends AbstractStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java index 9aaf4f00..0827bb08 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java @@ -6,7 +6,6 @@ import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -15,6 +14,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.XMaterial; public class StageEatDrink extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java index 0c9a0d59..5b846d86 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java @@ -8,7 +8,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -17,6 +16,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.XMaterial; public class StageEnchant extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java index 901e1b6c..60e80a9c 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java @@ -10,7 +10,6 @@ import org.bukkit.event.player.PlayerFishEvent.State; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -19,6 +18,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.XMaterial; public class StageFish extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java index 527c6d2d..fe60f1b4 100755 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java @@ -9,7 +9,6 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.gui.ItemUtils; @@ -24,6 +23,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; 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.gui.blocks.SelectBlockGUI; 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 92fb5702..82160697 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java @@ -9,7 +9,6 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.WaitBlockClick; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -23,6 +22,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; 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.types.BQLocation; 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 daeb18e2..4d06460b 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -7,7 +7,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.WaitClick; import fr.skytasul.quests.api.editors.parsers.NumberParser; @@ -24,6 +23,7 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.npc.NpcCreateGUI; import fr.skytasul.quests.utils.types.BQLocation; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java index 5fb52819..682c36f3 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java @@ -7,7 +7,6 @@ import org.bukkit.event.inventory.FurnaceExtractEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -16,6 +15,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractItemStage; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.XMaterial; public class StageMelt extends AbstractItemStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index da042945..01a1fa15 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -16,7 +16,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import com.gestankbratwurst.playerblocktracker.PlayerBlockTracker; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; @@ -35,6 +34,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.XMaterial; @LocatableType (types = LocatedType.BLOCK) public class StageMine extends AbstractCountableBlockStage implements Locatable.MultipleLocatable { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index dd79bbc1..691cb174 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -17,7 +17,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.events.internal.BQMobDeathEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -34,6 +33,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.gui.mobs.MobsListGUI; 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 176de9c7..e9a1d1ff 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -13,7 +13,6 @@ import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.AbstractHolograms; @@ -39,6 +38,7 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index 4dbced9f..bb2b6af4 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -9,7 +9,6 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; @@ -18,6 +17,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractCountableBlockStage; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.XMaterial; public class StagePlaceBlocks extends AbstractCountableBlockStage { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index fb00e7f1..4b239e07 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -7,7 +7,6 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; @@ -23,6 +22,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; import fr.skytasul.quests.api.utils.progress.HasProgress; diff --git a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java index cf7ab702..2d580a99 100755 --- a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java +++ b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java @@ -26,7 +26,7 @@ import fr.skytasul.quests.api.utils.progress.ProgressBarConfig; import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; -public class StageOptionProgressBar<T extends AbstractStage & HasProgress> extends StageOption<T> { +public class StageOptionProgressBar<T extends AbstractStage> extends StageOption<T> { private final @NotNull Map<Player, ProgressBar> bars = new HashMap<>(); @@ -62,7 +62,7 @@ public void load(@NotNull ConfigurationSection section) { @Override public void stageStart(PlayerAccount acc, StageController stage) { if (acc.isCurrent()) - createBar(acc.getPlayer(), (T) stage.getStage()); + createBar(acc.getPlayer(), stage.getStage()); } @Override @@ -73,7 +73,7 @@ public void stageEnd(PlayerAccount acc, StageController stage) { @Override public void stageJoin(Player p, StageController stage) { - createBar(p, (T) stage.getStage()); + createBar(p, stage.getStage()); } @Override @@ -102,14 +102,14 @@ public boolean areBarsEnabled() { return getProgressConfig().areBossBarsEnabled() && QuestsAPI.getAPI().hasBossBarManager(); } - protected void createBar(@NotNull Player p, T progress) { + protected void createBar(@NotNull Player p, AbstractStage stage) { if (areBarsEnabled()) { if (bars.containsKey(p)) { // NOSONAR Map#computeIfAbsent cannot be used here as we should log the issue QuestsPlugin.getPlugin().getLoggerExpanded() .warning("Trying to create an already existing bossbar for player " + p.getName()); return; } - bars.put(p, new ProgressBar(p, progress)); + bars.put(p, new ProgressBar<>(p, (AbstractStage & HasProgress) stage)); } } @@ -118,16 +118,16 @@ protected void removeBar(@NotNull Player p) { bars.remove(p).remove(); } - class ProgressBar { + class ProgressBar<P extends AbstractStage & HasProgress> { private final PlayerAccount acc; private final BQBossBar bar; - private final T progress; + private final P progress; private final int totalAmount; private final PlaceholderRegistry placeholders; private BukkitTask timer; - public ProgressBar(Player p, T progress) { + public ProgressBar(Player p, P progress) { this.progress = progress; this.acc = PlayersManager.getPlayerAccount(p); this.totalAmount = progress.getTotalAmount(); 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 a4cd56fa..db63f615 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 @@ -12,7 +12,6 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; @@ -26,6 +25,7 @@ import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.npcs.BqNpcImplementation; diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java index fe263a64..e8504286 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java @@ -9,9 +9,9 @@ import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.blocks.BQBlock; import fr.skytasul.quests.api.blocks.BQBlockOptions; +import fr.skytasul.quests.api.utils.XMaterial; public class Post1_13 { 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 60f9a19c..9d2f1cae 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java @@ -2,7 +2,6 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.AbstractHolograms; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; @@ -12,6 +11,7 @@ import fr.skytasul.quests.api.rewards.RewardCreator; 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.factions.FactionRequirement; import fr.skytasul.quests.integrations.jobs.JobLevelRequirement; import fr.skytasul.quests.integrations.maps.BQBlueMap; diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java index 62ffb708..a26953f4 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/factions/FactionRequirement.java @@ -9,7 +9,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import com.massivecraft.factions.FactionsIndex; import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.FactionColl; @@ -22,6 +21,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; import fr.skytasul.quests.api.requirements.AbstractRequirement; +import fr.skytasul.quests.api.utils.XMaterial; public class FactionRequirement extends AbstractRequirement { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQAdvancedSpawners.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQAdvancedSpawners.java index 23d71281..b3c2434a 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQAdvancedSpawners.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQAdvancedSpawners.java @@ -7,11 +7,11 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; 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.XMaterial; import gcspawners.AdvancedEntityDeathEvent; public class BQAdvancedSpawners implements MobFactory<String>, Listener { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQBoss.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQBoss.java index 9c43a11e..cf852e7d 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQBoss.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/BQBoss.java @@ -15,13 +15,13 @@ import org.mineacademy.boss.api.BossAPI; import org.mineacademy.boss.api.event.BossDeathEvent; import org.mineacademy.boss.model.Boss; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.PagedGUI; 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.Utils; +import fr.skytasul.quests.api.utils.XMaterial; public class BQBoss implements MobFactory<Boss>, Listener { 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 985c1f5f..682a3a5c 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 @@ -8,11 +8,11 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; 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; public class BQLevelledMobs implements LeveledMobFactory<EntityType> { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java index 1f504308..8ce1d52b 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java @@ -11,11 +11,11 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.CancellableEditor; 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.XMaterial; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.NPCDeathEvent; import net.citizensnpcs.api.event.NPCRightClickEvent; diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs.java index 5ca5580d..2948500d 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs.java @@ -11,7 +11,6 @@ import org.bukkit.event.Listener; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.PagedGUI; @@ -20,6 +19,7 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; import io.lumine.xikage.mythicmobs.mobs.MythicMob; import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderString; diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs5.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs5.java index 2444d958..7365b6c0 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs5.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/MythicMobs5.java @@ -12,7 +12,6 @@ import org.bukkit.event.Listener; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.PagedGUI; @@ -21,6 +20,7 @@ import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; +import fr.skytasul.quests.api.utils.XMaterial; import io.lumine.mythic.api.mobs.MythicMob; import io.lumine.mythic.api.skills.placeholders.PlaceholderString; import io.lumine.mythic.bukkit.MythicBukkit; diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java index 9d2c9175..2912e068 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java @@ -8,7 +8,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.WorldParser; import fr.skytasul.quests.api.gui.AbstractGui; @@ -17,6 +16,7 @@ import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.XMaterial; public class PermissionGUI extends AbstractGui { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java index 5824f014..7952d0c5 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionListGUI.java @@ -6,10 +6,10 @@ import org.bukkit.DyeColor; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.templates.ListGUI; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.XMaterial; public class PermissionListGUI extends ListGUI<Permission> { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/BQWorldGuard.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/BQWorldGuard.java index 9a8ddcdd..f07658ed 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/BQWorldGuard.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/BQWorldGuard.java @@ -6,7 +6,6 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import com.cryptomorin.xseries.XMaterial; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -18,6 +17,7 @@ import fr.skytasul.quests.api.requirements.RequirementCreator; import fr.skytasul.quests.api.stages.StageType; import fr.skytasul.quests.api.utils.MissingDependencyException; +import fr.skytasul.quests.api.utils.XMaterial; public class BQWorldGuard { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java index 1d6a8b3b..0c1dea2e 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java @@ -9,7 +9,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerMoveEvent; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -27,6 +26,7 @@ import fr.skytasul.quests.api.stages.types.Locatable; import fr.skytasul.quests.api.stages.types.Locatable.LocatableType; import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; +import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; From 6659099b5babfedc95d56eb66995e5b8eb38c8ae Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 24 Aug 2023 15:31:26 +0200 Subject: [PATCH 39/95] :bug: Fixed weird generics --- .../api/objects/QuestObjectCreator.java | 16 +++---- .../skytasul/quests/api/stages/StageType.java | 44 +++++++++---------- .../options/StageOptionAutoRegister.java | 3 +- .../stages/options/StageOptionCreator.java | 20 +++++++++ .../skytasul/quests/DefaultQuestFeatures.java | 14 +++--- .../options/StageOptionProgressBar.java | 16 +++---- 6 files changed, 65 insertions(+), 48 deletions(-) create mode 100755 api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionCreator.java diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java index 2243c829..8ac223d0 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObjectCreator.java @@ -5,12 +5,12 @@ import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.serializable.SerializableCreator; -public class QuestObjectCreator<T extends QuestObject> extends SerializableCreator<T> { - +public abstract class QuestObjectCreator<T extends QuestObject> extends SerializableCreator<T> { + private final @NotNull ItemStack item; private final boolean multiple; private @NotNull QuestObjectLocation @NotNull [] allowedLocations; - + /** * @param id unique identifier for the object * @param clazz Class extending {@link T} @@ -21,7 +21,7 @@ public QuestObjectCreator(@NotNull String id, @NotNull Class<? extends T> clazz, @NotNull Supplier<@NotNull T> newObjectSupplier) { this(id, clazz, item, newObjectSupplier, true); } - + /** * @param id unique identifier for the object * @param clazz Class extending {@link T} @@ -39,15 +39,15 @@ public QuestObjectCreator(@NotNull String id, @NotNull Class<? extends T> clazz, this.multiple = multiple; this.allowedLocations = allowedLocations; } - + public @NotNull ItemStack getItem() { return item; } - + public boolean canBeMultiple() { return multiple; } - + public boolean isAllowed(@NotNull QuestObjectLocation location) { if (allowedLocations.length == 0) return true; for (QuestObjectLocation allowed : allowedLocations) { @@ -55,5 +55,5 @@ public boolean isAllowed(@NotNull QuestObjectLocation location) { } return false; } - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java index b6e5d884..fe10fc80 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageType.java @@ -3,29 +3,29 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.serializable.SerializableRegistry; import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.options.StageOption; +import fr.skytasul.quests.api.stages.options.StageOptionCreator; import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class StageType<T extends AbstractStage> implements HasPlaceholders { - + private final @NotNull String id; private final @NotNull Class<T> clazz; private final @NotNull String name; private final @NotNull StageLoader<T> loader; private final @NotNull ItemStack item; private final @NotNull StageCreationSupplier<T> creationSupplier; - - private final @NotNull SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> optionsRegistry; + + private final @NotNull SerializableRegistry<StageOption<T>, StageOptionCreator<T>> optionsRegistry; private @NotNull PlaceholderRegistry placeholders; - + /** * Creates a stage type. - * + * * @param id unique string id for this stage * @param clazz class of this stage * @param name proper name of this stage @@ -41,38 +41,38 @@ public StageType(@NotNull String id, @NotNull Class<T> clazz, @NotNull String na this.item = item; this.loader = loader; this.creationSupplier = creationSupplier; - + this.optionsRegistry = new SerializableRegistry<>("stage-options-" + id); } - + public @NotNull String getID() { return id; } - + public @NotNull Class<T> getStageClass() { return clazz; } - + public @NotNull String getName() { return name; } - + public @NotNull StageLoader<T> getLoader() { return loader; } - + public @NotNull ItemStack getItem() { return item; } - + public @NotNull StageCreationSupplier<T> getCreationSupplier() { return creationSupplier; } - - public @NotNull SerializableRegistry<StageOption<T>, SerializableCreator<StageOption<T>>> getOptionsRegistry() { + + public @NotNull SerializableRegistry<StageOption<T>, StageOptionCreator<T>> getOptionsRegistry() { return optionsRegistry; } - + @Override public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { return PlaceholderRegistry.of("stage_type", name, "stage_type_id", id); @@ -80,18 +80,18 @@ public StageType(@NotNull String id, @NotNull Class<T> clazz, @NotNull String na @FunctionalInterface public static interface StageCreationSupplier<T extends AbstractStage> { - + @NotNull StageCreation<T> supply(@NotNull StageCreationContext<T> context); - + } - + @FunctionalInterface public static interface StageLoader<T extends AbstractStage> { - + @NotNull T supply(@NotNull ConfigurationSection section, @NotNull StageController controller); - + } - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java index d389217c..c3bf51e3 100755 --- a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionAutoRegister.java @@ -1,7 +1,6 @@ package fr.skytasul.quests.api.stages.options; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageType; @@ -9,6 +8,6 @@ public interface StageOptionAutoRegister { boolean appliesTo(@NotNull StageType<?> type); - <T extends AbstractStage> SerializableCreator<StageOption<T>> createOptionCreator(@NotNull StageType<T> type); + <T extends AbstractStage> StageOptionCreator<T> createOptionCreator(@NotNull StageType<T> type); } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionCreator.java b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionCreator.java new file mode 100755 index 00000000..0df971b1 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/stages/options/StageOptionCreator.java @@ -0,0 +1,20 @@ +package fr.skytasul.quests.api.stages.options; + +import java.util.function.Supplier; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.serializable.SerializableCreator; +import fr.skytasul.quests.api.stages.AbstractStage; + +public class StageOptionCreator<T extends AbstractStage> extends SerializableCreator<StageOption<T>> { + + public StageOptionCreator(@NotNull String id, @NotNull Class<? extends StageOption<T>> clazz, + @NotNull Supplier<@NotNull StageOption<T>> newObjectSupplier) { + super(id, clazz, newObjectSupplier); + } + + public static <T extends AbstractStage, O extends StageOption<T>> StageOptionCreator<T> create(@NotNull String id, + @NotNull Class<O> optionClass, @NotNull Supplier<@NotNull O> supplier) { + return new StageOptionCreator<>(id, optionClass, (@NotNull Supplier<@NotNull StageOption<T>>) supplier); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index b3c9e705..99792565 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -18,12 +18,11 @@ import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.rewards.RewardCreator; import fr.skytasul.quests.api.rewards.RewardList; -import fr.skytasul.quests.api.serializable.SerializableCreator; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageType; import fr.skytasul.quests.api.stages.StageTypeRegistry; -import fr.skytasul.quests.api.stages.options.StageOption; import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; +import fr.skytasul.quests.api.stages.options.StageOptionCreator; import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.api.utils.XMaterial; @@ -117,17 +116,16 @@ public boolean appliesTo(@NotNull StageType<?> type) { return HasProgress.class.isAssignableFrom(type.getStageClass()); } + @SuppressWarnings("rawtypes") @Override - public <T extends AbstractStage> SerializableCreator<StageOption<T>> createOptionCreator( - @NotNull StageType<T> type) { - return createCreator((StageType) type); + public <T extends AbstractStage> StageOptionCreator<T> createOptionCreator(@NotNull StageType<T> type) { + return createOptionCreatorInternal((@NotNull StageType) type); // NOSONAR magic } - public <T extends AbstractStage & HasProgress> SerializableCreator<StageOptionProgressBar<T>> createCreator( + private <T extends AbstractStage & HasProgress> StageOptionCreator<T> createOptionCreatorInternal( @NotNull StageType<T> type) { - return new SerializableCreator<>("progressbar", StageOptionProgressBar.class, + return StageOptionCreator.create("progressbar", StageOptionProgressBar.class, () -> new StageOptionProgressBar<>(type.getStageClass())); - } }); diff --git a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java index 2d580a99..cf7ab702 100755 --- a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java +++ b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java @@ -26,7 +26,7 @@ import fr.skytasul.quests.api.utils.progress.ProgressBarConfig; import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; -public class StageOptionProgressBar<T extends AbstractStage> extends StageOption<T> { +public class StageOptionProgressBar<T extends AbstractStage & HasProgress> extends StageOption<T> { private final @NotNull Map<Player, ProgressBar> bars = new HashMap<>(); @@ -62,7 +62,7 @@ public void load(@NotNull ConfigurationSection section) { @Override public void stageStart(PlayerAccount acc, StageController stage) { if (acc.isCurrent()) - createBar(acc.getPlayer(), stage.getStage()); + createBar(acc.getPlayer(), (T) stage.getStage()); } @Override @@ -73,7 +73,7 @@ public void stageEnd(PlayerAccount acc, StageController stage) { @Override public void stageJoin(Player p, StageController stage) { - createBar(p, stage.getStage()); + createBar(p, (T) stage.getStage()); } @Override @@ -102,14 +102,14 @@ public boolean areBarsEnabled() { return getProgressConfig().areBossBarsEnabled() && QuestsAPI.getAPI().hasBossBarManager(); } - protected void createBar(@NotNull Player p, AbstractStage stage) { + protected void createBar(@NotNull Player p, T progress) { if (areBarsEnabled()) { if (bars.containsKey(p)) { // NOSONAR Map#computeIfAbsent cannot be used here as we should log the issue QuestsPlugin.getPlugin().getLoggerExpanded() .warning("Trying to create an already existing bossbar for player " + p.getName()); return; } - bars.put(p, new ProgressBar<>(p, (AbstractStage & HasProgress) stage)); + bars.put(p, new ProgressBar(p, progress)); } } @@ -118,16 +118,16 @@ protected void removeBar(@NotNull Player p) { bars.remove(p).remove(); } - class ProgressBar<P extends AbstractStage & HasProgress> { + class ProgressBar { private final PlayerAccount acc; private final BQBossBar bar; - private final P progress; + private final T progress; private final int totalAmount; private final PlaceholderRegistry placeholders; private BukkitTask timer; - public ProgressBar(Player p, P progress) { + public ProgressBar(Player p, T progress) { this.progress = progress; this.acc = PlayersManager.getPlayerAccount(p); this.totalAmount = progress.getTotalAmount(); From 7c5dc4f740292ee88cd513869d05f580f36e2035 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 24 Aug 2023 18:37:16 +0200 Subject: [PATCH 40/95] :art: Changed various code aspects --- api/dependency-reduced-pom.xml | 21 +++ api/pom.xml | 25 +++- .../quests/api/events/DialogSendEvent.java | 39 ++--- .../api/events/DialogSendMessageEvent.java | 56 +++----- .../quests/api/localization/Locale.java | 26 ++-- .../quests/api/npcs/dialogs/DialogRunner.java | 9 ++ .../quests/api/options/QuestOption.java | 68 ++++----- .../quests/api/players/PlayerAccount.java | 1 + core/pom.xml | 14 -- .../QuestsConfigurationImplementation.java | 134 ++++++++---------- .../gui/creation/stages/StageRunnable.java | 27 ---- .../npcs/BqNpcManagerImplementation.java | 22 ++- .../players/PlayerAccountImplementation.java | 15 +- .../PlayerQuestDatasImplementation.java | 40 +++--- .../requirements/PermissionsRequirement.java | 24 ++-- .../quests/stages/StageInteractLocation.java | 27 ++-- .../BranchesManagerImplementation.java | 48 +++---- .../structure/QuestBranchImplementation.java | 62 ++++---- .../types/DialogRunnerImplementation.java | 89 ++++++------ .../integrations/IntegrationsLoader.java | 12 +- 20 files changed, 353 insertions(+), 406 deletions(-) delete mode 100644 core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageRunnable.java diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml index 6b97e5d6..b3ebabeb 100755 --- a/api/dependency-reduced-pom.xml +++ b/api/dependency-reduced-pom.xml @@ -41,6 +41,14 @@ </includes> </filter> </filters> + <shadeSourcesContent>true</shadeSourcesContent> + </configuration> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.0</version> + <configuration> + <parameters>true</parameters> </configuration> </plugin> <plugin> @@ -50,6 +58,19 @@ <skip>false</skip> </configuration> </plugin> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.1</version> + <executions> + <execution> + <id>attach-sources</id> + <phase>verify</phase> + <goals> + <goal>jar-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> <repositories> diff --git a/api/pom.xml b/api/pom.xml index 9a604c23..f032cbe9 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -21,7 +21,8 @@ <relocations> <relocation> <pattern>revxrsal.commands</pattern> - <shadedPattern>fr.skytasul.quests.api.commands.revxrsal</shadedPattern> + <shadedPattern> + fr.skytasul.quests.api.commands.revxrsal</shadedPattern> </relocation> <relocation> <pattern>com.cryptomorin.xseries</pattern> @@ -38,6 +39,7 @@ </includes> </filter> </filters> + <shadeSourcesContent>true</shadeSourcesContent> </configuration> <executions> <execution> @@ -48,6 +50,13 @@ </execution> </executions> </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.0</version> + <configuration> + <parameters>true</parameters> + </configuration> + </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> <version>3.4.1</version> @@ -55,6 +64,20 @@ <skip>false</skip> </configuration> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.1</version> + <executions> + <execution> + <id>attach-sources</id> + <phase>verify</phase> + <goals> + <goal>jar-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> diff --git a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java index 5130895c..914afcb6 100644 --- a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendEvent.java @@ -2,27 +2,20 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.npcs.BqNpc; -import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; -public class DialogSendEvent extends Event implements Cancellable { +public class DialogSendEvent extends PlayerEvent implements Cancellable { private boolean cancelled = false; - private final @NotNull Dialog dialog; - private final @NotNull BqNpc npc; - private final @NotNull Player player; - private final @NotNull Runnable runnable; + private final @NotNull DialogRunner dialog; - public DialogSendEvent(@NotNull Dialog dialog, @NotNull BqNpc npc, @NotNull Player player, @NotNull Runnable runnable) { - this.dialog = dialog; - this.npc = npc; - this.player = player; - this.runnable = runnable; - // TODO change this "runnable" thing + public DialogSendEvent(@NotNull Player who, @NotNull DialogRunner dialog) { + super(who); + this.dialog = dialog; } @Override @@ -35,21 +28,9 @@ public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } - public Dialog getDialog() { - return dialog; - } - - public BqNpc getNPC() { - return npc; - } - - public Player getPlayer(){ - return player; - } - - public Runnable getRunnable(){ - return runnable; - } + public @NotNull DialogRunner getDialog() { + return dialog; + } @Override public HandlerList getHandlers() { diff --git a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java index a666fc19..a3a58233 100644 --- a/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/events/DialogSendMessageEvent.java @@ -2,64 +2,52 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.npcs.BqNpc; -import fr.skytasul.quests.api.npcs.dialogs.Dialog; +import fr.skytasul.quests.api.npcs.dialogs.DialogRunner; import fr.skytasul.quests.api.npcs.dialogs.Message; -public class DialogSendMessageEvent extends Event implements Cancellable { - +public class DialogSendMessageEvent extends PlayerEvent implements Cancellable { + private boolean cancelled = false; - - private final @NotNull Dialog dialog; - private final @NotNull Message msg; - private final @NotNull BqNpc npc; - private final @NotNull Player player; - - public DialogSendMessageEvent(@NotNull Dialog dialog, @NotNull Message msg, @NotNull BqNpc npc, @NotNull Player player) { + + private final @NotNull DialogRunner dialog; + private final @NotNull Message message; + + public DialogSendMessageEvent(@NotNull Player who, @NotNull DialogRunner dialog, @NotNull Message message) { + super(who); this.dialog = dialog; - this.msg = msg; - this.npc = npc; - this.player = player; + this.message = message; } - + @Override public boolean isCancelled() { return cancelled; } - + @Override public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } - - public @NotNull Dialog getDialog() { + + public DialogRunner getDialog() { return dialog; } - - public @NotNull Message getMessage() { - return msg; - } - - public @NotNull BqNpc getNPC() { - return npc; - } - - public @NotNull Player getPlayer() { - return player; + + public Message getMessage() { + return message; } - + @Override public HandlerList getHandlers() { return handlers; } - + public static HandlerList getHandlerList() { return handlers; } - + private static final HandlerList handlers = new HandlerList(); - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java index 47e63d08..6643df08 100644 --- a/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java +++ b/api/src/main/java/fr/skytasul/quests/api/localization/Locale.java @@ -23,18 +23,18 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public interface Locale { - + @NotNull String getPath(); - + @NotNull String getValue(); - + @NotNull MessageType getType(); void setValue(@NotNull String value); - + default @NotNull String format(@Nullable HasPlaceholders placeholdersHolder) { return MessageUtils.format(getValue(), placeholdersHolder == null ? null : placeholdersHolder.getPlaceholdersRegistry()); @@ -43,12 +43,12 @@ public interface Locale { default @NotNull String format(@NotNull HasPlaceholders @NotNull... placeholdersHolders) { return format(PlaceholderRegistry.combine(placeholdersHolders)); } - + default @NotNull String quickFormat(@NotNull String key1, @Nullable Object value1) { // for performance reason: no need to allocate a new placeholder registry with a new placeholder String replacement = Objects.toString(value1); return getValue() - .replace("{0}", replacement) // TODO remove, migration + .replace("{0}", replacement) // TODO migration 1.0 .replace("{" + key1 + "}", replacement); } @@ -79,20 +79,20 @@ public static void loadStrings(@NotNull Locale @NotNull [] locales, @NotNull Yam l.setValue(ChatColorUtils.translateHexColorCodes(ChatColor.translateAlternateColorCodes('&', value == null ? "§cunknown string" : value))); } } - + public static YamlConfiguration loadLang(@NotNull Plugin plugin, @NotNull Locale @NotNull [] locales, @NotNull String loadedLanguage) throws IOException, URISyntaxException { long lastMillis = System.currentTimeMillis(); - + Utils.walkResources(plugin.getClass(), "/locales", 1, path -> { String localeFileName = path.getFileName().toString(); if (!localeFileName.toLowerCase().endsWith(".yml")) return; - + if (!Files.exists(plugin.getDataFolder().toPath().resolve("locales").resolve(localeFileName))) { plugin.saveResource("locales/" + localeFileName, false); } }); - + String language = "locales/" + loadedLanguage + ".yml"; File file = new File(plugin.getDataFolder(), language); InputStream res = plugin.getResource(language); @@ -118,14 +118,14 @@ public static YamlConfiguration loadLang(@NotNull Plugin plugin, @NotNull Locale } } loadStrings(locales, YamlConfiguration.loadConfiguration(new InputStreamReader(plugin.getResource("locales/en_US.yml"), StandardCharsets.UTF_8)), conf); - + if (changes) { plugin.getLogger().info("Copied new strings into " + language + " language file."); conf.save(file); // if there has been changes before, save the edited file } - + plugin.getLogger().info("Loaded language " + loadedLanguage + " (" + (((double) System.currentTimeMillis() - lastMillis) / 1000D) + "s)!"); return conf; } - + } \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java index 60d798d3..dd062f94 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/DialogRunner.java @@ -3,6 +3,7 @@ import java.util.function.Consumer; import java.util.function.Predicate; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; public interface DialogRunner { @@ -37,6 +38,14 @@ public interface DialogRunner { boolean removePlayer(Player player); + /** + * Forces the end of the dialog, toggles the end actions and removes the player from this dialog + * runner. + * + * @param player player to end the dialog for + */ + void forceFinish(@NotNull Player player); + public enum DialogNextReason { NPC_CLICK, AUTO_TIME, COMMAND, PLUGIN; } diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index 0cbb81e6..9d9ec801 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -19,124 +19,124 @@ @AutoRegistered public abstract class QuestOption<T> implements Cloneable { - + private final @NotNull QuestOptionCreator<T, QuestOption<T>> creator; - + private @Nullable T value; private @Nullable Quest attachedQuest; - + private final @NotNull Class<? extends QuestOption<?>> @NotNull [] requiredQuestOptions; private @Nullable Runnable valueUpdateListener; - + protected QuestOption(@NotNull Class<? extends QuestOption<?>> @NotNull... requiredQuestOptions) { this.requiredQuestOptions = requiredQuestOptions; - + this.creator = (QuestOptionCreator<T, QuestOption<T>>) QuestOptionCreator.creators.get(getClass()); if (creator == null) throw new IllegalArgumentException(getClass().getName() + " has not been registered as a quest option via the API."); - + setValue(creator.defaultValue == null ? null : cloneValue(creator.defaultValue)); } - + public @NotNull QuestOptionCreator<T, QuestOption<T>> getOptionCreator() { return creator; } - + public final boolean hasCustomValue() { return !Objects.equals(this.value, creator.defaultValue); } - + public final @Nullable T getValue() { return value; } - + public void setValue(@Nullable T value) { this.value = value; valueUpdated(); } - + public void resetValue() { setValue(creator.defaultValue); } - + protected void valueUpdated() { if (valueUpdateListener != null) valueUpdateListener.run(); } - + public void setValueUpdaterListener(@Nullable Runnable listener) { this.valueUpdateListener = listener; } - + public @NotNull Class<? extends QuestOption<?>> @NotNull [] getRequiredQuestOptions() { return requiredQuestOptions; } - + public @Nullable Quest getAttachedQuest() { return attachedQuest; } - + public void attach(@NotNull Quest quest) { Validate.notNull(quest, "Attached quest cannot be null"); if (this.attachedQuest != null) throw new IllegalStateException("This option is already attached to " + attachedQuest.getId()); this.attachedQuest = quest; - + if (this instanceof Listener) { Bukkit.getPluginManager().registerEvents((Listener) this, QuestsPlugin.getPlugin()); } - + if (this instanceof QuestDescriptionProvider) { quest.getDescriptions().add((QuestDescriptionProvider) this); } } - + public void detach() { Quest previous = this.attachedQuest; this.attachedQuest = null; - + if (this instanceof Listener) { HandlerList.unregisterAll((Listener) this); } - + if (previous != null && this instanceof QuestDescriptionProvider) { previous.getDescriptions().remove(this); } } - + public abstract @Nullable Object save(); - + public abstract void load(@NotNull ConfigurationSection config, @NotNull String key); - + public abstract @Nullable T cloneValue(@Nullable T value); - + @Override public @NotNull QuestOption<T> clone() { QuestOption<T> clone = creator.optionSupplier.get(); clone.setValue(value == null ? null : cloneValue(value)); return clone; } - + public boolean shouldDisplay(@NotNull OptionSet options) { return true; } - + public void onDependenciesUpdated(@NotNull OptionSet options/* , @NotNull ItemStack item TODO wtf */) {} - + public abstract @NotNull ItemStack getItemStack(@NotNull OptionSet options); - + public abstract void click(@NotNull QuestCreationGuiClickEvent event); - + public @NotNull String formatValue(@Nullable String valueString) { return formatNullableValue(valueString, !hasCustomValue()); } - + public static @Nullable String formatDescription(@Nullable String description) { return description == null ? null : "§8> §7" + description; } - + public static @NotNull String formatNullableValue(@Nullable Object value) { return formatNullableValue(value, false); } - + public static @NotNull String formatNullableValue(@Nullable Object value, @NotNull Object defaultValue) { return formatNullableValue(value == null ? defaultValue : value, value == null); } @@ -148,5 +148,5 @@ public void onDependenciesUpdated(@NotNull OptionSet options/* , @NotNull ItemSt valueString += " " + Lang.defaultValue.toString(); return valueString; } - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java b/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java index 99adab44..776ddf2d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java +++ b/api/src/main/java/fr/skytasul/quests/api/players/PlayerAccount.java @@ -13,6 +13,7 @@ import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; public interface PlayerAccount extends HasPlaceholders { + /** * @return if this account is currently used by the player (if true, {@link #getPlayer()} cannot * return a null player) diff --git a/core/pom.xml b/core/pom.xml index 52f3d890..b8a71a0f 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -64,20 +64,6 @@ </execution> </executions> </plugin> - <plugin> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.0</version> - <configuration> - <parameters>true</parameters> - </configuration> - </plugin> - <plugin> - <artifactId>maven-javadoc-plugin</artifactId> - <version>3.4.1</version> - <configuration> - <skip>false</skip> - </configuration> - </plugin> </plugins> </build> diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 7b7b2da5..60cc2c6a 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -1,16 +1,8 @@ package fr.skytasul.quests; -import java.util.Arrays; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; -import org.bukkit.Bukkit; -import org.bukkit.Color; -import org.bukkit.FireworkEffect; -import org.bukkit.Particle; -import org.bukkit.Sound; +import org.bukkit.*; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; @@ -23,11 +15,7 @@ import fr.skytasul.quests.api.npcs.NpcClickType; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescription; -import fr.skytasul.quests.api.utils.MinecraftNames; -import fr.skytasul.quests.api.utils.MinecraftVersion; -import fr.skytasul.quests.api.utils.PlayerListCategory; -import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.XMaterial; +import fr.skytasul.quests.api.utils.*; import fr.skytasul.quests.players.BqAccountsHook; import fr.skytasul.quests.utils.ParticleEffect; import fr.skytasul.quests.utils.ParticleEffect.ParticleShape; @@ -49,26 +37,26 @@ public static QuestsConfigurationImplementation getConfiguration() { private ParticleEffect particleStart; private ParticleEffect particleTalk; private ParticleEffect particleNext; - + private ItemStack holoLaunchItem = null; private ItemStack holoLaunchNoItem = null; private ItemStack holoTalkItem = null; - + private FireworkMeta defaultFirework = null; boolean backups = true; - + boolean saveCycleMessage = true; int saveCycle = 15; - int firstQuestID = -1; // changed in 0.19, TODO - + int firstQuestID = -1; // TODO migration 0.19 + private final FileConfiguration config; private QuestsConfig quests; private DialogsConfig dialogs; private QuestsMenuConfig menu; private StageDescriptionConfig stageDescription; private QuestDescriptionConfig questDescription; - + QuestsConfigurationImplementation(FileConfiguration config) { this.config = config; @@ -78,7 +66,7 @@ public static QuestsConfigurationImplementation getConfiguration() { stageDescription = new StageDescriptionConfig(config.getConfigurationSection("stage description")); questDescription = new QuestDescriptionConfig(config.getConfigurationSection("questDescription")); } - + boolean update() { boolean result = false; result |= dialogs.update(); @@ -86,11 +74,11 @@ boolean update() { result |= stageDescription.update(); return result; } - + void init() { backups = config.getBoolean("backups", true); if (!backups) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Backups are disabled due to the presence of \"backups: false\" in config.yml."); - + minecraftTranslationsFile = config.getString("minecraftTranslationsFile"); if (isMinecraftTranslationsEnabled()) initializeTranslations(); @@ -113,7 +101,7 @@ void init() { QuestsPlugin.getPlugin().getLoggerExpanded().info("AccountsHook is now managing player datas for quests !"); } usePlayerBlockTracker = config.getBoolean("usePlayerBlockTracker"); - + if (MinecraftVersion.MAJOR >= 9) { particleStart = loadParticles("start", new ParticleEffect(Particle.REDSTONE, ParticleShape.POINT, Color.YELLOW)); particleTalk = loadParticles("talk", new ParticleEffect(Particle.VILLAGER_HAPPY, ParticleShape.BAR, null)); @@ -123,7 +111,7 @@ void init() { holoLaunchItem = loadHologram("launchItem"); holoLaunchNoItem = loadHologram("nolaunchItem"); holoTalkItem = loadHologram("talkItem"); - + if (BeautyQuests.getInstance().getDataFile().contains("firework")) { defaultFirework = BeautyQuests.getInstance().getDataFile().getSerializable("firework", FireworkMeta.class); }else { @@ -133,7 +121,7 @@ void init() { defaultFirework = fm; } } - + private void initializeTranslations() { if (MinecraftVersion.MAJOR >= 13) { String fileName = minecraftTranslationsFile; @@ -172,14 +160,14 @@ private ParticleEffect loadParticles(String name, ParticleEffect defaultParticle } return particle; } - + private ItemStack loadHologram(String name) { if (BeautyQuests.getInstance().getDataFile().contains(name)){ return ItemStack.deserialize(BeautyQuests.getInstance().getDataFile().getConfigurationSection(name).getValues(false)); } return null; } - + private String loadSound(String key) { String sound = config.getString(key); try { @@ -190,7 +178,7 @@ private String loadSound(String key) { } return sound; } - + private boolean migrateEntry(ConfigurationSection oldConfig, String oldKey, ConfigurationSection newConfig, String newKey) { if (oldConfig.contains(oldKey)) { @@ -233,39 +221,39 @@ public FileConfiguration getConfig() { public String getPrefix() { return (enablePrefix) ? Lang.Prefix.toString() : "§6"; } - + public boolean isTextHologramDisabled() { return disableTextHologram; } - + public boolean showStartParticles() { return particleStart != null; } - + public ParticleEffect getParticleStart() { return particleStart; } - + public boolean showTalkParticles() { return particleTalk != null; } - + public ParticleEffect getParticleTalk() { return particleTalk; } - + public boolean showNextParticles() { return particleNext != null; } - + public ParticleEffect getParticleNext() { return particleNext; } - + public double getHologramsHeight() { return hologramsHeight; } - + public boolean isCustomHologramNameShown() { return showCustomHologramName; } @@ -281,27 +269,27 @@ public ItemStack getHoloLaunchNoItem() { public ItemStack getHoloTalkItem() { return holoTalkItem; } - + public FireworkMeta getDefaultFirework() { return defaultFirework; } - + public boolean hookAccounts() { return hookAcounts && InternalIntegrations.AccountsHook.isEnabled(); } - + public boolean usePlayerBlockTracker() { return usePlayerBlockTracker && InternalIntegrations.PlayerBlockTracker.isEnabled(); } - + public boolean isMinecraftTranslationsEnabled() { return minecraftTranslationsFile != null && !minecraftTranslationsFile.isEmpty(); } - + public QuestDescription getQuestDescription() { return questDescription; } - + public class QuestsConfig implements QuestsConfiguration.Quests { private int defaultTimer = 5; @@ -461,7 +449,7 @@ public boolean stageEndRewardsMessage() { } public class DialogsConfig implements QuestsConfiguration.Dialogs { - + private boolean inActionBar = false; private int defaultTime = 100; private boolean defaultSkippable = true; @@ -469,16 +457,16 @@ public class DialogsConfig implements QuestsConfiguration.Dialogs { private boolean history = true; private int maxMessagesPerHistoryPage = -1; private int maxDistance = 15, maxDistanceSquared = 15 * 15; - + private String defaultPlayerSound = null; private String defaultNPCSound = null; - + private ConfigurationSection config; - + private DialogsConfig(ConfigurationSection config) { this.config = config; } - + private boolean update() { boolean result = false; if (config.getParent() != null) { @@ -489,7 +477,7 @@ private boolean update() { } return result; } - + private void init() { inActionBar = MinecraftVersion.MAJOR > 8 && config.getBoolean("inActionBar"); defaultTime = config.getInt("defaultTime"); @@ -499,36 +487,36 @@ private void init() { maxMessagesPerHistoryPage = config.getInt("max messages per history page"); maxDistance = config.getInt("maxDistance"); maxDistanceSquared = maxDistance <= 0 ? 0 : (maxDistance * maxDistance); - + defaultPlayerSound = config.getString("defaultPlayerSound"); defaultNPCSound = config.getString("defaultNPCSound"); } - + @Override public boolean sendInActionBar() { return inActionBar; } - + @Override public int getDefaultTime() { return defaultTime; } - + @Override public boolean isSkippableByDefault() { return defaultSkippable; } - + @Override public boolean isClickDisabled() { return disableClick; } - + @Override public boolean isHistoryEnabled() { return history; } - + @Override public int getMaxMessagesPerHistoryPage() { return maxMessagesPerHistoryPage; @@ -538,36 +526,36 @@ public int getMaxMessagesPerHistoryPage() { public int getMaxDistance() { return maxDistance; } - + @Override public int getMaxDistanceSquared() { return maxDistanceSquared; } - + @Override public String getDefaultPlayerSound() { return defaultPlayerSound; } - + @Override public String getDefaultNPCSound() { return defaultNPCSound; } - + } - + public class QuestsMenuConfig implements QuestsConfiguration.QuestsMenu { - + private Set<PlayerListCategory> tabs; private boolean openNotStartedTabWhenEmpty = true; private boolean allowPlayerCancelQuest = true; - + private ConfigurationSection config; - + private QuestsMenuConfig(ConfigurationSection config) { this.config = config; } - + private boolean update() { boolean result = false; if (config.getParent() != null) { @@ -576,7 +564,7 @@ private boolean update() { } return result; } - + private void init() { tabs = config.getStringList("enabledTabs").stream().map(PlayerListCategory::fromString).collect(Collectors.toSet()); if (tabs.isEmpty()) { @@ -586,24 +574,24 @@ private void init() { openNotStartedTabWhenEmpty = config.getBoolean("openNotStartedTabWhenEmpty"); allowPlayerCancelQuest = config.getBoolean("allowPlayerCancelQuest"); } - + @Override public boolean isNotStartedTabOpenedWhenEmpty() { return openNotStartedTabWhenEmpty; } - + @Override public boolean allowPlayerCancelQuest() { return allowPlayerCancelQuest; } - + @Override public Set<PlayerListCategory> getEnabledTabs() { return tabs; } - + } - + public class StageDescriptionConfig implements QuestsConfiguration.StageDescription { private String itemSingleFormat, itemMultipleFormat; diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageRunnable.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageRunnable.java deleted file mode 100644 index 9ad78744..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageRunnable.java +++ /dev/null @@ -1,27 +0,0 @@ -package fr.skytasul.quests.gui.creation.stages; - -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.ItemStack; - -public interface StageRunnable { - - /** - * Called when the item is clicked - * @param p player who click on the item - * @param item item clicked - */ - public abstract void run(Player p, ItemStack item); - - public interface StageRunnableClick extends StageRunnable { - - @Override - default void run(Player p, ItemStack item) { - run(p, item, ClickType.RIGHT); - } - - public abstract void run(Player p, ItemStack item, ClickType click); - - } - -} 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 785c85de..6308ebcd 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -16,21 +16,17 @@ import com.google.common.collect.HashBiMap; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; -import fr.skytasul.quests.api.npcs.BqInternalNpc; -import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; +import fr.skytasul.quests.api.npcs.*; import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; -import fr.skytasul.quests.api.npcs.BqNpc; -import fr.skytasul.quests.api.npcs.BqNpcManager; -import fr.skytasul.quests.api.npcs.NpcClickType; import fr.skytasul.quests.utils.QuestUtils; public class BqNpcManagerImplementation implements BqNpcManager { - + private static final String SEPARATOR = "#"; private final BiMap<String, BqInternalNpcFactory> internalFactories = HashBiMap.create(); private final Map<String, BqNpcImplementation> npcs = new HashMap<>(); - + private BqInternalNpcFactory last = null; public @NotNull String getFactoryKey(@NotNull BqInternalNpcFactory internalFactory) { @@ -95,7 +91,7 @@ public boolean isNPC(@NotNull Entity entity) { npcs.put(npc.getId(), npc); return npc; } - + @Override public @Nullable BqNpcImplementation getById(String id) { return npcs.computeIfAbsent(id, this::registerNPC); @@ -110,7 +106,7 @@ private BqNpcImplementation registerNPC(String id) { int npcId; int separatorIndex = id.indexOf(SEPARATOR); - if (separatorIndex == -1) { // TODO remove, migration in 1.0 + if (separatorIndex == -1) { // TODO migration 1.0 QuestsPlugin.getPlugin().getLoggerExpanded() .warning("Loading NPC with id " + id + " from a previous version of the plugin."); factory = getMigrationFactory(); @@ -123,7 +119,7 @@ private BqNpcImplementation registerNPC(String id) { return new BqNpcImplementation(new WrappedInternalNpc(factory, npcId)); } - + @Override public void npcRemoved(BqInternalNpcFactory npcFactory, int id) { String npcId = getNpcId(npcFactory, id); @@ -132,7 +128,7 @@ public void npcRemoved(BqInternalNpcFactory npcFactory, int id) { npc.delete("NPC " + npcId + " removed"); npcs.remove(npcId); } - + @Override public void npcClicked(BqInternalNpcFactory npcFactory, @Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click) { @@ -143,7 +139,7 @@ public void npcClicked(BqInternalNpcFactory npcFactory, @Nullable Cancellable ev if (event != null) event.setCancelled(newEvent.isCancelled()); } - + @Override public void reload(BqInternalNpcFactory npcFactory) { npcs.forEach((id, npc) -> { @@ -163,7 +159,7 @@ public void unload() { npcs.values().forEach(BqNpcImplementation::unload); npcs.clear(); } - + class WrappedInternalNpc { private final BqInternalNpcFactory factory; 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 102c6fe5..6b0a1f56 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerAccountImplementation.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.players; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; @@ -40,25 +36,16 @@ protected PlayerAccountImplementation(@NotNull AbstractAccount account, int inde this.index = index; } - /** - * @return if this account is currently used by the player (if true, {@link #getPlayer()} cannot return a null player) - */ @Override public boolean isCurrent() { return abstractAcc.isCurrent(); } - /** - * @return the OfflinePlayer instance attached to this account (no matter if the player is online or not, or if the account is the currently used) - */ @Override public @NotNull OfflinePlayer getOfflinePlayer() { return abstractAcc.getOfflinePlayer(); } - /** - * @return the Player instance who own this account. If the account is not which in use by the player ({@link #isCurrent()}), this will return null. - */ @Override public @Nullable Player getPlayer() { return abstractAcc.getPlayer(); diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java index f0701f69..f5a4865e 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java @@ -23,7 +23,7 @@ public class PlayerQuestDatasImplementation implements PlayerQuestDatas { private int stage; protected Map<String, Object> additionalDatas; protected StringJoiner questFlow = new StringJoiner(";"); - + private Boolean hasDialogsCached = null; public PlayerQuestDatasImplementation(PlayerAccountImplementation acc, int questID) { @@ -47,12 +47,12 @@ public PlayerQuestDatasImplementation(PlayerAccountImplementation acc, int quest if (questFlow != null) this.questFlow.add(questFlow); if (branch != -1 && stage == -1) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Incorrect quest " + questID + " datas for " + acc.debugName()); } - + @Override public Quest getQuest() { return QuestsAPI.getAPI().getQuestsManager().getQuest(questID); } - + @Override public int getQuestID() { return questID; @@ -67,7 +67,7 @@ public boolean isFinished() { public void incrementFinished() { finished++; } - + @Override public int getTimesFinished() { return finished; @@ -102,17 +102,17 @@ public int getStage() { public void setStage(int stage) { this.stage = stage; } - + @Override public boolean hasStarted() { return branch != -1; } - + @Override public boolean isInQuestEnd() { return branch == -2; } - + @Override public void setInQuestEnd() { setBranch(-2); @@ -132,7 +132,7 @@ public void setInEndingStages() { public <T> T getAdditionalData(String key) { return (T) additionalDatas.get(key); } - + @Override public <T> T setAdditionalData(String key, T value) { return (T) (value == null ? additionalDatas.remove(key) : additionalDatas.put(key, value)); @@ -142,33 +142,33 @@ public <T> T setAdditionalData(String key, T value) { public Map<String, Object> getStageDatas(int stage) { return getAdditionalData("stage" + stage); } - + @Override public void setStageDatas(int stage, Map<String, Object> datas) { setAdditionalData("stage" + stage, datas); } - + @Override public long getStartingTime() { return getAdditionalData("starting_time"); } - + @Override public void setStartingTime(long time) { setAdditionalData("starting_time", time == 0 ? null : time); } - + @Override public String getQuestFlow() { return questFlow.toString(); } - + @Override public void addQuestFlow(StageController finished) { questFlow.add(finished.getBranch().getId() + ":" + finished.getFlowId()); hasDialogsCached = null; } - + @Override public void resetQuestFlow() { questFlow = new StringJoiner(";"); @@ -182,11 +182,11 @@ public boolean hasFlowDialogs() { } return hasDialogsCached.booleanValue(); } - + public void questEdited() { hasDialogsCached = null; } - + public Map<String, Object> serialize() { Map<String, Object> map = new HashMap<>(); @@ -203,20 +203,20 @@ public Map<String, Object> serialize() { public static PlayerQuestDatasImplementation deserialize(PlayerAccountImplementation acc, Map<String, Object> map) { PlayerQuestDatasImplementation datas = new PlayerQuestDatasImplementation(acc, (int) map.get("questID")); - if (map.containsKey("finished")) datas.finished = ((boolean) map.get("finished")) ? 1 : 0; // TODO remove, outdated since 0.19 + if (map.containsKey("finished")) datas.finished = ((boolean) map.get("finished")) ? 1 : 0; // TODO migration 0.19 if (map.containsKey("timesFinished")) datas.finished = (int) map.get("timesFinished"); if (map.containsKey("timer")) datas.timer = Utils.parseLong(map.get("timer")); if (map.containsKey("currentBranch")) datas.branch = (int) map.get("currentBranch"); if (map.containsKey("currentStage")) datas.stage = (int) map.get("currentStage"); if (map.containsKey("datas")) datas.additionalDatas = (Map<String, Object>) map.get("datas"); if (map.containsKey("questFlow")) datas.questFlow.add((String) map.get("questFlow")); - - for (int i = 0; i < 5; i++) { // TODO remove ; migration purpose ; added on 0.20 + + for (int i = 0; i < 5; i++) { // TODO migration 0.20 if (map.containsKey("stage" + i + "datas")) { datas.additionalDatas.put("stage" + i, map.get("stage" + i + "datas")); } } - + return datas; } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java index 73776bfc..b0497e3a 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/PermissionsRequirement.java @@ -22,11 +22,11 @@ public class PermissionsRequirement extends AbstractRequirement { private List<Permission> permissions; - + public PermissionsRequirement() { this(null, null, new ArrayList<>()); } - + public PermissionsRequirement(String customDescription, String customReason, List<Permission> permissions) { super(customDescription, customReason); this.permissions = permissions; @@ -51,7 +51,7 @@ protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(Lang.AmountPermissions.format(this)); } - + @Override protected void sendCustomReasonHelpMessage(Player p) { Lang.CHOOSE_PERM_REQUIRED_MESSAGE.send(p); @@ -60,12 +60,12 @@ protected void sendCustomReasonHelpMessage(Player p) { @Override public void itemClick(QuestObjectClickEvent event) { new ListGUI<Permission>(Lang.INVENTORY_PERMISSION_LIST.toString(), DyeColor.PURPLE, permissions) { - + @Override public ItemStack getObjectItemStack(Permission object) { return ItemUtils.item(XMaterial.PAPER, object.toString(), createLoreBuilder(object).toLoreArray()); } - + @Override public void createObject(Function<Permission, ItemStack> callback) { Lang.CHOOSE_PERM_REQUIRED.send(player); @@ -73,7 +73,7 @@ public void createObject(Function<Permission, ItemStack> callback) { callback.apply(Permission.fromString(obj)); }).useStrippedMessage().start(); } - + @Override public void finish(List<Permission> objects) { permissions = objects; @@ -83,26 +83,26 @@ public void finish(List<Permission> objects) { event.reopenGUI(); }).passNullIntoEndConsumer().start(); } - + }.open(event.getPlayer()); } - + @Override public AbstractRequirement clone() { return new PermissionsRequirement(getCustomDescription(), getCustomReason(), new ArrayList<>(permissions)); } - + @Override public void save(ConfigurationSection section) { super.save(section); section.set("permissions", permissions.stream().map(Permission::toString).collect(Collectors.toList())); } - + @Override public void load(ConfigurationSection section) { super.load(section); permissions = section.getStringList("permissions").stream().map(Permission::fromString).collect(Collectors.toList()); - if (section.contains("message")) // migration from 0.20.1 and before, TODO delete + if (section.contains("message")) // TODO migration 0.20.1 and before setCustomReason(section.getString("message")); } @@ -130,5 +130,5 @@ public static Permission fromString(String string) { return new Permission(string.substring(neg ? 1 : 0), !neg); } } - + } 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 82160697..8b8681cd 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java @@ -31,7 +31,7 @@ public class StageInteractLocation extends AbstractStage implements Locatable.Pr private final boolean left; private final BQLocation lc; - + private Located.LocatedBlock locatedBlock; public StageInteractLocation(StageController controller, boolean leftClick, BQLocation location) { @@ -47,7 +47,7 @@ public BQLocation getLocation() { public boolean needLeftClick(){ return left; } - + @Override public Located getLocated() { if (lc == null) @@ -59,19 +59,19 @@ public Located getLocated() { } return locatedBlock; } - + @EventHandler public void onInteract(PlayerInteractEvent e){ if (e.getClickedBlock() == null) return; if (MinecraftVersion.MAJOR >= 9 && e.getHand() != EquipmentSlot.HAND) return; - + if (left){ if (e.getAction() != Action.LEFT_CLICK_BLOCK) return; }else if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; - + if (!lc.equals(e.getClickedBlock().getLocation())) return; - + Player p = e.getPlayer(); if (hasStarted(p) && canUpdate(p)) { if (left) e.setCancelled(true); @@ -83,7 +83,8 @@ public void onInteract(PlayerInteractEvent e){ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); placeholders.compose(lc); - // TODO remove following, for migration only + + // TODO migration 1.0 placeholders.registerIndexed("location", lc.getBlockX() + " " + lc.getBlockY() + " " + lc.getBlockZ()); } @@ -97,17 +98,17 @@ protected void serialize(ConfigurationSection section) { section.set("leftClick", left); section.set("location", lc.serialize()); } - + public static StageInteractLocation deserialize(ConfigurationSection section, StageController controller) { return new StageInteractLocation(controller, section.getBoolean("leftClick"), BQLocation.deserialize(section.getConfigurationSection("location").getValues(false))); } public static class Creator extends StageCreation<StageInteractLocation> { - + private boolean leftClick = false; private Location location; - + public Creator(@NotNull StageCreationContext<StageInteractLocation> context) { super(context); } @@ -118,7 +119,7 @@ public void setupLine(@NotNull StageGuiLine line) { line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); } - + public void setLeftClick(boolean leftClick) { if (this.leftClick != leftClick) { this.leftClick = leftClick; @@ -140,7 +141,7 @@ public void setLocation(Location location) { item -> ItemUtils.loreOptionValue(item, Lang.Location.format(getBQLocation()))); this.location = location; } - + @Override public void start(Player p) { super.start(p); @@ -166,7 +167,7 @@ public void edit(StageInteractLocation stage) { public StageInteractLocation finishStage(StageController controller) { return new StageInteractLocation(controller, leftClick, getBQLocation()); } - + } } diff --git a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java index acc8c64d..b507d4f6 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java @@ -1,11 +1,7 @@ package fr.skytasul.quests.structure; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.TreeMap; import org.apache.commons.lang.Validate; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -23,23 +19,23 @@ public class BranchesManagerImplementation implements QuestBranchesManager { private @NotNull Map<Integer, QuestBranchImplementation> branches = new TreeMap<>(Integer::compare); - + private final @NotNull QuestImplementation quest; - + public BranchesManagerImplementation(@NotNull QuestImplementation quest) { this.quest = quest; } - + @Override public @NotNull QuestImplementation getQuest() { return quest; } - + public void addBranch(@NotNull QuestBranchImplementation branch) { Validate.notNull(branch, "Branch cannot be null !"); branches.put(branches.size(), branch); } - + @Override public int getId(@NotNull QuestBranch branch) { for (Entry<Integer, QuestBranchImplementation> en : branches.entrySet()){ @@ -49,33 +45,33 @@ public int getId(@NotNull QuestBranch branch) { .severe("Trying to get the ID of a branch not in manager of quest " + quest.getId()); return -1; } - + @SuppressWarnings("rawtypes") @Override public @UnmodifiableView @NotNull Collection<@NotNull QuestBranch> getBranches() { return (Collection) branches.values(); } - + @Override public @Nullable QuestBranchImplementation getBranch(int id) { return branches.get(id); } - + @Override public @Nullable QuestBranchImplementation getPlayerBranch(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(quest)) return null; return branches.get(acc.getQuestDatas(quest).getBranch()); } - + @Override public boolean hasBranchStarted(@NotNull PlayerAccount acc, @NotNull QuestBranch branch) { if (!acc.hasQuestDatas(quest)) return false; return acc.getQuestDatas(quest).getBranch() == branch.getId(); } - + /** * Called internally when the quest is updated for the player - * + * * @param player Player */ public final void questUpdated(@NotNull Player player) { @@ -91,20 +87,20 @@ public void startPlayer(@NotNull PlayerAccount acc) { datas.setStartingTime(System.currentTimeMillis()); branches.get(0).start(acc); } - + public void remove(@NotNull PlayerAccount acc) { if (!acc.hasQuestDatas(quest)) return; QuestBranchImplementation branch = getPlayerBranch(acc); if (branch != null) branch.remove(acc, true); } - + public void remove(){ for (QuestBranchImplementation branch : branches.values()){ branch.remove(); } branches.clear(); } - + public void save(@NotNull ConfigurationSection section) { ConfigurationSection branchesSection = section.createSection("branches"); branches.forEach((id, branch) -> { @@ -117,17 +113,17 @@ public void save(@NotNull ConfigurationSection section) { } }); } - + @Override public String toString() { return "BranchesManager{branches=" + branches.size() + "}"; } - + public static @NotNull BranchesManagerImplementation deserialize(@NotNull ConfigurationSection section, @NotNull QuestImplementation qu) { BranchesManagerImplementation bm = new BranchesManagerImplementation(qu); - + ConfigurationSection branchesSection; - if (section.isList("branches")) { // migration on 0.19.3: TODO remove + if (section.isList("branches")) { // TODO migration 0.19.3 List<Map<?, ?>> branches = section.getMapList("branches"); section.set("branches", null); branchesSection = section.createSection("branches"); @@ -163,7 +159,7 @@ public String toString() { return null; } } - + for (QuestBranchImplementation branch : tmpBranches.keySet()) { try { if (!branch.load(tmpBranches.get(branch))) { @@ -179,8 +175,8 @@ public String toString() { return null; } } - + return bm; } - + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java index 0e0720b2..5085c493 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -34,54 +34,54 @@ import fr.skytasul.quests.utils.QuestUtils; public class QuestBranchImplementation implements QuestBranch { - + private final List<EndingStageImplementation> endStages = new ArrayList<>(5); private final List<StageControllerImplementation> regularStages = new ArrayList<>(15); - + private final List<PlayerAccount> asyncReward = new ArrayList<>(5); private final @NotNull BranchesManagerImplementation manager; - + public QuestBranchImplementation(@NotNull BranchesManagerImplementation manager) { this.manager = manager; } - + @Override public @NotNull QuestImplementation getQuest() { return manager.getQuest(); } - + @Override public @NotNull BranchesManagerImplementation getManager() { return manager; } - + public int getStageSize(){ return regularStages.size(); } - + @Override public int getId() { return manager.getId(this); } - + public void addRegularStage(@NotNull StageControllerImplementation<?> stage) { Validate.notNull(stage, "Stage cannot be null !"); regularStages.add(stage); stage.load(); } - + public void addEndStage(@NotNull StageControllerImplementation<?> stage, @NotNull QuestBranchImplementation linked) { Validate.notNull(stage, "Stage cannot be null !"); endStages.add(new EndingStageImplementation(stage, linked)); stage.load(); } - + @Override public @NotNull @UnmodifiableView List<@NotNull StageController> getRegularStages() { return (List) regularStages; } - + @Override public @NotNull StageControllerImplementation<?> getRegularStage(int id) { return regularStages.get(id); @@ -91,12 +91,12 @@ public void addEndStage(@NotNull StageControllerImplementation<?> stage, @NotNul public @NotNull @UnmodifiableView List<EndingStage> getEndingStages() { return (List) endStages; } - + @Override public @NotNull StageController getEndingStage(int id) { return endStages.get(id).getStage(); // TODO beware index out of bounds } - + public @Nullable QuestBranchImplementation getLinkedBranch(@NotNull StageController endingStage) { return endStages.stream().filter(end -> end.getStage().equals(endingStage)).findAny().get().getBranch(); } @@ -166,7 +166,7 @@ public boolean hasStageLaunched(@Nullable PlayerAccount acc, @NotNull StageContr return getRegularStageId(stage) == datas.getStage(); } - + public void remove(@NotNull PlayerAccount acc, boolean end) { if (!acc.hasQuestDatas(getQuest())) return; PlayerQuestDatas datas = acc.getQuestDatas(getQuest()); @@ -179,7 +179,7 @@ public void remove(@NotNull PlayerAccount acc, boolean end) { datas.setBranch(-1); datas.setStage(-1); } - + public void start(@NotNull PlayerAccount acc) { acc.getQuestDatas(getQuest()).setBranch(getId()); if (!regularStages.isEmpty()){ @@ -188,7 +188,7 @@ public void start(@NotNull PlayerAccount acc) { setEndingStages(acc, true); } } - + public void finishStage(@NotNull Player p, @NotNull StageControllerImplementation<?> stage) { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Next stage for player " + p.getName() + " (coming from " + stage.toString() + ") via " + DebugUtils.stackTraces(1, 3)); PlayerAccount acc = PlayersManager.getPlayerAccount(p); @@ -236,7 +236,7 @@ public void finishStage(@NotNull Player p, @NotNull StageControllerImplementatio manager.questUpdated(p); }); } - + private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplementation<?> stage, @NotNull Runnable runAfter) { if (acc.isCurrent()){ @@ -284,7 +284,7 @@ private void endStage(@NotNull PlayerAccount acc, @NotNull StageControllerImplem runAfter.run(); } } - + public void setStage(@NotNull PlayerAccount acc, int id) { StageControllerImplementation<?> stage = regularStages.get(id); Player p = acc.getPlayer(); @@ -304,7 +304,7 @@ public void setStage(@NotNull PlayerAccount acc, int id) { Bukkit.getPluginManager().callEvent(new PlayerSetStageEvent(acc, getQuest(), stage)); } } - + public void setEndingStages(@NotNull PlayerAccount acc, boolean launchStage) { Player p = acc.getPlayer(); if (QuestsConfiguration.getConfig().getQuestsConfig().playerQuestUpdateMessage() && p != null && launchStage) @@ -324,14 +324,14 @@ private void playNextStage(@NotNull Player p) { if (QuestsConfigurationImplementation.getConfiguration().showNextParticles()) QuestsConfigurationImplementation.getConfiguration().getParticleNext().send(p, Arrays.asList(p)); } - + public void remove(){ regularStages.forEach(StageControllerImplementation::unload); regularStages.clear(); endStages.forEach(end -> end.getStage().unload()); endStages.clear(); } - + public void save(@NotNull ConfigurationSection section) { ConfigurationSection stagesSection = section.createSection("stages"); for (int i = 0; i < regularStages.size(); i++) { @@ -343,7 +343,7 @@ public void save(@NotNull ConfigurationSection section) { QuestsPlugin.getPlugin().noticeSavingFailure(); } } - + ConfigurationSection endSection = section.createSection("endingStages"); for (int i = 0; i < endStages.size(); i++) { EndingStageImplementation en = endStages.get(i); @@ -360,15 +360,15 @@ public void save(@NotNull ConfigurationSection section) { } } } - + @Override public String toString() { return "QuestBranch{regularStages=" + regularStages.size() + ",endingStages=" + endStages.size() + "}"; } - + public boolean load(@NotNull ConfigurationSection section) { ConfigurationSection stagesSection; - if (section.isList("stages")) { // migration on 0.19.3: TODO remove + if (section.isList("stages")) { // TODO migration 0.19.3 List<Map<?, ?>> stages = section.getMapList("stages"); section.set("stages", null); stagesSection = section.createSection("stages"); @@ -386,7 +386,7 @@ public boolean load(@NotNull ConfigurationSection section) { }else { stagesSection = section.getConfigurationSection("stages"); } - + for (int id : stagesSection.getKeys(false).stream().map(Integer::parseInt).sorted().collect(Collectors.toSet())) { try{ addRegularStage(StageControllerImplementation.loadFromConfig(this, @@ -398,9 +398,9 @@ public boolean load(@NotNull ConfigurationSection section) { return false; } } - + ConfigurationSection endingStagesSection = null; - if (section.isList("endingStages")) { // migration on 0.19.3: TODO remove + if (section.isList("endingStages")) { // TODO migration 0.19.3 List<Map<?, ?>> endingStages = section.getMapList("endingStages"); section.set("endingStages", null); endingStagesSection = section.createSection("endingStages"); @@ -411,7 +411,7 @@ public boolean load(@NotNull ConfigurationSection section) { }else if (section.contains("endingStages")) { endingStagesSection = section.getConfigurationSection("endingStages"); } - + if (endingStagesSection != null) { for (String key : endingStagesSection.getKeys(false)) { try{ @@ -426,8 +426,8 @@ public boolean load(@NotNull ConfigurationSection section) { } } } - + return true; } - + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java index 6b8b7853..d5c80c84 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/DialogRunnerImplementation.java @@ -9,6 +9,7 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; @@ -22,37 +23,37 @@ import fr.skytasul.quests.utils.DebugUtils; public class DialogRunnerImplementation implements DialogRunner { - + private final Dialog dialog; private final BqNpc npc; - + private List<Predicate<Player>> tests = new ArrayList<>(); private List<Predicate<Player>> testsCancelling = new ArrayList<>(); private List<Consumer<Player>> endActions = new ArrayList<>(); - + private Map<Player, PlayerStatus> players = new HashMap<>(); private Boolean navigationInitiallyPaused = null; - + public DialogRunnerImplementation(Dialog dialog, BqNpc npc) { this.dialog = dialog; this.npc = npc; } - + @Override public void addTest(Predicate<Player> test) { tests.add(test); } - + @Override public void addTestCancelling(Predicate<Player> test) { testsCancelling.add(test); } - + @Override public void addEndAction(Consumer<Player> action) { endActions.add(action); } - + private TestResult test(Player p) { if (!tests.stream().allMatch(x -> x.test(p))) return TestResult.DENY; @@ -60,7 +61,7 @@ private TestResult test(Player p) { return TestResult.DENY_CANCEL; return TestResult.ALLOW; } - + @Override public boolean canContinue(Player p) { if (npc == null || QuestsConfiguration.getConfig().getDialogsConfig().getMaxDistance() == 0) @@ -68,7 +69,7 @@ public boolean canContinue(Player p) { return p.getLocation().distanceSquared(npc.getLocation()) <= QuestsConfiguration.getConfig().getDialogsConfig() .getMaxDistanceSquared(); } - + private void end(Player p) { if (test(p) != TestResult.ALLOW) { QuestsPlugin.getPlugin().getLoggerExpanded() @@ -76,17 +77,17 @@ private void end(Player p) { + " whereas the dialog should end. This is a bug."); return; } - + endActions.forEach(x -> x.accept(p)); } - + @Override public TestResult onClick(Player p) { if (QuestsConfiguration.getConfig().getDialogsConfig().isClickDisabled()) { PlayerStatus status = players.get(p); if (status != null && status.task != null) return TestResult.DENY; } - + if (p.isSneaking() && dialog != null && dialog.isSkippable() && test(p) == TestResult.ALLOW) { Lang.DIALOG_SKIPPED.send(p); removePlayer(p); @@ -95,25 +96,25 @@ public TestResult onClick(Player p) { } return handleNext(p, DialogNextReason.NPC_CLICK); } - + @Override public TestResult handleNext(Player p, DialogNextReason reason) { TestResult test = test(p); if (test == TestResult.ALLOW) { // player fulfills conditions to start or continue the dialog - + if (dialog == null || npc == null) { end(p); return TestResult.ALLOW; } - - DialogSendEvent event = new DialogSendEvent(dialog, npc, p, () -> end(p)); + + DialogSendEvent event = new DialogSendEvent(p, this); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) return TestResult.DENY_CANCEL; - + PlayerStatus status = addPlayer(p); status.cancel(); - + if (send(p, status, reason)) { // when dialog finished removePlayer(p); @@ -142,10 +143,10 @@ public TestResult handleNext(Player p, DialogNextReason reason) { return test; } } - + /** * Sends the next dialog line for a player, or the first message if it has just begun the dialog. - * + * * @param p player to send the dialog to * @param reason reason the message has to be sent * @return <code>true</code> if the dialog ends following this call, <code>false</code>otherwise @@ -153,66 +154,72 @@ public TestResult handleNext(Player p, DialogNextReason reason) { private boolean send(Player p, PlayerStatus status, DialogNextReason reason) { if (dialog.getMessages().isEmpty()) return true; - + int id = ++status.lastId; boolean endOfDialog = id == dialog.getMessages().size(); - + if (status.runningMsg != null) status.runningMsg.finished(p, endOfDialog, reason != DialogNextReason.AUTO_TIME); if (status.runningMsgTask != null) status.runningMsgTask.cancel(); - + if (endOfDialog) return true; - + Message msg = dialog.getMessages().get(id); if (msg == null) { p.sendMessage("§cMessage with ID " + id + " does not exist. Please report this to an adminstrator. Method caller: " + DebugUtils.stackTraces(2, 3)); return true; } - + status.runningMsg = msg; - DialogSendMessageEvent event = new DialogSendMessageEvent(dialog, msg, npc, p); + DialogSendMessageEvent event = new DialogSendMessageEvent(p, this, msg); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) status.runningMsgTask = msg.sendMessage(p, npc, dialog.getNPCName(npc), id, dialog.getMessages().size()); - + return false; } - + @Override public boolean isPlayerInDialog(Player p) { return players.containsKey(p); } - + @Override public int getPlayerMessage(Player p) { return players.get(p).lastId; } - + public PlayerStatus addPlayer(Player player) { PlayerStatus status = players.get(player); if (status != null) return status; - + status = new PlayerStatus(); players.put(player, status); - + if (npc != null && navigationInitiallyPaused == null) { // pause NPC walking as there is a player in dialog navigationInitiallyPaused = npc.getNpc().setNavigationPaused(true); } return status; } - + @Override public boolean removePlayer(Player player) { PlayerStatus status = players.remove(player); if (status == null) return false; status.cancel(); - + handlePlayerChanges(); - + return true; } - + + @Override + public void forceFinish(@NotNull Player player) { + end(player); + removePlayer(player); + } + private void handlePlayerChanges() { if (players.isEmpty() && npc != null && navigationInitiallyPaused != null) { // if no more players are in dialog, resume NPC walking @@ -220,19 +227,19 @@ private void handlePlayerChanges() { navigationInitiallyPaused = null; } } - + public void unload() { if (!players.isEmpty()) players.values().forEach(PlayerStatus::cancel); players.clear(); handlePlayerChanges(); } - + class PlayerStatus { int lastId = -1; BukkitTask task = null; BukkitTask runningMsgTask = null; Message runningMsg = null; - + void cancel() { if (task != null) { task.cancel(); @@ -240,5 +247,5 @@ void cancel() { } } } - + } 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 9d2f1cae..de558e45 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java @@ -18,13 +18,7 @@ import fr.skytasul.quests.integrations.maps.BQDynmap; import fr.skytasul.quests.integrations.mcmmo.McCombatLevelRequirement; import fr.skytasul.quests.integrations.mcmmo.McMMOSkillRequirement; -import fr.skytasul.quests.integrations.mobs.BQAdvancedSpawners; -import fr.skytasul.quests.integrations.mobs.BQBoss; -import fr.skytasul.quests.integrations.mobs.BQLevelledMobs; -import fr.skytasul.quests.integrations.mobs.BQWildStacker; -import fr.skytasul.quests.integrations.mobs.CitizensFactory; -import fr.skytasul.quests.integrations.mobs.MythicMobs; -import fr.skytasul.quests.integrations.mobs.MythicMobs5; +import fr.skytasul.quests.integrations.mobs.*; import fr.skytasul.quests.integrations.npcs.BQCitizens; import fr.skytasul.quests.integrations.npcs.BQSentinel; import fr.skytasul.quests.integrations.npcs.BQServerNPCs; @@ -47,10 +41,6 @@ public static IntegrationsLoader getInstance() { return instance; } - //public static final BQDependency par = new BQDependency("Parties"); - //public static final BQDependency eboss = new BQDependency("EpicBosses", () -> Bukkit.getPluginManager().registerEvents(new EpicBosses(), BeautyQuests.getInstance())); - //public static final BQDependency interactions = new BQDependency("Interactions", () -> InteractionsAPI.); TODO - private IntegrationsConfiguration config; public IntegrationsLoader() { From bed6ee3c6f4570341c567751fd721fee90fc0572 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 24 Aug 2023 19:19:20 +0200 Subject: [PATCH 41/95] :recycle: Refactored message type thing --- api/dependency-reduced-pom.xml | 3 + api/pom.xml | 3 + .../fr/skytasul/quests/api/QuestsAPI.java | 15 +- .../fr/skytasul/quests/api/QuestsPlugin.java | 2 - .../quests/api/localization/Lang.java | 86 ++++----- .../quests/api/npcs/dialogs/Message.java | 6 +- .../api/requirements/AbstractRequirement.java | 2 +- .../StageDescriptionPlaceholdersContext.java | 8 +- .../api/utils/messaging/MessageProcessor.java | 9 +- .../api/utils/messaging/MessageType.java | 27 +-- .../api/utils/messaging/MessageUtils.java | 10 +- .../utils/messaging/PlaceholdersContext.java | 20 ++- .../utils/progress/ProgressPlaceholders.java | 12 +- .../java/fr/skytasul/quests/BeautyQuests.java | 1 - .../skytasul/quests/DefaultQuestFeatures.java | 31 ++-- .../quests/QuestsAPIImplementation.java | 51 ++++-- .../fr/skytasul/quests/QuestsListener.java | 2 +- .../quests/commands/CommandsAdmin.java | 2 +- .../CommandsManagerImplementation.java | 38 ++-- .../quests/commands/CommandsRoot.java | 2 +- .../quests/options/OptionDescription.java | 22 +-- .../quests/rewards/MessageReward.java | 2 +- .../quests/scoreboards/Scoreboard.java | 72 ++++---- .../quests/stages/StageBringBack.java | 62 +++---- .../fr/skytasul/quests/stages/StageChat.java | 42 ++--- .../fr/skytasul/quests/stages/StageMobs.java | 41 ++--- .../options/StageOptionProgressBar.java | 2 +- .../quests/structure/QuestImplementation.java | 165 +++++++----------- .../StageControllerImplementation.java | 10 +- .../skytasul/quests/utils/types/Command.java | 16 +- .../integrations/IntegrationsLoader.java | 8 +- .../placeholders/PapiMessageProcessor.java | 5 - .../placeholders/PlaceholderRequirement.java | 24 +-- .../integrations/worldguard/StageArea.java | 2 +- 34 files changed, 381 insertions(+), 422 deletions(-) diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml index b3ebabeb..f690137b 100755 --- a/api/dependency-reduced-pom.xml +++ b/api/dependency-reduced-pom.xml @@ -70,6 +70,9 @@ </goals> </execution> </executions> + <configuration> + <skipSource>false</skipSource> + </configuration> </plugin> </plugins> </build> diff --git a/api/pom.xml b/api/pom.xml index f032cbe9..733e7e20 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -68,6 +68,9 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.2.1</version> + <configuration> + <skipSource>false</skipSource> + </configuration> <executions> <execution> <id>attach-sources</id> diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java index d8f35551..eddc21f4 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -2,7 +2,6 @@ import java.util.Collection; import java.util.List; -import java.util.Set; import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -95,9 +94,19 @@ public interface QuestsAPI { void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> consumer); @NotNull - Set<MessageProcessor> getMessageProcessors(); + Collection<MessageProcessor> getMessageProcessors(); - void registerMessageProcessor(@NotNull MessageProcessor processor); + /** + * Registers a custom message processor into the pipeline.<br> + * If a processor with the same key and priority already exists, it will get replaced by this + * one.<br> + * Processors with the lowest priority are run first. + * + * @param key unique key of this message processor + * @param priority priority of this message processor + * @param processor processor + */ + void registerMessageProcessor(@NotNull String key, int priority, @NotNull MessageProcessor processor); public static @NotNull QuestsAPI getAPI() { return QuestsAPIProvider.getAPI(); diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java index 703080d0..be5d3053 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java @@ -30,8 +30,6 @@ public interface QuestsPlugin extends Plugin { public @NotNull IntegrationManager getIntegrationManager(); - public @NotNull String getPrefix(); // TODO maybe not necessary - public void notifyLoadingFailure(); public void noticeSavingFailure(); 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 30497965..d2c9c2d0 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 @@ -40,7 +40,7 @@ public enum Lang implements Locale { QUEST_CHECKPOINT("msg.quests.checkpoint"), QUEST_FAILED("msg.quests.failed"), - DIALOG_SKIPPED("msg.dialogs.skipped", MessageType.UNPREFIXED), + DIALOG_SKIPPED("msg.dialogs.skipped", MessageType.DefaultMessageType.UNPREFIXED), DIALOG_TOO_FAR("msg.dialogs.tooFar"), // 0: npc name POOL_NO_TIME("msg.pools.noTime"), // 0: time left @@ -159,25 +159,25 @@ public enum Lang implements Locale { COMMAND_TRANSLATION_EXISTS("msg.command.downloadTranslations.exists"), // 0: file COMMAND_TRANSLATION_DOWNLOADED("msg.command.downloadTranslations.downloaded"), // 0: lang - COMMAND_HELP("msg.command.help.header", MessageType.UNPREFIXED), - COMMAND_HELP_CREATE("msg.command.help.create", MessageType.UNPREFIXED), - COMMAND_HELP_EDIT("msg.command.help.edit", MessageType.UNPREFIXED), - COMMAND_HELP_REMOVE("msg.command.help.remove", MessageType.UNPREFIXED), - COMMAND_HELP_FINISH("msg.command.help.finishAll", MessageType.UNPREFIXED), - COMMAND_HELP_STAGE("msg.command.help.setStage", MessageType.UNPREFIXED), - COMMAND_HELP_DIALOG("msg.command.help.startDialog", MessageType.UNPREFIXED), - COMMAND_HELP_RESET("msg.command.help.resetPlayer", MessageType.UNPREFIXED), - COMMAND_HELP_RESETQUEST("msg.command.help.resetPlayerQuest", MessageType.UNPREFIXED), - COMMAND_HELP_SEE("msg.command.help.seePlayer", MessageType.UNPREFIXED), - COMMAND_HELP_RELOAD("msg.command.help.reload", MessageType.UNPREFIXED), - COMMAND_HELP_START("msg.command.help.start", MessageType.UNPREFIXED), - COMMAND_HELP_SETITEM("msg.command.help.setItem", MessageType.UNPREFIXED), - COMMAND_HELP_SETFIREWORK("msg.command.help.setFirework", MessageType.UNPREFIXED), - COMMAND_HELP_ADMINMODE("msg.command.help.adminMode", MessageType.UNPREFIXED), - COMMAND_HELP_VERSION("msg.command.help.version", MessageType.UNPREFIXED), - COMMAND_HELP_DOWNLOAD_TRANSLATIONS("msg.command.help.downloadTranslations", MessageType.UNPREFIXED), - COMMAND_HELP_SAVE("msg.command.help.save", MessageType.UNPREFIXED), - COMMAND_HELP_LIST("msg.command.help.list", MessageType.UNPREFIXED), + COMMAND_HELP("msg.command.help.header", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_CREATE("msg.command.help.create", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_EDIT("msg.command.help.edit", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_REMOVE("msg.command.help.remove", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_FINISH("msg.command.help.finishAll", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_STAGE("msg.command.help.setStage", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_DIALOG("msg.command.help.startDialog", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_RESET("msg.command.help.resetPlayer", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_RESETQUEST("msg.command.help.resetPlayerQuest", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_SEE("msg.command.help.seePlayer", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_RELOAD("msg.command.help.reload", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_START("msg.command.help.start", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_SETITEM("msg.command.help.setItem", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_SETFIREWORK("msg.command.help.setFirework", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_ADMINMODE("msg.command.help.adminMode", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_VERSION("msg.command.help.version", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_DOWNLOAD_TRANSLATIONS("msg.command.help.downloadTranslations", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_SAVE("msg.command.help.save", MessageType.DefaultMessageType.UNPREFIXED), + COMMAND_HELP_LIST("msg.command.help.list", MessageType.DefaultMessageType.UNPREFIXED), // * Editors * ALREADY_EDITOR("msg.editor.already"), @@ -283,22 +283,22 @@ public enum Lang implements Locale { DIALOG_SKIPPABLE_SET("msg.editor.dialog.skippable.set"), // 0: previous, 1: new DIALOG_SKIPPABLE_UNSET("msg.editor.dialog.skippable.unset"), // 0: previous DIALOG_CLEARED("msg.editor.dialog.cleared"), - DIALOG_HELP_HEADER("msg.editor.dialog.help.header", MessageType.UNPREFIXED), - DIALOG_HELP_NPC("msg.editor.dialog.help.npc", MessageType.UNPREFIXED), - DIALOG_HELP_PLAYER("msg.editor.dialog.help.player", MessageType.UNPREFIXED), - DIALOG_HELP_NOTHING("msg.editor.dialog.help.nothing", MessageType.UNPREFIXED), - DIALOG_HELP_REMOVE("msg.editor.dialog.help.remove", MessageType.UNPREFIXED), - DIALOG_HELP_LIST("msg.editor.dialog.help.list", MessageType.UNPREFIXED), - DIALOG_HELP_NPCINSERT("msg.editor.dialog.help.npcInsert", MessageType.UNPREFIXED), - DIALOG_HELP_PLAYERINSERT("msg.editor.dialog.help.playerInsert", MessageType.UNPREFIXED), - DIALOG_HELP_NOTHINGINSERT("msg.editor.dialog.help.nothingInsert", MessageType.UNPREFIXED), - DIALOG_HELP_EDIT("msg.editor.dialog.help.edit", MessageType.UNPREFIXED), - DIALOG_HELP_ADDSOUND("msg.editor.dialog.help.addSound", MessageType.UNPREFIXED), - DIALOG_HELP_SETTIME("msg.editor.dialog.help.setTime", MessageType.UNPREFIXED), - DIALOG_HELP_NPCNAME("msg.editor.dialog.help.npcName", MessageType.UNPREFIXED), - DIALOG_HELP_SKIPPABLE("msg.editor.dialog.help.skippable", MessageType.UNPREFIXED), - DIALOG_HELP_CLEAR("msg.editor.dialog.help.clear", MessageType.UNPREFIXED), - DIALOG_HELP_CLOSE("msg.editor.dialog.help.close", MessageType.UNPREFIXED), + DIALOG_HELP_HEADER("msg.editor.dialog.help.header", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_NPC("msg.editor.dialog.help.npc", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_PLAYER("msg.editor.dialog.help.player", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_NOTHING("msg.editor.dialog.help.nothing", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_REMOVE("msg.editor.dialog.help.remove", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_LIST("msg.editor.dialog.help.list", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_NPCINSERT("msg.editor.dialog.help.npcInsert", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_PLAYERINSERT("msg.editor.dialog.help.playerInsert", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_NOTHINGINSERT("msg.editor.dialog.help.nothingInsert", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_EDIT("msg.editor.dialog.help.edit", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_ADDSOUND("msg.editor.dialog.help.addSound", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_SETTIME("msg.editor.dialog.help.setTime", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_NPCNAME("msg.editor.dialog.help.npcName", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_SKIPPABLE("msg.editor.dialog.help.skippable", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_CLEAR("msg.editor.dialog.help.clear", MessageType.DefaultMessageType.UNPREFIXED), + DIALOG_HELP_CLOSE("msg.editor.dialog.help.close", MessageType.DefaultMessageType.UNPREFIXED), MYTHICMOB_LIST("msg.editor.mythicmobs.list"), MYTHICMOB_NOT_EXISTS("msg.editor.mythicmobs.isntMythicMob"), @@ -308,11 +308,11 @@ public enum Lang implements Locale { TEXTLIST_SYNTAX("msg.editor.textList.syntax"), TEXTLIST_TEXT_ADDED("msg.editor.textList.added"), TEXTLIST_TEXT_REMOVED("msg.editor.textList.removed"), - TEXTLIST_TEXT_HELP_HEADER("msg.editor.textList.help.header", MessageType.UNPREFIXED), - TEXTLIST_TEXT_HELP_ADD("msg.editor.textList.help.add", MessageType.UNPREFIXED), - TEXTLIST_TEXT_HELP_REMOVE("msg.editor.textList.help.remove", MessageType.UNPREFIXED), - TEXTLIST_TEXT_HELP_LIST("msg.editor.textList.help.list", MessageType.UNPREFIXED), - TEXTLIST_TEXT_HELP_CLOSE("msg.editor.textList.help.close", MessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_HEADER("msg.editor.textList.help.header", MessageType.DefaultMessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_ADD("msg.editor.textList.help.add", MessageType.DefaultMessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_REMOVE("msg.editor.textList.help.remove", MessageType.DefaultMessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_LIST("msg.editor.textList.help.list", MessageType.DefaultMessageType.UNPREFIXED), + TEXTLIST_TEXT_HELP_CLOSE("msg.editor.textList.help.close", MessageType.DefaultMessageType.UNPREFIXED), // * Quests lists* @@ -851,7 +851,7 @@ public enum Lang implements Locale { private Lang(@NotNull String path) { - this(path, MessageType.PREFIXED, null); + this(path, MessageType.DefaultMessageType.PREFIXED, null); } private Lang(@NotNull String path, @NotNull MessageType type) { @@ -859,7 +859,7 @@ private Lang(@NotNull String path, @NotNull MessageType type) { } private Lang(@NotNull String path, @Nullable Lang prefix) { - this(path, MessageType.PREFIXED, prefix); + this(path, MessageType.DefaultMessageType.PREFIXED, prefix); } private Lang(@NotNull String path, @NotNull MessageType type, @Nullable Lang prefix) { diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java index e2696df9..9acc3861 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java @@ -97,15 +97,15 @@ public String formatMessage(@NotNull Player p, @Nullable BqNpc npc, @Nullable St switch (sender) { case PLAYER: sent = MessageUtils.finalFormat(Lang.SelfText.toString(), registry.withoutIndexes("npc_name_message"), - PlaceholdersContext.of(p, true)); + PlaceholdersContext.of(p, true, null)); break; case NPC: sent = MessageUtils.finalFormat(Lang.NpcText.toString(), registry.withoutIndexes("player_name"), - PlaceholdersContext.of(p, true)); + PlaceholdersContext.of(p, true, null)); break; case NOSENDER: sent = MessageUtils.finalFormat(text, registry.withoutIndexes("npc_name_message", "player_name"), - PlaceholdersContext.of(p, true)); + PlaceholdersContext.of(p, true, null)); break; } return sent; diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index d4bf8a7a..cae5afec 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -62,7 +62,7 @@ else if (customReason != null) reason = getDefaultReason(player); if (reason != null && !reason.isEmpty() && !"none".equals(reason)) { - MessageUtils.sendMessage(player, reason, MessageType.PREFIXED, getPlaceholdersRegistry()); + MessageUtils.sendMessage(player, reason, MessageType.DefaultMessageType.PREFIXED, getPlaceholdersRegistry()); return true; } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java index f1848765..b660da6a 100755 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageDescriptionPlaceholdersContext.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; @@ -18,7 +19,7 @@ public interface StageDescriptionPlaceholdersContext extends PlaceholdersContext DescriptionSource getDescriptionSource(); static @NotNull StageDescriptionPlaceholdersContext of(boolean replacePluginPlaceholders, @NotNull PlayerAccount account, - @NotNull DescriptionSource source) { + @NotNull DescriptionSource source, @Nullable MessageType messageType) { return new StageDescriptionPlaceholdersContext() { @Override @@ -40,6 +41,11 @@ public boolean replacePluginPlaceholders() { public @NotNull DescriptionSource getDescriptionSource() { return source; } + + @Override + public @Nullable MessageType getMessageType() { + return messageType; + } }; } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java index a9c08f69..73ed5a63 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageProcessor.java @@ -3,7 +3,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface MessageProcessor extends Comparable<MessageProcessor> { +public interface MessageProcessor { default @Nullable PlaceholderRegistry processPlaceholders(@Nullable PlaceholderRegistry placeholders, @NotNull PlaceholdersContext context) { @@ -14,11 +14,4 @@ public interface MessageProcessor extends Comparable<MessageProcessor> { return string; } - int getPriority(); - - @Override - default int compareTo(MessageProcessor o) { - return Integer.compare(getPriority(), o.getPriority()); - } - } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java index d368b860..41746822 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageType.java @@ -1,32 +1,11 @@ package fr.skytasul.quests.api.utils.messaging; -import org.jetbrains.annotations.NotNull; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.localization.Lang; +public interface MessageType { -public enum MessageType { + public enum DefaultMessageType implements MessageType { - PREFIXED() { - @Override - public @NotNull String process(@NotNull String msg) { - return QuestsPlugin.getPlugin().getPrefix() + msg; - } - }, - UNPREFIXED() { - @Override - public @NotNull String process(@NotNull String msg) { - return "§6" + msg; - } - }, - OFF() { - @Override - public @NotNull String process(@NotNull String msg) { - return Lang.OffText.quickFormat("message", msg); - } - }; + PREFIXED, UNPREFIXED, OFF; - public @NotNull String process(@NotNull String msg) { - return msg; } } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java index 1a4d65d9..6dd88be4 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -23,15 +23,7 @@ public static void sendMessage(@NotNull CommandSender sender, @Nullable String m public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type, @Nullable PlaceholderRegistry placeholders) { - sendMessage(sender, message, type, placeholders, PlaceholdersContext.of(sender, false)); - } - - public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type, - @Nullable PlaceholderRegistry placeholders, @NotNull PlaceholdersContext context) { - if (message == null || message.isEmpty()) - return; - - sendRawMessage(sender, type.process(message), placeholders, context); + sendRawMessage(sender, message, placeholders, PlaceholdersContext.of(sender, false, type)); } public static void sendRawMessage(@NotNull CommandSender sender, @Nullable String text, diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java index e2327332..f10844db 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholdersContext.java @@ -9,14 +9,17 @@ public interface PlaceholdersContext { - static final @NotNull PlaceholdersContext DEFAULT_CONTEXT = of(null, true); + static final @NotNull PlaceholdersContext DEFAULT_CONTEXT = of(null, true, null); @Nullable CommandSender getActor(); boolean replacePluginPlaceholders(); - static PlaceholdersContext of(@Nullable CommandSender actor, boolean replacePluginPlaceholders) { + @Nullable MessageType getMessageType(); + + static PlaceholdersContext of(@Nullable CommandSender actor, boolean replacePluginPlaceholders, + @Nullable MessageType messageType) { return new PlaceholdersContext() { @Override @@ -28,10 +31,16 @@ public boolean replacePluginPlaceholders() { public @Nullable CommandSender getActor() { return actor; } + + @Override + public @Nullable MessageType getMessageType() { + return messageType; + } }; } - static PlayerPlaceholdersContext of(@Nullable Player actor, boolean replacePluginPlaceholders) { + static PlayerPlaceholdersContext of(@Nullable Player actor, boolean replacePluginPlaceholders, + @Nullable MessageType messageType) { return new PlayerPlaceholdersContext() { @Override @@ -43,6 +52,11 @@ public boolean replacePluginPlaceholders() { public @NotNull Player getActor() { return actor; } + + @Override + public @Nullable MessageType getMessageType() { + return messageType; + } }; } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java index ae41dd6d..bd5e9ad5 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java @@ -3,19 +3,20 @@ import java.util.Map; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; import fr.skytasul.quests.api.utils.CountableObject; +import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.Placeholder; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext.PlayerPlaceholdersContext; -import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration; -import fr.skytasul.quests.api.utils.progress.itemdescription.ItemsDescriptionConfiguration; import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasMultipleObjects; import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; +import fr.skytasul.quests.api.utils.progress.itemdescription.ItemsDescriptionConfiguration; public final class ProgressPlaceholders { @@ -82,7 +83,7 @@ public static <T> void registerObjects(@NotNull PlaceholderRegistry placeholders String operation = matcher.group(2); if (operation == null) return formatObject(item, context); - + return DESCRIPTION_REGISTRY.resolve(operation, new ProgressObjectPlaceholderContext(context.getActor(), context.replacePluginPlaceholders(), item)); })); @@ -157,6 +158,11 @@ public boolean replacePluginPlaceholders() { return progress; } + @Override + public @Nullable MessageType getMessageType() { + return null; + } + } private static class ProgressObjectPlaceholderContext extends ProgressPlaceholderContext { diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 3b25ba2e..fe1d7982 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -747,7 +747,6 @@ public boolean hasSavingFailed() { return ensureLoaded(logger); } - @Override public @NotNull String getPrefix() { return config.getPrefix(); } diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index 99792565..e307655d 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -9,7 +9,6 @@ import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; -import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectLocation; @@ -27,6 +26,7 @@ import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageProcessor; +import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.api.utils.progress.HasProgress; @@ -306,9 +306,22 @@ public static void registerMessageProcessors() { PlaceholderRegistry defaultPlaceholders = new PlaceholderRegistry() .registerContextual("player", PlaceholdersContext.class, context -> context.getActor().getName()) .registerContextual("PLAYER", PlaceholdersContext.class, context -> context.getActor().getName()) - .register("prefix", () -> QuestsPlugin.getPlugin().getPrefix()); + .register("prefix", () -> BeautyQuests.getInstance().getPrefix()); - QuestsAPI.getAPI().registerMessageProcessor(new MessageProcessor() { + QuestsAPI.getAPI().registerMessageProcessor("default_message_type", 1, new MessageProcessor() { + @Override + public String processString(String string, PlaceholdersContext context) { + if (context.getMessageType() == MessageType.DefaultMessageType.PREFIXED) + return BeautyQuests.getInstance().getPrefix() + string; + if (context.getMessageType() == MessageType.DefaultMessageType.UNPREFIXED) + return "§6" + string; + if (context.getMessageType() == MessageType.DefaultMessageType.OFF) + return Lang.OffText.quickFormat("message", string); + return string; + } + }); + + QuestsAPI.getAPI().registerMessageProcessor("default_placeholders", 2, new MessageProcessor() { @Override public PlaceholderRegistry processPlaceholders(PlaceholderRegistry placeholders, PlaceholdersContext context) { if (context.replacePluginPlaceholders()) @@ -316,23 +329,13 @@ public PlaceholderRegistry processPlaceholders(PlaceholderRegistry placeholders, else return placeholders; } - - @Override - public int getPriority() { - return 1; - } }); - QuestsAPI.getAPI().registerMessageProcessor(new MessageProcessor() { + QuestsAPI.getAPI().registerMessageProcessor("legacy_colors", 10, new MessageProcessor() { @Override public String processString(String string, PlaceholdersContext context) { return ChatColor.translateAlternateColorCodes('&', string); } - - @Override - public int getPriority() { - return 10; - } }); } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java index e0f17690..c70114db 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -1,21 +1,12 @@ package fr.skytasul.quests; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.AbstractHolograms; -import fr.skytasul.quests.api.BossBarManager; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsHandler; -import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.*; import fr.skytasul.quests.api.comparison.ItemComparison; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.MobFactory; @@ -52,7 +43,7 @@ public class QuestsAPIImplementation implements QuestsAPI { private final Set<QuestsHandler> handlers = new HashSet<>(); - private final Set<MessageProcessor> processors = new TreeSet<>(); + private final Set<MessageProcessorInfo> processors = new TreeSet<>(); private QuestsAPIImplementation() {} @@ -63,7 +54,7 @@ private QuestsAPIImplementation() {} /** * Register new mob factory - * + * * @param factory MobFactory instance */ @Override @@ -204,13 +195,20 @@ public void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> co } @Override - public @NotNull Set<MessageProcessor> getMessageProcessors() { - return processors; + public @NotNull Collection<MessageProcessor> getMessageProcessors() { + return processors.stream().map(x -> x.processor).collect(Collectors.toList()); } @Override - public void registerMessageProcessor(@NotNull MessageProcessor processor) { - processors.add(processor); + public void registerMessageProcessor(@NotNull String key, int priotity, @NotNull MessageProcessor processor) { + Optional<MessageProcessorInfo> existing = + processors.stream().filter(x -> x.key.equals(key) && x.priority == priotity).findAny(); + if (existing.isPresent()) { + processors.remove(existing.get()); + BeautyQuests.getInstance().getLogger().warning("Replacing message processor " + key); + } + + processors.add(new MessageProcessorInfo(key, priotity, processor)); } @Override @@ -228,4 +226,21 @@ public void registerMessageProcessor(@NotNull MessageProcessor processor) { return BeautyQuests.getInstance(); } + private class MessageProcessorInfo implements Comparable<MessageProcessorInfo> { + private String key; + private int priority; + private MessageProcessor processor; + + public MessageProcessorInfo(String key, int priority, MessageProcessor processor) { + this.key = key; + this.priority = priority; + this.processor = processor; + } + + @Override + public int compareTo(MessageProcessorInfo o) { + return Integer.compare(priority, o.priority); + } + } + } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 47d84fd3..769c54d5 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -124,7 +124,7 @@ public void onNPCClick(BQNPCClickEvent e) { requirements.get(0).testRequirements(p, acc, true); }else { npc.getPools().iterator().next().give(p) - .thenAccept(result -> MessageUtils.sendMessage(p, result, MessageType.PREFIXED)); + .thenAccept(result -> MessageUtils.sendMessage(p, result, MessageType.DefaultMessageType.PREFIXED)); } e.setCancelled(false); } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 2735564e..8049e0f8 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -185,7 +185,7 @@ public void list(Player player) { if (NMS.isValid()) { ListBook.openQuestBook(player); } else - MessageUtils.sendMessage(player, "Version not supported", MessageType.PREFIXED); + MessageUtils.sendMessage(player, "Version not supported", MessageType.DefaultMessageType.PREFIXED); } @Subcommand ("downloadTranslations") 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 ccd55ecd..275bdd31 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsManagerImplementation.java @@ -28,17 +28,17 @@ import fr.skytasul.quests.scoreboards.Scoreboard; public class CommandsManagerImplementation implements CommandsManager { - + private static String[] COMMAND_ALIASES = { "quests", "quest", "bq", "beautyquests", "bquests" }; - + private BukkitCommandHandler handler; private boolean locked = false; - + public CommandsManagerImplementation() { handler = BukkitCommandHandler.create(BeautyQuests.getInstance()); - handler.setMessagePrefix(QuestsPlugin.getPlugin().getPrefix()); + handler.setMessagePrefix(BeautyQuests.getInstance().getPrefix()); handler.failOnTooManyArguments(); - + handler.registerValueResolver(Quest.class, context -> { int id = context.popInt(); Quest quest = QuestsAPI.getAPI().getQuestsManager().getQuest(id); @@ -51,7 +51,7 @@ public CommandsManagerImplementation() { .stream() .map(quest -> Integer.toString(quest.getId())) .collect(Collectors.toList()))); - + handler.registerValueResolver(QuestPool.class, context -> { int id = context.popInt(); QuestPool pool = QuestsAPI.getAPI().getPoolsManager().getPool(id); @@ -64,7 +64,7 @@ public CommandsManagerImplementation() { .stream() .map(pool -> Integer.toString(pool.getId())) .collect(Collectors.toList()))); - + handler.registerValueResolver(BqNpc.class, context -> { String id = context.pop(); BqNpc npc = QuestsPlugin.getPlugin().getNpcManager().getById(id); @@ -74,7 +74,7 @@ public CommandsManagerImplementation() { }); handler.getAutoCompleter().registerParameterSuggestions(BqNpc.class, SuggestionProvider.of(() -> BeautyQuests.getInstance().getNpcManager().getAvailableIds())); - + handler.registerCondition((@NotNull CommandActor actor, @NotNull ExecutableCommand command, @NotNull @Unmodifiable List<String> arguments) -> { if (command.hasAnnotation(OutsideEditor.class)) { BukkitCommandActor bukkitActor = (BukkitCommandActor) actor; @@ -84,7 +84,7 @@ public CommandsManagerImplementation() { throw new CommandErrorException(Lang.ALREADY_EDITOR.toString()); } }); - + handler.setHelpWriter((command, actor) -> { if (!command.hasPermission(actor)) return null; for (Lang lang : Lang.values()) { @@ -96,33 +96,33 @@ public CommandsManagerImplementation() { } return null; }); - + handler.registerResponseHandler(String.class, (msg, actor, command) -> { - MessageUtils.sendMessage(((BukkitCommandActor) actor).getSender(), msg, MessageType.PREFIXED); + MessageUtils.sendMessage(((BukkitCommandActor) actor).getSender(), msg, MessageType.DefaultMessageType.PREFIXED); }); handler.registerContextResolver(Scoreboard.class, context -> { return BeautyQuests.getInstance().getScoreboardManager().getPlayerScoreboard(context.getResolvedArgument(Player.class)); }); - + handler.registerCondition((actor, command, arguments) -> { QuestsPlugin.getPlugin().getLoggerExpanded().debug(actor.getName() + " executed command: " + command.getPath().toRealString() + " " + String.join(" ", arguments)); }); } - + @Override public BukkitCommandHandler getHandler() { return handler; } - + public void initializeCommands() { handler.register(new CommandsRoot()); - + registerCommands("", new CommandsAdmin(), new CommandsPlayer(), new CommandsPlayerManagement()); registerCommands("scoreboard", new CommandsScoreboard()); registerCommands("pools", new CommandsPools()); } - + @Override public void registerCommands(String subpath, OrphanCommand... commands) { Orphans path; @@ -134,7 +134,7 @@ public void registerCommands(String subpath, OrphanCommand... commands) { handler.register(Arrays.stream(commands).map(path::handler).toArray()); // if (locked) QuestsPlugin.getPlugin().getLoggerExpanded().warning("Registered commands after final locking."); } - + public void lockCommands() { if (locked) return; locked = true; @@ -143,9 +143,9 @@ public void lockCommands() { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Brigadier registered!"); }); } - + public void unload() { handler.unregisterAllCommands(); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java index b0574c0c..c69ed8f5 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsRoot.java @@ -19,7 +19,7 @@ public class CommandsRoot { @Subcommand ("help") public void help(BukkitCommandActor actor, CommandHelp<String> helpEntries) { Lang.COMMAND_HELP.send(actor.getSender()); - helpEntries.forEach(help -> MessageUtils.sendMessage(actor.getSender(), help, MessageType.UNPREFIXED)); + helpEntries.forEach(help -> MessageUtils.sendMessage(actor.getSender(), help, MessageType.DefaultMessageType.UNPREFIXED)); } @Subcommand ("version") diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java index 5c38653e..0cee5e54 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionDescription.java @@ -15,10 +15,10 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; public class OptionDescription extends QuestOptionString implements QuestDescriptionProvider { - + private Cache<QuestDescriptionContext, List<String>> cachedDescription = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build(); - + @Override public void setValue(String value) { super.setValue(value); @@ -26,44 +26,44 @@ public void setValue(String value) { if (cachedDescription != null) // not in constructor cachedDescription.invalidateAll(); } - + @Override public void sendIndication(Player p) { Lang.QUEST_DESCRIPTION.send(p); } - + @Override public XMaterial getItemMaterial() { return XMaterial.OAK_SIGN; } - + @Override public String getItemName() { return Lang.customDescription.toString(); } - + @Override public String getItemDescription() { return Lang.customDescriptionLore.toString(); } - + @Override public boolean isMultiline() { return true; } - + @Override public List<String> provideDescription(QuestDescriptionContext context) { List<String> description = cachedDescription.getIfPresent(context); if (description == null) { description = Arrays .asList("§7" + MessageUtils.finalFormat(getValue(), null, - PlaceholdersContext.of(context.getPlayerAccount().getPlayer(), true))); + PlaceholdersContext.of(context.getPlayerAccount().getPlayer(), true, null))); cachedDescription.put(context, description); } return description; } - + @Override public String getDescriptionId() { return "description"; @@ -73,5 +73,5 @@ public String getDescriptionId() { public double getDescriptionPriority() { return 0; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java index 6ea8aba0..b09fe20d 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/MessageReward.java @@ -27,7 +27,7 @@ public MessageReward(String customDescription, String text) { @Override public List<String> give(Player p) { - MessageUtils.sendMessage(p, text, MessageType.OFF); + MessageUtils.sendMessage(p, text, MessageType.DefaultMessageType.OFF); return Collections.emptyList(); } diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java index d1f00552..635fd63c 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/Scoreboard.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.scoreboards; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bukkit.Bukkit; @@ -35,14 +31,14 @@ public class Scoreboard extends BukkitRunnable implements Listener { private static final Pattern QUEST_PLACEHOLDER = Pattern.compile("\\{quest_(.+)\\}"); private static final int maxLength = MinecraftVersion.MAJOR >= 13 ? 1024 : 30; - + private PlayerAccount acc; private Player p; private FastBoard board; private ScoreboardManager manager; - + private LinkedList<Line> lines = new LinkedList<>(); - + private Quest shown = null; private List<Quest> launched; private boolean hid = false; @@ -62,7 +58,7 @@ public class Scoreboard extends BukkitRunnable implements Listener { launched = QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, false, true); hid = !manager.isWorldAllowed(p.getWorld().getName()); - + super.runTaskTimerAsynchronously(BeautyQuests.getInstance(), 2L, 20L); } @@ -97,13 +93,13 @@ public void run() { updateBoard(false, true); } - + protected void questAdd(Quest quest) { launched.add(launched.indexOf(shown) + 1, quest); shown = quest; refreshQuestsLines(true); } - + protected void questRemove(Quest quest) { int id = launched.indexOf(quest); if (id == -1) return; @@ -115,7 +111,7 @@ protected void questRemove(Quest quest) { refreshQuestsLines(true); } } - + protected void questEdited(Quest newQuest, Quest oldQuest) { int index = launched.indexOf(oldQuest); if (index == -1) { @@ -124,14 +120,14 @@ protected void questEdited(Quest newQuest, Quest oldQuest) { if (newQuest.isScoreboardEnabled() && newQuest.hasStarted(acc)) launched.add(newQuest); return; } - + // if scoreboard has been disabled during quest edition, // we remove the quest from the player list as it should no longer be displayed if (!newQuest.isScoreboardEnabled()) { questRemove(oldQuest); return; } - + // we replace the old quest instance by the new one launched.set(index, newQuest); if (shown == oldQuest) { @@ -139,7 +135,7 @@ protected void questEdited(Quest newQuest, Quest oldQuest) { refreshQuestsLines(true); } } - + protected void worldChange(boolean toAllowed) { if (hid) { if (toAllowed) show(false); @@ -147,19 +143,19 @@ protected void worldChange(boolean toAllowed) { if (!toAllowed) hide(false); } } - + public Quest getShownQuest() { return shown; } - + public boolean isHidden() { return hid; } - + public boolean isForceHidden() { return hidForce; } - + public void hide(boolean force) { hid = true; if (force) hidForce = true; @@ -167,7 +163,7 @@ public void hide(boolean force) { deleteBoard(); } } - + public void show(boolean force) { if (hidForce && !force) return; hid = false; @@ -177,13 +173,13 @@ public void show(boolean force) { updateBoard(true, false); } } - + private void deleteBoard() { board.delete(); board = null; for (Line line : lines) line.reset(); } - + public void setShownQuest(Quest quest, boolean errorWhenUnknown) { if (!quest.isScoreboardEnabled()) return; if (!launched.contains(quest)) { @@ -206,7 +202,7 @@ public void refreshQuestsLines(boolean updateBoard) { if (updateBoard) updateBoard(false, false); } } - + private void updateBoard(boolean update, boolean time) { if (board == null && !time) return; List<String> linesStrings = new ArrayList<>(lines.size()); @@ -228,7 +224,7 @@ private void updateBoard(boolean update, boolean time) { } if (update && board != null) board.updateLines(linesStrings); } - + public void setCustomLine(int id, String value){ if (lines.size() <= id){ Line line = new Line(new ScoreboardLine(value)); @@ -241,7 +237,7 @@ public void setCustomLine(int id, String value){ } updateBoard(true, false); } - + public boolean resetLine(int id){ if (lines.size() <= id) return false; Line line = lines.get(id); @@ -254,21 +250,21 @@ public boolean resetLine(int id){ updateBoard(true, false); return true; } - + public boolean removeLine(int id){ if (lines.size() <= id) return false; lines.remove(id); updateBoard(true, false); return true; } - + @Override public synchronized void cancel() throws IllegalStateException { super.cancel(); HandlerList.unregisterAll(this); if (board != null) deleteBoard(); } - + public void initScoreboard(){ board = new FastBoard(p); board.updateTitle(Lang.SCOREBOARD_NAME.toString()); @@ -278,21 +274,21 @@ class Line{ ScoreboardLine param; int timeLeft = 0; - + private String customValue = null; boolean createdLine = false; - + boolean willRefresh = false; String lastValue = null; List<String> lines; - + boolean hasQuestPlaceholders; private Line(ScoreboardLine param) { this.param = param; computeHasQuestPlaceholders(); } - + private boolean tryRefresh(boolean time) { if (!willRefresh && lines != null && param.getRefreshTime() == 0) return false; if (timeLeft == 0 || willRefresh) { @@ -308,7 +304,7 @@ private boolean tryRefresh(boolean time) { lines = Collections.emptyList(); lastValue = null; } else { - text = MessageUtils.finalFormat(text, null, PlaceholdersContext.of(p, true)); + text = MessageUtils.finalFormat(text, null, PlaceholdersContext.of(p, true, null)); if (text.equals(lastValue)) return false; @@ -321,17 +317,17 @@ private boolean tryRefresh(boolean time) { if (time) timeLeft--; return false; } - + private void reset() { timeLeft = 0; lines = null; lastValue = null; } - + public String getValue(){ return customValue == null ? param.getValue() : customValue; } - + public void setCustomValue(String value) { customValue = value; computeHasQuestPlaceholders(); @@ -340,7 +336,7 @@ public void setCustomValue(String value) { private void computeHasQuestPlaceholders() { hasQuestPlaceholders = QUEST_PLACEHOLDER.matcher(getValue()).find(); } - + private String formatQuestPlaceholders(String text) { StringBuffer textBuffer = new StringBuffer(); Matcher matcher = QUEST_PLACEHOLDER.matcher(text); @@ -383,5 +379,5 @@ private String formatQuestPlaceholders(String text) { } } - + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index b4ebf536..57b011e6 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.stages; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -36,19 +32,19 @@ import fr.skytasul.quests.gui.items.ItemsGUI; public class StageBringBack extends StageNPC{ - + protected final ItemStack[] items; protected final String customMessage; protected final ItemComparisonMap comparisons; - + protected final Map<ItemStack, Integer> amountsMap = new HashMap<>(); protected final String[] itemsDescriptions; - + public StageBringBack(StageController controller, ItemStack[] items, String customMessage, ItemComparisonMap comparisons) { super(controller); this.customMessage = customMessage; this.comparisons = comparisons; - + this.items = items; for (ItemStack item : items) { int amount = (amountsMap.containsKey(item) ? amountsMap.get(item) : 0) + item.getAmount(); @@ -72,9 +68,9 @@ public int getPlayerAmount(@NotNull PlayerAccount account) { public int getObjectAmount() { return item.getAmount(); } - }, PlaceholdersContext.of((Player) null, false))).toArray(String[]::new); + }, PlaceholdersContext.of((Player) null, false, null))).toArray(String[]::new); } - + public boolean checkItems(Player p, boolean msg){ boolean done = true; for (Entry<ItemStack, Integer> en : amountsMap.entrySet()) { @@ -90,21 +86,21 @@ public boolean checkItems(Player p, boolean msg){ public void sendNeedMessage(Player p) { new Message(MessageUtils.format(getMessage(), getPlaceholdersRegistry(), StageDescriptionPlaceholdersContext.of(true, - PlayersManager.getPlayerAccount(p), DescriptionSource.FORCELINE)), Sender.NPC).sendMessage(p, getNPC(), + PlayersManager.getPlayerAccount(p), DescriptionSource.FORCELINE, null)), Sender.NPC).sendMessage(p, getNPC(), getNpcName(), 1, 1); } - + public void removeItems(Player p){ for(ItemStack is : items){ comparisons.removeItems(p.getInventory(), is); } p.updateInventory(); } - + public ItemStack[] getItems(){ return items; } - + protected String getMessage() { return customMessage == null ? Lang.NEED_OBJECTS.toString() : customMessage; } @@ -128,15 +124,15 @@ public void started(PlayerAccount acc) { if (acc.isCurrent() && sendStartMessage()) sendNeedMessage(acc.getPlayer()); } - + @Override protected void initDialogRunner() { super.initDialogRunner(); - + getNPC().addStartablePredicate(p -> { return canUpdate(p, false) && checkItems(p, false); }, this); - + dialogRunner.addTest(p -> { if (getNPC().canGiveSomething(p)) { // if the NPC can offer something else to the player @@ -149,16 +145,16 @@ protected void initDialogRunner() { return true; }); dialogRunner.addTestCancelling(p -> checkItems(p, true)); - + dialogRunner.addEndAction(this::removeItems); } - + @Override public void unload() { super.unload(); if (getNPC() != null) getNPC().removeStartablePredicate(this); } - + @Override public void serialize(ConfigurationSection section) { super.serialize(section); @@ -166,7 +162,7 @@ public void serialize(ConfigurationSection section) { if (customMessage != null) section.set("customMessage", customMessage); if (!comparisons.getNotDefault().isEmpty()) section.createSection("itemComparisons", comparisons.getNotDefault()); } - + public static StageBringBack deserialize(ConfigurationSection section, StageController controller) { ItemStack[] items = section.getList("items").toArray(new ItemStack[0]); String customMessage = section.getString("customMessage", null); @@ -180,7 +176,7 @@ public static StageBringBack deserialize(ConfigurationSection section, StageCont } public abstract static class AbstractCreator<T extends StageBringBack> extends StageNPC.AbstractCreator<T> { - + private static final ItemStack stageItems = ItemUtils.item(XMaterial.CHEST, Lang.stageItems.toString()); private static final ItemStack stageMessage = ItemUtils.item(XMaterial.PAPER, Lang.stageItemsMessage.toString()); private static final ItemStack stageComparison = ItemUtils.item(XMaterial.PRISMARINE_SHARD, Lang.stageItemsComparison.toString()); @@ -188,7 +184,7 @@ public abstract static class AbstractCreator<T extends StageBringBack> extends S protected List<ItemStack> items; protected String message = null; protected ItemComparisonMap comparisons = new ItemComparisonMap(); - + protected AbstractCreator(@NotNull StageCreationContext<T> context) { super(context); } @@ -196,7 +192,7 @@ protected AbstractCreator(@NotNull StageCreationContext<T> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(5, stageItems, event -> { new ItemsGUI(items -> { setItems(items); @@ -216,18 +212,18 @@ public void setupLine(@NotNull StageGuiLine line) { }).open(event.getPlayer()); }); } - + public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); getLine().refreshItemLore(5, QuestOption.formatNullableValue(Lang.AmountItems.quickFormat("amount", this.items.size()))); } - + public void setMessage(String message) { this.message = message; getLine().refreshItemLore(9, QuestOption.formatNullableValue(message, Lang.NEED_OBJECTS)); } - + public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; getLine().refreshItemLore(10, @@ -235,7 +231,7 @@ public void setComparisons(ItemComparisonMap comparisons) { Lang.AmountComparisons.quickFormat("amount", this.comparisons.getEffective().size()), comparisons.isDefault())); } - + @Override public void start(Player p) { new ItemsGUI(items -> { @@ -251,11 +247,11 @@ public void edit(T stage) { setMessage(stage.customMessage); setComparisons(stage.comparisons.clone()); } - + } - + public static class Creator extends AbstractCreator<StageBringBack> { - + public Creator(@NotNull StageCreationContext<StageBringBack> context) { super(context); } @@ -264,7 +260,7 @@ public Creator(@NotNull StageCreationContext<StageBringBack> context) { protected StageBringBack createStage(StageController controller) { return new StageBringBack(controller, items.toArray(new ItemStack[0]), message, comparisons); } - + } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index cd0252ba..7392a9cd 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -23,16 +23,16 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; public class StageChat extends AbstractStage{ - + private final String text; private final boolean cancel; private final boolean ignoreCase; private final boolean placeholders; private final boolean command; - + public StageChat(StageController controller, String text, boolean cancel, boolean ignoreCase, boolean placeholders) { super(controller); - + Validate.notNull(text, "Text cannot be null"); this.text = text; this.command = text.startsWith("/"); @@ -47,20 +47,20 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol super.createdPlaceholdersRegistry(placeholders); placeholders.registerIndexed("text", text); } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_CHAT.toString(); } - + public String getText() { return text; } - + public boolean isEventCancelled() { return cancel; } - + public boolean isCaseIgnored() { return ignoreCase; } @@ -70,23 +70,23 @@ public void onTchat(AsyncPlayerChatEvent e) { if (command) return; if (check(e.getMessage(), e.getPlayer()) && cancel) e.setCancelled(true); } - + @EventHandler public void onCommand(PlayerCommandPreprocessEvent e) { if (!command) return; if (check(e.getMessage(), e.getPlayer()) && cancel) e.setCancelled(true); } - + private boolean check(String message, Player p) { if (placeholders) - message = MessageUtils.finalFormat(text, null, PlaceholdersContext.of(p, true)); + message = MessageUtils.finalFormat(text, null, PlaceholdersContext.of(p, true, null)); if (!(ignoreCase ? message.equalsIgnoreCase(text) : message.equals(text))) return false; if (!hasStarted(p)) return false; if (canUpdate(p)) finishStage(p); return true; } - + @Override public void serialize(ConfigurationSection section) { Validate.notNull(text, "Text cannot be null"); @@ -95,23 +95,23 @@ public void serialize(ConfigurationSection section) { if (ignoreCase) section.set("ignoreCase", true); if (!placeholders) section.set("placeholders", false); } - + public static StageChat deserialize(ConfigurationSection section, StageController controller) { return new StageChat(controller, section.getString("writeText"), section.getBoolean("cancel", true), section.getBoolean("ignoreCase", false), section.getBoolean("placeholders", true)); } public static class Creator extends StageCreation<StageChat> { - + private static final int PLACEHOLDERS_SLOT = 5; private static final int IGNORE_CASE_SLOT = 6; private static final int CANCEL_EVENT_SLOT = 7; private static final int MESSAGE_SLOT = 8; - + private String text; private boolean placeholders = true; private boolean cancel = true; private boolean ignoreCase = false; - + public Creator(@NotNull StageCreationContext<StageChat> context) { super(context); } @@ -119,7 +119,7 @@ public Creator(@NotNull StageCreationContext<StageChat> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(PLACEHOLDERS_SLOT, ItemUtils.itemSwitch(Lang.placeholders.toString(), placeholders), event -> setPlaceholders(!placeholders)); line.setItem(IGNORE_CASE_SLOT, ItemUtils.itemSwitch(Lang.ignoreCase.toString(), ignoreCase), @@ -129,26 +129,26 @@ public void setupLine(@NotNull StageGuiLine line) { line.setItem(MESSAGE_SLOT, ItemUtils.item(XMaterial.PLAYER_HEAD, Lang.editMessage.toString()), event -> launchEditor(event.getPlayer())); } - + public void setText(String text) { this.text = text; getLine().refreshItem(MESSAGE_SLOT, item -> ItemUtils.lore(item, QuestOption.formatNullableValue(text))); } - + public void setPlaceholders(boolean placeholders) { if (this.placeholders != placeholders) { this.placeholders = placeholders; getLine().refreshItem(PLACEHOLDERS_SLOT, item -> ItemUtils.setSwitch(item, placeholders)); } } - + public void setIgnoreCase(boolean ignoreCase) { if (this.ignoreCase != ignoreCase) { this.ignoreCase = ignoreCase; getLine().refreshItem(IGNORE_CASE_SLOT, item -> ItemUtils.setSwitch(item, ignoreCase)); } } - + public void setCancel(boolean cancel) { if (this.cancel != cancel) { this.cancel = cancel; @@ -175,7 +175,7 @@ public void edit(StageChat stage) { public StageChat finishStage(StageController controller) { return new StageChat(controller, text, cancel, ignoreCase, placeholders); } - + private void launchEditor(Player p) { Lang.CHAT_MESSAGE.send(p); new TextEditor<String>(p, () -> { diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index 691cb174..94007dea 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -1,15 +1,7 @@ package fr.skytasul.quests.stages; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; -import java.util.Spliterator; -import java.util.Spliterators; import java.util.stream.Collectors; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -43,7 +35,7 @@ public class StageMobs extends AbstractCountableStage<Mob<?>> implements Locatable.MultipleLocatable { private boolean shoot = false; - + public StageMobs(StageController controller, List<CountableObject<Mob<?>>> mobs) { super(controller, mobs); } @@ -55,7 +47,7 @@ public boolean isShoot() { public void setShoot(boolean shoot) { this.shoot = shoot; } - + @EventHandler public void onMobKilled(BQMobDeathEvent e){ if (shoot && e.getBukkitEntity() != null && e.getBukkitEntity().getLastDamageCause() != null @@ -67,7 +59,7 @@ public void onMobKilled(BQMobDeathEvent e){ if (hasStarted(p)) event(p, new KilledMob(e.getPluginMob(), e.getBukkitEntity()), e.getAmount()); } - + @Override protected boolean objectApplies(Mob<?> object, Object other) { KilledMob otherMob = (KilledMob) other; @@ -92,14 +84,13 @@ protected boolean objectApplies(Mob<?> object, Object other) { public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_NONE.toString(); } - + @Override public void started(PlayerAccount acc) { super.started(acc); if (acc.isCurrent() && sendStartMessage()) { - MessageUtils.sendMessage(acc.getPlayer(), Lang.STAGE_MOBSLIST.toString(), MessageType.PREFIXED, - getPlaceholdersRegistry(), - StageDescriptionPlaceholdersContext.of(true, acc, DescriptionSource.FORCELINE)); + MessageUtils.sendRawMessage(acc.getPlayer(), Lang.STAGE_MOBSLIST.toString(), getPlaceholdersRegistry(), + StageDescriptionPlaceholdersContext.of(true, acc, DescriptionSource.FORCELINE, MessageType.DefaultMessageType.PREFIXED)); Lang.STAGE_MOBSLIST.send(acc.getPlayer(), this); } } @@ -108,7 +99,7 @@ public void started(PlayerAccount acc) { protected Mob<?> cloneObject(Mob<?> object) { return object.clone(); } - + @Override protected String getName(Mob<?> object) { return object.getName(); @@ -129,12 +120,12 @@ protected void serialize(ConfigurationSection section) { super.serialize(section); if (shoot) section.set("shoot", true); } - + @Override public boolean canBeFetchedAsynchronously() { return false; } - + @Override public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { if (!fetcher.isTargeting(LocatedType.ENTITY)) return Spliterators.emptySpliterator(); @@ -152,7 +143,7 @@ public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { .<Located>map(entry -> Located.LocatedEntity.create(entry.getKey())) .spliterator(); } - + public static StageMobs deserialize(ConfigurationSection section, StageController controller) { StageMobs stage = new StageMobs(controller, new ArrayList<>()); stage.deserialize(section); @@ -165,7 +156,7 @@ public static class Creator extends StageCreation<StageMobs> { private List<MutableCountableObject<Mob<?>>> mobs; private boolean shoot = false; - + public Creator(@NotNull StageCreationContext<StageMobs> context) { super(context); } @@ -173,7 +164,7 @@ public Creator(@NotNull StageCreationContext<StageMobs> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(7, ItemUtils.item(XMaterial.STONE_SWORD, Lang.editMobs.toString()), event -> { new MobsListGUI(mobs, newMobs -> { setMobs(newMobs); @@ -182,20 +173,20 @@ public void setupLine(@NotNull StageGuiLine line) { }); line.setItem(6, ItemUtils.itemSwitch(Lang.mobsKillType.toString(), shoot), event -> setShoot(!shoot)); } - + public void setMobs(List<MutableCountableObject<Mob<?>>> mobs) { this.mobs = mobs; getLine().refreshItem(7, item -> ItemUtils.loreOptionValue(item, Lang.AmountMobs.quickFormat("mobs_amount", mobs.size()))); } - + public void setShoot(boolean shoot) { if (this.shoot != shoot) { this.shoot = shoot; getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, shoot)); } } - + @Override public void start(Player p) { super.start(p); diff --git a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java index cf7ab702..afd1fe90 100755 --- a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java +++ b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java @@ -169,7 +169,7 @@ public void update() { + acc.getNameAndID() + ": " + playerRemaining + " > " + totalAmount); bar.setTitle(MessageUtils.format(getProgressConfig().getBossBarFormat(), placeholders, - PlaceholdersContext.of(acc.getPlayer(), true))); + PlaceholdersContext.of(acc.getPlayer(), true, null))); } private void timer() { diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index 1d4e1a91..266b5a7b 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -5,13 +5,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.OptionalInt; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.regex.Pattern; import org.bukkit.Bukkit; @@ -25,11 +19,7 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.events.PlayerQuestResetEvent; -import fr.skytasul.quests.api.events.QuestFinishEvent; -import fr.skytasul.quests.api.events.QuestLaunchEvent; -import fr.skytasul.quests.api.events.QuestPreLaunchEvent; -import fr.skytasul.quests.api.events.QuestRemoveEvent; +import fr.skytasul.quests.api.events.*; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.options.QuestOption; @@ -46,70 +36,45 @@ import fr.skytasul.quests.api.utils.PlayerListCategory; import fr.skytasul.quests.api.utils.QuestVisibilityLocation; import fr.skytasul.quests.api.utils.Utils; -import fr.skytasul.quests.api.utils.messaging.DefaultErrors; -import fr.skytasul.quests.api.utils.messaging.MessageType; -import fr.skytasul.quests.api.utils.messaging.MessageUtils; -import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; +import fr.skytasul.quests.api.utils.messaging.*; import fr.skytasul.quests.npcs.BqNpcImplementation; -import fr.skytasul.quests.options.OptionBypassLimit; -import fr.skytasul.quests.options.OptionCancelRewards; -import fr.skytasul.quests.options.OptionCancellable; -import fr.skytasul.quests.options.OptionConfirmMessage; -import fr.skytasul.quests.options.OptionDescription; -import fr.skytasul.quests.options.OptionEndMessage; -import fr.skytasul.quests.options.OptionEndRewards; -import fr.skytasul.quests.options.OptionEndSound; -import fr.skytasul.quests.options.OptionFirework; -import fr.skytasul.quests.options.OptionHideNoRequirements; -import fr.skytasul.quests.options.OptionName; -import fr.skytasul.quests.options.OptionQuestItem; -import fr.skytasul.quests.options.OptionQuestPool; -import fr.skytasul.quests.options.OptionRepeatable; -import fr.skytasul.quests.options.OptionRequirements; -import fr.skytasul.quests.options.OptionScoreboardEnabled; -import fr.skytasul.quests.options.OptionStartDialog; -import fr.skytasul.quests.options.OptionStartMessage; -import fr.skytasul.quests.options.OptionStartRewards; -import fr.skytasul.quests.options.OptionStarterNPC; -import fr.skytasul.quests.options.OptionTimer; -import fr.skytasul.quests.options.OptionVisibility; +import fr.skytasul.quests.options.*; import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.rewards.MessageReward; import fr.skytasul.quests.structure.pools.QuestPoolImplementation; import fr.skytasul.quests.utils.QuestUtils; public class QuestImplementation implements Quest, QuestDescriptionProvider { - + private static final Pattern PERMISSION_PATTERN = Pattern.compile("^beautyquests\\.start\\.(\\d+)$"); private final int id; private final File file; private BranchesManagerImplementation manager; - + private List<QuestOption<?>> options = new ArrayList<>(); private List<QuestDescriptionProvider> descriptions = new ArrayList<>(); - + private boolean removed = false; public List<Player> inAsyncStart = new ArrayList<>(); - + private PlaceholderRegistry placeholders; public QuestImplementation(int id) { this(id, new File(BeautyQuests.getInstance().getQuestsManager().getSaveFolder(), id + ".yml")); } - + public QuestImplementation(int id, @NotNull File file) { this.id = id; this.file = file; this.manager = new BranchesManagerImplementation(this); this.descriptions.add(this); } - + public void load() { QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questLoaded(this)); } - + @Override public boolean isValid() { return !removed; @@ -119,13 +84,13 @@ public boolean isValid() { public @NotNull List<QuestDescriptionProvider> getDescriptions() { return descriptions; } - + @SuppressWarnings("rawtypes") @Override public Iterator<QuestOption> iterator() { return (Iterator) options.iterator(); } - + @Override public @NotNull <T extends QuestOption<?>> T getOption(@NotNull Class<T> clazz) { for (QuestOption<?> option : options) { @@ -133,7 +98,7 @@ public Iterator<QuestOption> iterator() { } throw new NullPointerException("Quest " + id + " do not have option " + clazz.getName()); } - + @Override public boolean hasOption(@NotNull Class<? extends QuestOption<?>> clazz) { for (QuestOption<?> option : options) { @@ -141,7 +106,7 @@ public boolean hasOption(@NotNull Class<? extends QuestOption<?>> clazz) { } return false; } - + @Override public void addOption(@NotNull QuestOption<?> option) { if (!option.hasCustomValue()) return; @@ -154,7 +119,7 @@ public void addOption(@NotNull QuestOption<?> option) { } }); } - + @Override public void removeOption(@NotNull Class<? extends QuestOption<?>> clazz) { for (Iterator<QuestOption<?>> iterator = options.iterator(); iterator.hasNext();) { @@ -166,20 +131,20 @@ public void removeOption(@NotNull Class<? extends QuestOption<?>> clazz) { } } } - + public boolean isRemoved(){ return removed; } - + @Override public int getId() { return id; } - + public File getFile(){ return file; } - + public String getNameAndId() { return getName() + " (#" + id + ")"; } @@ -188,47 +153,47 @@ public String getNameAndId() { public @Nullable String getName() { return getOptionValueOrDef(OptionName.class); } - + @Override public @Nullable String getDescription() { return getOptionValueOrDef(OptionDescription.class); } - + @Override public @NotNull ItemStack getQuestItem() { return getOptionValueOrDef(OptionQuestItem.class); } - + @Override public boolean isScoreboardEnabled() { return getOptionValueOrDef(OptionScoreboardEnabled.class); } - + @Override public boolean isCancellable() { return getOptionValueOrDef(OptionCancellable.class); } - + @Override public boolean isRepeatable() { return getOptionValueOrDef(OptionRepeatable.class); } - + @Override public boolean isHidden(QuestVisibilityLocation location) { return !getOptionValueOrDef(OptionVisibility.class).contains(location); } - + @Override public boolean isHiddenWhenRequirementsNotMet() { return getOptionValueOrDef(OptionHideNoRequirements.class); } - + @Override public boolean canBypassLimit() { return getOptionValueOrDef(OptionBypassLimit.class); } - + @Override public @Nullable BqNpc getStarterNpc() { return getOptionValueOrDef(OptionStarterNPC.class); @@ -246,7 +211,7 @@ public boolean hasAsyncEnd() { public @NotNull BranchesManagerImplementation getBranchesManager() { return manager; } - + public @NotNull String getTimeLeft(@NotNull PlayerAccount acc) { return Utils.millisToHumanString(acc.getQuestDatas(this).getTimer() - System.currentTimeMillis()); } @@ -264,7 +229,7 @@ public boolean hasStarted(@NotNull PlayerAccount acc) { public boolean hasFinished(@NotNull PlayerAccount acc) { return acc.hasQuestDatas(this) && acc.getQuestDatas(this).isFinished(); } - + @Override public boolean cancelPlayer(@NotNull PlayerAccount acc) { PlayerQuestDatas datas = acc.getQuestDatasIfPresent(this); @@ -280,7 +245,7 @@ private void cancelInternal(@NotNull PlayerAccount acc) { manager.remove(acc); QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questReset(acc, this)); Bukkit.getPluginManager().callEvent(new PlayerQuestResetEvent(acc, this)); - + if (acc.isCurrent()) { try { getOptionValueOrDef(OptionCancelRewards.class).giveRewards(acc.getPlayer()); @@ -289,7 +254,7 @@ private void cancelInternal(@NotNull PlayerAccount acc) { } } } - + @Override public @NotNull CompletableFuture<Boolean> resetPlayer(@NotNull PlayerAccount acc) { boolean hadDatas = false; @@ -309,7 +274,7 @@ && getOption(OptionStartDialog.class).getDialogRunner().removePlayer(acc.getPlay return future == null ? CompletableFuture.completedFuture(hadDatas) : future.thenApply(__ -> true); } - + @Override public boolean canStart(@NotNull Player p, boolean sendMessage) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); @@ -322,7 +287,7 @@ public boolean canStart(@NotNull Player p, boolean sendMessage) { if (!testRequirements(p, acc, sendMessage)) return false; return true; } - + public boolean testRequirements(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { if (!p.hasPermission("beautyquests.start")) return false; if (!testQuestLimit(p, acc, sendMessage)) return false; @@ -331,7 +296,7 @@ public boolean testRequirements(@NotNull Player p, @NotNull PlayerAccount acc, b || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); return getOptionValueOrDef(OptionRequirements.class).testPlayer(p, sendMessage); } - + public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { if (Boolean.TRUE.equals(getOptionValueOrDef(OptionBypassLimit.class))) return true; @@ -368,24 +333,24 @@ public boolean testTimer(@NotNull PlayerAccount acc, boolean sendMessage) { } return true; } - + public boolean isInDialog(@NotNull Player p) { return hasOption(OptionStartDialog.class) && getOption(OptionStartDialog.class).getDialogRunner().isPlayerInDialog(p); } - + public void clickNPC(@NotNull Player p) { if (hasOption(OptionStartDialog.class)) { getOption(OptionStartDialog.class).getDialogRunner().onClick(p); } else attemptStart(p); } - + public void leave(@NotNull Player p) { if (hasOption(OptionStartDialog.class)) { getOption(OptionStartDialog.class).getDialogRunner().removePlayer(p); } } - + @Override public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { if (!acc.hasQuestDatas(this)) throw new IllegalArgumentException("Account does not have quest datas for quest " + id); @@ -407,7 +372,7 @@ public void leave(@NotNull Player p) { return Arrays.asList(getDescriptionLine(context.getPlayerAccount(), context.getSource())); } - + @Override public @NotNull String getDescriptionId() { return "advancement"; @@ -417,7 +382,7 @@ public void leave(@NotNull Player p) { public double getDescriptionPriority() { return 15; } - + @Override public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { if (placeholders == null) { @@ -451,12 +416,12 @@ public double getDescriptionPriority() { return CompletableFuture.completedFuture(true); } } - + @Override public void start(@NotNull Player p) { start(p, false); } - + @Override public void start(@NotNull Player p, boolean silently) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); @@ -472,9 +437,9 @@ public void start(@NotNull Player p, boolean silently) { if (!silently) { String startMsg = getOptionValueOrDef(OptionStartMessage.class); if (!"none".equals(startMsg)) - MessageUtils.sendRawMessage(p, startMsg, getPlaceholdersRegistry(), PlaceholdersContext.of(p, true)); + MessageUtils.sendRawMessage(p, startMsg, getPlaceholdersRegistry(), PlaceholdersContext.of(p, true, null)); } - + Runnable run = () -> { List<String> msg = Collections.emptyList(); try { @@ -487,7 +452,7 @@ public void start(@NotNull Player p, boolean silently) { Lang.FINISHED_OBTAIN.quickSend(p, "rewards", MessageUtils.itemsToFormattedString(msg.toArray(new String[0]))); inAsyncStart.remove(p); - + QuestUtils.runOrSync(() -> { manager.startPlayer(acc); QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questStart(acc, this)); @@ -499,13 +464,13 @@ public void start(@NotNull Player p, boolean silently) { QuestUtils.runAsync(run); }else run.run(); } - + @Override public void finish(@NotNull Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); AdminMode.broadcast(p.getName() + " is completing the quest " + id); PlayerQuestDatas questDatas = acc.getQuestDatas(this); - + Runnable run = () -> { try { List<String> msg = getOptionValueOrDef(OptionEndRewards.class).giveRewards(p); @@ -514,16 +479,16 @@ public void finish(@NotNull Player p) { String endMsg = getOption(OptionEndMessage.class).getValue(); if (!"none".equals(endMsg)) MessageUtils.sendRawMessage(p, endMsg, PlaceholderRegistry.of("rewards", obtained).with(this), - PlaceholdersContext.of(p, true)); + PlaceholdersContext.of(p, true, null)); } else MessageUtils.sendMessage(p, Lang.FINISHED_BASE.format(this) + (msg.isEmpty() ? "" : " " + Lang.FINISHED_OBTAIN.quickFormat("rewards", obtained)), - MessageType.PREFIXED); + MessageType.DefaultMessageType.PREFIXED); }catch (Exception ex) { DefaultErrors.sendGeneric(p, "reward message"); QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while giving quest end rewards.", ex); } - + QuestUtils.runOrSync(() -> { manager.remove(acc); questDatas.setBranch(-1); @@ -538,12 +503,12 @@ public void finish(@NotNull Player p) { } QuestUtils.spawnFirework(p.getLocation(), getOptionValueOrDef(OptionFirework.class)); QuestUtils.playPluginSound(p, getOptionValueOrDef(OptionEndSound.class), 1); - + QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questFinish(acc, this)); Bukkit.getPluginManager().callEvent(new QuestFinishEvent(p, this)); }); }; - + if (hasAsyncEnd()) { questDatas.setInQuestEnd(); new Thread(() -> { @@ -573,13 +538,13 @@ public void delete(boolean silently, boolean keepDatas) { if (!silently) QuestsPlugin.getPlugin().getLoggerExpanded().info("The quest \"" + getName() + "\" has been removed"); } - + public void unload(){ QuestsAPI.getAPI().propagateQuestsHandlers(handler -> handler.questUnload(this)); manager.remove(); options.forEach(QuestOption::detach); } - + @Override public String toString(){ return "Quest{id=" + id + ", npcID=" + ", branches=" + manager.toString() + ", name=" + getName() + "}"; @@ -587,7 +552,7 @@ public String toString(){ public boolean saveToFile() throws IOException { YamlConfiguration fc = new YamlConfiguration(); - + BeautyQuests.getInstance().resetSavingFailure(); save(fc); if (BeautyQuests.getInstance().hasSavingFailed()) { @@ -610,7 +575,7 @@ public boolean saveToFile() throws IOException { return true; } } - + private void save(@NotNull ConfigurationSection section) { for (QuestOption<?> option : options) { try { @@ -619,11 +584,11 @@ private void save(@NotNull ConfigurationSection section) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("An exception occured when saving an option for quest " + id, ex); } } - + manager.save(section.createSection("manager")); section.set("id", id); } - + public static @Nullable QuestImplementation loadFromFile(@NotNull File file) { try { @@ -635,18 +600,18 @@ private void save(@NotNull ConfigurationSection section) { return null; } } - + private static @Nullable QuestImplementation deserialize(@NotNull File file, @NotNull ConfigurationSection map) { if (!map.contains("id")) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Quest doesn't have an id."); return null; } - + QuestImplementation qu = new QuestImplementation(map.getInt("id"), file); - + qu.manager = BranchesManagerImplementation.deserialize(map.getConfigurationSection("manager"), qu); if (qu.manager == null) return null; - + for (String key : map.getKeys(false)) { for (QuestOptionCreator<?, ?> creator : QuestOptionCreator.creators.values()) { if (creator.applies(key)) { @@ -676,5 +641,5 @@ private void save(@NotNull ConfigurationSection section) { return qu; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index c1c802fd..7c2ff63c 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -19,11 +19,7 @@ import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; -import fr.skytasul.quests.api.stages.AbstractStage; -import fr.skytasul.quests.api.stages.StageController; -import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; -import fr.skytasul.quests.api.stages.StageHandler; -import fr.skytasul.quests.api.stages.StageType; +import fr.skytasul.quests.api.stages.*; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.utils.QuestUtils; @@ -100,7 +96,7 @@ public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nu @Override public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { try { - StageDescriptionPlaceholdersContext context = StageDescriptionPlaceholdersContext.of(true, acc, source); + StageDescriptionPlaceholdersContext context = StageDescriptionPlaceholdersContext.of(true, acc, source, null); String description = stage.getCustomText() == null ? stage.getDefaultDescription(context) : ("§e" + stage.getCustomText()); return MessageUtils.finalFormat(description, stage.getPlaceholdersRegistry(), context); @@ -126,7 +122,7 @@ private void propagateStageHandlers(@NotNull Consumer<@NotNull StageHandler> con public void start(@NotNull PlayerAccount acc) { if (acc.isCurrent()) - MessageUtils.sendMessage(acc.getPlayer(), stage.getStartMessage(), MessageType.OFF); + MessageUtils.sendMessage(acc.getPlayer(), stage.getStartMessage(), MessageType.DefaultMessageType.OFF); Map<String, Object> datas = new HashMap<>(); stage.initPlayerDatas(acc, datas); acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java index cd34d16b..08fbcffb 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java @@ -21,7 +21,7 @@ public class Command implements HasPlaceholders { public final boolean console; public final boolean parse; public final int delay; - + private @Nullable PlaceholderRegistry placeholders; public Command(String label, boolean console, boolean parse, int delay) { @@ -30,10 +30,10 @@ public Command(String label, boolean console, boolean parse, int delay) { this.parse = parse; this.delay = delay; } - + public void execute(Player o){ Runnable run = () -> { - String formattedCommand = MessageUtils.finalFormat(label, null, PlaceholdersContext.of(o, parse)); + String formattedCommand = MessageUtils.finalFormat(label, null, PlaceholdersContext.of(o, parse, null)); CommandSender sender = console ? Bukkit.getConsoleSender() : o; Bukkit.dispatchCommand(sender, formattedCommand); @@ -43,7 +43,7 @@ public void execute(Player o){ run.run(); }else Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), run, delay); } - + @Override public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { if (placeholders == null) { @@ -58,17 +58,17 @@ public void execute(Player o){ public Map<String, Object> serialize(){ Map<String, Object> map = new HashMap<>(); - + map.put("label", label); map.put("console", console); if (parse) map.put("parse", parse); if (delay > 0) map.put("delay", delay); - + return map; } - + public static Command deserialize(Map<String, Object> map){ return new Command((String) map.get("label"), (boolean) map.get("console"), (boolean) map.getOrDefault("parse", Boolean.FALSE), (int) map.getOrDefault("delay", 0)); } - + } 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 de558e45..da8fe491 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java @@ -34,13 +34,13 @@ import fr.skytasul.quests.integrations.worldguard.BQWorldGuard; public class IntegrationsLoader { - + private static IntegrationsLoader instance; public static IntegrationsLoader getInstance() { return instance; } - + private IntegrationsConfiguration config; public IntegrationsLoader() { @@ -121,7 +121,7 @@ private void registerPapi() { QuestsAPI.getAPI().getRequirements() .register(new RequirementCreator("placeholderRequired", PlaceholderRequirement.class, ItemUtils.item(XMaterial.NAME_TAG, Lang.RPlaceholder.toString()), PlaceholderRequirement::new)); - QuestsAPI.getAPI().registerMessageProcessor(new PapiMessageProcessor()); + QuestsAPI.getAPI().registerMessageProcessor("placeholderapi_replace", 5, new PapiMessageProcessor()); } private void registerVault() { @@ -211,7 +211,7 @@ private boolean isZnpcsVersionValid(Plugin plugin) { + plugin.getDescription().getVersion() + ") is not supported by BeautyQuests."); return false; } - + public IntegrationsConfiguration getConfig() { return config; } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java index 78ffd0a7..70ac4e1b 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PapiMessageProcessor.java @@ -8,11 +8,6 @@ public class PapiMessageProcessor implements MessageProcessor { - @Override - public int getPriority() { - return 5; - } - @Override public @NotNull String processString(@NotNull String string, @NotNull PlaceholdersContext context) { if (context.replacePluginPlaceholders() && context.getActor() instanceof Player) { diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java index 946bed7d..fce48ede 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/PlaceholderRequirement.java @@ -21,10 +21,10 @@ public class PlaceholderRequirement extends AbstractRequirement { private String rawPlaceholder; - + private PlaceholderExpansion hook; private String params; - + private String value; private ComparisonMethod comparison; private boolean parseValue = false; @@ -32,7 +32,7 @@ public class PlaceholderRequirement extends AbstractRequirement { public PlaceholderRequirement(){ this(null, null, null, null, ComparisonMethod.EQUALS); } - + public PlaceholderRequirement(String customDescription, String customReason, String placeholder, String value, ComparisonMethod comparison) { super(customDescription, customReason); @@ -70,10 +70,10 @@ public boolean test(Player p){ if (comparison == ComparisonMethod.DIFFERENT) return !value.equals(request); String value = this.value; if (parseValue) - value = MessageUtils.finalFormat(value, null, PlaceholdersContext.of(p, true)); + value = MessageUtils.finalFormat(value, null, PlaceholdersContext.of(p, true, null)); return value.equals(request); } - + @Override public boolean isValid() { return hook != null; @@ -83,7 +83,7 @@ public boolean isValid() { protected String getInvalidReason() { return "unknown placeholder " + rawPlaceholder; } - + public void setPlaceholder(String placeholder){ this.rawPlaceholder = placeholder; int index = placeholder.indexOf("_"); @@ -104,19 +104,19 @@ public void setPlaceholder(String placeholder){ } } } - + public void setValue(String value){ this.value = value; } - + public String getPlaceholder(){ return rawPlaceholder; } - + public String getValue(){ return value; } - + @Override public void save(ConfigurationSection section) { super.save(section); @@ -168,10 +168,10 @@ public void itemClick(QuestObjectClickEvent event) { }).start(); }).useStrippedMessage().start(); } - + @Override public AbstractRequirement clone() { return new PlaceholderRequirement(getCustomDescription(), getCustomReason(), rawPlaceholder, value, comparison); } - + } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java index 0c1dea2e..1237e7e6 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java @@ -177,7 +177,7 @@ public void setExit(boolean exit) { private void launchRegionEditor(Player p, boolean first) { MessageUtils.sendMessage(p, Lang.REGION_NAME.toString() + (first ? "" : "\n" + Lang.TYPE_CANCEL.toString()), - MessageType.PREFIXED); + MessageType.DefaultMessageType.PREFIXED); new TextEditor<String>(p, () -> { if (first) context.remove(); From cc26130818dd3d9e1c5f36f33e30ce078b041da6 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 24 Aug 2023 21:36:45 +0200 Subject: [PATCH 42/95] :memo: Added some javadoc on the API --- .../fr/skytasul/quests/api/QuestsAPI.java | 154 +++++++++++++++++- .../fr/skytasul/quests/api/QuestsPlugin.java | 20 ++- .../quests/api/npcs/BqNpcManager.java | 6 + .../api/serializable/SerializableObject.java | 28 ++-- .../java/fr/skytasul/quests/BeautyQuests.java | 2 +- .../quests/QuestsAPIImplementation.java | 10 -- .../BranchesManagerImplementation.java | 2 +- .../structure/QuestBranchImplementation.java | 4 +- 8 files changed, 189 insertions(+), 37 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java index eddc21f4..72e975ba 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -10,6 +10,7 @@ import fr.skytasul.quests.api.mobs.MobFactory; import fr.skytasul.quests.api.mobs.MobStacker; import fr.skytasul.quests.api.npcs.BqInternalNpcFactory; +import fr.skytasul.quests.api.npcs.BqNpcManager; import fr.skytasul.quests.api.objects.QuestObjectsRegistry; import fr.skytasul.quests.api.options.QuestOptionCreator; import fr.skytasul.quests.api.pools.QuestPoolsManager; @@ -27,72 +28,212 @@ */ public interface QuestsAPI { + /** + * Utility method to get the instance of the plugin. + * + * @return the plugin instance + */ @NotNull QuestsPlugin getPlugin(); + /** + * Gets the quests manager, which provides methods to get and manage quests and also get list of + * quests based on player progress. + * + * @return the quest manager + */ @NotNull QuestsManager getQuestsManager(); + /** + * Gets the quest pools manager, which provides methods to get and manage pools. + * + * @return the pools manager + */ @NotNull QuestPoolsManager getPoolsManager(); /** - * Register new mob factory - * @param factory MobFactory instance + * Registers a new mob factory. + * + * @param factory a MobFactory instance that has not yet been registered */ void registerMobFactory(@NotNull MobFactory<?> factory); + /** + * Registers a new quest option creator. + * + * @param creator instance of the option creator + */ void registerQuestOption(@NotNull QuestOptionCreator<?, ?> creator); + /** + * Gets all registered item comparisons. + * + * @return immutable list of registered comparisons + */ @NotNull List<@NotNull ItemComparison> getItemComparisons(); + /** + * Registers a new item comparison instance. + * + * @param comparison instance of an item comparison that has not already been registered + */ void registerItemComparison(@NotNull ItemComparison comparison); + /** + * Unregisters a previsouly registered item comparison instance. + * + * @param comparison instance of an item comparison that has been registered + */ void unregisterItemComparison(@NotNull ItemComparison comparison); + /** + * Gets a list of registered mob stackers. + * + * @return immutable list of registered stackers + */ @NotNull List<@NotNull MobStacker> getMobStackers(); + /** + * Registers a new mob stacker instance. + * + * @param stacker instance of a mob stacker that has not already been registered + */ void registerMobStacker(@NotNull MobStacker stacker); + /** + * Gets the stage type registry, which provides methods to register stage types, stage options and + * get existing stage type. + * + * @return the stage type registry + */ @NotNull StageTypeRegistry getStages(); + /** + * Gets the requirements registry, which provides methods to register and get requirements. + * + * @return the requirements registry + */ @NotNull QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getRequirements(); + /** + * Gets the rewards registry, which provides methods to register and get rewards. + * + * @return the rewards registry + */ @NotNull QuestObjectsRegistry<AbstractReward, RewardCreator> getRewards(); + /** + * Adds a new npc factory to the npc manager. + * + * @param key unique key of the npc factory + * @param factory factory + * @see BqNpcManager#addInternalFactory(String, BqInternalNpcFactory) + */ void addNpcFactory(@NotNull String key, @NotNull BqInternalNpcFactory factory); - boolean hasHologramsManager(); + /** + * Checks if there is an hologram manager registered. + * + * @return <code>true</code> if {@link #getHologramsManager()} will not return <code>null</code>, + * <code>false</code> otherwise + */ + default boolean hasHologramsManager() { + return getHologramsManager() != null; + } + /** + * Gets the currently registered holograms manager. + * + * @return the current holograms manager + */ @Nullable AbstractHolograms<?> getHologramsManager(); + /** + * Sets the plugin's holograms manager to the one passed as argument.<br> + * If there is already an holograms manager registered, this one will replace it. + * + * @param newHologramsManager holograms manager to register + */ void setHologramsManager(@NotNull AbstractHolograms<?> newHologramsManager); - boolean hasBossBarManager(); + /** + * Checks if there is a boss bar manager registered. + * + * @return <code>true</code> if {@link #getBossBarManager()} will not return <code>null</code>, + * <code>false</code> otherwise + */ + default boolean hasBossBarManager() { + return getBossBarManager() != null; + } + /** + * Gets the currently registered boss bars manager. + * + * @return the current boss bars manager + */ @Nullable BossBarManager getBossBarManager(); + /** + * Sets the plugin's boss bars manager to the one passed as argument.<br> + * If there is already a boss bars manager registered, this one will replace it. + * + * @param newBossBarManager boss bars manager to register + */ void setBossBarManager(@NotNull BossBarManager newBossBarManager); + /** + * Gets the blocks manager, which provides methods to register custom block types and deserialize + * blocks. + * + * @return the blocks manager + */ @NotNull BQBlocksManager getBlocksManager(); + /** + * Registers a quests handler and calls {@link QuestsHandler#load()} if it was not already + * registered. + * + * @param handler handler to register + */ void registerQuestsHandler(@NotNull QuestsHandler handler); + /** + * Unregisters a quests handler and calls {@link QuestsHandler#unload()} if it was registered. + * + * @param handler handler to unregister + */ void unregisterQuestsHandler(@NotNull QuestsHandler handler); + /** + * Gets the registered quests handlers. + * + * @return an unmodifiable collection of registered quest handlers + */ @NotNull Collection<@NotNull QuestsHandler> getQuestsHandlers(); + /** + * Utility method to call a method on every registered quests handlers. + * + * @param consumer action to do on quests handlers + */ void propagateQuestsHandlers(@NotNull Consumer<@NotNull QuestsHandler> consumer); + /** + * Gets all registered message processors. + * + * @return an unmodifiable collection of registered message processors + */ @NotNull Collection<MessageProcessor> getMessageProcessors(); @@ -108,6 +249,11 @@ public interface QuestsAPI { */ void registerMessageProcessor(@NotNull String key, int priority, @NotNull MessageProcessor processor); + /** + * Utility method to get an instance of the API object. + * + * @return the api object + */ public static @NotNull QuestsAPI getAPI() { return QuestsAPIProvider.getAPI(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java index be5d3053..d0a8b40f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java @@ -12,16 +12,21 @@ public interface QuestsPlugin extends Plugin { + /** + * Utility method to get the API object. + * + * @return the api object + */ public @NotNull QuestsAPI getAPI(); public @NotNull CommandsManager getCommand(); - + public @NotNull QuestsConfiguration getConfiguration(); - + public @NotNull PlayersManager getPlayersManager(); public @NotNull LoggerExpanded getLoggerExpanded(); - + public @NotNull GuiManager getGuiManager(); public @NotNull EditorManager getEditorManager(); @@ -32,8 +37,13 @@ public interface QuestsPlugin extends Plugin { public void notifyLoadingFailure(); - public void noticeSavingFailure(); - + public void notifySavingFailure(); + + /** + * Utility method to get the plugin object. + * + * @return the plugin object + */ public static @NotNull QuestsPlugin getPlugin() { return QuestsAPIProvider.getAPI().getPlugin(); } diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java index f963f21f..6900dc63 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java @@ -14,6 +14,12 @@ public interface BqNpcManager { boolean isEnabled(); + /** + * Adds a new npc factory to the npc manager. + * + * @param key unique key of the npc factory + * @param internalFactory factory + */ void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactory internalFactory); @NotNull diff --git a/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java b/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java index 40de71f5..f78b1360 100644 --- a/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/serializable/SerializableObject.java @@ -12,14 +12,14 @@ import fr.skytasul.quests.api.utils.Utils; public abstract class SerializableObject { - + protected final @NotNull SerializableCreator creator; protected SerializableObject(@NotNull SerializableRegistry registry) { this.creator = registry.getByClass(getClass()); if (creator == null) throw new IllegalArgumentException(getClass().getName() + " has not been registered as an object."); } - + protected SerializableObject(@NotNull SerializableCreator creator) { this.creator = creator; if (creator == null) throw new IllegalArgumentException("Creator cannot be null."); @@ -35,11 +35,11 @@ protected SerializableObject(@NotNull SerializableCreator creator) { @Override public abstract @NotNull SerializableObject clone(); - + public abstract void save(@NotNull ConfigurationSection section); - + public abstract void load(@NotNull ConfigurationSection section); - + public final void serialize(@NotNull ConfigurationSection section) { section.set("id", creator.getID()); save(section); @@ -49,20 +49,20 @@ public static <T extends SerializableObject, C extends SerializableCreator<T>> T @NotNull Map<String, Object> map, @NotNull SerializableRegistry<T, C> registry) { return deserialize(Utils.createConfigurationSection(map), registry); } - + public static <T extends SerializableObject, C extends SerializableCreator<T>> @NotNull T deserialize( @NotNull ConfigurationSection section, @NotNull SerializableRegistry<T, C> registry) { SerializableCreator<T> creator = null; - + String id = section.getString("id"); if (id != null) creator = registry.getByID(id); - + if (creator == null && section.contains("class")) { String className = section.getString("class"); try { creator = registry.getByClass(Class.forName(className)); }catch (ClassNotFoundException e) {} - + if (creator == null) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot find object class " + className); return null; @@ -85,19 +85,19 @@ public static <T extends SerializableObject, C extends SerializableCreator<T>> T T object = deserializeFunction.apply((Map<String, Object>) objectMap); if (object == null) { QuestsPlugin.getPlugin().notifyLoadingFailure(); - QuestsPlugin.getPlugin().getLoggerExpanded().severe("The quest object for class " - + String.valueOf(objectMap.get("class")) + " has not been deserialized."); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("The quest object for id " + + String.valueOf(objectMap.get("id")) + " has not been deserialized."); }else objects.add(object); }catch (Exception e) { QuestsPlugin.getPlugin().notifyLoadingFailure(); QuestsPlugin.getPlugin().getLoggerExpanded().severe( - "An exception occured while deserializing a quest object (class " + objectMap.get("class") + ").", + "An exception occured while deserializing a quest object (id " + objectMap.get("id") + ").", e); } } return objects; } - + public static @NotNull List<Map<String, Object>> serializeList(@NotNull List<? extends SerializableObject> objects) { return objects.stream().map(object -> { MemoryConfiguration section = new MemoryConfiguration(); @@ -105,5 +105,5 @@ public static <T extends SerializableObject, C extends SerializableCreator<T>> T return section.getValues(false); }).collect(Collectors.toList()); } - + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index fe1d7982..48d45ade 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -724,7 +724,7 @@ public boolean hasLoadingFailed() { } @Override - public void noticeSavingFailure() { + public void notifySavingFailure() { savingFailure = true; } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java index c70114db..012f738f 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -118,11 +118,6 @@ public void addNpcFactory(@NotNull String key, @NotNull BqInternalNpcFactory fac QuestsPlugin.getPlugin().getNpcManager().addInternalFactory(key, factory); } - @Override - public boolean hasHologramsManager() { - return hologramsManager != null; - } - @Override public @Nullable AbstractHolograms<?> getHologramsManager() { return hologramsManager; @@ -139,11 +134,6 @@ public void setHologramsManager(@NotNull AbstractHolograms<?> newHologramsManage .debug("Holograms manager has been registered: " + newHologramsManager.getClass().getName()); } - @Override - public boolean hasBossBarManager() { - return bossBarManager != null; - } - @Override public @Nullable BossBarManager getBossBarManager() { return bossBarManager; diff --git a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java index b507d4f6..c51673c8 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/BranchesManagerImplementation.java @@ -109,7 +109,7 @@ public void save(@NotNull ConfigurationSection section) { }catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded() .severe("Error when serializing the branch " + id + " for the quest " + quest.getId(), ex); - QuestsPlugin.getPlugin().noticeSavingFailure(); + QuestsPlugin.getPlugin().notifySavingFailure(); } }); } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java index 5085c493..a43e445b 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -340,7 +340,7 @@ public void save(@NotNull ConfigurationSection section) { }catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded() .severe("Error when serializing the stage " + i + " for the quest " + getQuest().getId(), ex); - QuestsPlugin.getPlugin().noticeSavingFailure(); + QuestsPlugin.getPlugin().notifySavingFailure(); } } @@ -356,7 +356,7 @@ public void save(@NotNull ConfigurationSection section) { }catch (Exception ex){ QuestsPlugin.getPlugin().getLoggerExpanded() .severe("Error when serializing the ending stage " + i + " for the quest " + getQuest().getId(), ex); - QuestsPlugin.getPlugin().noticeSavingFailure(); + QuestsPlugin.getPlugin().notifySavingFailure(); } } } From 35abdf2371072f050c851f0214d2682b8d27c7e4 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 24 Aug 2023 23:02:58 +0200 Subject: [PATCH 43/95] :sparkles: Checkpoint system now follows quest flow --- .../quests/api/players/PlayerQuestDatas.java | 3 + .../quests/commands/CommandsPlayer.java | 36 ++++++------ .../quests/gui/quests/DialogHistoryGUI.java | 57 +++++++------------ .../PlayerQuestDatasImplementation.java | 21 +++++++ 4 files changed, 61 insertions(+), 56 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java b/api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java index b4cd056e..f5ba748a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java +++ b/api/src/main/java/fr/skytasul/quests/api/players/PlayerQuestDatas.java @@ -1,6 +1,7 @@ package fr.skytasul.quests.api.players; import java.util.Map; +import java.util.stream.Stream; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.quests.Quest; @@ -61,4 +62,6 @@ public interface PlayerQuestDatas { void resetQuestFlow(); + Stream<StageController> getQuestFlowStages(); + } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java index c77c3202..676fb974 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPlayer.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.commands; +import java.util.Objects; import java.util.Optional; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsPlugin; @@ -16,12 +17,10 @@ import fr.skytasul.quests.api.players.PlayerQuestDatas; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.quests.branches.QuestBranch; -import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.rewards.CheckpointReward; public class CommandsPlayer implements OrphanCommand { - + @Default @CommandPermission ("beautyquests.command.listPlayer") public void menu(BukkitCommandActor actor, ExecutableCommand command, @@ -35,28 +34,27 @@ public void menu(BukkitCommandActor actor, ExecutableCommand command, } else QuestsPlugin.getPlugin().getGuiManager().getFactory().createPlayerQuestsMenu(acc).open(actor.getAsPlayer()); } - + @Subcommand ("checkpoint") @CommandPermission ("beautyquests.command.checkpoint") public void checkpoint(Player player, Quest quest) { PlayerAccount account = PlayersManager.getPlayerAccount(player); if (account.hasQuestDatas(quest)) { PlayerQuestDatas datas = account.getQuestDatas(quest); - QuestBranch branch = quest.getBranchesManager().getBranch(datas.getBranch()); - int max = datas.isInEndingStages() ? branch.getRegularStages().size() : datas.getStage(); - - // TODO: should use quest flow - - for (int id = max - 1; id >= 0; id--) { - AbstractStage stage = branch.getRegularStage(id).getStage(); - Optional<CheckpointReward> optionalCheckpoint = stage.getRewards().stream().filter(CheckpointReward.class::isInstance).findAny().map(CheckpointReward.class::cast); - if (optionalCheckpoint.isPresent()) { - optionalCheckpoint.get().applies(player); - return; - } - } - Lang.COMMAND_CHECKPOINT_NO.send(player, quest.getPlaceholdersRegistry()); + + Optional<CheckpointReward> optionalCheckpoint = datas.getQuestFlowStages() + .map(controller -> controller.getStage().getRewards().stream() + .filter(CheckpointReward.class::isInstance).findAny() + .map(CheckpointReward.class::cast).orElse(null)) + .filter(Objects::nonNull) + .reduce((left, right) -> right); + + if (optionalCheckpoint.isPresent()) + optionalCheckpoint.get().applies(player); + else + Lang.COMMAND_CHECKPOINT_NO.send(player, quest.getPlaceholdersRegistry()); + }else Lang.COMMAND_CHECKPOINT_NOT_STARTED.send(player); } - + } 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 5d040c07..3f04f408 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 @@ -1,10 +1,6 @@ package fr.skytasul.quests.gui.quests; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import java.util.stream.Stream; import org.apache.commons.lang.Validate; import org.bukkit.DyeColor; @@ -22,7 +18,6 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayerQuestDatas; import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.api.utils.ChatColorUtils; import fr.skytasul.quests.api.utils.XMaterial; @@ -31,32 +26,32 @@ import fr.skytasul.quests.utils.QuestUtils; public class DialogHistoryGUI extends PagedGUI<WrappedDialogable> { - + private final Runnable end; private final Player player; - + public DialogHistoryGUI(PlayerAccount acc, Quest quest, Runnable end) { super(quest.getName(), DyeColor.LIGHT_BLUE, Collections.emptyList(), x -> end.run(), null); this.end = end; - + Validate.isTrue(acc.hasQuestDatas(quest), "Player must have started the quest"); Validate.isTrue(acc.isCurrent(), "Player must be online"); - + player = acc.getPlayer(); - + if (quest.hasOption(OptionStartDialog.class)) objects.add(new WrappedDialogable(quest.getOption(OptionStartDialog.class))); - + getDialogableStream(acc.getQuestDatas(quest), quest) .map(WrappedDialogable::new) .forEach(objects::add); } - + @Override public ItemStack getItemStack(WrappedDialogable object) { return object.setMeta(XMaterial.WRITTEN_BOOK.parseItem()); } - + @Override public void click(WrappedDialogable existing, ItemStack item, ClickType clickType) { boolean changed = false; @@ -73,10 +68,10 @@ public void click(WrappedDialogable existing, ItemStack item, ClickType clickTyp QuestUtils.playPluginSound(player, "ENTITY_BAT_TAKEOFF", 0.4f, 1.7f); } } - + if (changed) existing.setMeta(item); } - + @Override public CloseBehavior onClose(Player p) { QuestUtils.runSync(end); @@ -84,32 +79,20 @@ public CloseBehavior onClose(Player p) { } public static Stream<Dialogable> getDialogableStream(PlayerQuestDatas datas, Quest quest) { - return Arrays.stream(datas.getQuestFlow().split(";")) - .filter(x -> !x.isEmpty()) - .map(arg -> { - String[] args = arg.split(":"); - int branchID = Integer.parseInt(args[0]); - QuestBranch branch = quest.getBranchesManager().getBranch(branchID); - if (branch == null) return null; - if (args[1].startsWith("E")) { - return branch.getEndingStage(Integer.parseInt(args[1].substring(1))); - }else { - return branch.getRegularStage(Integer.parseInt(args[1])); - } - }) + return datas.getQuestFlowStages() .filter(Dialogable.class::isInstance) .map(Dialogable.class::cast) .filter(Dialogable::hasDialog); } - + class WrappedDialogable { static final int MAX_LINES = 9; - + final Dialogable dialogable; final List<Page> pages; - + int page = 0; - + WrappedDialogable(Dialogable dialogable) { this.dialogable = dialogable; @@ -172,11 +155,11 @@ class WrappedDialogable { pages.add(page); } } - + public Page getCurrentPage() { return pages.get(page); } - + public ItemStack setMeta(ItemStack item) { ItemMeta meta = item.getItemMeta(); meta.setLore(getCurrentPage().lines); @@ -187,10 +170,10 @@ public ItemStack setMeta(ItemStack item) { return item; } } - + class Page { LinkedList<String> lines = new LinkedList<>(); String header; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java index f5a4865e..bc37ddfe 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java @@ -1,12 +1,15 @@ package fr.skytasul.quests.players; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.StringJoiner; +import java.util.stream.Stream; import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.players.PlayerQuestDatas; import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.quests.branches.QuestBranch; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.gui.quests.DialogHistoryGUI; @@ -163,6 +166,24 @@ public String getQuestFlow() { return questFlow.toString(); } + @Override + public Stream<StageController> getQuestFlowStages() { + return Arrays.stream(getQuestFlow().split(";")) + .filter(x -> !x.isEmpty()) + .map(arg -> { + String[] args = arg.split(":"); + int branchID = Integer.parseInt(args[0]); + QuestBranch branch = getQuest().getBranchesManager().getBranch(branchID); + if (branch == null) + return null; + if (args[1].startsWith("E")) { + return branch.getEndingStage(Integer.parseInt(args[1].substring(1))); + } else { + return branch.getRegularStage(Integer.parseInt(args[1])); + } + }); + } + @Override public void addQuestFlow(StageController finished) { questFlow.add(finished.getBranch().getId() + ":" + finished.getFlowId()); From 2b68313b5404b67595a217193cb8f285250d11b2 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 3 Sep 2023 12:46:58 +0200 Subject: [PATCH 44/95] :bug: Fixed several bugs preventing plugin to load --- .../api/stages/creation/StageGuiLine.java | 2 +- .../quests/api/utils/AutoRegistered.java | 4 +- .../quests/api/utils/IntegrationManager.java | 2 +- .../HasItemsDescriptionConfiguration.java | 3 - .../quests/commands/CommandsPools.java | 6 +- .../stages/StageLineImplementation.java | 12 ++-- .../quests/gui/creation/stages/StagesGUI.java | 34 +++++----- .../fr/skytasul/quests/gui/misc/TitleGUI.java | 34 ++++------ .../quests/gui/quests/PlayerListGUI.java | 64 +++++++++---------- .../skytasul/quests/utils/ParticleEffect.java | 46 ++++++------- .../fr/skytasul/quests/utils/QuestUtils.java | 25 ++++++-- dist/pom.xml | 7 ++ 12 files changed, 131 insertions(+), 108 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java index ef575d24..8071a15f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageGuiLine.java @@ -12,7 +12,7 @@ public interface StageGuiLine { @Nullable ItemStack getItem(int slot); - void setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHandler click); + int setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHandler click); void refreshItem(int slot, @NotNull ItemStack item); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java b/api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java index e2c3f01a..54692c64 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/AutoRegistered.java @@ -2,6 +2,7 @@ import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.Target; import org.bukkit.event.Listener; @@ -9,10 +10,11 @@ /** * Marks classes that will be automatically registered as event listener if they implement the * {@link Listener} interface. - * + * * @author SkytAsul */ @Retention(RUNTIME) @Target(TYPE) +@Inherited public @interface AutoRegistered { } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java b/api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java index 7a0e4468..9f395189 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/IntegrationManager.java @@ -13,7 +13,7 @@ public class IntegrationManager implements Listener { - private List<BQDependency> dependencies; + private final List<BQDependency> dependencies = new ArrayList<>(); private boolean dependenciesTested = false; private boolean dependenciesInitialized = false; private boolean lockDependencies = false; diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/HasItemsDescriptionConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/HasItemsDescriptionConfiguration.java index ecad9e0b..4b56ed61 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/HasItemsDescriptionConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/itemdescription/HasItemsDescriptionConfiguration.java @@ -23,9 +23,6 @@ public interface HasSingleObject extends HasItemsDescriptionConfiguration, HasPr int getObjectAmount(); - @Override - int getPlayerAmount(@NotNull PlayerAccount account); - @Override default int getTotalAmount() { return getObjectAmount(); diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index c26178a0..6c51a592 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java @@ -11,9 +11,9 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.pools.PoolsManageGUI; -import fr.skytasul.quests.structure.pools.QuestPoolImplementation; public class CommandsPools implements OrphanCommand { @@ -25,7 +25,7 @@ public void pools(Player player) { @Subcommand("resetPlayer") @CommandPermission("beautyquests.command.resetPlayer") - public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPoolImplementation pool, @Switch boolean timer) { + public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPool pool, @Switch boolean timer) { PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (timer) { pool.resetPlayerTimer(acc); @@ -40,7 +40,7 @@ public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPoolIm @Subcommand("start") @CommandPermission("beautyquests.command.pools.start") - public void start(BukkitCommandActor actor, Player player, QuestPoolImplementation pool) { + public void start(BukkitCommandActor actor, Player player, QuestPool pool) { PlayerAccount acc = PlayersManager.getPlayerAccount(player); if (!pool.canGive(player)) { Lang.POOL_START_ERROR.send(player, pool, acc); diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java index 28ba0b6f..bdb8014c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java @@ -12,7 +12,7 @@ public class StageLineImplementation implements StageGuiLine { private final @NotNull StagesGUI.Line line; private final @NotNull Map<Integer, LineItem> items = new HashMap<>(); - + private int page, maxPage; public StageLineImplementation(StagesGUI.Line line) { @@ -32,9 +32,11 @@ public boolean isEmpty() { } @Override - public void setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHandler click) { - if (items.containsKey(slot)) - throw new IllegalArgumentException("Slot " + slot + " already taken"); + public int setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHandler click) { + while (items.containsKey(slot)) + slot++; + // this ensures no item is at the slot + // if there was an item in the original slot, then a higher slot is selected items.put(slot, new LineItem(item, click)); @@ -42,6 +44,8 @@ public void setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHa if (isSlotShown(slot)) refresh(); + + return slot; } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index f0ae5f0b..9b0ae0fd 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -34,35 +34,34 @@ public class StagesGUI extends AbstractGui { private static final int SLOT_FINISH = 52; - + private static final ItemStack stageCreate = ItemUtils.item(XMaterial.SLIME_BALL, Lang.stageCreate.toString()); private static final ItemStack notDone = ItemUtils.lore(ItemUtils.itemNotDone.clone(), Lang.cantFinish.toString()); - + private List<Line> lines = new ArrayList<>(); - + private final QuestCreationSession session; private final StagesGUI previousBranch; - public Inventory inv; int page; private boolean stop = false; public StagesGUI(QuestCreationSession session) { this(session, null); } - + public StagesGUI(QuestCreationSession session, StagesGUI previousBranch) { this.session = session; this.previousBranch = previousBranch; } - + @Override protected Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, 54, Lang.INVENTORY_STAGES.toString()); } @Override - protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + protected void populate(@NotNull Player player, @NotNull Inventory inv) { page = 0; for (int i = 0; i < 20; i++) lines.add(new Line(i, i >= 15)); @@ -99,12 +98,12 @@ public Line getLine(int id) { } return null; } - + public boolean isEmpty(){ if (lines.isEmpty()) return true; // if this StagesGUI has never been opened return !getLine(0).isActive() && !getLine(15).isActive(); } - + public void deleteStageLine(Line line) { if (line.isActive()) line.remove(); @@ -162,9 +161,14 @@ public void onClick(@NotNull GuiClickEvent event) { } private void refresh() { - for (int i = 0; i < 3; i++) inv.setItem(i + 46, ItemUtils.item(i == page ? XMaterial.LIME_STAINED_GLASS_PANE : XMaterial.WHITE_STAINED_GLASS_PANE, Lang.regularPage.toString())); - inv.setItem(49, ItemUtils.item(page == 3 ? XMaterial.MAGENTA_STAINED_GLASS_PANE : XMaterial.PURPLE_STAINED_GLASS_PANE, Lang.branchesPage.toString())); - + for (int i = 0; i < 3; i++) + getInventory().setItem(i + 46, + ItemUtils.item(i == page ? XMaterial.LIME_STAINED_GLASS_PANE : XMaterial.WHITE_STAINED_GLASS_PANE, + Lang.regularPage.toString())); + getInventory().setItem(49, + ItemUtils.item(page == 3 ? XMaterial.MAGENTA_STAINED_GLASS_PANE : XMaterial.PURPLE_STAINED_GLASS_PANE, + Lang.branchesPage.toString())); + lines.forEach(l -> l.lineObj.refresh()); } @@ -173,7 +177,7 @@ public List<StageCreationContextImplementation> getStageCreations() { return lines.stream().sorted(Comparator.comparingInt(line -> line.lineId)).filter(line -> line.isActive()) .map(line -> line.context).collect(Collectors.toList()); } - + private void editBranch(QuestBranchImplementation branch){ for (StageController stage : branch.getRegularStages()) { getLine(branch.getRegularStageId(stage)).setStageEdition(stage); @@ -222,7 +226,7 @@ <T extends AbstractStage> StageCreation<T> setStageCreation(StageType<T> type) { context.setCreation( (StageCreation) type.getCreationSupplier().supply((@NotNull StageCreationContext<T>) context)); - inv.setItem(SLOT_FINISH, ItemUtils.itemDone); + getInventory().setItem(SLOT_FINISH, ItemUtils.itemDone); int maxStages = ending ? 20 : 15; ItemStack manageItem = ItemUtils.item(XMaterial.BARRIER, Lang.stageType.format(type), getLineManageLore(lineId)); @@ -315,7 +319,7 @@ void remove() { if (!isFirst()) getLine(lineId - 1).updateLineManageLore(); if (isEmpty()) - inv.setItem(SLOT_FINISH, notDone); + getInventory().setItem(SLOT_FINISH, notDone); } void descend() { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index ac13d4a7..92b25f86 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -36,8 +36,6 @@ public class TitleGUI extends AbstractGui { private boolean canFinish = false; - private Inventory inv; - public TitleGUI(Consumer<Title> end) { this.end = end; } @@ -55,39 +53,37 @@ public TitleGUI edit(Title edit) { private void updateFinishState() { canFinish = title != null || subtitle != null; - if (inv != null) { - Material material = canFinish ? Material.DIAMOND : Material.COAL; - ItemStack item = inv.getItem(8); - if (item.getType() != material) - item.setType(material); - } + Material material = canFinish ? Material.DIAMOND : Material.COAL; + ItemStack item = getInventory().getItem(8); + if (item.getType() != material) + item.setType(material); } public void setTitle(String title) { this.title = title; - ItemUtils.lore(inv.getItem(SLOT_TITLE), QuestOption.formatNullableValue(title)); + ItemUtils.loreOptionValue(getInventory().getItem(SLOT_TITLE), title); } public void setSubtitle(String subtitle) { this.subtitle = subtitle; - ItemUtils.lore(inv.getItem(SLOT_SUBTITLE), QuestOption.formatNullableValue(subtitle)); + ItemUtils.loreOptionValue(getInventory().getItem(SLOT_SUBTITLE), subtitle); } public void setFadeIn(int fadeIn) { this.fadeIn = fadeIn; - ItemUtils.lore(inv.getItem(SLOT_FADE_IN), + ItemUtils.lore(getInventory().getItem(SLOT_FADE_IN), QuestOption.formatNullableValue(Lang.Ticks.quickFormat("ticks", fadeIn), fadeIn == Title.FADE_IN)); } public void setStay(int stay) { this.stay = stay; - ItemUtils.lore(inv.getItem(SLOT_STAY), + ItemUtils.lore(getInventory().getItem(SLOT_STAY), QuestOption.formatNullableValue(Lang.Ticks.quickFormat("ticks", stay), stay == Title.STAY)); } public void setFadeOut(int fadeOut) { this.fadeOut = fadeOut; - ItemUtils.lore(inv.getItem(SLOT_FADE_OUT), + ItemUtils.lore(getInventory().getItem(SLOT_FADE_OUT), QuestOption.formatNullableValue(Lang.Ticks.quickFormat("ticks", fadeOut), fadeOut == Title.FADE_OUT)); } @@ -154,22 +150,18 @@ public CloseBehavior onClose(Player p) { private void startStringEditor(Player p, Lang helpMsg, Consumer<String> setter) { helpMsg.send(p); - new TextEditor<String>(p, () -> { - p.openInventory(inv); - }, msg -> { + new TextEditor<String>(p, () -> reopen(p), msg -> { setter.accept(msg); updateFinishState(); - p.openInventory(inv); + reopen(p); }).passNullIntoEndConsumer().start(); } private void startIntEditor(Player p, Lang helpMsg, Consumer<Integer> setter) { helpMsg.send(p); - new TextEditor<>(p, () -> { - p.openInventory(inv); - }, msg -> { + new TextEditor<>(p, () -> reopen(p), msg -> { setter.accept(msg); - p.openInventory(inv); + reopen(p); }, NumberParser.INTEGER_PARSER_POSITIVE).start(); } 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 de369289..d0026f94 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 @@ -34,25 +34,24 @@ public class PlayerListGUI extends AbstractGui { static final String UNSELECTED_PREFIX = "§7○ "; private static final String SELECTED_PREFIX = "§b§l● "; - - private Inventory inv; + private Player open; private PlayerAccountImplementation acc; private boolean hide; - + private int page = 0; private @Nullable PlayerListCategory cat = null; private List<Quest> quests; - + public PlayerListGUI(PlayerAccountImplementation acc) { this(acc, true); } - + public PlayerListGUI(PlayerAccountImplementation acc, boolean hide) { this.acc = acc; this.hide = hide; } - + @Override protected Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc)); @@ -62,7 +61,7 @@ protected Inventory instanciate(@NotNull Player player) { protected void populate(@NotNull Player player, @NotNull Inventory inventory) { setBarItem(0, ItemUtils.itemLaterPage); setBarItem(4, ItemUtils.itemNextPage); - + for (PlayerListCategory enabledCat : QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs()) { setBarItem(enabledCat.getSlot(), ItemUtils.item(enabledCat.getMaterial(), UNSELECTED_PREFIX + enabledCat.getName())); @@ -77,12 +76,12 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { setCategory(PlayerListCategory.NOT_STARTED); }else setCategory(PlayerListCategory.FINISHED); } - + private void setQuests(List<Quest> quests) { this.quests = quests; quests.sort(null); } - + private void setCategory(PlayerListCategory category){ if (cat == category) return; if (cat != null) @@ -91,15 +90,16 @@ private void setCategory(PlayerListCategory category){ page = 0; toggleCategorySelected(); setItems(); - + DyeColor color = cat == PlayerListCategory.FINISHED ? DyeColor.GREEN: (cat == PlayerListCategory.IN_PROGRESS ? DyeColor.YELLOW : DyeColor.RED); - for (int i = 0; i < 5; i++) inv.setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); + for (int i = 0; i < 5; i++) + getInventory().setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); } - + private void setItems(){ for (int i = 0; i < 35; i++) setMainItem(i, null); switch (cat){ - + case FINISHED: displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide), qu -> { List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), @@ -112,12 +112,12 @@ private void setItems(){ return createQuestItem(qu, lore); }); break; - + case IN_PROGRESS: displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false), qu -> { List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), qu, acc, cat, DescriptionSource.MENU).formatDescription(); - + boolean hasDialogs = QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() && acc.getQuestDatas(qu).hasFlowDialogs(); boolean cancellable = @@ -130,7 +130,7 @@ private void setItems(){ return createQuestItem(qu, lore); }); break; - + case NOT_STARTED: displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) @@ -145,7 +145,7 @@ private void setItems(){ break; } } - + private void displayQuests(List<Quest> quests, Function<Quest, ItemStack> itemProvider) { setQuests(quests); for (int i = page * 35; i < quests.size(); i++) { @@ -161,27 +161,27 @@ private void displayQuests(List<Quest> quests, Function<Quest, ItemStack> itemPr setMainItem(i - page * 35, item); } } - + private int setMainItem(int mainSlot, ItemStack is){ int line = (int) Math.floor(mainSlot * 1.0 / 7.0); int slot = mainSlot + (2 * line); - inv.setItem(slot, is); + getInventory().setItem(slot, is); return slot; } - + private int setBarItem(int barSlot, ItemStack is){ int slot = barSlot * 9 + 8; - inv.setItem(slot, is); + getInventory().setItem(slot, is); return slot; } - + private ItemStack createQuestItem(Quest qu, List<String> lore) { return ItemUtils.nameAndLore(qu.getQuestItem().clone(), open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu) : Lang.formatNormal.format(qu), lore); } - + private void toggleCategorySelected() { - ItemStack is = inv.getItem(cat.ordinal() * 9 + 8); + ItemStack is = getInventory().getItem(cat.ordinal() * 9 + 8); ItemMeta im = is.getItemMeta(); String name = im.getDisplayName(); if (!im.hasEnchant(Enchantment.DURABILITY)) { @@ -195,7 +195,7 @@ private void toggleCategorySelected() { is.setItemMeta(im); } - + @Override public void onClick(GuiClickEvent event) { switch (event.getSlot() % 9) { @@ -211,20 +211,20 @@ public void onClick(GuiClickEvent event) { page++; setItems(); break; - + case 1: case 2: case 3: PlayerListCategory category = PlayerListCategory.values()[barSlot]; if (category.isEnabled()) setCategory(category); break; - + } break; - + case 7: break; - + default: int id = (int) (event.getSlot() - (Math.floor(event.getSlot() * 1D / 9D) * 2) + page * 35); Quest qu = quests.get(id); @@ -254,13 +254,13 @@ public void onClick(GuiClickEvent event) { } } break; - + } } - + @Override public CloseBehavior onClose(Player p) { return StandardCloseBehavior.REMOVE; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java b/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java index 2922b4db..8021300c 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java +++ b/core/src/main/java/fr/skytasul/quests/utils/ParticleEffect.java @@ -14,22 +14,22 @@ import fr.skytasul.quests.utils.nms.NMS; public class ParticleEffect { - + private static Random random = new Random(); - + private final ParticleType type; private final ParticleShape shape; private final Color color; - + private final double[] colors; private final Object dustColor; - + public ParticleEffect(Particle bukkitType, ParticleShape shape, Color color) { Validate.notNull(bukkitType); this.type = new ParticleType(bukkitType); this.shape = shape; this.color = color; - + if (type.dustColored) { dustColor = Post1_13.getDustColor(color, 1); colors = null; @@ -45,28 +45,28 @@ public ParticleEffect(Particle bukkitType, ParticleShape shape, Color color) { color = null; } } - + public Particle getParticle() { return type.particle; } - + public ParticleShape getShape() { return shape; } - + public Color getColor() { return color; } - + @Override public String toString() { return type.particle.name() + (shape == null ? "" : " in shape " + shape.name()) + (type.colored ? " with color " + (type.particle != Particle.NOTE ? "R" + color.getRed() + " G" + color.getGreen() + " B" + color.getBlue() : "random") : ""); } - + public void send(Entity entity, List<Player> players) { send(entity.getLocation(), NMS.getNMS().entityNameplateHeight(entity), players); } - + public void send(Location bottom, double height, List<Player> players) { if (players.isEmpty()) return; switch (shape) { @@ -88,7 +88,7 @@ public void send(Location bottom, double height, List<Player> players) { break; } } - + public void sendParticle(Location lc, List<Player> players, double offX, double offY, double offZ, int amount) { double extra = 0.001; Object data = null; @@ -108,12 +108,12 @@ public void sendParticle(Location lc, List<Player> players, double offX, double amount = 0; // amount must be 0 for colors to be enabled extra = 1; // the extra field controls the brightness } - + for (Player p : players) { p.spawnParticle(type.particle, lc, amount, offX, offY, offZ, extra, data); } } - + public void serialize(ConfigurationSection section) { section.set("particleEffect", type.particle.name()); section.set("particleShape", shape.name()); @@ -126,25 +126,25 @@ public static ParticleEffect deserialize(ConfigurationSection data) { ParticleShape.valueOf(data.getString("particleShape").toUpperCase()), data.contains("particleColor") ? Color.deserialize(data.getConfigurationSection("particleColor").getValues(false)) : null); } - + public static boolean canHaveColor(Particle particle) { if (MinecraftVersion.MAJOR >= 13) return particle.getDataType() == Post1_13.getDustOptionClass(); return particle == Particle.REDSTONE || particle == Particle.SPELL_MOB || particle == Particle.SPELL_MOB_AMBIENT; } - + public enum ParticleShape { POINT, NEAR, BAR, EXCLAMATION, SPOT; } - + private static class ParticleType { - + private final Particle particle; private final boolean colored; private final boolean dustColored; - + private ParticleType(Particle particle) { this.particle = particle; - + if (particle == Particle.NOTE) { colored = true; dustColored = false; @@ -160,10 +160,10 @@ private ParticleType(Particle particle) { colored = particle == Particle.REDSTONE || particle == Particle.SPELL_MOB || particle == Particle.SPELL_MOB_AMBIENT; dustColored = false; } - + if (particle.getDataType() != Void.class && !dustColored) throw new IllegalArgumentException("Particle type " + particle.name() + " must have a " + particle.getDataType().getName() + " data"); } - + } - + } \ No newline at end of file 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 75e780e2..7f4e51b2 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -1,5 +1,7 @@ package fr.skytasul.quests.utils; +import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; import java.util.function.BiConsumer; import java.util.function.Consumer; import org.bukkit.Bukkit; @@ -133,10 +135,25 @@ public static void spawnFirework(Location lc, FireworkMeta meta) { }); } + public static boolean hasAnnotation(Class<?> clazz, Class<? extends Annotation> annotation) { + if (clazz.isAnnotationPresent(annotation)) + return true; + + if (!annotation.isAnnotationPresent(Inherited.class)) + return false; + + for (Class<?> interf : clazz.getInterfaces()) { + if (hasAnnotation(interf, annotation)) + return true; + } + + return false; + } + public static void autoRegister(Object object) { - if (!object.getClass().isAnnotationPresent(AutoRegistered.class)) + if (!hasAnnotation(object.getClass(), AutoRegistered.class)) throw new IllegalArgumentException("The class " + object.getClass().getName() - + " does not have the @AutoRegistered annotation and thus cannot be automatically registed as evenet listener."); + + " does not have the @AutoRegistered annotation and thus cannot be automatically registered as an events listener."); if (object instanceof Listener) { Bukkit.getPluginManager().registerEvents((Listener) object, BeautyQuests.getInstance()); @@ -144,9 +161,9 @@ public static void autoRegister(Object object) { } public static void autoUnregister(Object object) { - if (!object.getClass().isAnnotationPresent(AutoRegistered.class)) + if (!hasAnnotation(object.getClass(), AutoRegistered.class)) throw new IllegalArgumentException("The class " + object.getClass().getName() - + " does not have the @AutoRegistered annotation and thus cannot be automatically registed as evenet listener."); + + " does not have the @AutoRegistered annotation and thus cannot be automatically registered as an events listener."); if (object instanceof Listener) { HandlerList.unregisterAll((Listener) object); diff --git a/dist/pom.xml b/dist/pom.xml index d475dfd3..0f178dd7 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -37,6 +37,13 @@ </build> <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>beautyquests-api</artifactId> + <version>${project.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>beautyquests-core</artifactId> From 5c875530e597f79892d5b728a599d9c7a02e9494 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 5 Sep 2023 17:43:07 +0200 Subject: [PATCH 45/95] :bug: Fixed GUI issues --- api/dependency-reduced-pom.xml | 7 -- api/pom.xml | 7 -- core/pom.xml | 7 ++ .../quests/commands/CommandsAdmin.java | 62 ++++++----- .../quests/gui/GuiManagerImplementation.java | 9 +- .../gui/creation/QuestCreationSession.java | 17 ++- .../StageCreationContextImplementation.java | 18 +++- .../stages/StageLineImplementation.java | 34 +++--- .../quests/gui/creation/stages/StagesGUI.java | 29 +++-- .../quests/gui/quests/PlayerListGUI.java | 102 +++++++++--------- 10 files changed, 164 insertions(+), 128 deletions(-) diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml index d9402fd9..eea86111 100755 --- a/api/dependency-reduced-pom.xml +++ b/api/dependency-reduced-pom.xml @@ -44,13 +44,6 @@ <shadeSourcesContent>true</shadeSourcesContent> </configuration> </plugin> - <plugin> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.0</version> - <configuration> - <parameters>true</parameters> - </configuration> - </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> <version>3.4.1</version> diff --git a/api/pom.xml b/api/pom.xml index a94ab0a7..249c67e8 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -50,13 +50,6 @@ </execution> </executions> </plugin> - <plugin> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.0</version> - <configuration> - <parameters>true</parameters> - </configuration> - </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> <version>3.4.1</version> diff --git a/core/pom.xml b/core/pom.xml index d4082469..dce0a225 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -64,6 +64,13 @@ </execution> </executions> </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.0</version> + <configuration> + <parameters>true</parameters> <!-- For commands --> + </configuration> + </plugin> </plugins> </build> diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 79e52bf4..8bcb8ce6 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -44,35 +44,39 @@ import fr.skytasul.quests.utils.nms.NMS; public class CommandsAdmin implements OrphanCommand { - + @Subcommand ("create") @CommandPermission (value = "beautyquests.command.create") @OutsideEditor public void create(Player player, @Optional @Flag Integer id) { - QuestCreationSession session = new QuestCreationSession(); + QuestCreationSession session = new QuestCreationSession(player); if (id != null) { if (id.intValue() < 0) throw new CommandErrorException(Lang.NUMBER_NEGATIVE.toString()); if (QuestsAPI.getAPI().getQuestsManager().getQuest(id) != null) throw new CommandErrorException("Invalid quest ID: another quest exists with ID {0}", id); - + session.setCustomID(id); } session.openStagesGUI(player); } - + @Subcommand ("edit") @CommandPermission (value = "beautyquests.command.edit") @OutsideEditor public void edit(Player player, @Optional Quest quest) { if (quest != null) { - new QuestCreationSession((QuestImplementation) quest).openStagesGUI(player); + QuestCreationSession session = new QuestCreationSession(player); + session.setQuestEdited((QuestImplementation) quest); + session.openStagesGUI(player); }else { Lang.CHOOSE_NPC_STARTER.send(player); new SelectNPC(player, () -> {}, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { ChooseQuestGUI.choose(player, npc.getQuests(), clickedQuest -> { - new QuestCreationSession((QuestImplementation) clickedQuest).openStagesGUI(player); + QuestCreationSession session = new QuestCreationSession(player); + session.setQuestEdited((QuestImplementation) quest); + session.openStagesGUI(player); }, null, false); }else { Lang.NPC_NOT_QUEST.send(player); @@ -80,7 +84,7 @@ public void edit(Player player, @Optional Quest quest) { }).start(); } } - + @Subcommand ("remove") @CommandPermission (value = "beautyquests.command.remove") @OutsideEditor @@ -101,7 +105,7 @@ public void remove(BukkitCommandActor actor, @Optional Quest quest) { }).start(); } } - + private void doRemove(BukkitCommandActor sender, Quest quest) { if (sender.isPlayer()) { QuestsPlugin.getPlugin().getGuiManager().getFactory().createConfirmation(() -> { @@ -113,14 +117,14 @@ private void doRemove(BukkitCommandActor sender, Quest quest) { Lang.SUCCESFULLY_REMOVED.send(sender.getSender(), quest); } } - - + + @Subcommand ("reload") @CommandPermission ("beautyquests.command.manage") public void reload(BukkitCommandActor actor) { BeautyQuests.getInstance().performReload(actor.getSender()); } - + @Subcommand ("save") @CommandPermission ("beautyquests.command.manage") public void save(BukkitCommandActor actor) { @@ -133,12 +137,12 @@ public void save(BukkitCommandActor actor) { actor.error("Error while saving the data file."); } } - + @Subcommand ("backup") @CommandPermission ("beautyquests.command.manage") public void backup(BukkitCommandActor actor, @Switch boolean force) { if (!force) save(actor); - + boolean success = true; QuestsPlugin.getPlugin().getLoggerExpanded().info("Creating backup due to " + actor.getName() + "'s manual command."); Path backup = BeautyQuests.getInstance().backupDir(); @@ -152,20 +156,20 @@ public void backup(BukkitCommandActor actor, @Switch boolean force) { } if (success) Lang.BACKUP_CREATED.send(actor.getSender()); } - + @Subcommand ("adminMode") @CommandPermission ("beautyquests.command.adminMode") public void adminMode(BukkitCommandActor actor) { AdminMode.toggle(actor.getSender()); } - + @Subcommand ("exitEditor") @SecretCommand public void exitEditor(Player player) { QuestsPlugin.getPlugin().getGuiManager().closeAndExit(player); QuestsPlugin.getPlugin().getEditorManager().leave(player); } - + @Subcommand ("reopenInventory") @SecretCommand public void reopenInventory(Player player) { @@ -173,7 +177,7 @@ public void reopenInventory(Player player) { QuestsPlugin.getPlugin().getGuiManager().getOpenedGui(player).open(player); } } - + @Subcommand ("list") @CommandPermission ("beautyquests.command.list") public void list(Player player) { @@ -182,26 +186,26 @@ public void list(Player player) { } else MessageUtils.sendMessage(player, "Version not supported", MessageType.DefaultMessageType.PREFIXED); } - + @Subcommand ("downloadTranslations") @CommandPermission ("beautyquests.command.manage") public void downloadTranslations(BukkitCommandActor actor, @Optional String lang, @Switch boolean overwrite) { if (MinecraftVersion.MAJOR < 13) throw new CommandErrorException(Lang.VERSION_REQUIRED.quickFormat("version", "≥ 1.13")); - + if (lang == null) throw new CommandErrorException(Lang.COMMAND_TRANSLATION_SYNTAX.toString()); - + String version = MinecraftVersion.VERSION_STRING; String url = MinecraftNames.LANG_DOWNLOAD_URL.replace("%version%", version).replace("%language%", lang); - + try { File destination = new File(BeautyQuests.getInstance().getDataFolder(), lang + ".json"); if (destination.isDirectory()) throw new CommandErrorException(Lang.ERROR_OCCURED.quickFormat("error", lang + ".json is a directory")); if (!overwrite && destination.exists()) throw new CommandErrorException(Lang.COMMAND_TRANSLATION_EXISTS.quickFormat("file_name", lang + ".json")); - + try (ReadableByteChannel channel = Channels.newChannel(new URL(url).openStream())) { destination.createNewFile(); try (FileOutputStream output = new FileOutputStream(destination)) { @@ -218,13 +222,13 @@ public void downloadTranslations(BukkitCommandActor actor, @Optional String lang Lang.ERROR_OCCURED.quickFormat("error", "IO Exception when downloading translation.")); } } - + @Subcommand ("migrateDatas") @CommandPermission ("beautyquests.command.manage") public void migrateDatas(BukkitCommandActor actor) { if (!(QuestsPlugin.getPlugin().getPlayersManager() instanceof PlayersManagerYAML)) throw new CommandErrorException("§cYou can't migrate YAML datas to a DB system if you are already using the DB system."); - + QuestUtils.runAsync(() -> { actor.reply("§aConnecting to the database."); Database db = null; @@ -252,7 +256,7 @@ public void migrateDatas(BukkitCommandActor actor) { } }); } - + @Subcommand ("setItem") @CommandPermission ("beautyquests.command.setItem") public void setItem(Player player, ItemHologram position) { @@ -265,7 +269,7 @@ public void setItem(Player player, ItemHologram position) { BeautyQuests.getInstance().getDataFile().set(position.name().toLowerCase() + "Item", item.serialize()); Lang.ITEM_CHANGED.send(player); } - + @Subcommand ("setFirework") @CommandPermission ("beautyquests.command.setItem") public void setFirework(Player player, @Switch boolean remove) { @@ -284,7 +288,7 @@ public void setFirework(Player player, @Switch boolean remove) { } } } - + @Subcommand ("testNPC") @CommandPermission (value = "beautyquests.command.create") @SecretCommand @@ -292,9 +296,9 @@ public String testNPC(BukkitCommandActor actor, BqNpc npc) { ((BqNpcImplementation) npc).toggleDebug(); return npc.toString(); } - + public enum ItemHologram { TALK, LAUNCH, NOLAUNCH; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index b1831e07..017e9993 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -7,11 +7,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.inventory.*; import org.bukkit.inventory.Inventory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -155,6 +151,9 @@ public void onClick(InventoryClickEvent event) { return; } + if (event.getClickedInventory() == null) // click outside of the inventory + return; + ClickType click = event.getClick(); if (click == ClickType.NUMBER_KEY || click == ClickType.DOUBLE_CLICK || click == ClickType.DROP || click == ClickType.CONTROL_DROP || click.name().equals("SWAP_OFFHAND")) { // SWAP_OFFHAND introduced diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java index 4eb420e3..79ad9c57 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/QuestCreationSession.java @@ -1,6 +1,7 @@ package fr.skytasul.quests.gui.creation; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.gui.creation.quest.QuestCreationGuiImplementation; import fr.skytasul.quests.gui.creation.stages.StagesGUI; import fr.skytasul.quests.structure.QuestImplementation; @@ -10,17 +11,19 @@ public class QuestCreationSession { private StagesGUI stagesGUI; private QuestCreationGuiImplementation creationGUI; - private final QuestImplementation questEdited; + private final @NotNull Player player; + + private QuestImplementation questEdited; private boolean stagesEdited = false; private int customID = -1; - public QuestCreationSession() { - this(null); + public QuestCreationSession(@NotNull Player player) { + this.player = player; } - public QuestCreationSession(QuestImplementation questEdited) { - this.questEdited = questEdited; + public @NotNull Player getPlayer() { + return player; } public boolean hasCustomID() { @@ -43,6 +46,10 @@ public QuestImplementation getQuestEdited() { return questEdited; } + public void setQuestEdited(QuestImplementation questEdited) { + this.questEdited = questEdited; + } + public void setStagesEdited() { stagesEdited = true; } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java index a31e7d06..a72fe208 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageCreationContextImplementation.java @@ -13,14 +13,17 @@ public class StageCreationContextImplementation<T extends AbstractStage> impleme private final @NotNull StageGuiLine line; private final @NotNull StageType<T> type; + private final @NotNull StagesGUI gui; private final boolean ending; private @Nullable StagesGUI endingBranch; private @Nullable StageCreation<T> creation; - public StageCreationContextImplementation(@NotNull StageGuiLine line, @NotNull StageType<T> type, boolean ending) { + public StageCreationContextImplementation(@NotNull StageGuiLine line, @NotNull StageType<T> type, boolean ending, + StagesGUI gui) { this.line = line; this.type = type; this.ending = ending; + this.gui = gui; } @Override @@ -56,12 +59,19 @@ void setCreation(StageCreation<T> creation) { } @Override - public void remove() {} + public void remove() { + gui.deleteStageLine(line); + } @Override - public void reopenGui() {} + public void reopenGui() { + gui.reopen(); + } @Override - public void removeAndReopenGui() {} + public void removeAndReopenGui() { + gui.deleteStageLine(line); + gui.reopen(); + } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java index bdb8014c..5ebc5df0 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java @@ -5,6 +5,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.stages.creation.StageGuiClickHandler; import fr.skytasul.quests.api.stages.creation.StageGuiLine; @@ -40,9 +41,11 @@ public int setItem(int slot, @NotNull ItemStack item, @Nullable StageGuiClickHan items.put(slot, new LineItem(item, click)); + boolean wasSinglePage = maxPage == 0; computeMaxPage(); - if (isSlotShown(slot)) + boolean pageArrowChanged = wasSinglePage && maxPage > 0; + if (pageArrowChanged || isSlotShown(slot)) refresh(); return slot; @@ -60,15 +63,17 @@ public void refreshItem(int slot, @NotNull ItemStack item) { public void removeItem(int slot) { items.remove(slot); + boolean wasMultiplePage = maxPage != 0; computeMaxPage(); - if (isSlotShown(slot)) + boolean pageArrowChanged = wasMultiplePage && maxPage == 0; + if (pageArrowChanged || isSlotShown(slot)) refresh(); } public void clearItems() { items.clear(); - maxPage = 1; + maxPage = 0; page = 0; clearLine(); } @@ -86,17 +91,22 @@ public void setPage(int page) { clearLine(); this.page = page; - int pageFirst = page == 0 ? 0 : 8 + page * 7; - int pageCapacity = page == 0 ? 8 : 7; + int pageFirst = page == 0 ? 0 : 1 + page * 7; + int pageCapacity = page == 0 ? (maxPage == 0 ? 9 : 8) : 7; int rawSlot = page == 0 ? 0 : 1; for (int slot = pageFirst; slot < pageFirst + pageCapacity; slot++) { LineItem item = items.get(slot); if (item != null) { setRawItem(rawSlot, item.item); item.item = getRawItem(rawSlot); - rawSlot++; } + rawSlot++; } + + if (page > 0) + setRawItem(0, ItemUtils.itemLaterPage); + if (page < maxPage) + setRawItem(8, ItemUtils.itemNextPage); } @Override @@ -104,7 +114,7 @@ public StageGuiClickHandler getClick(int rawSlot) { if (rawSlot == 0 && page > 0) { setPage(page - 1); return null; - } else if (rawSlot == 8 && page < maxPage - 1) { + } else if (rawSlot == 8 && page < maxPage) { setPage(page + 1); return null; } else { @@ -120,14 +130,14 @@ private void computeMaxPage() { // next lines: 7 slots (1 to 7, 0 is prev page and 8 is next page) int last = items.keySet().stream().mapToInt(Integer::intValue).max().orElse(0); - if (last < 8) { - maxPage = 1; + if (last <= 8) { + maxPage = 0; } else { - maxPage = (int) (1 + Math.ceil((last - 8D + 1D) / 7D)); + maxPage = (int) Math.ceil((last - 8D + 1D) / 7D); } - if (page >= maxPage) { - page = maxPage - 1; + if (page > maxPage) { + page = maxPage; } } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 9b0ae0fd..e781bb9f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -22,10 +22,7 @@ import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageType; -import fr.skytasul.quests.api.stages.creation.StageCreation; -import fr.skytasul.quests.api.stages.creation.StageCreationContext; -import fr.skytasul.quests.api.stages.creation.StageGuiClickEvent; -import fr.skytasul.quests.api.stages.creation.StageGuiClickHandler; +import fr.skytasul.quests.api.stages.creation.*; import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.structure.QuestBranchImplementation; @@ -82,6 +79,14 @@ protected void populate(@NotNull Player player, @NotNull Inventory inv) { } } + public QuestCreationSession getSession() { + return session; + } + + public void reopen() { + reopen(session.getPlayer()); + } + private String[] getLineManageLore(int line) { return new String[] { "§7" + Lang.ClickRight + "/" + Lang.ClickLeft + " > §c" + Lang.stageRemove.toString(), @@ -104,9 +109,10 @@ public boolean isEmpty(){ return !getLine(0).isActive() && !getLine(15).isActive(); } - public void deleteStageLine(Line line) { - if (line.isActive()) - line.remove(); + public void deleteStageLine(StageGuiLine line) { + lines.stream().filter(x -> x.lineObj == line).findAny() + .filter(Line::isActive) + .ifPresent(Line::remove); } @Override @@ -222,9 +228,10 @@ void setSelectionState() { <T extends AbstractStage> StageCreation<T> setStageCreation(StageType<T> type) { lineObj.clearItems(); - context = new StageCreationContextImplementation<>(lineObj, type, ending); - context.setCreation( - (StageCreation) type.getCreationSupplier().supply((@NotNull StageCreationContext<T>) context)); + context = new StageCreationContextImplementation<>(lineObj, type, ending, StagesGUI.this); + StageCreation<T> creation = type.getCreationSupplier().supply((@NotNull StageCreationContext<T>) context); + context.setCreation((StageCreation) creation); + creation.setupLine(lineObj); getInventory().setItem(SLOT_FINISH, ItemUtils.itemDone); @@ -263,7 +270,7 @@ <T extends AbstractStage> StageCreation<T> setStageCreation(StageType<T> type) { if (lineId != 0 && lineId != 15) getLine(lineId - 1).updateLineManageLore(); - return (StageCreation<T>) context.getCreation(); + return creation; } void setStageEdition(StageController stage) { 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 d0026f94..a48252fd 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 @@ -1,5 +1,6 @@ package fr.skytasul.quests.gui.quests; +import java.util.Arrays; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; @@ -59,6 +60,8 @@ protected Inventory instanciate(@NotNull Player player) { @Override protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + open = player; + setBarItem(0, ItemUtils.itemLaterPage); setBarItem(4, ItemUtils.itemNextPage); @@ -181,7 +184,7 @@ private ItemStack createQuestItem(Quest qu, List<String> lore) { } private void toggleCategorySelected() { - ItemStack is = getInventory().getItem(cat.ordinal() * 9 + 8); + ItemStack is = getInventory().getItem(cat.getSlot() * 9 + 8); ItemMeta im = is.getItemMeta(); String name = im.getDisplayName(); if (!im.hasEnchant(Enchantment.DURABILITY)) { @@ -199,61 +202,64 @@ private void toggleCategorySelected() { @Override public void onClick(GuiClickEvent event) { switch (event.getSlot() % 9) { - case 8: + case 8: int barSlot = (event.getSlot() - 8) / 9; - switch (barSlot){ - case 0: - if (page == 0) break; - page--; - setItems(); - break; - case 4: - page++; - setItems(); - break; + switch (barSlot) { + case 0: + if (page == 0) + break; + page--; + setItems(); + break; + case 4: + page++; + setItems(); + break; + + case 1: + case 2: + case 3: + Arrays.stream(PlayerListCategory.values()).filter(cat -> cat.getSlot() == barSlot).findAny() + .filter(cat -> cat.isEnabled()).ifPresent(this::setCategory); + break; - case 1: - case 2: - case 3: - PlayerListCategory category = PlayerListCategory.values()[barSlot]; - if (category.isEnabled()) setCategory(category); + } break; - } - break; - - case 7: - break; + case 7: + break; - default: - int id = (int) (event.getSlot() - (Math.floor(event.getSlot() * 1D / 9D) * 2) + page * 35); - Quest qu = quests.get(id); - if (cat == PlayerListCategory.NOT_STARTED) { - if (!qu.getOptionValueOrDef(OptionStartable.class)) break; - if (!acc.isCurrent()) break; - Player target = acc.getPlayer(); - if (qu.canStart(target, true)) { - event.close(); - qu.attemptStart(target); - } - }else { - if (event.getClick().isRightClick()) { - if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() - && acc.getQuestDatas(qu).hasFlowDialogs()) { - QuestUtils.playPluginSound(event.getPlayer(), "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); - new DialogHistoryGUI(acc, qu, event::reopen).open(event.getPlayer()); + default: + int id = (int) (event.getSlot() - (Math.floor(event.getSlot() * 1D / 9D) * 2) + page * 35); + Quest qu = quests.get(id); + if (cat == PlayerListCategory.NOT_STARTED) { + if (!qu.getOptionValueOrDef(OptionStartable.class)) + break; + if (!acc.isCurrent()) + break; + Player target = acc.getPlayer(); + if (qu.canStart(target, true)) { + event.close(); + qu.attemptStart(target); } - } else if (event.getClick().isLeftClick()) { - if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() - && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { - QuestsPlugin.getPlugin().getGuiManager().getFactory() - .createConfirmation(() -> qu.cancelPlayer(acc), event::reopen, - Lang.INDICATION_CANCEL.format(qu)) - .open(event.getPlayer()); + } else { + if (event.getClick().isRightClick()) { + if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs()) { + QuestUtils.playPluginSound(event.getPlayer(), "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); + new DialogHistoryGUI(acc, qu, event::reopen).open(event.getPlayer()); + } + } else if (event.getClick().isLeftClick()) { + if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() + && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { + QuestsPlugin.getPlugin().getGuiManager().getFactory() + .createConfirmation(() -> qu.cancelPlayer(acc), event::reopen, + Lang.INDICATION_CANCEL.format(qu)) + .open(event.getPlayer()); + } } } - } - break; + break; } } From 6ba8029a6645ddca9e9b458b515a57622ca74e01 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 9 Sep 2023 13:28:01 +0200 Subject: [PATCH 46/95] :bug: Fixed stages not being registered as event listeners --- .../api/utils/messaging/MessageUtils.java | 3 +- .../fr/skytasul/quests/stages/StageBreed.java | 19 +++--- .../skytasul/quests/stages/StageBucket.java | 17 +++--- .../fr/skytasul/quests/stages/StageChat.java | 3 +- .../fr/skytasul/quests/stages/StageCraft.java | 33 ++++++----- .../quests/stages/StageDealDamage.java | 59 ++++++++++--------- .../fr/skytasul/quests/stages/StageDeath.java | 41 ++++++------- .../skytasul/quests/stages/StageEatDrink.java | 23 ++++---- .../skytasul/quests/stages/StageEnchant.java | 21 +++---- .../fr/skytasul/quests/stages/StageFish.java | 17 +++--- .../quests/stages/StageInteractBlock.java | 35 +++++------ .../quests/stages/StageInteractLocation.java | 3 +- .../skytasul/quests/stages/StageLocation.java | 43 +++++++------- .../fr/skytasul/quests/stages/StageMelt.java | 19 +++--- .../fr/skytasul/quests/stages/StageMine.java | 36 +++++------ .../fr/skytasul/quests/stages/StageMobs.java | 3 +- .../fr/skytasul/quests/stages/StageNPC.java | 3 +- .../quests/stages/StagePlaceBlocks.java | 13 ++-- .../fr/skytasul/quests/stages/StageTame.java | 23 ++++---- core/src/main/resources/config.yml | 2 +- .../integrations/worldguard/StageArea.java | 43 +++++++------- 21 files changed, 237 insertions(+), 222 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java index 6dd88be4..a741dacc 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.api.utils.messaging; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bukkit.command.CommandSender; @@ -71,7 +72,7 @@ public static String itemsToFormattedString(String[] items, String separator) { public static @NotNull String format(@NotNull String msg, @Nullable PlaceholderRegistry placeholders, @NotNull PlaceholdersContext context) { if (placeholders != null) { - Matcher matcher = PLACEHOLDER_PATTERN.matcher(msg); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(Objects.requireNonNull(msg)); // re-implementation of the "matcher.appendReplacement" system to allow replacement of colors StringBuilder output = null; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java index 0bc13d15..a22815ef 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBreed.java @@ -5,6 +5,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityBreedEvent; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.localization.Lang; @@ -13,12 +14,12 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractEntityStage; -public class StageBreed extends AbstractEntityStage { - +public class StageBreed extends AbstractEntityStage implements Listener { + public StageBreed(StageController controller, EntityType entity, int amount) { super(controller, entity, amount); } - + @EventHandler public void onBreed(EntityBreedEvent e) { if (e.getBreeder() instanceof Player) { @@ -26,7 +27,7 @@ public void onBreed(EntityBreedEvent e) { event(p, e.getEntityType()); } } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_BREED.toString(); @@ -36,9 +37,9 @@ public static StageBreed deserialize(ConfigurationSection section, StageControll String type = section.getString("entityType"); return new StageBreed(controller, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); } - + public static class Creator extends AbstractEntityStage.AbstractCreator<StageBreed> { - + public Creator(@NotNull StageCreationContext<StageBreed> context) { super(context); } @@ -47,12 +48,12 @@ public Creator(@NotNull StageCreationContext<StageBreed> context) { protected boolean canUseEntity(EntityType type) { return Breedable.class.isAssignableFrom(type.getEntityClass()); } - + @Override protected StageBreed finishStage(StageController controller) { return new StageBreed(controller, entity, amount); } - + } - + } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java index d7a14092..17586c69 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBucket.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -30,7 +31,7 @@ import fr.skytasul.quests.api.utils.progress.itemdescription.ItemsDescriptionConfiguration; import fr.skytasul.quests.gui.misc.BucketTypeGUI; -public class StageBucket extends AbstractStage implements HasSingleObject { +public class StageBucket extends AbstractStage implements HasSingleObject, Listener { private BucketType bucket; private int amount; @@ -154,10 +155,10 @@ public static BucketType[] getAvailable() { } public static class Creator extends StageCreation<StageBucket> { - + private BucketType bucket; private int amount; - + public Creator(@NotNull StageCreationContext<StageBucket> context) { super(context); } @@ -165,7 +166,7 @@ public Creator(@NotNull StageCreationContext<StageBucket> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(6, ItemUtils.item(XMaterial.REDSTONE, Lang.editBucketAmount.toString()), event -> { Lang.BUCKET_AMOUNT.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { @@ -180,19 +181,19 @@ public void setupLine(@NotNull StageGuiLine line) { }).open(event.getPlayer()); }); } - + public void setBucket(BucketType bucket) { this.bucket = bucket; ItemStack newItem = ItemUtils.lore(getLine().getItem(7), QuestOption.formatNullableValue(bucket.getName())); newItem.setType(bucket.type.parseMaterial()); getLine().refreshItem(7, newItem); } - + public void setAmount(int amount) { this.amount = amount; getLine().refreshItemLore(6, Lang.Amount.quickFormat("amount", amount)); } - + @Override public void start(Player p) { super.start(p); @@ -212,7 +213,7 @@ public void edit(StageBucket stage) { setBucket(stage.getBucketType()); setAmount(stage.getBucketAmount()); } - + @Override public StageBucket finishStage(StageController controller) { return new StageBucket(controller, bucket, amount); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index 7392a9cd..b1242be2 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -4,6 +4,7 @@ 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.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.jetbrains.annotations.NotNull; @@ -22,7 +23,7 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; -public class StageChat extends AbstractStage{ +public class StageChat extends AbstractStage implements Listener { private final String text; private final boolean cancel; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java index 0c6082c7..964bf332 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageCraft.java @@ -6,6 +6,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.inventory.FurnaceExtractEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -34,22 +35,22 @@ /** * @author SkytAsul, ezeiger92, TheBusyBiscuit */ -public class StageCraft extends AbstractStage implements HasSingleObject { +public class StageCraft extends AbstractStage implements HasSingleObject, Listener { private final ItemStack result; private final ItemComparisonMap comparisons; - + public StageCraft(StageController controller, ItemStack result, ItemComparisonMap comparisons) { super(controller); this.result = result; this.comparisons = comparisons; if (result.getAmount() == 0) result.setAmount(1); } - + public ItemStack getItem(){ return result; } - + @EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = true) public void onFurnaceExtract(FurnaceExtractEvent event) { Player p = event.getPlayer(); @@ -62,14 +63,14 @@ public void onFurnaceExtract(FurnaceExtractEvent event) { } } } - + @EventHandler public void onCraft(BQCraftEvent event) { Player p = event.getPlayer(); if (hasStarted(p) && canUpdate(p)) { ItemStack item = event.getResult(); if (comparisons.isSimilar(result, item)) { - + int recipeAmount = item.getAmount(); switch (event.getClickEvent().getClick()) { @@ -97,7 +98,7 @@ public void onCraft(BQCraftEvent event) { recipeAmount = ((capacity + recipeAmount - 1) / recipeAmount) * recipeAmount; }else recipeAmount = event.getMaxCraftable(); break; - + default: cursor = event.getClickEvent().getCursor(); if (cursor != null && cursor.getType() != Material.AIR) { @@ -122,7 +123,7 @@ public void onCraft(BQCraftEvent event) { } } } - + @Override public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { super.initPlayerDatas(acc, datas); @@ -159,10 +160,10 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol @Override protected void serialize(ConfigurationSection section) { section.set("result", result.serialize()); - + if (!comparisons.getNotDefault().isEmpty()) section.createSection("itemComparisons", comparisons.getNotDefault()); } - + public static StageCraft deserialize(ConfigurationSection section, StageController controller) { return new StageCraft(controller, ItemStack.deserialize(section.getConfigurationSection("result").getValues(false)), section.contains("itemComparisons") ? new ItemComparisonMap(section.getConfigurationSection("itemComparisons")) : new ItemComparisonMap()); } @@ -180,12 +181,12 @@ else if (is.isSimilar(stack)) } public static class Creator extends StageCreation<StageCraft> { - + private static final int ITEM_SLOT = 6, COMPARISONS_SLOT = 7; - + private ItemStack item; private ItemComparisonMap comparisons = new ItemComparisonMap(); - + public Creator(@NotNull StageCreationContext<StageCraft> context) { super(context); } @@ -193,7 +194,7 @@ public Creator(@NotNull StageCreationContext<StageCraft> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(ITEM_SLOT, ItemUtils.item(XMaterial.CHEST, Lang.editItem.toString()), event -> { QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemSelection(is -> { if (is != null) @@ -215,7 +216,7 @@ public void setItem(ItemStack item) { item2 -> ItemUtils.lore(item2, QuestOption.formatNullableValue(Utils.getStringFromItemStack(item, "§8", true)))); } - + public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; getLine().refreshItem(COMPARISONS_SLOT, item -> ItemUtils.lore(item, @@ -238,7 +239,7 @@ public void edit(StageCraft stage) { setItem(stage.getItem()); setComparisons(stage.comparisons.clone()); } - + @Override public StageCraft finishStage(StageController controller) { return new StageCraft(controller, item, comparisons); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index ae3a4d2f..6038d143 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -11,6 +11,7 @@ import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.projectiles.ProjectileSource; @@ -37,23 +38,23 @@ import fr.skytasul.quests.mobs.Mob; @SuppressWarnings ("rawtypes") -public class StageDealDamage extends AbstractStage implements HasProgress { - +public class StageDealDamage extends AbstractStage implements HasProgress, Listener { + private final double damage; private final List<Mob> targetMobs; - + public StageDealDamage(StageController controller, double damage, List<Mob> targetMobs) { super(controller); this.damage = damage; this.targetMobs = targetMobs; } - + @Override public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { super.initPlayerDatas(acc, datas); datas.put("amount", damage); } - + @EventHandler (priority = EventPriority.MONITOR) public void onDamage(EntityDamageByEntityEvent event) { Player player; @@ -64,15 +65,15 @@ public void onDamage(EntityDamageByEntityEvent event) { }else if (event.getDamager() instanceof Player) { player = (Player) event.getDamager(); }else return; - + if (targetMobs != null && !targetMobs.isEmpty() && targetMobs.stream().noneMatch(mob -> mob.appliesEntity(event.getEntity()))) return; - + PlayerAccount account = PlayersManager.getPlayerAccount(player); - + if (!hasStarted(player) || !canUpdate(player)) return; - + double amount = getData(account, "amount"); amount -= event.getFinalDamage(); if (amount <= 0) { @@ -81,7 +82,7 @@ public void onDamage(EntityDamageByEntityEvent event) { updateObjective(player, "amount", amount); } } - + public double getPlayerAmountDouble(@NotNull PlayerAccount account) { return getData(account, "amount"); } @@ -108,20 +109,20 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol return targetMobs == null || targetMobs.isEmpty() ? Lang.SCOREBOARD_DEAL_DAMAGE_ANY.toString() : Lang.SCOREBOARD_DEAL_DAMAGE_MOBS.toString(); } - + @Override protected void serialize(ConfigurationSection section) { section.set("damage", damage); if (targetMobs != null && !targetMobs.isEmpty()) section.set("targetMobs", targetMobs.stream().map(Mob::serialize).collect(Collectors.toList())); } - + public static StageDealDamage deserialize(ConfigurationSection section, StageController controller) { return new StageDealDamage(controller, section.getDouble("damage"), section.contains("targetMobs") ? section.getMapList("targetMobs").stream().map(map -> Mob.deserialize((Map) map)).collect(Collectors.toList()) : null); } - + private static String getTargetMobsString(List<Mob> targetMobs) { if (targetMobs == null || targetMobs.isEmpty()) return Lang.EntityTypeAny.toString(); @@ -129,13 +130,13 @@ private static String getTargetMobsString(List<Mob> targetMobs) { } public static class Creator extends StageCreation<StageDealDamage> { - + private static final int SLOT_DAMAGE = 6; private static final int SLOT_MOBS = 7; - + private double damage; private List<Mob> targetMobs; - + public Creator(@NotNull StageCreationContext<StageDealDamage> context) { super(context); } @@ -143,7 +144,7 @@ public Creator(@NotNull StageCreationContext<StageDealDamage> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(SLOT_DAMAGE, ItemUtils.item(XMaterial.REDSTONE, Lang.stageDealDamageValue.toString()), event -> { Lang.DAMAGE_AMOUNT.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopen, newDamage -> { @@ -151,51 +152,51 @@ public void setupLine(@NotNull StageGuiLine line) { event.reopen(); }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).start(); }); - + line.setItem(SLOT_MOBS, ItemUtils.item(XMaterial.BLAZE_SPAWN_EGG, Lang.stageDealDamageMobs.toString(), QuestOption.formatNullableValue(Lang.EntityTypeAny.toString(), true)), event -> { new ListGUI<Mob>(Lang.stageDealDamageMobs.toString(), DyeColor.RED, targetMobs == null ? Collections.emptyList() : targetMobs) { - + @Override public void finish(List<Mob> objects) { setTargetMobs(objects.isEmpty() ? null : objects); event.reopen(); } - + @Override public ItemStack getObjectItemStack(Mob object) { return ItemUtils.item(object.getMobItem(), object.getName(), createLoreBuilder(object).toLoreArray()); } - + @Override public void createObject(Function<Mob, ItemStack> callback) { new MobSelectionGUI(callback::apply).open(player); } - + }.open(event.getPlayer()); }); } - + public void setDamage(double damage) { this.damage = damage; getLine().refreshItem(SLOT_DAMAGE, item -> ItemUtils.lore(item, QuestOption.formatNullableValue(Double.toString(damage)))); } - + public void setTargetMobs(List<Mob> targetMobs) { this.targetMobs = targetMobs; boolean noMobs = targetMobs == null || targetMobs.isEmpty(); getLine().refreshItem(SLOT_MOBS, item -> ItemUtils.lore(item, QuestOption.formatNullableValue(getTargetMobsString(targetMobs), noMobs))); } - + @Override public void edit(StageDealDamage stage) { super.edit(stage); setDamage(stage.damage); setTargetMobs(stage.targetMobs); } - + @Override public void start(Player p) { super.start(p); @@ -205,12 +206,12 @@ public void start(Player p) { context.reopenGui(); }, NumberParser.DOUBLE_PARSER_STRICT_POSITIVE).start(); } - + @Override protected StageDealDamage finishStage(StageController controller) { return new StageDealDamage(controller, damage, targetMobs); } - + } - + } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java index 7736ed88..84895ae3 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDeath.java @@ -6,6 +6,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.PlayerDeathEvent; @@ -21,39 +22,39 @@ import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.gui.misc.DamageCausesGUI; -public class StageDeath extends AbstractStage { - +public class StageDeath extends AbstractStage implements Listener { + private List<DamageCause> causes; - + public StageDeath(StageController controller, List<DamageCause> causes) { super(controller); this.causes = causes; } - + @EventHandler public void onPlayerDeath(PlayerDeathEvent event) { Player p = event.getEntity(); if (!hasStarted(p)) return; - + if (!causes.isEmpty()) { EntityDamageEvent lastDamage = p.getLastDamageCause(); if (lastDamage == null) return; if (!causes.contains(lastDamage.getCause())) return; } - + if (canUpdate(p, true)) finishStage(p); } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_DIE.toString(); } - + @Override protected void serialize(ConfigurationSection section) { if (!causes.isEmpty()) section.set("causes", causes.stream().map(DamageCause::name).collect(Collectors.toList())); } - + public static StageDeath deserialize(ConfigurationSection section, StageController controller) { List<DamageCause> causes; if (section.contains("causes")) { @@ -63,13 +64,13 @@ public static StageDeath deserialize(ConfigurationSection section, StageControll } return new StageDeath(controller, causes); } - + public static class Creator extends StageCreation<StageDeath> { - + private static final int CAUSES_SLOT = 7; - + private List<DamageCause> causes; - + public Creator(@NotNull StageCreationContext<StageDeath> context) { super(context); } @@ -77,7 +78,7 @@ public Creator(@NotNull StageCreationContext<StageDeath> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(CAUSES_SLOT, ItemUtils.item(XMaterial.SKELETON_SKULL, Lang.stageDeathCauses.toString()), event -> { new DamageCausesGUI(causes, newCauses -> { setCauses(newCauses); @@ -85,30 +86,30 @@ public void setupLine(@NotNull StageGuiLine line) { }).open(event.getPlayer()); }); } - + public void setCauses(List<DamageCause> causes) { this.causes = causes; getLine().refreshItemLoreOptionValue(CAUSES_SLOT, causes.isEmpty() ? Lang.stageDeathCauseAny : Lang.stageDeathCausesSet.quickFormat("causes_amount", causes.size())); } - + @Override public void start(Player p) { super.start(p); setCauses(Collections.emptyList()); } - + @Override public void edit(StageDeath stage) { super.edit(stage); setCauses(stage.causes); } - + @Override protected StageDeath finishStage(StageController controller) { return new StageDeath(controller, causes); } - + } - + } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java index 0827bb08..e7d0df3e 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEatDrink.java @@ -3,6 +3,7 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -16,30 +17,30 @@ import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.XMaterial; -public class StageEatDrink extends AbstractItemStage { - +public class StageEatDrink extends AbstractItemStage implements Listener { + public StageEatDrink(StageController controller, List<CountableObject<ItemStack>> objects, ItemComparisonMap comparisons) { super(controller, objects, comparisons); } - + public StageEatDrink(ConfigurationSection section, StageController controller) { super(controller, section); } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_EAT_DRINK.toString(); } - + @EventHandler public void onItemConsume(PlayerItemConsumeEvent event) { event(event.getPlayer(), event.getItem(), 1); } - + public static class Creator extends AbstractItemStage.Creator<StageEatDrink> { - + private static final ItemStack editItems = ItemUtils.item(XMaterial.COOKED_PORKCHOP, Lang.stageEatDrinkItems.toString()); - + public Creator(@NotNull StageCreationContext<StageEatDrink> context) { super(context); } @@ -48,12 +49,12 @@ public Creator(@NotNull StageCreationContext<StageEatDrink> context) { protected ItemStack getEditItem() { return editItems; } - + @Override protected StageEatDrink finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageEatDrink(controller, items, comparisons); } - + } - + } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java index 5b846d86..f9cdedbc 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageEnchant.java @@ -4,6 +4,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.enchantment.EnchantItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -18,12 +19,12 @@ import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.XMaterial; -public class StageEnchant extends AbstractItemStage { - +public class StageEnchant extends AbstractItemStage implements Listener { + public StageEnchant(StageController controller, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { super(controller, fishes, comparisons); } - + public StageEnchant(StageController controller, ConfigurationSection section) { super(controller, section); } @@ -32,15 +33,15 @@ public StageEnchant(StageController controller, ConfigurationSection section) { public void onEnchant(EnchantItemEvent e) { if (!hasStarted(e.getEnchanter())) return; - + ItemStack finalItem = e.getItem().clone(); ItemMeta meta = finalItem.getItemMeta(); e.getEnchantsToAdd().forEach((enchant, level) -> meta.addEnchant(enchant, level, false)); finalItem.setItemMeta(meta); - + event(e.getEnchanter(), finalItem, e.getItem().getAmount()); } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_ENCHANT.toString(); @@ -51,9 +52,9 @@ public static StageEnchant deserialize(ConfigurationSection section, StageContro } public static class Creator extends AbstractItemStage.Creator<StageEnchant> { - + private static final ItemStack editItems = ItemUtils.item(XMaterial.ENCHANTING_TABLE, Lang.editItemsToEnchant.toString()); - + public Creator(@NotNull StageCreationContext<StageEnchant> context) { super(context); } @@ -62,12 +63,12 @@ public Creator(@NotNull StageCreationContext<StageEnchant> context) { protected ItemStack getEditItem() { return editItems; } - + @Override protected StageEnchant finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageEnchant(controller, items, comparisons); } - + } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java index 60e80a9c..34ebaad8 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageFish.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageFish.java @@ -6,6 +6,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerFishEvent.State; import org.bukkit.inventory.ItemStack; @@ -20,12 +21,12 @@ import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.XMaterial; -public class StageFish extends AbstractItemStage { - +public class StageFish extends AbstractItemStage implements Listener { + public StageFish(StageController controller, List<CountableObject<ItemStack>> fishes, ItemComparisonMap comparisons) { super(controller, fishes, comparisons); } - + public StageFish(StageController controller, ConfigurationSection section) { super(controller, section); } @@ -41,18 +42,18 @@ public void onFish(PlayerFishEvent e){ event(p, fish, fish.getAmount()); } } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_FISH.toString(); } - + public static StageFish deserialize(ConfigurationSection section, StageController controller) { return new StageFish(controller, section); } public static class Creator extends AbstractItemStage.Creator<StageFish> { - + private static final ItemStack editFishesItem = ItemUtils.item(XMaterial.FISHING_ROD, Lang.editFishes.toString()); public Creator(@NotNull StageCreationContext<StageFish> context) { @@ -63,12 +64,12 @@ public Creator(@NotNull StageCreationContext<StageFish> context) { protected ItemStack getEditItem() { return editFishesItem; } - + @Override protected StageFish finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageFish(controller, items, comparisons); } - + } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java index fe60f1b4..69f36591 100755 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java @@ -5,6 +5,7 @@ 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; @@ -28,17 +29,17 @@ import fr.skytasul.quests.gui.blocks.SelectBlockGUI; @LocatableType(types = LocatedType.BLOCK) -public class StageInteractBlock extends AbstractStage implements Locatable.MultipleLocatable { +public class StageInteractBlock extends AbstractStage implements Locatable.MultipleLocatable, Listener { private final boolean left; private final @NotNull BQBlock block; - + public StageInteractBlock(StageController controller, boolean leftClick, BQBlock block) { super(controller); this.left = leftClick; this.block = block; } - + public BQBlock getBlockType() { return block; } @@ -46,33 +47,33 @@ public BQBlock getBlockType() { public boolean needLeftClick(){ return left; } - + @Override public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { if (block == null) return null; - + return QuestsAPI.getAPI().getBlocksManager().getNearbyBlocks(fetcher, Collections.singleton(block)); } - + @EventHandler public void onInteract(PlayerInteractEvent e){ if (e.getClickedBlock() == null) return; if (MinecraftVersion.MAJOR >= 9 && e.getHand() != EquipmentSlot.HAND) return; - + if (left){ if (e.getAction() != Action.LEFT_CLICK_BLOCK) return; }else if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; - + if (!block.applies(e.getClickedBlock())) return; - + Player p = e.getPlayer(); if (hasStarted(p) && canUpdate(p)) { if (left) e.setCancelled(true); finishStage(p); } } - + @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); @@ -89,7 +90,7 @@ protected void serialize(ConfigurationSection section) { section.set("leftClick", left); section.set("block", block.getAsString()); } - + public static StageInteractBlock deserialize(ConfigurationSection section, StageController controller) { BQBlock block; if (section.contains("material")) { @@ -102,10 +103,10 @@ public static StageInteractBlock deserialize(ConfigurationSection section, Stage } public static class Creator extends StageCreation<StageInteractBlock> { - + private boolean leftClick = false; private BQBlock block; - + public Creator(@NotNull StageCreationContext<StageInteractBlock> context) { super(context); } @@ -116,14 +117,14 @@ public void setupLine(@NotNull StageGuiLine line) { line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); } - + public void setLeftClick(boolean leftClick) { if (this.leftClick != leftClick) { this.leftClick = leftClick; getLine().refreshItem(6, item -> ItemUtils.setSwitch(item, leftClick)); } } - + public void setMaterial(BQBlock block) { if (this.block == null) { getLine().setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), event -> { @@ -136,7 +137,7 @@ public void setMaterial(BQBlock block) { getLine().refreshItem(7, item -> ItemUtils.loreOptionValue(item, block.getName())); this.block = block; } - + @Override public void start(Player p) { super.start(p); @@ -157,7 +158,7 @@ public void edit(StageInteractBlock stage) { public StageInteractBlock finishStage(StageController controller) { return new StageInteractBlock(controller, leftClick, block); } - + } } 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 8b8681cd..3215bda6 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java @@ -5,6 +5,7 @@ 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; @@ -27,7 +28,7 @@ import fr.skytasul.quests.utils.types.BQLocation; @LocatableType (types = { LocatedType.BLOCK, LocatedType.OTHER }) -public class StageInteractLocation extends AbstractStage implements Locatable.PreciseLocatable { +public class StageInteractLocation extends AbstractStage implements Locatable.PreciseLocatable, Listener { private final boolean left; private final BQLocation lc; 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 4d06460b..7f8220fc 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageLocation.java @@ -5,6 +5,7 @@ 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; @@ -29,45 +30,45 @@ import fr.skytasul.quests.utils.types.BQLocation; @LocatableType (types = LocatedType.OTHER) -public class StageLocation extends AbstractStage implements Locatable.PreciseLocatable { +public class StageLocation extends AbstractStage implements Locatable.PreciseLocatable, Listener { private final BQLocation lc; private final int radius; private final int radiusSquared; - + public StageLocation(StageController controller, BQLocation lc, int radius) { super(controller); this.lc = lc; this.radius = radius; this.radiusSquared = radius * radius; } - + public BQLocation getLocation() { return lc; } - + @Override public Located getLocated() { return lc; } - + public int getRadius(){ return radius; } - + @EventHandler public void onPlayerMove(PlayerMoveEvent e){ if (e.getFrom().getBlockX() == e.getTo().getBlockX() && e.getFrom().getBlockY() == e.getTo().getBlockY() && e.getFrom().getBlockZ() == e.getTo().getBlockZ()) return; // only rotation if (!lc.isWorld(e.getTo().getWorld())) return; - + Player p = e.getPlayer(); if (hasStarted(p) && canUpdate(p)) { if (lc.distanceSquared(e.getTo()) <= radiusSquared) finishStage(p); } } - + @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); @@ -76,7 +77,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol placeholders.registerIndexed("target_z", lc.getBlockZ()); placeholders.registerIndexed("target_world", lc.getWorldName()); } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_LOCATION.toString(); @@ -93,17 +94,17 @@ public static StageLocation deserialize(ConfigurationSection section, StageContr BQLocation.deserialize(section.getConfigurationSection("location").getValues(false)), section.getInt("radius")); } - + public static class Creator extends StageCreation<StageLocation> { - + private static final int SLOT_RADIUS = 6; private static final int SLOT_LOCATION = 7; private static final int SLOT_WORLD_PATTERN = 8; - + private Location location; private Pattern pattern; private int radius; - + public Creator(@NotNull StageCreationContext<StageLocation> context) { super(context); } @@ -134,19 +135,19 @@ public void setupLine(@NotNull StageGuiLine line) { }, PatternParser.PARSER).passNullIntoEndConsumer().start(); }); } - + public void setLocation(Location location) { this.location = location; getLine().refreshItem(SLOT_LOCATION, item -> ItemUtils.loreOptionValue(item, Lang.Location.format(getBQLocation()))); } - + public void setRadius(int radius) { this.radius = radius; getLine().refreshItem(SLOT_RADIUS, item -> ItemUtils.lore(item, Lang.stageLocationCurrentRadius.quickFormat("radius", radius))); } - + public void setPattern(Pattern pattern) { this.pattern = pattern; getLine().refreshItem(SLOT_WORLD_PATTERN, @@ -154,13 +155,13 @@ public void setPattern(Pattern pattern) { "", pattern == null ? Lang.NotSet.toString() : QuestOption.formatNullableValue(pattern.pattern()))); } - + private BQLocation getBQLocation() { BQLocation loc = new BQLocation(location); if (pattern != null) loc.setWorldPattern(pattern); return loc; } - + @Override public void start(Player p) { super.start(p); @@ -179,12 +180,12 @@ public void edit(StageLocation stage) { setRadius(stage.getRadius()); setPattern(stage.getLocation().getWorldPattern()); } - + @Override public StageLocation finishStage(StageController controller) { return new StageLocation(controller, getBQLocation(), radius); } - + } - + } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java index 682c36f3..ba9f9c1a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMelt.java @@ -4,6 +4,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.inventory.FurnaceExtractEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -17,32 +18,32 @@ import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.XMaterial; -public class StageMelt extends AbstractItemStage { - +public class StageMelt extends AbstractItemStage implements Listener { + public StageMelt(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { super(controller, items, comparisons); } - + public StageMelt(StageController controller, ConfigurationSection section) { super(controller, section); } - + @EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = true) public void onMelt(FurnaceExtractEvent event) { event(event.getPlayer(), new ItemStack(event.getItemType()), event.getItemAmount()); } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_MELT.toString(); } - + public static StageMelt deserialize(ConfigurationSection section, StageController controller) { return new StageMelt(controller, section); } public static class Creator extends AbstractItemStage.Creator<StageMelt> { - + private static final ItemStack editItems = ItemUtils.item(XMaterial.FURNACE, Lang.editItemsToMelt.toString()); public Creator(@NotNull StageCreationContext<StageMelt> context) { @@ -53,12 +54,12 @@ public Creator(@NotNull StageCreationContext<StageMelt> context) { protected ItemStack getEditItem() { return editItems; } - + @Override protected StageMelt finishStage(StageController controller, List<CountableObject<ItemStack>> items, ItemComparisonMap comparisons) { return new StageMelt(controller, items, comparisons); } - + } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java index 01a1fa15..b7bdf44b 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMine.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMine.java @@ -1,17 +1,13 @@ package fr.skytasul.quests.stages; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Spliterator; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; import org.bukkit.block.Block; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; @@ -37,14 +33,14 @@ import fr.skytasul.quests.api.utils.XMaterial; @LocatableType (types = LocatedType.BLOCK) -public class StageMine extends AbstractCountableBlockStage implements Locatable.MultipleLocatable { +public class StageMine extends AbstractCountableBlockStage implements Locatable.MultipleLocatable, Listener { private boolean placeCancelled; - + public StageMine(StageController controller, List<CountableObject<BQBlock>> blocks) { super(controller, blocks); } - + public boolean isPlaceCancelled() { return placeCancelled; } @@ -57,7 +53,7 @@ public void setPlaceCancelled(boolean cancelPlaced) { public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_MINE.toString(); } - + @EventHandler (priority = EventPriority.MONITOR) public void onMine(BQBlockBreakEvent e) { Player p = e.getPlayer(); @@ -80,7 +76,7 @@ public void onMine(BQBlockBreakEvent e) { return; } } - + @EventHandler (priority = EventPriority.MONITOR) public void onPlace(BlockPlaceEvent e){ if (QuestsConfigurationImplementation.getConfiguration().usePlayerBlockTracker()) @@ -103,19 +99,19 @@ public void onPlace(BlockPlaceEvent e){ } } } - + @Override public Spliterator<Located> getNearbyLocated(NearbyFetcher fetcher) { return QuestsAPI.getAPI().getBlocksManager().getNearbyBlocks(fetcher, objects.stream().map(CountableObject::getObject).collect(Collectors.toList())); } - + @Override protected void serialize(ConfigurationSection section) { super.serialize(section); if (placeCancelled) section.set("placeCancelled", placeCancelled); } - + public static StageMine deserialize(ConfigurationSection section, StageController controller) { StageMine stage = new StageMine(controller, new ArrayList<>()); stage.deserialize(section); @@ -125,9 +121,9 @@ public static StageMine deserialize(ConfigurationSection section, StageControlle } public static class Creator extends AbstractCountableBlockStage.AbstractCreator<StageMine> { - + private boolean prevent = false; - + public Creator(@NotNull StageCreationContext<StageMine> context) { super(context); } @@ -135,15 +131,15 @@ public Creator(@NotNull StageCreationContext<StageMine> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(6, ItemUtils.itemSwitch(Lang.preventBlockPlace.toString(), prevent), event -> setPrevent(!prevent)); } - + @Override protected ItemStack getBlocksItem() { return ItemUtils.item(XMaterial.STONE_PICKAXE, Lang.editBlocksMine.toString()); } - + public void setPrevent(boolean prevent) { if (this.prevent != prevent) { this.prevent = prevent; @@ -156,7 +152,7 @@ public void edit(StageMine stage) { super.edit(stage); setPrevent(stage.isPlaceCancelled()); } - + @Override public StageMine finishStage(StageController controller) { StageMine stage = new StageMine(controller, getImmutableBlocks()); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index 94007dea..fc349eed 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -7,6 +7,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.events.internal.BQMobDeathEvent; @@ -32,7 +33,7 @@ import fr.skytasul.quests.mobs.Mob; @LocatableType (types = LocatedType.ENTITY) -public class StageMobs extends AbstractCountableStage<Mob<?>> implements Locatable.MultipleLocatable { +public class StageMobs extends AbstractCountableStage<Mob<?>> implements Locatable.MultipleLocatable, Listener { private boolean shoot = false; 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 e9a1d1ff..a83c9af3 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -9,6 +9,7 @@ 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; @@ -44,7 +45,7 @@ import fr.skytasul.quests.utils.types.DialogRunnerImplementation; @LocatableType(types = LocatedType.ENTITY) -public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable { +public class StageNPC extends AbstractStage implements Locatable.PreciseLocatable, Dialogable, Listener { private BqNpc npc; private String npcID; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java index bb2b6af4..34807859 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlaceBlocks.java @@ -6,6 +6,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -19,8 +20,8 @@ import fr.skytasul.quests.api.utils.CountableObject; import fr.skytasul.quests.api.utils.XMaterial; -public class StagePlaceBlocks extends AbstractCountableBlockStage { - +public class StagePlaceBlocks extends AbstractCountableBlockStage implements Listener { + public StagePlaceBlocks(StageController controller, List<CountableObject<BQBlock>> blocks) { super(controller, blocks); } @@ -29,7 +30,7 @@ public StagePlaceBlocks(StageController controller, List<CountableObject<BQBlock public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_PLACE.toString(); } - + @EventHandler (priority = EventPriority.MONITOR) public void onPlace(BlockPlaceEvent e) { if (e.isCancelled()) return; @@ -37,7 +38,7 @@ public void onPlace(BlockPlaceEvent e) { if (hasStarted(p)) event(p, e.getBlock(), 1); } - + public static StagePlaceBlocks deserialize(ConfigurationSection section, StageController controller) { StagePlaceBlocks stage = new StagePlaceBlocks(controller, new ArrayList<>()); stage.deserialize(section); @@ -45,7 +46,7 @@ public static StagePlaceBlocks deserialize(ConfigurationSection section, StageCo } public static class Creator extends AbstractCountableBlockStage.AbstractCreator<StagePlaceBlocks> { - + public Creator(@NotNull StageCreationContext<StagePlaceBlocks> context) { super(context); } @@ -54,7 +55,7 @@ public Creator(@NotNull StageCreationContext<StagePlaceBlocks> context) { protected ItemStack getBlocksItem() { return ItemUtils.item(XMaterial.STONE, Lang.editBlocksPlace.toString()); } - + @Override public StagePlaceBlocks finishStage(StageController controller) { return new StagePlaceBlocks(controller, getImmutableBlocks()); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java index db725a97..43f09b57 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageTame.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageTame.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityTameEvent; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.localization.Lang; @@ -13,12 +14,12 @@ import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.types.AbstractEntityStage; -public class StageTame extends AbstractEntityStage { - +public class StageTame extends AbstractEntityStage implements Listener { + public StageTame(StageController controller, EntityType entity, int amount) { super(controller, entity, amount); } - + @EventHandler public void onTame(EntityTameEvent e) { if (e.getOwner() instanceof Player) { @@ -26,33 +27,33 @@ public void onTame(EntityTameEvent e) { event(p, e.getEntityType()); } } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_TAME.toString(); } - + public static StageTame deserialize(ConfigurationSection section, StageController controller) { String type = section.getString("entityType"); return new StageTame(controller, "any".equals(type) ? null : EntityType.valueOf(type), section.getInt("amount")); } - + public static class Creator extends AbstractEntityStage.AbstractCreator<StageTame> { - + public Creator(@NotNull StageCreationContext<StageTame> context) { super(context); } - + @Override protected boolean canUseEntity(EntityType type) { return Tameable.class.isAssignableFrom(type.getEntityClass()); } - + @Override protected StageTame finishStage(StageController controller) { return new StageTame(controller, entity, amount); } - + } - + } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index dd6960cc..4a9db6b2 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -139,7 +139,7 @@ dynmap: # Describes the way stage with multiple objects are described stage description: # Available placeholders are: {stage_index}, {stage_amount}, {stage_description} - descriptionFormat: "§8({stage_index}/{stage_amount}) §e{stage_description}" + description format: "§8({stage_index}/{stage_amount}) §e{stage_description}" # Format used for items, mobs, buckets... in stage descriptions. # Available placeholders are: {name}, {remaining} (decreasing), {done} (increasing), {total}, {percentage} (0 to 100). # Example: "{name} {done}/{total}" diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java index 1237e7e6..6f0a025a 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/worldguard/StageArea.java @@ -7,6 +7,7 @@ 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 com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -32,31 +33,31 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @LocatableType (types = LocatedType.OTHER) -public class StageArea extends AbstractStage implements Locatable.PreciseLocatable { - +public class StageArea extends AbstractStage implements Locatable.PreciseLocatable, Listener { + private static final long REFRESH_CENTER = 60 * 1000L; - + private final ProtectedRegion region; private final boolean exit; private final World world; - + private Locatable.Located center = null; private long lastCenter = 0; - + public StageArea(StageController controller, String regionName, String worldName, boolean exit) { super(controller); - + World w = Bukkit.getWorld(worldName); Validate.notNull(w, "No world with specified name (\"" + worldName + "\")"); this.world = w; - + ProtectedRegion reg = BQWorldGuard.getInstance().getRegion(regionName, w); Validate.notNull(reg, "No region with specified name (\"" + regionName + "\")"); this.region = reg; - + this.exit = exit; } - + @EventHandler public void onPlayerMove(PlayerMoveEvent e){ if (BQWorldGuard.getInstance().doHandleEntry()) return; // on WG 7.0 or higher @@ -67,7 +68,7 @@ public void onPlayerMove(PlayerMoveEvent e){ } } } - + @EventHandler public void onRegionEntry(WorldGuardEntryEvent e) { if (exit) @@ -110,7 +111,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol @Override public Located getLocated() { if (region instanceof GlobalProtectedRegion) return null; - + if (System.currentTimeMillis() - lastCenter > REFRESH_CENTER) { Location centerLoc = BukkitAdapter.adapt(world, region.getMaximumPoint() @@ -118,28 +119,28 @@ public Located getLocated() { .divide(2) .add(region.getMinimumPoint())) // midpoint .add(0.5, 0.5, 0.5); - + center = Locatable.Located.create(centerLoc); lastCenter = System.currentTimeMillis(); } return center; } - + public ProtectedRegion getRegion(){ return region; } - + public World getWorld(){ return world; } - + @Override public void serialize(ConfigurationSection section) { section.set("region", region.getId()); section.set("world", world.getName()); section.set("exit", exit); } - + public static StageArea deserialize(ConfigurationSection section, StageController controller) { return new StageArea(controller, section.getString("region"), section.getString("world"), section.getBoolean("exit", false)); } @@ -149,7 +150,7 @@ public static class Creator extends StageCreation<StageArea> { private boolean exit = false; private String regionName; private String worldName; - + public Creator(@NotNull StageCreationContext<StageArea> context) { super(context); } @@ -161,13 +162,13 @@ public void setupLine(@NotNull StageGuiLine line) { event -> launchRegionEditor(event.getPlayer(), false)); line.setItem(6, ItemUtils.itemSwitch(Lang.stageRegionExit.toString(), exit), event -> setExit(!exit)); } - + public void setRegion(String regionName, String worldName) { this.regionName = regionName; this.worldName = worldName; getLine().refreshItemLore(7, QuestOption.formatNullableValue(regionName + " (" + worldName + ")")); } - + public void setExit(boolean exit) { if (this.exit != exit) { this.exit = exit; @@ -193,7 +194,7 @@ private void launchRegionEditor(Player p, boolean first) { context.reopenGui(); }).useStrippedMessage().start(); } - + @Override public void start(Player p) { super.start(p); @@ -206,7 +207,7 @@ public void edit(StageArea stage) { setRegion(stage.getRegion().getId(), BQWorldGuard.getInstance().getWorld(stage.getRegion().getId()).getName()); setExit(stage.exit); } - + @Override public StageArea finishStage(StageController controller) { return new StageArea(controller, regionName, worldName, exit); From 44528f028451b2a971dde3306511566e49f25e23 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 9 Sep 2023 15:09:37 +0200 Subject: [PATCH 47/95] :bug: Fixed various bugs --- .../quests/api/gui/layout/LayoutedGUI.java | 4 +- .../quests/api/localization/Lang.java | 205 +++++++++--------- .../quests/api/objects/QuestObject.java | 40 ++-- .../quests/api/stages/StageTypeRegistry.java | 32 +-- .../blocks/BQBlocksManagerImplementation.java | 8 +- .../quests/gui/blocks/SelectBlockGUI.java | 2 +- .../fr/skytasul/quests/stages/StageChat.java | 2 +- .../StageControllerImplementation.java | 5 + core/src/main/resources/locales/en_US.yml | 11 +- 9 files changed, 156 insertions(+), 153 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java index c1392461..47ce3b2d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java @@ -87,7 +87,7 @@ protected LayoutedRowsGUI(@Nullable String name, @NotNull Map<Integer, LayoutedB @Override protected final Inventory instanciate(@NotNull Player player) { - return Bukkit.createInventory(null, rows, name); + return Bukkit.createInventory(null, rows * 9, name); } } @@ -151,7 +151,7 @@ private Builder() {} public @NotNull LayoutedGUI build() { if (buttons.isEmpty()) throw new IllegalArgumentException("Cannot build a layouted GUI with no buttons"); - + if (type != null) return new LayoutedTypeGUI(name, buttons, closeBehavior, type); 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 1fc9bef5..8de0233b 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 @@ -10,7 +10,7 @@ */ @SuppressWarnings("squid:S115") public enum Lang implements Locale { - + /* Formats (must be first to be used after) */ Prefix("misc.format.prefix"), NpcText("misc.format.npcText"), // 0: npc, 1: msg, 2: index, 3: max @@ -20,7 +20,7 @@ public enum Lang implements Locale { ErrorPrefix("misc.format.errorPrefix"), SuccessPrefix("misc.format.successPrefix"), RequirementNotMetPrefix("misc.format.requirementNotMetPrefix"), - + /* Messages */ FINISHED_BASE("msg.quest.finished.base"), FINISHED_OBTAIN("msg.quest.finished.obtain"), @@ -34,26 +34,26 @@ public enum Lang implements Locale { POOL_INVALID("msg.quest.invalidPoolID"), // 0: pool id ALREADY_STARTED("msg.quest.alreadyStarted"), QUEST_NOT_STARTED("msg.quest.notStarted"), - + QUESTS_MAX_LAUNCHED("msg.quests.maxLaunched"), // 0: max quests QUEST_UPDATED("msg.quests.updated"), QUEST_CHECKPOINT("msg.quests.checkpoint"), QUEST_FAILED("msg.quests.failed"), - + DIALOG_SKIPPED("msg.dialogs.skipped", MessageType.DefaultMessageType.UNPREFIXED), DIALOG_TOO_FAR("msg.dialogs.tooFar"), // 0: npc name - + POOL_NO_TIME("msg.pools.noTime"), // 0: time left POOL_ALL_COMPLETED("msg.pools.allCompleted"), POOL_NO_AVAILABLE("msg.pools.noAvailable"), POOL_MAX_QUESTS("msg.pools.maxQuests"), // 0: max quests - + QUEST_ITEM_DROP("msg.questItem.drop"), QUEST_ITEM_CRAFT("msg.questItem.craft"), QUEST_ITEM_EAT("msg.questItem.eat"), - + STAGE_MOBSLIST("msg.stageMobs.listMobs"), - + TYPE_CANCEL("msg.typeCancel"), NPC_TEXT("msg.writeNPCText"), REGION_NAME("msg.writeRegionName"), @@ -68,8 +68,8 @@ public enum Lang implements Locale { DESC_MESSAGE("msg.writeDescriptionText"), START_TEXT("msg.writeStageText"), MOVE_TELEPORT_POINT("msg.moveToTeleportPoint"), - NPC_NAME("msg.writeNpcName"), - NPC_SKIN("msg.writeNpcSkinName"), + NPC_NAME("msg.writeNpcName"), + NPC_SKIN("msg.writeNpcSkinName"), QUEST_NAME("msg.writeQuestName"), COMMAND("msg.writeCommand"), COMMAND_DELAY("msg.writeCommandDelay"), @@ -78,7 +78,7 @@ public enum Lang implements Locale { CONFIRM_MESSAGE("msg.writeConfirmMessage"), QUEST_DESCRIPTION("msg.writeQuestDescription"), QUEST_MATERIAL("msg.writeQuestMaterial"), - + REQUIREMENT_QUEST("msg.requirements.quest"), REQUIREMENT_LEVEL("msg.requirements.level"), REQUIREMENT_JOB("msg.requirements.job"), @@ -86,10 +86,10 @@ public enum Lang implements Locale { REQUIREMENT_COMBAT_LEVEL("msg.requirements.combatLevel"), REQUIREMENT_MONEY("msg.requirements.money"), // 0: money QUEST_WAIT("msg.requirements.waitTime"), //0: time - + XP_EDITED("msg.experience.edited"), SELECT_KILL_NPC("msg.selectNPCToKill"), - + REGION_DOESNT_EXIST("msg.regionDoesntExists"), NPC_DOESNT_EXIST("msg.npcDoesntExist"), NUMBER_NEGATIVE("msg.number.negative"), @@ -100,16 +100,16 @@ public enum Lang implements Locale { OUT_OF_BOUNDS("msg.indexOutOfBounds"), INVALID_BLOCK_DATA("msg.invalidBlockData"), // 0: blockdata, 1: material INVALID_BLOCK_TAG("msg.invalidBlockTag"), // 0: tag - + NEED_OBJECTS("msg.bringBackObjects"), ITEM_DROPPED("msg.inventoryFull"), - + VERSION_REQUIRED("msg.versionRequired", ErrorPrefix), // 0: version - + RESTART_SERVER("msg.restartServer"), - + // * Commands * - + COMMAND_DOESNT_EXIST_NOSLASH("msg.command.invalidCommand.simple"), ITEM_CHANGED("msg.command.itemChanged"), ITEM_REMOVED("msg.command.itemRemoved"), @@ -133,7 +133,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 - + COMMAND_SCOREBOARD_LINESET("msg.command.scoreboard.lineSet"), // 0: line id COMMAND_SCOREBOARD_LINERESET("msg.command.scoreboard.lineReset"), // 0: line id COMMAND_SCOREBOARD_LINEREMOVE("msg.command.scoreboard.lineRemoved"), // 0: line id @@ -158,7 +158,7 @@ public enum Lang implements Locale { COMMAND_TRANSLATION_NOT_FOUND("msg.command.downloadTranslations.notFound"), // 0: lang, 1: version COMMAND_TRANSLATION_EXISTS("msg.command.downloadTranslations.exists"), // 0: file COMMAND_TRANSLATION_DOWNLOADED("msg.command.downloadTranslations.downloaded"), // 0: lang - + COMMAND_HELP("msg.command.help.header", MessageType.DefaultMessageType.UNPREFIXED), COMMAND_HELP_CREATE("msg.command.help.create", MessageType.DefaultMessageType.UNPREFIXED), COMMAND_HELP_EDIT("msg.command.help.edit", MessageType.DefaultMessageType.UNPREFIXED), @@ -178,7 +178,7 @@ public enum Lang implements Locale { COMMAND_HELP_DOWNLOAD_TRANSLATIONS("msg.command.help.downloadTranslations", MessageType.DefaultMessageType.UNPREFIXED), COMMAND_HELP_SAVE("msg.command.help.save", MessageType.DefaultMessageType.UNPREFIXED), COMMAND_HELP_LIST("msg.command.help.list", MessageType.DefaultMessageType.UNPREFIXED), - + // * Editors * ALREADY_EDITOR("msg.editor.already"), ENTER_EDITOR_TITLE("msg.editor.enter.title"), @@ -191,50 +191,50 @@ public enum Lang implements Locale { CHOOSE_NPC_STARTER("msg.editor.npc.choseStarter"), NPC_NOT_QUEST("msg.editor.npc.notStarter"), - + CLICK_BLOCK("msg.editor.selectWantedBlock"), BLOCKS_AMOUNT("msg.editor.blockAmount"), BLOCK_NAME("msg.editor.blockName"), BLOCK_DATA("msg.editor.blockData"), // 0: available block datas BLOCK_TAGS("msg.editor.blockTag"), // 0: available block tags - + BUCKET_AMOUNT("msg.editor.typeBucketAmount"), DAMAGE_AMOUNT("msg.editor.typeDamageAmount", EditorPrefix), - + LOCATION_GO("msg.editor.goToLocation"), LOCATION_RADIUS("msg.editor.typeLocationRadius"), LOCATION_WORLDPATTERN("msg.editor.stage.location.typeWorldPattern"), - + GAME_TICKS("msg.editor.typeGameTicks"), - + AVAILABLE_ELEMENTS("msg.editor.availableElements"), // 0: available elements NO_SUCH_ELEMENT("msg.editor.noSuchElement", EditorPrefix), // 0: available elements INVALID_PATTERN("msg.editor.invalidPattern"), // 0: pattern COMPARISON_TYPE("msg.editor.comparisonTypeDefault"), // 0: available comparisons, 1: default comparison - + SCOREBOARD_OBJECTIVE_NOT_FOUND("msg.editor.scoreboardObjectiveNotFound"), - + POOL_HOLOGRAM_TEXT("msg.editor.pool.hologramText", EditorPrefix), POOL_MAXQUESTS("msg.editor.pool.maxQuests", EditorPrefix), POOL_QUESTS_PER_LAUNCH("msg.editor.pool.questsPerLaunch", EditorPrefix), POOL_TIME("msg.editor.pool.timeMsg", EditorPrefix), - + TITLE_TITLE("msg.editor.title.title", EditorPrefix), TITLE_SUBTITLE("msg.editor.title.subtitle", EditorPrefix), TITLE_FADEIN("msg.editor.title.fadeIn", EditorPrefix), TITLE_STAY("msg.editor.title.stay", EditorPrefix), TITLE_FADEOUT("msg.editor.title.fadeOut", EditorPrefix), - + COLOR_NAMED_EDITOR("msg.editor.colorNamed", EditorPrefix), COLOR_EDITOR("msg.editor.color", EditorPrefix), INVALID_COLOR("msg.editor.invalidColor", ErrorPrefix), - + FIREWORK_INVALID("msg.editor.firework.invalid", ErrorPrefix), FIREWORK_INVALID_HAND("msg.editor.firework.invalidHand", ErrorPrefix), FIREWORK_EDITED("msg.editor.firework.edited", SuccessPrefix), FIREWORK_REMOVED("msg.editor.firework.removed", SuccessPrefix), - + // requirements CHOOSE_XP_REQUIRED("msg.editor.text.chooseLvlRequired"), CHOOSE_JOB_REQUIRED("msg.editor.text.chooseJobRequired"), @@ -250,7 +250,7 @@ public enum Lang implements Locale { CHOOSE_REQUIREMENT_CUSTOM_REASON("msg.editor.text.chooseRequirementCustomReason", EditorPrefix), CHOOSE_REQUIREMENT_CUSTOM_DESCRIPTION("msg.editor.text.chooseRequirementCustomDescription", EditorPrefix), CHOOSE_REWARD_CUSTOM_DESCRIPTION("msg.editor.text.chooseRewardCustomDescription", EditorPrefix), - + // rewards CHOOSE_PERM_REWARD("msg.editor.text.reward.permissionName"), CHOOSE_PERM_WORLD("msg.editor.text.reward.permissionWorld"), @@ -267,7 +267,7 @@ public enum Lang implements Locale { INVALID_ITEM_TYPE("msg.editor.itemCreator.invalidItemType"), UNKNOWN_BLOCK_TYPE("msg.editor.itemCreator.unknownBlockType"), INVALID_BLOCK_TYPE("msg.editor.itemCreator.invalidBlockType"), - + DIALOG_MESSAGE_SYNTAX("msg.editor.dialog.syntaxMessage"), DIALOG_REMOVE_SYNTAX("msg.editor.dialog.syntaxRemove"), DIALOG_MSG_ADDED_PLAYER("msg.editor.dialog.player"), @@ -299,12 +299,12 @@ public enum Lang implements Locale { DIALOG_HELP_SKIPPABLE("msg.editor.dialog.help.skippable", MessageType.DefaultMessageType.UNPREFIXED), DIALOG_HELP_CLEAR("msg.editor.dialog.help.clear", MessageType.DefaultMessageType.UNPREFIXED), DIALOG_HELP_CLOSE("msg.editor.dialog.help.close", MessageType.DefaultMessageType.UNPREFIXED), - + MYTHICMOB_LIST("msg.editor.mythicmobs.list"), MYTHICMOB_NOT_EXISTS("msg.editor.mythicmobs.isntMythicMob"), MYTHICMOB_DISABLED("msg.editor.mythicmobs.disabled"), ADVANCED_SPAWNERS_MOB("msg.editor.advancedSpawnersMob", EditorPrefix), - + TEXTLIST_SYNTAX("msg.editor.textList.syntax"), TEXTLIST_TEXT_ADDED("msg.editor.textList.added"), TEXTLIST_TEXT_REMOVED("msg.editor.textList.removed"), @@ -313,22 +313,22 @@ public enum Lang implements Locale { TEXTLIST_TEXT_HELP_REMOVE("msg.editor.textList.help.remove", MessageType.DefaultMessageType.UNPREFIXED), TEXTLIST_TEXT_HELP_LIST("msg.editor.textList.help.list", MessageType.DefaultMessageType.UNPREFIXED), TEXTLIST_TEXT_HELP_CLOSE("msg.editor.textList.help.close", MessageType.DefaultMessageType.UNPREFIXED), - + // * Quests lists* Finished("advancement.finished"), Not_Started("advancement.notStarted"), - + /* Inventories */ done("inv.validate"), cancel("inv.cancel"), search("inv.search"), addObject("inv.addObject"), - + INVENTORY_CONFIRM("inv.confirm.name"), confirmYes("inv.confirm.yes"), confirmNo("inv.confirm.no"), - + stageCreate("inv.create.stageCreate"), stageRemove("inv.create.stageRemove"), stageUp("inv.create.stageUp"), @@ -385,7 +385,7 @@ public enum Lang implements Locale { editBucketAmount("inv.create.editBucketAmount"), changeTicksRequired("inv.create.changeTicksRequired"), changeEntityType("inv.create.changeEntityType"), - + stageLocationLocation("inv.create.editLocation"), stageLocationRadius("inv.create.editRadius"), stageLocationCurrentRadius("inv.create.currentRadius"), // 0: radius @@ -395,12 +395,12 @@ public enum Lang implements Locale { stageDeathCauses("inv.create.stage.death.causes"), stageDeathCauseAny("inv.create.stage.death.anyCause"), stageDeathCausesSet("inv.create.stage.death.setCauses"), // 0: causes amount - + stageDealDamageValue("inv.create.stage.dealDamage.damage"), stageDealDamageMobs("inv.create.stage.dealDamage.targetMobs"), - + stageEatDrinkItems("inv.create.stage.eatDrink.items"), - + INVENTORY_STAGES("inv.stages.name"), nextPage("inv.stages.nextPage"), laterPage("inv.stages.laterPage"), @@ -412,7 +412,7 @@ public enum Lang implements Locale { descMessage("inv.stages.descriptionTextItem"), previousBranch("inv.stages.previousBranch"), newBranch("inv.stages.newBranch"), - + INVENTORY_DETAILS("inv.details.name"), multiple("inv.details.multipleTime.itemName"), multipleLore("inv.details.multipleTime.itemLore"), @@ -494,12 +494,12 @@ public enum Lang implements Locale { optionValue("inv.details.optionValue"), // 0: value defaultValue("inv.details.defaultValue"), requiredParameter("inv.details.requiredParameter"), - + INVENTORY_ITEMS("inv.itemsSelect.name"), itemsNone("inv.itemsSelect.none"), - + INVENTORY_ITEM("inv.itemSelect.name"), - + INVENTORY_NPC("inv.npcCreate.name"), name("inv.npcCreate.setName"), skin("inv.npcCreate.setSkin"), @@ -511,14 +511,13 @@ public enum Lang implements Locale { INVENTORY_SELECT("inv.npcSelect.name"), selectNPC("inv.npcSelect.selectStageNPC"), createNPC("inv.npcSelect.createStageNPC"), - + INVENTORY_TYPE("inv.entityType.name"), INVENTORY_CHOOSE("inv.chooseQuest.name"), questMenu("inv.chooseQuest.menu"), questMenuLore("inv.chooseQuest.menuLore"), - + INVENTORY_MOBS("inv.mobs.name"), - click("inv.mobs.clickLore"), editAmount("inv.mobs.editAmount"), editMobName("inv.mobs.editMobName"), setLevel("inv.mobs.setLevel"), @@ -529,25 +528,25 @@ public enum Lang implements Locale { epicBoss("inv.mobSelect.epicBoss"), boss("inv.mobSelect.boss"), advancedSpawners("inv.mobSelect.advancedSpawners"), - + location("inv.stageEnding.locationTeleport"), command("inv.stageEnding.command"), - + INVENTORY_REQUIREMENTS("inv.requirements.name"), setRequirementReason("inv.requirements.setReason"), requirementReason("inv.requirements.reason"), // 0: message - + INVENTORY_REWARDS("inv.rewards.name"), commands("inv.rewards.commands"), rewardRandomRewards("inv.rewards.random.rewards"), rewardRandomMinMax("inv.rewards.random.minMax"), - + INVENTORY_CHECKPOINT_ACTIONS("inv.checkpointActions.name"), - + INVENTORY_CANCEL_ACTIONS("inv.cancelActions.name"), INVENTORY_REWARDS_WITH_REQUIREMENTS("inv.rewardsWithRequirements.name"), - + INVENTORY_QUESTS_LIST("inv.listAllQuests.name"), INVENTORY_PLAYER_LIST("inv.listPlayerQuests.name"), notStarteds("inv.listQuests.notStarted"), @@ -562,26 +561,26 @@ public enum Lang implements Locale { timesFinished("inv.listQuests.timesFinished"), // 0: times finished formatNormal("inv.listQuests.format.normal"), formatId("inv.listQuests.format.withId"), - + INVENTORY_CREATOR("inv.itemCreator.name"), itemType("inv.itemCreator.itemType"), itemFlags("inv.itemCreator.itemFlags"), itemName("inv.itemCreator.itemName"), itemLore("inv.itemCreator.itemLore"), itemQuest("inv.itemCreator.isQuestItem"), - + INVENTORY_COMMAND("inv.command.name"), commandValue("inv.command.value"), commandConsole("inv.command.console"), commandParse("inv.command.parse"), commandDelay("inv.command.delay"), - + INVENTORY_COMMANDS_LIST("inv.commandsList.name"), commandsListValue("inv.commandsList.value"), commandsListConsole("inv.commandsList.console"), - + INVENTORY_CHOOSEACCOUNT("inv.chooseAccount.name"), - + INVENTORY_BLOCK("inv.block.name"), materialName("inv.block.material"), materialNotItemLore("inv.block.materialNotItemLore"), // 0: block id @@ -589,15 +588,15 @@ public enum Lang implements Locale { blockData("inv.block.blockData"), blockTag("inv.block.blockTag"), blockTagLore("inv.block.blockTagLore"), - + INVENTORY_BLOCKSLIST("inv.blocksList.name"), - + INVENTORY_BLOCK_ACTION("inv.blockAction.name"), clickLocation("inv.blockAction.location"), clickMaterial("inv.blockAction.material"), - + INVENTORY_BUCKETS("inv.buckets.name"), - + INVENTORY_PERMISSION("inv.permission.name"), perm("inv.permission.perm"), world("inv.permission.world"), @@ -608,10 +607,10 @@ public enum Lang implements Locale { INVENTORY_PERMISSION_LIST("inv.permissionList.name"), permRemoved("inv.permissionList.removed"), permWorld("inv.permissionList.world"), - + INVENTORY_CLASSES_REQUIRED("inv.classesRequired.name"), INVENTORY_CLASSES_LIST("inv.classesList.name"), - + INVENTORY_FACTIONS_REQUIRED("inv.factionsRequired.name"), INVENTORY_FACTIONS_LIST("inv.factionsList.name"), @@ -628,7 +627,7 @@ public enum Lang implements Locale { poolEdit("inv.poolsManage.edit"), poolChoose("inv.poolsManage.choose"), poolCreate("inv.poolsManage.create"), - + INVENTORY_POOL_CREATE("inv.poolCreation.name"), poolEditHologramText("inv.poolCreation.hologramText"), poolMaxQuests("inv.poolCreation.maxQuests"), @@ -638,9 +637,9 @@ public enum Lang implements Locale { poolAvoidDuplicates("inv.poolCreation.avoidDuplicates"), poolAvoidDuplicatesLore("inv.poolCreation.avoidDuplicatesLore"), poolRequirements("inv.poolCreation.requirements"), - + INVENTORY_POOLS_LIST("inv.poolsList.name"), - + INVENTORY_ITEM_COMPARISONS("inv.itemComparisons.name"), comparisonBukkit("inv.itemComparisons.bukkit"), comparisonBukkitLore("inv.itemComparisons.bukkitLore"), @@ -660,34 +659,34 @@ public enum Lang implements Locale { comparisonItemsAdderLore("inv.itemComparisons.itemsAdderLore"), comparisonMmoItems("inv.itemComparisons.mmoItems"), comparisonMmoItemsLore("inv.itemComparisons.mmoItemsLore"), - + INVENTORY_EDIT_TITLE("inv.editTitle.name"), title_title("inv.editTitle.title"), title_subtitle("inv.editTitle.subtitle"), title_fadeIn("inv.editTitle.fadeIn"), title_stay("inv.editTitle.stay"), title_fadeOut("inv.editTitle.fadeOut"), - + INVENTORY_PARTICLE_EFFECT("inv.particleEffect.name"), particle_shape("inv.particleEffect.shape"), particle_type("inv.particleEffect.type"), particle_color("inv.particleEffect.color"), - + INVENTORY_PARTICLE_LIST("inv.particleList.name"), particle_colored("inv.particleList.colored"), - + INVENTORY_DAMAGE_CAUSE("inv.damageCause.name"), - + INVENTORY_DAMAGE_CAUSES_LIST("inv.damageCausesList.name"), - + INVENTORY_VISIBILITY("inv.visibility.name"), visibility_notStarted("inv.visibility.notStarted"), visibility_inProgress("inv.visibility.inProgress"), visibility_finished("inv.visibility.finished"), visibility_maps("inv.visibility.maps"), - + INVENTORY_EQUIPMENT_SLOTS("inv.equipmentSlots.name"), - + object_description_set("inv.questObjects.setCustomDescription"), object_description("inv.questObjects.description"), // 0: description @@ -698,9 +697,9 @@ public enum Lang implements Locale { BOOK_REQUIREMENTS("inv.listBook.requirements"), BOOK_STAGES("inv.listBook.questStages"), BOOK_NOQUEST("inv.listBook.noQuests"), - + /* Scoreboard */ - + SCOREBOARD_NAME("scoreboard.name"), SCOREBOARD_NONE("scoreboard.noLaunched"), SCOREBOARD_NONE_NAME("scoreboard.noLaunchedName"), @@ -729,9 +728,9 @@ public enum Lang implements Locale { SCOREBOARD_DEAL_DAMAGE_ANY("scoreboard.stage.dealDamage.any"), // 0: damage SCOREBOARD_DEAL_DAMAGE_MOBS("scoreboard.stage.dealDamage.mobs"), // 0: damage, 1: mobs SCOREBOARD_EAT_DRINK("scoreboard.stage.eatDrink"), // 0: items - + /* Indications */ - + INDICATION_START("indication.startQuest"), // 0: quest name INDICATION_CLOSE("indication.closeInventory"), INDICATION_CANCEL("indication.cancelQuest"), // 0: quest name @@ -739,7 +738,7 @@ public enum Lang implements Locale { INDICATION_REMOVE_POOL("indication.removePool"), /* Description */ - + RDTitle("description.requirement.title"), RDLevel("description.requirement.level"), // 0: lvl RDJobLevel("description.requirement.jobLevel"), // 0: lvl, 1: job @@ -748,17 +747,17 @@ public enum Lang implements Locale { RDClass("description.requirement.class"), // 0: classes RDFaction("description.requirement.faction"), // 0: factions RDQuest("description.requirement.quest"), // 0: quest - + RWDTitle("description.reward.title"), - + /* Misc */ - + TimeWeeks("misc.time.weeks"), TimeDays("misc.time.days"), TimeHours("misc.time.hours"), TimeMinutes("misc.time.minutes"), TimeLessMinute("misc.time.lessThanAMinute"), - + Find("misc.stageType.region"), Talk("misc.stageType.npc"), Items("misc.stageType.items"), @@ -780,7 +779,7 @@ public enum Lang implements Locale { Death("misc.stageType.die"), DealDamage("misc.stageType.dealDamage"), EatDrink("misc.stageType.eatDrink"), - + ComparisonEquals("misc.comparison.equals"), ComparisonDifferent("misc.comparison.different"), ComparisonLess("misc.comparison.less"), @@ -803,27 +802,27 @@ public enum Lang implements Locale { RSkillLvl("misc.requirement.mcMMOSkillLevel"), RMoney("misc.requirement.money"), REquipment("misc.requirement.equipment"), - + RWSkillApiXp("misc.reward.skillApiXp"), BucketWater("misc.bucket.water"), BucketLava("misc.bucket.lava"), BucketMilk("misc.bucket.milk"), BucketSnow("misc.bucket.snow"), - + ClickRight("misc.click.right"), ClickLeft("misc.click.left"), ClickShiftRight("misc.click.shift-right"), ClickShiftLeft("misc.click.shift-left"), ClickMiddle("misc.click.middle"), - + AmountItems("misc.amounts.items"), // 0: amount AmountComparisons("misc.amounts.comparisons"), // 0: amount AmountDialogLines("misc.amounts.dialogLines"), // 0: amount AmountPermissions("misc.amounts.permissions"), // 0: amount AmountMobs("misc.amounts.mobs"), // 0: amount AmountXp("misc.amounts.xp"), - + HologramText("misc.hologramText"), PoolHologramText("misc.poolHologramText"), EntityType("misc.entityType"), @@ -842,24 +841,24 @@ public enum Lang implements Locale { Yes("misc.yes"), No("misc.no"), And("misc.and"); - + private static final String DEFAULT_STRING = "§cnot loaded"; - + private final @NotNull String path; private final @NotNull MessageType type; private final @Nullable Lang prefix; - + private @NotNull String value = DEFAULT_STRING; private Lang(@NotNull String path) { this(path, MessageType.DefaultMessageType.PREFIXED, null); } - + private Lang(@NotNull String path, @NotNull MessageType type) { this(path, type, null); } - + private Lang(@NotNull String path, @Nullable Lang prefix) { this(path, MessageType.DefaultMessageType.PREFIXED, prefix); } @@ -869,12 +868,12 @@ private Lang(@NotNull String path, @NotNull MessageType type, @Nullable Lang pre this.type = type; this.prefix = prefix; } - + @Override public @NotNull String getPath() { return path; } - + @Override public @NotNull MessageType getType() { return type; @@ -884,15 +883,15 @@ private Lang(@NotNull String path, @NotNull MessageType type, @Nullable Lang pre public void setValue(@NotNull String value) { this.value = Objects.requireNonNull(value); } - + @Override public @NotNull String getValue() { return prefix == null ? value : (prefix.toString() + value); } - + @Override public String toString() { return getValue(); } - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index 28d26545..4699920b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -18,36 +18,36 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public abstract class QuestObject extends SerializableObject implements Cloneable, HasPlaceholders { - + protected static final String CUSTOM_DESCRIPTION_KEY = "customDescription"; private Quest quest; private String customDescription; - + private @Nullable PlaceholderRegistry placeholders; protected QuestObject(@NotNull QuestObjectsRegistry registry, @Nullable String customDescription) { super(registry); this.customDescription = customDescription; } - + @Override public QuestObjectCreator getCreator() { return (QuestObjectCreator) super.getCreator(); } - + public void attach(@NotNull Quest quest) { this.quest = quest; } - + public void detach() { this.quest = null; } - + public @Nullable Quest getAttachedQuest() { return quest; } - + public @Nullable String getCustomDescription() { return customDescription; } @@ -59,7 +59,7 @@ public void setCustomDescription(@Nullable String customDescription) { public @NotNull String debugName() { return getClass().getSimpleName() + (quest == null ? ", unknown quest" : (", quest " + quest.getId())); } - + public boolean isValid() { return true; } @@ -80,41 +80,42 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol @Override public abstract @NotNull QuestObject clone(); - + @Override public void save(@NotNull ConfigurationSection section) { if (customDescription != null) section.set(CUSTOM_DESCRIPTION_KEY, customDescription); } - + @Override public void load(@NotNull ConfigurationSection section) { if (section.contains(CUSTOM_DESCRIPTION_KEY)) customDescription = section.getString(CUSTOM_DESCRIPTION_KEY); } - + public final @Nullable String getDescription(Player player) { String string = customDescription == null ? getDefaultDescription(player) : customDescription; - string = MessageUtils.format(string, getPlaceholdersRegistry()); + if (string != null) + string = MessageUtils.format(string, getPlaceholdersRegistry()); return string; } /** * Gets the description shown in the GUIs for this quest object. - * + * * @param player player to get the description for * @return the description of this object (nullable) */ protected @Nullable String getDefaultDescription(@NotNull Player p) { return null; } - + public @NotNull String @Nullable [] getItemLore() { LoreBuilder lore = new LoreBuilder(); addLore(lore); return lore.toLoreArray(); } - + protected void addLore(@NotNull LoreBuilder loreBuilder) { loreBuilder.addClick(getRemoveClick(), "§c" + Lang.Remove.toString()); loreBuilder.addClick(getCustomDescriptionClick(), Lang.object_description_set.toString()); @@ -126,14 +127,15 @@ protected void addLore(@NotNull LoreBuilder loreBuilder) { description = "§cerror"; QuestsPlugin.getPlugin().getLoggerExpanded().warning("Could not get quest object description during edition", ex); } - loreBuilder.addDescription(Lang.object_description.format(PlaceholderRegistry.of("description", - description + (customDescription == null ? " " + Lang.defaultValue : "")))); + if (description != null) + loreBuilder.addDescription(Lang.object_description.format(PlaceholderRegistry.of("description", + description + (customDescription == null ? " " + Lang.defaultValue : "")))); } public @NotNull ItemStack getItemStack() { return ItemUtils.lore(getCreator().getItem().clone(), getItemLore()); } - + public @Nullable ClickType getRemoveClick() { return ClickType.SHIFT_LEFT; } @@ -158,7 +160,7 @@ public final void click(@NotNull QuestObjectClickEvent event) { clickInternal(event); } } - + protected abstract void clickInternal(@NotNull QuestObjectClickEvent event); } \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java index b48fea72..d2c0dc23 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageTypeRegistry.java @@ -10,10 +10,10 @@ import fr.skytasul.quests.api.stages.options.StageOptionAutoRegister; public class StageTypeRegistry implements Iterable<StageType<?>> { - + private final @NotNull List<@NotNull StageType<?>> types = new ArrayList<>(); private final @NotNull List<@NotNull StageOptionAutoRegister> autoRegisteringOptions = new ArrayList<>(2); - + /** * Registers new stage type into the plugin. * @param type StageType instance @@ -22,29 +22,29 @@ public void register(@NotNull StageType<? extends AbstractStage> type) { Validate.notNull(type); types.add(type); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Stage registered (" + type.getName() + ", " + (types.size() - 1) + ")"); - applyAutoregisteringOptions(type); + + for (StageOptionAutoRegister autoRegister : autoRegisteringOptions) + applyAutoregisteringOptions(type, autoRegister); } - - private <T extends AbstractStage> void applyAutoregisteringOptions(@NotNull StageType<T> type) { - for (StageOptionAutoRegister autoRegister : autoRegisteringOptions) { - if (autoRegister.appliesTo(type)) - type.getOptionsRegistry().register(autoRegister.createOptionCreator(type)); - } + + private <T extends AbstractStage> void applyAutoregisteringOptions(@NotNull StageType<T> type, + @NotNull StageOptionAutoRegister autoRegister) { + if (autoRegister.appliesTo(type)) + type.getOptionsRegistry().register(autoRegister.createOptionCreator(type)); } public void autoRegisterOption(@NotNull StageOptionAutoRegister autoRegister) { Validate.notNull(autoRegister); autoRegisteringOptions.add(autoRegister); - for (StageType<?> type : types) { - applyAutoregisteringOptions(type); - } + for (StageType<?> type : types) + applyAutoregisteringOptions(type, autoRegister); } public @NotNull List<@NotNull StageType<?>> getTypes() { return types; } - + public <T extends AbstractStage> @NotNull Optional<StageType<T>> getType(@NotNull Class<T> stageClass) { return types .stream() @@ -52,17 +52,17 @@ public void autoRegisterOption(@NotNull StageOptionAutoRegister autoRegister) { .map(type -> (StageType<T>) type) .findAny(); } - + public @NotNull Optional<StageType<?>> getType(@NotNull String id) { return types .stream() .filter(type -> type.getID().equals(id)) .findAny(); } - + @Override public Iterator<StageType<?>> iterator() { return types.iterator(); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java index cfdb5c35..2b3f71c6 100644 --- a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.blocks; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Spliterator; -import java.util.Spliterators; +import java.util.*; import org.bukkit.block.Block; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,7 +35,7 @@ public BQBlocksManagerImplementation() { private void registerDefaultTypes() { materialType = (string, options) -> new BQBlockMaterial(options, XMaterial.valueOf(string)); - registerBlockType(null, materialType); + registerBlockType("", materialType); if (MinecraftVersion.MAJOR >= 13) { blockdataType = (string, options) -> new Post1_13.BQBlockData(options, string); 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 61007060..6e02ae98 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 @@ -80,7 +80,7 @@ public void place(@NotNull Inventory inventory, int slot) { }, this::dataClick)); buttons.put(6, LayoutedButton.create(() -> { - ItemStack item = ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.blockTag.toString(), + ItemStack item = ItemUtils.item(XMaterial.FILLED_MAP, Lang.blockTag.toString(), QuestOption.formatDescription(Lang.blockTagLore.toString()), "", QuestOption.formatNullableValue(tag, tag == null)); if (tag != null) diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java index b1242be2..f7be8718 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageChat.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageChat.java @@ -80,7 +80,7 @@ public void onCommand(PlayerCommandPreprocessEvent e) { private boolean check(String message, Player p) { if (placeholders) - message = MessageUtils.finalFormat(text, null, PlaceholdersContext.of(p, true, null)); + message = MessageUtils.finalFormat(message, null, PlaceholdersContext.of(p, true, null)); if (!(ignoreCase ? message.equalsIgnoreCase(text) : message.equals(text))) return false; if (!hasStarted(p)) return false; if (canUpdate(p)) finishStage(p); diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index 7c2ff63c..9b29ce10 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -6,12 +6,15 @@ import java.util.Optional; import java.util.function.Consumer; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; 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; import fr.skytasul.quests.api.events.accounts.PlayerAccountJoinEvent; @@ -148,12 +151,14 @@ public void leaves(@NotNull Player player) { public void load() { QuestUtils.autoRegister(stage); + Bukkit.getPluginManager().registerEvents(this, BeautyQuests.getInstance()); propagateStageHandlers(handler -> handler.stageLoad(this)); stage.load(); } public void unload() { QuestUtils.autoUnregister(stage); + HandlerList.unregisterAll(this); propagateStageHandlers(handler -> handler.stageUnload(this)); stage.unload(); } diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index a78904c6..1f31217a 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -354,8 +354,8 @@ inv: mineBlocks: §aBreak blocks placeBlocks: §aPlace blocks talkChat: §aWrite in chat - interact: §aInteract with block - interactBlock: §aInteract with block at location + interact: §aInteract with a type of block + interactLocation: §aInteract with block at location fish: §aCatch fishes melt: §6Melt items enchant: §dEnchant items @@ -549,6 +549,7 @@ inv: mythicMob: §6Select Mythic Mob epicBoss: §6Select Epic Boss boss: §6Select a Boss + advancedSpawners: §6Select an AdvancedSpawners mob stageEnding: locationTeleport: §eEdit teleport location command: §eEdit executed command @@ -580,9 +581,9 @@ inv: loreCancelClick: §cCancel the quest loreStart: §a§oClick to start the quest. loreStartUnavailable: §c§oYou do not meet requirements to start the quest. - timeToWaitRedo: §3§oYou can restart this quest in {time_left}. - canRedo: §3§oYou can restart this quest! - timesFinished: §3Quest done {times_finished} times. + timeToWaitRedo: §7§oYou can restart this quest in {time_left}... + canRedo: §e§oYou can restart this quest! + timesFinished: §eCompleted §6{times_finished} x§e. format: normal: §6§l§o{quest_name} withId: §6§l§o{quest_name}§r §e#{quest_id} From 0649b7380084f2bbfa26b25f29352d9db24342ec Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 9 Sep 2023 18:42:39 +0200 Subject: [PATCH 48/95] :sparkles: NPCs plugin are now optional! --- .../quests/api/editors/EditorFactory.java | 6 + .../skytasul/quests/api/pools/QuestPool.java | 25 ++-- .../quests/api/pools/QuestPoolsManager.java | 5 +- .../api/utils/messaging/MessageUtils.java | 4 +- .../java/fr/skytasul/quests/BeautyQuests.java | 130 +++++++++--------- .../skytasul/quests/DefaultQuestFeatures.java | 42 +++--- .../fr/skytasul/quests/QuestsListener.java | 40 +++--- .../quests/commands/CommandsAdmin.java | 7 +- .../quests/editor/DefaultEditorFactory.java | 10 ++ .../editor/EditorManagerImplementation.java | 14 +- .../fr/skytasul/quests/editor}/SelectNPC.java | 24 +++- .../quests/gui/npc/NpcFactoryGUI.java | 2 + .../skytasul/quests/gui/npc/NpcSelectGUI.java | 10 +- .../quests/gui/pools/PoolEditGUI.java | 57 ++++---- .../quests/npcs}/BQNPCClickEvent.java | 2 +- .../npcs/BqNpcManagerImplementation.java | 4 +- .../fr/skytasul/quests/stages/StageNPC.java | 2 +- .../QuestPoolsManagerImplementation.java | 6 +- 18 files changed, 220 insertions(+), 170 deletions(-) rename {api/src/main/java/fr/skytasul/quests/api/editors => core/src/main/java/fr/skytasul/quests/editor}/SelectNPC.java (52%) rename {api/src/main/java/fr/skytasul/quests/api/events/internal => core/src/main/java/fr/skytasul/quests/npcs}/BQNPCClickEvent.java (95%) diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java b/api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java index b108c28a..d5116aaf 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/EditorFactory.java @@ -1,11 +1,17 @@ package fr.skytasul.quests.api.editors; +import java.util.function.Consumer; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.editors.parsers.AbstractParser; +import fr.skytasul.quests.api.npcs.BqNpc; public interface EditorFactory { public @NotNull AbstractParser<XMaterial> getMaterialParser(boolean item, boolean block); + public @NotNull Editor createNpcSelection(@NotNull Player player, @NotNull Runnable cancel, + @NotNull Consumer<BqNpc> callback); + } 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 46ea676c..6c5f884c 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 @@ -4,6 +4,8 @@ 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; @@ -14,8 +16,10 @@ public interface QuestPool extends HasPlaceholders { int getId(); + @Nullable String getNpcId(); + @Nullable String getHologram(); int getMaxQuests(); @@ -28,22 +32,27 @@ public interface QuestPool extends HasPlaceholders { boolean doAvoidDuplicates(); + @NotNull RequirementList getRequirements(); - List<Quest> getQuests(); + @NotNull + List<@NotNull Quest> getQuests(); - void addQuest(Quest quest); + void addQuest(@NotNull Quest quest); - void removeQuest(Quest quest); + void removeQuest(@NotNull Quest quest); - ItemStack getItemStack(String action); + @NotNull + ItemStack getItemStack(@NotNull String action); - CompletableFuture<PlayerPoolDatas> resetPlayer(PlayerAccount acc); + @NotNull + CompletableFuture<PlayerPoolDatas> resetPlayer(@NotNull PlayerAccount acc); - void resetPlayerTimer(PlayerAccount acc); + void resetPlayerTimer(@NotNull PlayerAccount acc); - boolean canGive(Player p); + boolean canGive(@NotNull Player p); - CompletableFuture<String> give(Player p); + @NotNull + CompletableFuture<String> give(@NotNull Player p); } diff --git a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java index cbe0a73c..3a5614ca 100644 --- a/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/pools/QuestPoolsManager.java @@ -8,8 +8,9 @@ public interface QuestPoolsManager { - public @NotNull QuestPool createPool(@Nullable QuestPool editing, String npcID, @Nullable String hologram, int maxQuests, - int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements); + public @NotNull QuestPool createPool(@Nullable QuestPool editing, @Nullable String npcID, @Nullable String hologram, + int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, + @NotNull RequirementList requirements); public void removePool(int id); diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java index a741dacc..fcac0bcd 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -87,8 +87,8 @@ public static String itemsToFormattedString(String[] items, String separator) { String substring = msg.substring(lastAppend, matcher.start()); colors = ChatColorUtils.getLastColors(colors, substring); output.append(substring); - Matcher replMatcher = RESET_PATTERN.matcher(replacement); - output.append(replMatcher.replaceAll("§r" + colors)); + if (replacement != null) + output.append(RESET_PATTERN.matcher(replacement).replaceAll("§r" + colors)); lastAppend = matcher.end(); } diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 48d45ade..3964bce5 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -67,9 +67,9 @@ public class BeautyQuests extends JavaPlugin implements QuestsPlugin { private static BeautyQuests instance; private BukkitRunnable saveTask; private boolean isPaper; - + /* --------- Storage --------- */ - + private String lastVersion; private QuestsConfigurationImplementation config; @@ -80,9 +80,9 @@ public class BeautyQuests extends JavaPlugin implements QuestsPlugin { private YamlConfiguration data; private File dataFile; private File saveFolder; - + private Path backupDir = null; - + /* --------- Datas --------- */ private final @NotNull BqNpcManagerImplementation npcManager = new BqNpcManagerImplementation(); @@ -90,21 +90,21 @@ public class BeautyQuests extends JavaPlugin implements QuestsPlugin { private @Nullable QuestsManagerImplementation quests; private @Nullable QuestPoolsManagerImplementation pools; private @Nullable AbstractPlayersManager players; - + /* ---------- Operations -------- */ private boolean disable = false; protected boolean loadingFailure = false; protected boolean savingFailure = false; protected boolean loaded = false; - + private @NotNull IntegrationManager integrations = new IntegrationManager(); private @Nullable CommandsManagerImplementation command; private @Nullable LoggerExpanded logger; private @Nullable LoggerHandler loggerHandler; private @Nullable GuiManagerImplementation guiManager; private @Nullable EditorManagerImplementation editorManager; - + /* ---------------------------------------------- */ @Override @@ -131,7 +131,7 @@ public void onLoad(){ setEnabled(false); } } - + @Override public void onEnable(){ if (disable) @@ -139,9 +139,9 @@ public void onEnable(){ try { logger.info("------------ BeautyQuests ------------"); - + checkPaper(); - + loadDefaultIntegrations(); integrations.testCompatibilities(); Bukkit.getPluginManager().registerEvents(integrations, this); @@ -155,17 +155,13 @@ public void onEnable(){ loadConfigParameters(true); registerCommands(); - + try { integrations.initializeCompatibilities(); }catch (Exception ex) { logger.severe("An error occurred while initializing compatibilities. Consider restarting.", ex); } - - if (!npcManager.isEnabled()) { - throw new LoadingException("No NPC plugin installed - please install Citizens or znpcs"); - } - + // Launch loading task String pluginVersion = getDescription().getVersion(); new BukkitRunnable() { @@ -180,7 +176,7 @@ public void run() { getServer().getPluginManager().registerEvents(new QuestsListener(), BeautyQuests.this); if (MinecraftVersion.MAJOR >= 16) getServer().getPluginManager().registerEvents(new Post1_16(), BeautyQuests.this); - + launchSaveCycle(); if (!lastVersion.equals(pluginVersion)) { // maybe change in data structure : update of all quest files @@ -225,7 +221,7 @@ public void onDisable(){ }catch (Throwable ex) { logger.severe("An error occurred while disabling command manager.", ex); } - + try { editorManager.leaveAll(); guiManager.closeAll(); @@ -233,7 +229,7 @@ public void onDisable(){ }catch (Throwable ex) { logger.severe("An error occurred while disabling editing systems.", ex); } - + try { if (!disable) saveAllConfig(true); }catch (Exception e) { @@ -244,15 +240,15 @@ public void onDisable(){ }catch (Exception e) { logger.severe("An error occurred while disabling plugin integrations.", e); } - + getServer().getScheduler().cancelTasks(this); }finally { if (loggerHandler != null) loggerHandler.close(); } } - + /* ---------- Various init ---------- */ - + private void initApi() throws ReflectiveOperationException { Method setMethod = QuestsAPIProvider.class.getDeclaredMethod("setAPI", QuestsAPI.class); setMethod.setAccessible(true); // NOSONAR @@ -275,7 +271,7 @@ private void registerCommands(){ command.initializeCommands(); command.lockCommands(); // we are obligated to register Brigadier during plugin initialization... } - + private void launchSaveCycle(){ if (config.saveCycle > 0 && saveTask == null) { int cycle = config.saveCycle * 60 * 20; @@ -294,7 +290,7 @@ public void run() { logger.info("Periodic saves task started (" + cycle + " ticks). Task ID: " + saveTask.runTaskTimerAsynchronously(this, cycle, cycle).getTaskId()); } } - + private void stopSaveCycle(){ if (config.saveCycle > 0 && saveTask != null) { saveTask.cancel(); @@ -302,7 +298,7 @@ private void stopSaveCycle(){ logger.info("Periodic saves task stopped."); } } - + private void launchMetrics(String pluginVersion) { Metrics metrics = new Metrics(this, 7460); metrics.addCustomChart(new DrilldownPie("customPluginVersion", () -> { @@ -340,7 +336,7 @@ private void launchMetrics(String pluginVersion) { })); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Started bStats metrics"); } - + private void launchUpdateChecker(String pluginVersion) { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Starting Spigot updater"); UpdateChecker checker; @@ -367,9 +363,9 @@ private void launchUpdateChecker(String pluginVersion) { .setNotifyOpsOnJoin(false) .checkNow(); } - + /* ---------- YAML ---------- */ - + private void loadConfigParameters(boolean init) throws LoadingException { try{ File configFile = new File(getDataFolder(), "config.yml"); @@ -381,7 +377,7 @@ private void loadConfigParameters(boolean init) throws LoadingException { if (init) loadLang(); ConfigUpdater.update(this, "config.yml", configFile); config.init(); - + ConfigurationSection dbConfig = config.getConfig().getConfigurationSection("database"); if (dbConfig.getBoolean("enabled")) { db = null; @@ -394,9 +390,9 @@ private void loadConfigParameters(boolean init) throws LoadingException { throw new LoadingException("Connection to database has failed.", ex); } } - + players = db == null ? new PlayersManagerYAML() : new PlayersManagerDB(db); - + /* static initialization */ if (init) { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default stage types."); @@ -436,7 +432,7 @@ private void loadDefaultIntegrations() { } InternalIntegrations.AccountsHook.isEnabled(); // to initialize the class } - + private YamlConfiguration loadLang() throws LoadingException { try { loadedLanguage = config.getConfig().getString("lang", "en_US"); @@ -445,7 +441,7 @@ private YamlConfiguration loadLang() throws LoadingException { throw new LoadingException("Couldn't load language file.", ex); } } - + private void loadDataFile() throws LoadingException { dataFile = new File(getDataFolder(), "data.yml"); if (!dataFile.exists()){ @@ -458,7 +454,7 @@ private void loadDataFile() throws LoadingException { } QuestsPlugin.getPlugin().getLoggerExpanded().debug("Loading data file, last time edited : " + new Date(dataFile.lastModified()).toString()); data = YamlConfiguration.loadConfiguration(dataFile); - + if (data.contains("version")){ lastVersion = data.getString("version"); if (!lastVersion.equals(getDescription().getVersion())){ @@ -471,12 +467,12 @@ private void loadDataFile() throws LoadingException { data.options().header("Do not edit ANYTHING here."); data.options().copyHeader(true); } - + private void loadAllDatas() throws Throwable { if (disable) return; integrations.lockDependencies(); // command.lockCommands(); we cannot register Brigadier after plugin initialization... - + if (scoreboards == null && config.getQuestsConfig().scoreboards()) { File scFile = new File(getDataFolder(), "scoreboard.yml"); if (!scFile.exists()) saveResource("scoreboard.yml", true); @@ -487,13 +483,13 @@ private void loadAllDatas() throws Throwable { try{ if (db == null && backupDir != null) createPlayerDatasBackup(backupDir, (PlayersManagerYAML) players); - + players.load(); }catch (Exception ex) { if (backupDir == null) createDataBackup(backupDir()); logger.severe("Error while loading player datas.", ex); } - + getAPI().getQuestsHandlers().forEach(handler -> { try { handler.load(); @@ -501,10 +497,10 @@ private void loadAllDatas() throws Throwable { logger.severe("Cannot load quest handler " + handler.getClass().getName(), ex); } }); - + pools = new QuestPoolsManagerImplementation(new File(getDataFolder(), "questPools.yml")); quests = new QuestsManagerImplementation(this, data.getInt("lastID"), saveFolder); - + if (config.firstQuestID != -1) { logger.warning("The config option \"firstQuest\" is present in your config.yml but is now unsupported. Please remove it."); QuestImplementation quest = quests.getQuest(config.firstQuestID); @@ -523,7 +519,7 @@ private void loadAllDatas() throws Throwable { } } } - + Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), () -> { for (Player p : Bukkit.getOnlinePlayers()) { players.loadPlayer(p); @@ -535,7 +531,7 @@ private void loadAllDatas() throws Throwable { public void saveAllConfig(boolean unload) throws Exception { if (unload) { if (quests != null) quests.unloadQuests(); - + getAPI().getQuestsHandlers().forEach(handler -> { try { handler.unload(); @@ -544,12 +540,12 @@ public void saveAllConfig(boolean unload) throws Exception { } }); } - + if (loaded) { long time = System.currentTimeMillis(); data.set("lastID", quests.getLastID()); data.set("version", getDescription().getVersion()); - + try { players.save(); }catch (Exception ex) { @@ -558,13 +554,13 @@ public void saveAllConfig(boolean unload) throws Exception { data.save(dataFile); QuestsPlugin.getPlugin().getLoggerExpanded().debug("Saved datas (" + (((double) System.currentTimeMillis() - time) / 1000D) + "s)!"); } - + if (unload){ npcManager.unload(); resetDatas(); } } - + private void resetDatas(){ quests = null; pools = null; @@ -577,9 +573,9 @@ private void resetDatas(){ //HandlerList.unregisterAll(this); loaded = false; } - + /* ---------- Backups ---------- */ - + public boolean createFolderBackup(Path backup) { if (!config.backups) return false; @@ -603,7 +599,7 @@ public boolean createFolderBackup(Path backup) { return false; } } - + public boolean createDataBackup(Path backup) { if (!config.backups) return false; @@ -622,11 +618,11 @@ public boolean createDataBackup(Path backup) { return false; } } - + public boolean createPlayerDatasBackup(Path backup, PlayersManagerYAML yamlManager) { if (!config.backups) return false; - + logger.info("Creating player datas backup..."); Path backupDir = backup.resolve("players"); Path playersFolderPath = yamlManager.getDirectory().toPath(); @@ -667,11 +663,11 @@ public boolean createQuestBackup(Path file, String msg) { } private SimpleDateFormat format = new SimpleDateFormat("yyyy'-'MM'-'dd'-'hh'-'mm'-'ss"); - + public Path backupDir() { return getDataFolder().toPath().resolve("backup-" + format.format(new Date())); } - + public void performReload(CommandSender sender){ try { sender.sendMessage("§c§l-- ⚠ Warning ! This command can occur §omuch§r§c§l bugs ! --"); @@ -682,7 +678,7 @@ public void performReload(CommandSender sender){ e.printStackTrace(); return; } - + try{ reloadConfig(); loadConfigParameters(false); @@ -692,7 +688,7 @@ public void performReload(CommandSender sender){ e.printStackTrace(); return; } - + sender.sendMessage("§7...Waiting for loading quests..."); new BukkitRunnable() { @Override @@ -709,7 +705,7 @@ public void run() { } }.runTaskLater(BeautyQuests.getInstance(), 20L); } - + @Override public void notifyLoadingFailure() { loadingFailure = true; @@ -755,16 +751,16 @@ public boolean hasSavingFailed() { public @NotNull CommandsManagerImplementation getCommand() { return ensureLoaded(command); } - + @Override public @NotNull QuestsConfigurationImplementation getConfiguration() { return config; } - + public @NotNull FileConfiguration getDataFile() { return data; } - + public @Nullable Database getBQDatabase() { return db; } @@ -772,15 +768,15 @@ public boolean hasSavingFailed() { public @Nullable ScoreboardManager getScoreboardManager() { return scoreboards; } - + public @NotNull QuestsManagerImplementation getQuestsManager() { return ensureLoaded(quests); } - + public @NotNull QuestPoolsManagerImplementation getPoolsManager() { return ensureLoaded(pools); } - + @Override public @NotNull GuiManager getGuiManager() { return ensureLoaded(guiManager); @@ -810,7 +806,7 @@ public boolean hasSavingFailed() { public @NotNull AbstractPlayersManager getPlayersManager() { return ensureLoaded(players); } - + public boolean isRunningPaper() { return isPaper; } @@ -819,7 +815,7 @@ public boolean isRunningPaper() { public static @NotNull BeautyQuests getInstance() { return instance; } - + public static class LoadingException extends Exception { private static final long serialVersionUID = -2811265488885752109L; @@ -833,11 +829,11 @@ public LoadingException(String loggerMessage, Throwable cause) { super(cause); this.loggerMessage = loggerMessage; } - + public String getLoggerMessage() { return loggerMessage; } - + } - + } diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index e307655d..fcac004f 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -43,16 +43,12 @@ public final class DefaultQuestFeatures { - private DefaultQuestFeatures() {} + private static boolean npcFeaturesRegistered = false; + private DefaultQuestFeatures() {} public static void registerStages() { StageTypeRegistry stages = QuestsAPI.getAPI().getStages(); - stages.register(new StageType<>("NPC", StageNPC.class, Lang.Talk.name(), - StageNPC::deserialize, item(XMaterial.OAK_SIGN, Lang.stageNPC.toString()), StageNPC.Creator::new)); - stages.register(new StageType<>("ITEMS", StageBringBack.class, Lang.Items.name(), - StageBringBack::deserialize, item(XMaterial.CHEST, Lang.stageBring.toString()), - StageBringBack.Creator::new)); stages.register(new StageType<>("MOBS", StageMobs.class, Lang.Mobs.name(), StageMobs::deserialize, item(XMaterial.WOODEN_SWORD, Lang.stageMobs.toString()), StageMobs.Creator::new)); @@ -143,8 +139,6 @@ public static void registerQuestOptions() { "customMaterial")); QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("confirmMessage", 15, OptionConfirmMessage.class, OptionConfirmMessage::new, null)); - QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramText", 17, OptionHologramText.class, - OptionHologramText::new, Lang.HologramText.toString())); QuestsAPI.getAPI().registerQuestOption( new QuestOptionCreator<>("bypassLimit", 18, OptionBypassLimit.class, OptionBypassLimit::new, false)); QuestsAPI.getAPI().registerQuestOption( @@ -155,10 +149,6 @@ public static void registerQuestOptions() { new QuestOptionCreator<>("cancellable", 21, OptionCancellable.class, OptionCancellable::new, true)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("cancelActions", 22, OptionCancelRewards.class, OptionCancelRewards::new, new RewardList())); - QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunch", 25, OptionHologramLaunch.class, - OptionHologramLaunch::new, QuestsConfigurationImplementation.getConfiguration().getHoloLaunchItem())); - QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunchNo", 26, OptionHologramLaunchNo.class, - OptionHologramLaunchNo::new, QuestsConfigurationImplementation.getConfiguration().getHoloLaunchNoItem())); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("scoreboard", 27, OptionScoreboardEnabled.class, OptionScoreboardEnabled::new, true)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hideNoRequirements", 28, @@ -182,10 +172,6 @@ public static void registerQuestOptions() { QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("startMessage", 39, OptionStartMessage.class, OptionStartMessage::new, QuestsConfigurationImplementation.getConfiguration().getPrefix() + Lang.STARTED_QUEST.toString())); - QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("starterNPC", 40, OptionStarterNPC.class, - OptionStarterNPC::new, null, "starterID")); - QuestsAPI.getAPI().registerQuestOption( - new QuestOptionCreator<>("startDialog", 41, OptionStartDialog.class, OptionStartDialog::new, null)); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endRewards", 43, OptionEndRewards.class, OptionEndRewards::new, new RewardList(), "rewardsList")); QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("endMsg", 44, OptionEndMessage.class, @@ -339,4 +325,28 @@ public String processString(String string, PlaceholdersContext context) { }); } + public static void registerNpcFeatures() { + if (npcFeaturesRegistered) + return; + npcFeaturesRegistered = true; + + StageTypeRegistry stages = QuestsAPI.getAPI().getStages(); + stages.register(new StageType<>("NPC", StageNPC.class, Lang.Talk.name(), + StageNPC::deserialize, item(XMaterial.OAK_SIGN, Lang.stageNPC.toString()), StageNPC.Creator::new)); + stages.register(new StageType<>("ITEMS", StageBringBack.class, Lang.Items.name(), + StageBringBack::deserialize, item(XMaterial.CHEST, Lang.stageBring.toString()), + StageBringBack.Creator::new)); + + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("starterNPC", 40, OptionStarterNPC.class, + OptionStarterNPC::new, null, "starterID")); + QuestsAPI.getAPI().registerQuestOption( + new QuestOptionCreator<>("startDialog", 41, OptionStartDialog.class, OptionStartDialog::new, null)); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramText", 17, OptionHologramText.class, + OptionHologramText::new, Lang.HologramText.toString())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunch", 25, OptionHologramLaunch.class, + OptionHologramLaunch::new, QuestsConfigurationImplementation.getConfiguration().getHoloLaunchItem())); + QuestsAPI.getAPI().registerQuestOption(new QuestOptionCreator<>("hologramLaunchNo", 26, OptionHologramLaunchNo.class, + OptionHologramLaunchNo::new, QuestsConfigurationImplementation.getConfiguration().getHoloLaunchNoItem())); + } + } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 769c54d5..592685e5 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -28,7 +28,6 @@ import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; import fr.skytasul.quests.api.events.internal.BQCraftEvent; -import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; @@ -41,34 +40,35 @@ import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.gui.quests.ChooseQuestGUI; import fr.skytasul.quests.gui.quests.PlayerListGUI; +import fr.skytasul.quests.npcs.BQNPCClickEvent; import fr.skytasul.quests.options.OptionAutoQuest; import fr.skytasul.quests.players.PlayerAccountImplementation; import fr.skytasul.quests.structure.QuestImplementation; import fr.skytasul.quests.utils.compatibility.Paper; public class QuestsListener implements Listener{ - + @EventHandler (priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onNPCClick(BQNPCClickEvent e) { if (e.isCancelled()) return; if (!QuestsConfiguration.getConfig().getQuestsConfig().getNpcClicks().contains(e.getClick())) return; - + Player p = e.getPlayer(); BqNpc npc = e.getNPC(); - + if (QuestsPlugin.getPlugin().getGuiManager().hasGuiOpened(p) || QuestsPlugin.getPlugin().getEditorManager().isInEditor(p)) return; - + PlayerAccountImplementation acc = BeautyQuests.getInstance().getPlayersManager().getAccount(p); if (acc == null) return; - + Set<Quest> quests = npc.getQuests(); quests = quests.stream().filter(qu -> !qu.hasStarted(acc) && (qu.isRepeatable() || !qu.hasFinished(acc))) .collect(Collectors.toSet()); if (quests.isEmpty() && npc.getPools().isEmpty()) return; - + List<QuestImplementation> launcheable = new ArrayList<>(); List<QuestImplementation> requirements = new ArrayList<>(); List<QuestImplementation> timer = new ArrayList<>(); @@ -87,7 +87,7 @@ public void onNPCClick(BQNPCClickEvent e) { + " for player " + p.getName(), ex); } } - + Set<QuestPool> startablePools = npc.getPools().stream().filter(pool -> { try { return pool.canGive(p); @@ -96,7 +96,7 @@ public void onNPCClick(BQNPCClickEvent e) { return false; } }).collect(Collectors.toSet()); - + e.setCancelled(true); if (!launcheable.isEmpty()) { for (QuestImplementation quest : launcheable) { @@ -129,7 +129,7 @@ public void onNPCClick(BQNPCClickEvent e) { e.setCancelled(false); } } - + @EventHandler (priority = EventPriority.LOWEST) public void onJoin(PlayerJoinEvent e){ Player player = e.getPlayer(); @@ -141,7 +141,7 @@ public void onJoin(PlayerJoinEvent e){ BeautyQuests.getInstance().getPlayersManager().loadPlayer(player); } } - + @EventHandler public void onQuit(PlayerQuitEvent e) { Player player = e.getPlayer(); @@ -157,7 +157,7 @@ public void onAccountJoin(PlayerAccountJoinEvent e) { QuestsAPI.getAPI().getQuestsManager().getQuests().stream().filter(qu -> qu.getOptionValueOrDef(OptionAutoQuest.class)).forEach(qu -> qu.start(e.getPlayer())); } } - + @EventHandler public void onAccountLeave(PlayerAccountLeaveEvent e) { BeautyQuests.getInstance().getQuestsManager().getQuestsRaw().forEach(x -> x.leave(e.getPlayer())); @@ -170,12 +170,12 @@ public void onDrop(PlayerDropItemEvent e){ Lang.QUEST_ITEM_DROP.send(e.getPlayer()); } } - + @EventHandler public void onEntityDamage(EntityDamageByEntityEvent e) { // firework damage if (e.getDamager().hasMetadata("questFinish")) e.setCancelled(true); } - + @EventHandler (priority = EventPriority.HIGH) public void onCraft(CraftItemEvent e) { for (ItemStack item : e.getInventory().getMatrix()) { @@ -186,7 +186,7 @@ public void onCraft(CraftItemEvent e) { } } } - + @EventHandler (priority = EventPriority.HIGH) public void onEat(PlayerItemConsumeEvent e) { if (Utils.isQuestItem(e.getItem())) { @@ -194,12 +194,12 @@ public void onEat(PlayerItemConsumeEvent e) { Lang.QUEST_ITEM_EAT.send(e.getPlayer()); } } - + @EventHandler (priority = EventPriority.HIGH) public void onDeath(PlayerDeathEvent e) { if (BeautyQuests.getInstance().isRunningPaper()) Paper.handleDeathItems(e, Utils::isQuestItem); } - + @EventHandler(priority = EventPriority.HIGHEST) public void onBreak(BlockBreakEvent e) { if (e.isCancelled()) return; @@ -219,7 +219,7 @@ public void onCraftMonitor(CraftItemEvent e){ materialCount = is.getAmount(); int maxCraftAmount = resultCount * materialCount; - + ItemStack item = e.getRecipe().getResult(); if (item.getType() == Material.AIR && e.getRecipe() instanceof ComplexRecipe) { String key = ((ComplexRecipe) e.getRecipe()).getKey().toString(); @@ -227,8 +227,8 @@ public void onCraftMonitor(CraftItemEvent e){ item = XMaterial.SUSPICIOUS_STEW.parseItem(); } } - + Bukkit.getPluginManager().callEvent(new BQCraftEvent(e, item, maxCraftAmount)); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 8bcb8ce6..a5a0ec56 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -22,7 +22,6 @@ import fr.skytasul.quests.api.commands.revxrsal.bukkit.annotation.CommandPermission; import fr.skytasul.quests.api.commands.revxrsal.exception.CommandErrorException; import fr.skytasul.quests.api.commands.revxrsal.orphan.OrphanCommand; -import fr.skytasul.quests.api.editors.SelectNPC; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.quests.Quest; @@ -70,7 +69,8 @@ public void edit(Player player, @Optional Quest quest) { session.openStagesGUI(player); }else { Lang.CHOOSE_NPC_STARTER.send(player); - new SelectNPC(player, () -> {}, npc -> { + QuestsPlugin.getPlugin().getEditorManager().getFactory().createNpcSelection(player, () -> { + }, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { ChooseQuestGUI.choose(player, npc.getQuests(), clickedQuest -> { @@ -93,7 +93,8 @@ public void remove(BukkitCommandActor actor, @Optional Quest quest) { doRemove(actor, quest); }else { Lang.CHOOSE_NPC_STARTER.send(actor.requirePlayer()); - new SelectNPC(actor.getAsPlayer(), () -> {}, npc -> { + QuestsPlugin.getPlugin().getEditorManager().getFactory().createNpcSelection(actor.getAsPlayer(), () -> { + }, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { ChooseQuestGUI.choose(actor.getAsPlayer(), npc.getQuests(), clickedQuest -> { diff --git a/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java b/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java index b555d814..f6fedd13 100644 --- a/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java +++ b/core/src/main/java/fr/skytasul/quests/editor/DefaultEditorFactory.java @@ -1,8 +1,12 @@ package fr.skytasul.quests.editor; +import java.util.function.Consumer; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.editors.Editor; import fr.skytasul.quests.api.editors.EditorFactory; import fr.skytasul.quests.api.editors.parsers.AbstractParser; +import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.editor.parsers.MaterialParser; @@ -24,4 +28,10 @@ public class DefaultEditorFactory implements EditorFactory { throw new IllegalArgumentException("Material parser must be either for items, for blocks or both, not neither."); } + @Override + public @NotNull Editor createNpcSelection(@NotNull Player player, @NotNull Runnable cancel, + @NotNull Consumer<BqNpc> callback) { + return new SelectNPC(player, cancel, callback); + } + } diff --git a/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java index 8fbdde94..43b072c8 100644 --- a/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/editor/EditorManagerImplementation.java @@ -19,6 +19,7 @@ import fr.skytasul.quests.api.editors.EditorManager; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.utils.MinecraftVersion; +import fr.skytasul.quests.api.utils.messaging.DefaultErrors; import fr.skytasul.quests.utils.QuestUtils; public class EditorManagerImplementation implements EditorManager, Listener { @@ -51,9 +52,6 @@ public <T extends Editor> T start(@NotNull T editor) { QuestsPlugin.getPlugin().getGuiManager().closeAndExit(player); QuestsPlugin.getPlugin().getLoggerExpanded() .debug(player.getName() + " is entering editor " + editor.getClass().getName() + "."); - editor.begin(); - - QuestUtils.autoRegister(editor); if (MinecraftVersion.MAJOR > 11) { player.sendTitle(Lang.ENTER_EDITOR_TITLE.toString(), Lang.ENTER_EDITOR_SUB.toString(), 5, 50, 5); @@ -64,6 +62,16 @@ public <T extends Editor> T start(@NotNull T editor) { if (bar != null) bar.addPlayer(player); + QuestUtils.autoRegister(editor); + + try { + editor.begin(); + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while beginning editor", ex); + DefaultErrors.sendGeneric(player, "impossible to begin editor"); + editor.cancel(); + } + return editor; } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java b/core/src/main/java/fr/skytasul/quests/editor/SelectNPC.java similarity index 52% rename from api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java rename to core/src/main/java/fr/skytasul/quests/editor/SelectNPC.java index 96aa7779..febb67e9 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/SelectNPC.java +++ b/core/src/main/java/fr/skytasul/quests/editor/SelectNPC.java @@ -1,22 +1,27 @@ -package fr.skytasul.quests.api.editors; +package fr.skytasul.quests.editor; import java.util.function.Consumer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; -import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.editors.InventoryClear; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; +import fr.skytasul.quests.api.utils.messaging.MessageType.DefaultMessageType; +import fr.skytasul.quests.api.utils.messaging.MessageUtils; +import fr.skytasul.quests.npcs.BQNPCClickEvent; +import fr.skytasul.quests.utils.QuestUtils; public class SelectNPC extends InventoryClear{ - + private Consumer<BqNpc> run; - + public SelectNPC(Player p, Runnable cancel, Consumer<BqNpc> end) { super(p, cancel); this.run = end; } - + @EventHandler (priority = EventPriority.LOW) private void onNPCClick(BQNPCClickEvent e) { if (e.getPlayer() != player) return; @@ -24,10 +29,17 @@ private void onNPCClick(BQNPCClickEvent e) { stop(); run.accept(e.getNPC()); } - + @Override public void begin(){ super.begin(); + if (!QuestsPlugin.getPlugin().getNpcManager().isEnabled()) { + MessageUtils.sendMessage(player, "§cWARNING: No NPC plugin registered.\nLeft editor.", + DefaultMessageType.PREFIXED); + QuestUtils.runSync(this::cancel); + return; + } + Lang.NPC_EDITOR_ENTER.send(player); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java index c4d1745a..0357fce3 100755 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcFactoryGUI.java @@ -30,6 +30,8 @@ public NpcFactoryGUI(@NotNull Collection<BqInternalNpcFactory> objects, @NotNull @Override public void open(@NotNull Player player) { + if (objects.isEmpty()) + throw new IllegalStateException("No NPCs factory found"); if (objects.size() == 1) callback.accept(objects.get(0)); else diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index bfdf8f36..75f6b5d4 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -6,7 +6,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.BeautyQuests; -import fr.skytasul.quests.api.editors.SelectNPC; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -21,12 +21,15 @@ public final class NpcSelectGUI { private NpcSelectGUI() {} - + public static ItemStack createNPC = ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.createNPC.toString()); public static ItemStack selectNPC = ItemUtils.item(XMaterial.STICK, Lang.selectNPC.toString()); public static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BqNpc> end, boolean nullable) { + if (!QuestsPlugin.getPlugin().getNpcManager().isEnabled()) + throw new IllegalArgumentException("No NPCs plugin registered"); + Builder builder = LayoutedGUI.newBuilder().addButton(1, LayoutedButton.create(createNPC, event -> { new NpcFactoryGUI(BeautyQuests.getInstance().getNpcManager() .getInternalFactories().stream() @@ -37,7 +40,8 @@ public static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BqN .open(event.getPlayer()); }).open(event.getPlayer()); })).addButton(3, LayoutedButton.create(selectNPC, event -> { - new SelectNPC(event.getPlayer(), event::reopen, end).start(); + QuestsPlugin.getPlugin().getEditorManager().getFactory() + .createNpcSelection(event.getPlayer(), event::reopen, end).start(); })); if (nullable) builder.addButton(2, LayoutedButton.create(ItemUtils.itemNone, event -> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index 4a9ea525..438da325 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -2,7 +2,6 @@ import java.util.concurrent.TimeUnit; import org.bukkit.Bukkit; -import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.jetbrains.annotations.NotNull; @@ -25,7 +24,7 @@ import fr.skytasul.quests.api.utils.XMaterial; public class PoolEditGUI extends AbstractGui { - + private static final int SLOT_NPC = 1; private static final int SLOT_HOLOGRAM = 2; private static final int SLOT_MAX_QUESTS = 3; @@ -36,9 +35,9 @@ public class PoolEditGUI extends AbstractGui { private static final int SLOT_REQUIREMENTS = 8; private static final int SLOT_CANCEL = 12; private static final int SLOT_CREATE = 14; - + private final Runnable end; - + private String hologram; private int maxQuests = 1; private int questsPerLaunch = 1; @@ -47,10 +46,9 @@ public class PoolEditGUI extends AbstractGui { private String npcID = null; private boolean avoidDuplicates = true; private RequirementList requirements = new RequirementList(); - - private boolean canFinish = false; + private QuestPool editing; - + public PoolEditGUI(Runnable end, QuestPool editing) { this.end = end; this.editing = editing; @@ -65,39 +63,32 @@ public PoolEditGUI(Runnable end, QuestPool editing) { requirements = editing.getRequirements(); } } - + private String[] getNPCLore() { return new String[] {"§8> " + Lang.requiredParameter.toString(), "", QuestOption.formatNullableValue("NPC " + npcID)}; } - + private String[] getHologramLore() { return new String[] { "", hologram == null ? QuestOption.formatNullableValue(Lang.PoolHologramText.toString()) + " " + Lang.defaultValue.toString() : QuestOption.formatNullableValue(hologram) }; } - + private String[] getMaxQuestsLore() { return new String[] { "", QuestOption.formatNullableValue(maxQuests) }; } - + private String[] getQuestsPerLaunchLore() { return new String[] { "", QuestOption.formatNullableValue(Integer.toString(questsPerLaunch), questsPerLaunch == 1) }; } - + private String[] getTimeLore() { return new String[] {"", QuestOption.formatNullableValue(Utils.millisToHumanString(timeDiff))}; } - + private String[] getRequirementsLore() { return new String[] {"", QuestOption.formatDescription(requirements.getSizeString())}; } - - private void handleDoneButton(Inventory inv) { - boolean newState = npcID != null; - if (newState == canFinish) return; - inv.getItem(SLOT_CREATE).setType((newState ? XMaterial.DIAMOND : XMaterial.CHARCOAL).parseMaterial()); - canFinish = newState; - } - + @Override protected Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, 18, Lang.INVENTORY_POOL_CREATE.toString()); @@ -105,7 +96,9 @@ protected Inventory instanciate(@NotNull Player player) { @Override protected void populate(@NotNull Player player, @NotNull Inventory inv) { - inv.setItem(SLOT_NPC, ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString(), getNPCLore())); + if (QuestsPlugin.getPlugin().getNpcManager().isEnabled()) + inv.setItem(SLOT_NPC, + ItemUtils.item(XMaterial.VILLAGER_SPAWN_EGG, Lang.stageNPCSelect.toString(), getNPCLore())); inv.setItem(SLOT_HOLOGRAM, ItemUtils.item(XMaterial.OAK_SIGN, Lang.poolEditHologramText.toString(), getHologramLore())); inv.setItem(SLOT_MAX_QUESTS, ItemUtils.item(XMaterial.REDSTONE, Lang.poolMaxQuests.toString(), getMaxQuestsLore())); inv.setItem(SLOT_QUESTS_PER_LAUNCH, ItemUtils.item(XMaterial.GUNPOWDER, Lang.poolQuestsPerLaunch.toString(), getQuestsPerLaunchLore())); @@ -113,12 +106,11 @@ protected void populate(@NotNull Player player, @NotNull Inventory inv) { inv.setItem(SLOT_REDO, ItemUtils.itemSwitch(Lang.poolRedo.toString(), redoAllowed)); inv.setItem(SLOT_DUPLICATE, ItemUtils.itemSwitch(Lang.poolAvoidDuplicates.toString(), avoidDuplicates, Lang.poolAvoidDuplicatesLore.toString())); inv.setItem(SLOT_REQUIREMENTS, ItemUtils.item(XMaterial.NETHER_STAR, Lang.poolRequirements.toString(), getRequirementsLore())); - + inv.setItem(SLOT_CANCEL, ItemUtils.itemCancel); - inv.setItem(SLOT_CREATE, ItemUtils.item(XMaterial.CHARCOAL, Lang.done.toString())); - handleDoneButton(inv); + inv.setItem(SLOT_CREATE, ItemUtils.itemDone); } - + @Override public void onClick(GuiClickEvent event) { switch (event.getSlot()) { @@ -126,7 +118,6 @@ public void onClick(GuiClickEvent event) { QuestsPlugin.getPlugin().getGuiManager().getFactory().createNpcSelection(event::reopen, npc -> { npcID = npc.getId(); ItemUtils.lore(event.getClicked(), getNPCLore()); - handleDoneButton(getInventory()); reopen(event.getPlayer()); }, false).open(event.getPlayer()); break; @@ -175,18 +166,16 @@ public void onClick(GuiClickEvent event) { reopen(event.getPlayer()); }, requirements).open(event.getPlayer()); break; - + case SLOT_CANCEL: end.run(); break; case SLOT_CREATE: - if (canFinish) { - BeautyQuests.getInstance().getPoolsManager().createPool(editing, npcID, hologram, maxQuests, questsPerLaunch, redoAllowed, timeDiff, avoidDuplicates, requirements); - end.run(); - } else - event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); + BeautyQuests.getInstance().getPoolsManager().createPool(editing, npcID, hologram, maxQuests, questsPerLaunch, + redoAllowed, timeDiff, avoidDuplicates, requirements); + end.run(); break; } } - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java b/core/src/main/java/fr/skytasul/quests/npcs/BQNPCClickEvent.java similarity index 95% rename from api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java rename to core/src/main/java/fr/skytasul/quests/npcs/BQNPCClickEvent.java index b7aa5aea..8145cd5a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/events/internal/BQNPCClickEvent.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BQNPCClickEvent.java @@ -1,4 +1,4 @@ -package fr.skytasul.quests.api.events.internal; +package fr.skytasul.quests.npcs; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; 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 6308ebcd..ecb693fd 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -14,8 +14,8 @@ 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.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.npcs.*; import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.utils.QuestUtils; @@ -65,6 +65,8 @@ public void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactor last = internalFactory; QuestUtils.autoRegister(internalFactory); + + DefaultQuestFeatures.registerNpcFeatures(); } @Override 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 a83c9af3..c5ed7a79 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -21,7 +21,6 @@ import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.DialogEditor; -import fr.skytasul.quests.api.events.internal.BQNPCClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; @@ -41,6 +40,7 @@ import fr.skytasul.quests.api.stages.types.Locatable.LocatedType; import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; +import fr.skytasul.quests.npcs.BQNPCClickEvent; import fr.skytasul.quests.utils.QuestUtils; import fr.skytasul.quests.utils.types.DialogRunnerImplementation; diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java index cea587fc..bfa31c4a 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java @@ -57,9 +57,9 @@ public void save(@NotNull QuestPoolImplementation pool) { } @Override - public @NotNull QuestPoolImplementation createPool(@Nullable QuestPool editing, String npcID, @Nullable String hologram, - int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, - @NotNull RequirementList requirements) { + public @NotNull QuestPoolImplementation createPool(@Nullable QuestPool editing, @Nullable String npcID, + @Nullable String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, + boolean avoidDuplicates, @NotNull RequirementList requirements) { if (editing != null) ((QuestPoolImplementation) editing).unload(); From b2d26d7d837d8b0153d6898b99c453ff2a0ec85e Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 11 Sep 2023 14:31:19 +0200 Subject: [PATCH 49/95] :bug: Fixed various bugs related with configuration migration and progress --- .../utils/messaging/PlaceholderRegistry.java | 14 ++-- .../java/fr/skytasul/quests/BeautyQuests.java | 7 +- .../QuestsConfigurationImplementation.java | 25 +++---- .../blocks/BQBlocksManagerImplementation.java | 25 ++++--- .../npcs/BqNpcManagerImplementation.java | 19 ++--- .../quests/stages/StageBringBack.java | 53 ++++++++------ .../quests/stages/StageDealDamage.java | 2 + .../fr/skytasul/quests/stages/StageNPC.java | 1 + .../options/StageOptionProgressBar.java | 3 +- .../pools/QuestPoolImplementation.java | 71 ++++++++++--------- core/src/main/resources/config.yml | 5 +- 11 files changed, 119 insertions(+), 106 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java index 398fea97..a2a36109 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java @@ -99,7 +99,7 @@ public boolean hasPlaceholder(@NotNull String key) { /** * Adds all the placeholders from the passed placeholders holders to this placeholders registry and * keeps indexed placeholders. - * + * * @param placeholdersHolders holders to get the placeholders from * @return this placeholder registry */ @@ -109,7 +109,7 @@ public boolean hasPlaceholder(@NotNull String key) { /** * Adds all the placeholders from the passed placeholders holders to this placeholders registry. - * + * * @param withIndexes should the indexed placeholders of the passed placeholders holders be kept as * indexed * @param placeholdersHolders holders to get the placeholders from @@ -119,7 +119,7 @@ public boolean hasPlaceholder(@NotNull String key) { @NotNull HasPlaceholders @NotNull... placeholdersHolders) { for (HasPlaceholders holder : placeholdersHolders) { this.placeholders.addAll(holder.getPlaceholdersRegistry().placeholders); - if (!holder.getPlaceholdersRegistry().indexed.isEmpty()) + if (withIndexes && !holder.getPlaceholdersRegistry().indexed.isEmpty()) this.indexed.addAll(holder.getPlaceholdersRegistry().indexed); } return this; @@ -128,7 +128,7 @@ public boolean hasPlaceholder(@NotNull String key) { /** * Creates a <i>new</i> placeholders registry containing the placeholders of this instance in * addition with those from the passed placeholders holders. - * + * * @param placeholdersHolders holders to get the placeholders from * @return a new placeholder registry containing all placeholders * @see #combine(HasPlaceholders...) @@ -143,7 +143,7 @@ public boolean hasPlaceholder(@NotNull String key) { /** * Creates a <i>new</i> placeholders registry containing the same placeholders as this instance but * with the placeholers passed as parameter no longer being indexed. - * + * * @param exceptedPlaceholders placeholders no longer being indexed * @return a copy of this registry without some indexed placeholders */ @@ -170,7 +170,7 @@ public boolean hasPlaceholder(@NotNull String key) { /** * Creates a <i>new</i> placeholders registry containing the same placeholders as this instance but * with the indexed placeholers being shifted so that the passed placeholder is the first one. - * + * * @param placeholder first placeholder to be indexed * @return a copy of this registry with the indexed placeholders shifted */ @@ -216,7 +216,7 @@ public boolean hasPlaceholder(@NotNull String key) { /** * Creates a placeholders registry containing the placeholders of all the passed placeholder * holders. - * + * * @param placeholdersHolders holders to get the placeholders from * @return a new placeholder registry containing all placeholders */ diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 3964bce5..dda48136 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -153,6 +153,7 @@ public void onEnable(){ if (!saveFolder.exists()) saveFolder.mkdirs(); loadDataFile(); loadConfigParameters(true); + checkLastVersion(); registerCommands(); @@ -454,7 +455,11 @@ private void loadDataFile() throws LoadingException { } QuestsPlugin.getPlugin().getLoggerExpanded().debug("Loading data file, last time edited : " + new Date(dataFile.lastModified()).toString()); data = YamlConfiguration.loadConfiguration(dataFile); + data.options().header("Do not edit ANYTHING here."); + data.options().copyHeader(true); + } + private void checkLastVersion() { if (data.contains("version")){ lastVersion = data.getString("version"); if (!lastVersion.equals(getDescription().getVersion())){ @@ -464,8 +469,6 @@ private void loadDataFile() throws LoadingException { createDataBackup(backupDir); } }else lastVersion = getDescription().getVersion(); - data.options().header("Do not edit ANYTHING here."); - data.options().copyHeader(true); } private void loadAllDatas() throws Throwable { diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 60cc2c6a..fc03cecd 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -603,7 +603,7 @@ public class StageDescriptionConfig implements QuestsConfiguration.StageDescript private String bossBarFormat; private int bossBarTimeout = 15; - private ConfigurationSection config; + private final ConfigurationSection config; public StageDescriptionConfig(ConfigurationSection config) { this.config = config; @@ -631,19 +631,16 @@ private void init() { private boolean update() { boolean result = false; - if (config == null) { - migrateEntry(QuestsConfigurationImplementation.this.config, "stageDescriptionItemsSplit", - QuestsConfigurationImplementation.this.config, "stage description"); - config = QuestsConfigurationImplementation.this.config.getConfigurationSection("stage description"); - result = true; - } + ConfigurationSection oldConfig = config.getParent().getConfigurationSection("stageDescriptionItemsSplit"); result |= migrateEntry(config.getParent(), "stageDescriptionFormat", config, "description format"); - result |= migrateEntry(config, "prefix", config, "line prefix"); - result |= migrateEntry(config, "sources", config, "split sources"); - if (config.contains("amountFormat")) { - String amountFormat = config.getString("amountFormat"); - boolean showXOne = config.getBoolean("showXOne"); + if (oldConfig != null) { + migrateEntry(oldConfig, "prefix", config, "line prefix"); + migrateEntry(oldConfig, "sources", config, "split sources"); + migrateEntry(oldConfig, "inlineAlone", config, "inline alone"); + + String amountFormat = oldConfig.getString("amountFormat"); + boolean showXOne = oldConfig.getBoolean("showXOne"); String itemNameColor = config.getParent().getString("itemNameColor"); String itemAmountColor = config.getParent().getString("itemAmountColor"); @@ -652,10 +649,10 @@ private boolean update() { config.set("item formats.multiple", multipleFormat); config.set("item formats.single", singleFormat); - config.set("amountFormat", null); - config.set("showXOne", null); config.getParent().set("itemNameColor", null); config.getParent().set("itemAmountColor", null); + config.getParent().set("stageDescriptionItemsSplit", null); + result = true; } diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java index 2b3f71c6..9ce4339a 100644 --- a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java @@ -20,9 +20,6 @@ public class BQBlocksManagerImplementation implements BQBlocksManager { - public static final String BLOCKDATA_HEADER = "blockdata:"; - public static final String TAG_HEADER = "tag:"; - private final BiMap<String, BQBlockType> types = HashBiMap.create(5); private BQBlockType materialType; @@ -39,10 +36,10 @@ private void registerDefaultTypes() { if (MinecraftVersion.MAJOR >= 13) { blockdataType = (string, options) -> new Post1_13.BQBlockData(options, string); - registerBlockType("blockdata:", blockdataType); + registerBlockType("blockdata", blockdataType); tagType = (string, options) -> new Post1_13.BQBlockTag(options, string); - registerBlockType("tag:", tagType); + registerBlockType("tag", tagType); } } @@ -50,23 +47,25 @@ private void registerDefaultTypes() { public @NotNull BQBlock deserialize(@NotNull String string) throws IllegalArgumentException { BQBlockType type; + int headerSeparator = string.indexOf(HEADER_SEPARATOR); + int nameIndex = string.lastIndexOf(CUSTOM_NAME_FOOTER); + String header = ""; - int separator = string.indexOf(HEADER_SEPARATOR); - if (separator != -1) { - header = string.substring(0, separator); - string = string.substring(separator + 1); + int dataStart = 0; + int dataEnd = nameIndex == -1 ? string.length() : nameIndex; + + if (headerSeparator != -1 && (nameIndex == -1 || headerSeparator < nameIndex)) { + header = string.substring(0, headerSeparator); + dataStart = headerSeparator + 1; } type = types.get(header); if (type == null) throw new IllegalArgumentException("Unknown block header: " + header); - int nameIndex = string.lastIndexOf(CUSTOM_NAME_FOOTER); String customName = nameIndex == -1 ? null : string.substring(nameIndex + CUSTOM_NAME_FOOTER.length()); - int dataEnd = nameIndex == -1 ? string.length() : nameIndex; - - return type.deserialize(string.substring(0, dataEnd), new BQBlockOptions(type, customName)); + return type.deserialize(string.substring(dataStart, dataEnd), new BQBlockOptions(type, customName)); } @Override 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 ecb693fd..7b12f140 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -75,7 +75,7 @@ public void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactor .stream() .flatMap(factory -> factory.getIDs() .stream() - .map(String::valueOf)) + .map(id -> getNpcId(factory, id))) .collect(Collectors.toList()); } @@ -103,7 +103,7 @@ public boolean isNPC(@NotNull Entity entity) { return npcs.computeIfAbsent(getNpcId(npcFactory, id), this::registerNPC); } - private BqNpcImplementation registerNPC(String id) { + private @Nullable BqNpcImplementation registerNPC(String id) { BqInternalNpcFactory factory; int npcId; @@ -119,7 +119,14 @@ private BqNpcImplementation registerNPC(String id) { npcId = Integer.parseInt(id.substring(separatorIndex + SEPARATOR.length())); } - return new BqNpcImplementation(new WrappedInternalNpc(factory, npcId)); + if (factory == null) + throw new IllegalArgumentException("Cannot find factory for NPC " + id + ". Is your NPC plugin installed?"); + + BqInternalNpc npc = factory.fetchNPC(npcId); + if (npc == null) + return null; + + return new BqNpcImplementation(new WrappedInternalNpc(factory, npc)); } @Override @@ -168,12 +175,6 @@ class WrappedInternalNpc { private final int id; private BqInternalNpc npc; - public WrappedInternalNpc(BqInternalNpcFactory factory, int id) { - this.factory = factory; - this.id = id; - this.npc = factory.fetchNPC(id); - } - public WrappedInternalNpc(BqInternalNpcFactory factory, BqInternalNpc npc) { this.factory = factory; this.npc = npc; diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 57b011e6..62db759f 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -25,7 +25,6 @@ import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageUtils; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.api.utils.messaging.PlaceholdersContext; import fr.skytasul.quests.api.utils.progress.ProgressPlaceholders; import fr.skytasul.quests.api.utils.progress.itemdescription.HasItemsDescriptionConfiguration.HasSingleObject; import fr.skytasul.quests.gui.items.ItemComparisonGUI; @@ -38,7 +37,7 @@ public class StageBringBack extends StageNPC{ protected final ItemComparisonMap comparisons; protected final Map<ItemStack, Integer> amountsMap = new HashMap<>(); - protected final String[] itemsDescriptions; + protected String[] itemsDescriptions; public StageBringBack(StageController controller, ItemStack[] items, String customMessage, ItemComparisonMap comparisons) { super(controller); @@ -50,25 +49,6 @@ public StageBringBack(StageController controller, ItemStack[] items, String cust int amount = (amountsMap.containsKey(item) ? amountsMap.get(item) : 0) + item.getAmount(); amountsMap.put(item, amount); } - - itemsDescriptions = - Arrays.stream(items).map(item -> ProgressPlaceholders.formatObject(new HasSingleObject() { - - @Override - public int getPlayerAmount(@NotNull PlayerAccount account) { - return item.getAmount(); - } - - @Override - public @NotNull String getObjectName() { - return ItemUtils.getName(item); - } - - @Override - public int getObjectAmount() { - return item.getAmount(); - } - }, PlaceholdersContext.of((Player) null, false, null))).toArray(String[]::new); } public boolean checkItems(Player p, boolean msg){ @@ -113,9 +93,36 @@ protected String getMessage() { @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); + placeholders.registerIndexedContextual("items", StageDescriptionPlaceholdersContext.class, - context -> ProgressPlaceholders.formatObjectList(context.getDescriptionSource(), - QuestsConfiguration.getConfig().getStageDescriptionConfig(), itemsDescriptions)); + context -> { + // We cannot initialize itemsDescription in constructor as a player instance is needed for the + // placeholder parsing event though it is not actually used. + // Therefore, we initialize itemsDescription the first time we actually use it: now. + if (itemsDescriptions == null) { + itemsDescriptions = + Arrays.stream(items).map(item -> ProgressPlaceholders.formatObject(new HasSingleObject() { + + @Override + public int getPlayerAmount(@NotNull PlayerAccount account) { + return item.getAmount(); + } + + @Override + public @NotNull String getObjectName() { + return ItemUtils.getName(item); + } + + @Override + public int getObjectAmount() { + return item.getAmount(); + } + }, context)).toArray(String[]::new); + } + + return ProgressPlaceholders.formatObjectList(context.getDescriptionSource(), + QuestsConfiguration.getConfig().getStageDescriptionConfig(), itemsDescriptions); + }); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java index 6038d143..921687fd 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageDealDamage.java @@ -101,6 +101,8 @@ public int getTotalAmount() { protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); ProgressPlaceholders.registerProgress(placeholders, "damage", this); + placeholders.registerIndexedContextual("damage_remaining", StageDescriptionPlaceholdersContext.class, + context -> Integer.toString(getPlayerAmount(context.getPlayerAccount()))); placeholders.registerIndexed("target_mobs", getTargetMobsString(targetMobs)); } 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 c5ed7a79..544f7c6d 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -136,6 +136,7 @@ public void setNPC(String npcID) { if (npc == null) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("The NPC " + npcID + " does not exist for " + toString()); } else { + this.npcID = npc.getId(); // TODO migration 1.0 initDialogRunner(); } } diff --git a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java index afd1fe90..51afb5f1 100755 --- a/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java +++ b/core/src/main/java/fr/skytasul/quests/stages/options/StageOptionProgressBar.java @@ -132,7 +132,7 @@ public ProgressBar(Player p, T progress) { this.acc = PlayersManager.getPlayerAccount(p); this.totalAmount = progress.getTotalAmount(); this.placeholders = PlaceholderRegistry.combine(progress); // to make a copy - ProgressPlaceholders.registerProgress(placeholders, "stage", progress); + ProgressPlaceholders.registerProgress(placeholders, "progress", progress); BarStyle style = null; if (totalAmount % 20 == 0) { @@ -170,6 +170,7 @@ public void update() { bar.setTitle(MessageUtils.format(getProgressConfig().getBossBarFormat(), placeholders, PlaceholdersContext.of(acc.getPlayer(), true, null))); + bar.addPlayer(acc.getPlayer()); } private void timer() { 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 db63f615..bf06e427 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 @@ -33,10 +33,10 @@ import fr.skytasul.quests.utils.QuestUtils; public class QuestPoolImplementation implements Comparable<QuestPoolImplementation>, QuestPool { - + private final int id; - - private final String npcId; + + private String npcId; private final String hologram; private final int maxQuests; private final int questsPerLaunch; @@ -44,12 +44,12 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati private final long timeDiff; private final boolean avoidDuplicates; private final RequirementList requirements; - + BqNpcImplementation npc; List<Quest> quests = new ArrayList<>(); private @Nullable PlaceholderRegistry placeholders; - + QuestPoolImplementation(int id, String npcID, String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, boolean avoidDuplicates, RequirementList requirements) { this.id = id; @@ -61,82 +61,83 @@ public class QuestPoolImplementation implements Comparable<QuestPoolImplementati this.timeDiff = timeDiff; this.avoidDuplicates = avoidDuplicates; this.requirements = requirements; - + if (npcID != null) { npc = BeautyQuests.getInstance().getNpcManager().getById(npcID); if (npc != null) { + this.npcId = npc.getId(); // TODO migration 1.0 npc.addPool(this); return; } } QuestsPlugin.getPlugin().getLoggerExpanded().warning("Unknown NPC " + npcID + " for quest pool #" + id); } - + @Override public int getId() { return id; } - + @Override public String getNpcId() { return npcId; } - + @Override public String getHologram() { return hologram; } - + @Override public int getMaxQuests() { return maxQuests; } - + @Override public int getQuestsPerLaunch() { return questsPerLaunch; } - + @Override public boolean isRedoAllowed() { return redoAllowed; } - + @Override public long getTimeDiff() { return timeDiff; } - + @Override public boolean doAvoidDuplicates() { return avoidDuplicates; } - + @Override public RequirementList getRequirements() { return requirements; } - + @Override public List<Quest> getQuests() { return quests; } - + @Override public void addQuest(Quest quest) { quests.add(quest); } - + @Override public void removeQuest(Quest quest) { quests.remove(quest); } - + @Override public int compareTo(QuestPoolImplementation o) { return Integer.compare(id, o.id); } - + @Override public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { if (placeholders == null) { @@ -171,32 +172,32 @@ public ItemStack getItemStack(String action) { Lang.poolItemQuestsList.format(this), "", action); } - + @Override public CompletableFuture<PlayerPoolDatas> resetPlayer(PlayerAccount acc) { return acc.removePoolDatas(this); } - + @Override public void resetPlayerTimer(PlayerAccount acc) { if (!acc.hasPoolDatas(this)) return; acc.getPoolDatas(this).setLastGive(0); } - + public void questCompleted(PlayerAccount acc, Quest quest) { if (!avoidDuplicates) return; PlayerPoolDatasImplementation poolDatas = (PlayerPoolDatasImplementation) acc.getPoolDatas(this); poolDatas.getCompletedQuests().add(quest.getId()); poolDatas.updatedCompletedQuests(); } - + @Override public boolean canGive(Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); PlayerPoolDatas datas = acc.getPoolDatas(this); - + if (datas.getLastGive() + timeDiff > System.currentTimeMillis()) return false; - + for (AbstractRequirement requirement : requirements) { try { if (!requirement.test(p)) return false; @@ -205,22 +206,22 @@ public boolean canGive(Player p) { return false; } } - + List<Quest> notDoneQuests = avoidDuplicates ? quests.stream() .filter(quest -> !datas.getCompletedQuests().contains(quest.getId())).collect(Collectors.toList()) : quests; if (notDoneQuests.isEmpty()) { // all quests completed if (!redoAllowed) return false; return quests.stream().anyMatch(quest -> quest.isRepeatable() && quest.canStart(p, false)); }else if (acc.getQuestsDatas().stream().filter(quest -> quest.hasStarted() && quests.contains(quest.getQuest())).count() >= maxQuests) return false; - + return notDoneQuests.stream().anyMatch(quest -> quest.canStart(p, false)); } - + @Override public CompletableFuture<String> give(Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); PlayerPoolDatas datas = acc.getPoolDatas(this); - + long time = (datas.getLastGive() + timeDiff) - System.currentTimeMillis(); if (time > 0) return CompletableFuture @@ -315,15 +316,15 @@ private List<Quest> replenishQuests(PlayerPoolDatas datas) { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Replenished available quests of " + datas.getAccount().getNameAndID() + " for pool " + id); return notDoneQuests; } - + void unload() { if (npc != null) npc.removePool(this); } - + public void unloadStarter() { npc = null; } - + public void save(ConfigurationSection config) { config.set("hologram", hologram); config.set("maxQuests", maxQuests); @@ -335,14 +336,14 @@ public void save(ConfigurationSection config) { if (!requirements.isEmpty()) config.set("requirements", requirements.serialize()); } - + public static QuestPoolImplementation deserialize(int id, ConfigurationSection config) { return new QuestPoolImplementation(id, config.getString("npcID"), config.getString("hologram"), config.getInt("maxQuests"), config.getInt("questsPerLaunch", 1), config.getBoolean("redoAllowed"), config.getLong("timeDiff"), config.getBoolean("avoidDuplicates", true), RequirementList.deserialize(config.getMapList("requirements"))); } - + private static class PoolGiveResult { private final Quest quest; private final String reason; diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 4a9db6b2..d471d4db 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -157,8 +157,9 @@ stage description: # Show boss bars for stages with progress boss bars: true # Format of the boss bar for stages with progress. - # Available placeholders are: {quest_name}, {stage_done}, {stage_remaining}, {stage_total}, {stage_percentage} - boss bar format: "§6{quest_name}: §e{stage_done}/{stage_total}" + # Available placeholders are: {progress_done}, {progress_remaining}, {progress_amount}, {progress_percentage} + # and all other placeholders from quest and stage (i.e. {quest_name}) + boss bar format: "§6{quest_name}: §e{progress_done}/{progress_amount}" # Seconds before the progress bar disappear (set it to 0 to make it persistent) boss bar timeout: 15 From 7b169fd10272e3932a4dde28eebb6c9e0e99ec97 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 14 Sep 2023 16:35:54 +0200 Subject: [PATCH 50/95] :bug: Fixed many bugs with stages --- .../quests/api/editors/CancellableEditor.java | 30 ------------ .../quests/api/editors/WaitBlockClick.java | 11 +++-- .../quests/api/editors/WaitClick.java | 11 +++-- .../api/stages/types/AbstractItemStage.java | 44 ++++++++--------- .../utils/progress/ProgressPlaceholders.java | 23 +++++---- .../java/fr/skytasul/quests/BeautyQuests.java | 1 + .../skytasul/quests/DefaultQuestFeatures.java | 3 +- .../QuestsConfigurationImplementation.java | 2 +- .../fr/skytasul/quests/editor/SelectNPC.java | 3 +- .../skytasul/quests/gui/mobs/MobsListGUI.java | 4 +- .../quests/gui/quests/DialogHistoryGUI.java | 8 ++-- .../npcs/BqNpcManagerImplementation.java | 26 +++++----- .../quests/stages/StageBringBack.java | 6 +-- .../fr/skytasul/quests/stages/StageMobs.java | 3 +- .../fr/skytasul/quests/stages/StageNPC.java | 12 ++--- .../QuestPoolsManagerImplementation.java | 7 +++ .../skytasul/quests/utils/types/Command.java | 3 +- core/src/main/resources/config.yml | 4 +- .../integrations/mobs/CitizensFactory.java | 6 +-- .../quests/integrations/npcs/BQCitizens.java | 47 ++++++++++--------- .../integrations/npcs/BQServerNPCs.java | 41 ++++++++-------- .../quests/integrations/npcs/BQZNPCsPlus.java | 3 +- 22 files changed, 142 insertions(+), 156 deletions(-) delete mode 100644 api/src/main/java/fr/skytasul/quests/api/editors/CancellableEditor.java diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/CancellableEditor.java b/api/src/main/java/fr/skytasul/quests/api/editors/CancellableEditor.java deleted file mode 100644 index a01542e3..00000000 --- a/api/src/main/java/fr/skytasul/quests/api/editors/CancellableEditor.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.skytasul.quests.api.editors; - -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.player.PlayerInteractEvent; -import fr.skytasul.quests.api.gui.ItemUtils; - -public abstract class CancellableEditor extends InventoryClear { - - public CancellableEditor(Player p, Runnable cancel) { - super(p, cancel); - } - - @EventHandler (priority = EventPriority.LOW) - public void onClick(PlayerInteractEvent e) { - if (e.getPlayer() != player) return; - if (ItemUtils.itemCancel.equals(e.getItem())) { - e.setCancelled(true); - cancel(); - } - } - - @Override - public void begin() { - super.begin(); - if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); - } - -} diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java b/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java index a1ef6256..b5d76804 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java @@ -4,22 +4,23 @@ import org.bukkit.Location; 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.ItemStack; import fr.skytasul.quests.api.gui.ItemUtils; -public class WaitBlockClick extends InventoryClear{ - +public class WaitBlockClick extends InventoryClear implements Listener { + private Consumer<Location> run; private ItemStack item; - + public WaitBlockClick(Player p, Runnable cancel, Consumer<Location> end, ItemStack is) { super(p, cancel); this.run = end; this.item = is; } - + @EventHandler public void onClick(PlayerInteractEvent e){ if (e.getPlayer() != player) return; @@ -42,5 +43,5 @@ public void begin(){ player.getInventory().setHeldItemSlot(4); if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); } - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java b/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java index 9e6506ab..21777dbc 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java @@ -3,13 +3,14 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import fr.skytasul.quests.api.gui.ItemUtils; -public class WaitClick extends InventoryClear{ - +public class WaitClick extends InventoryClear implements Listener { + private ItemStack validateItem; private ItemStack noneItem; private Runnable validate; @@ -18,7 +19,7 @@ public class WaitClick extends InventoryClear{ public WaitClick(Player p, Runnable cancel, ItemStack validateItem, Runnable validate) { this(p, cancel, validateItem, validate, null, null); } - + public WaitClick(Player p, Runnable cancel, ItemStack validateItem, Runnable validate, ItemStack noneItem, Runnable none) { super(p, cancel); this.validateItem = validateItem; @@ -26,7 +27,7 @@ public WaitClick(Player p, Runnable cancel, ItemStack validateItem, Runnable val this.validate = validate; this.none = none; } - + @EventHandler (priority = EventPriority.LOW) public void onInteract(PlayerInteractEvent e) { if (e.getPlayer() != player) return; @@ -58,5 +59,5 @@ public void begin(){ } if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); } - + } diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java index 6ec47793..f47d46de 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractItemStage.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.api.stages.types; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -23,7 +19,7 @@ import fr.skytasul.quests.api.utils.Utils; public abstract class AbstractItemStage extends AbstractCountableStage<ItemStack> { - + protected final @NotNull ItemComparisonMap comparisons; protected AbstractItemStage(@NotNull StageController controller, @@ -32,14 +28,14 @@ protected AbstractItemStage(@NotNull StageController controller, super(controller, objects); this.comparisons = comparisons; } - + protected AbstractItemStage(@NotNull StageController controller, @NotNull ConfigurationSection section) { super(controller, new ArrayList<>()); - + if (section.contains("itemComparisons")) { comparisons = new ItemComparisonMap(section.getConfigurationSection("itemComparisons")); }else comparisons = new ItemComparisonMap(); - + super.deserialize(section); } @@ -78,14 +74,14 @@ protected void serialize(@NotNull ConfigurationSection section) { super.serialize(section); if (!comparisons.getNotDefault().isEmpty()) section.createSection("itemComparisons", comparisons.getNotDefault()); } - + public abstract static class Creator<T extends AbstractItemStage> extends StageCreation<T> { - + private static final ItemStack stageComparison = ItemUtils.item(XMaterial.PRISMARINE_SHARD, Lang.stageItemsComparison.toString()); - + private @NotNull List<ItemStack> items; private @NotNull ItemComparisonMap comparisons = new ItemComparisonMap(); - + public Creator(@NotNull StageCreationContext<T> context) { super(context); } @@ -93,7 +89,7 @@ public Creator(@NotNull StageCreationContext<T> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + line.setItem(6, getEditItem().clone(), event -> { QuestsPlugin.getPlugin().getGuiManager().getFactory().createItemsSelection(items -> { setItems(items); @@ -107,20 +103,20 @@ public void setupLine(@NotNull StageGuiLine line) { }).open(event.getPlayer()); }); } - + protected abstract @NotNull ItemStack getEditItem(); - + public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); - getLine().refreshItemLoreOptionValue(6, Lang.AmountItems.quickFormat("amount", this.items.size())); + getLine().refreshItemLoreOptionValue(6, Lang.AmountItems.quickFormat("items_amount", this.items.size())); } - + public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; getLine().refreshItemLoreOptionValue(7, - Lang.AmountComparisons.quickFormat("amount", this.comparisons.getEffective().size())); + Lang.AmountComparisons.quickFormat("comparisons_amount", this.comparisons.getEffective().size())); } - + @Override public void start(Player p) { super.start(p); @@ -129,7 +125,7 @@ public void start(Player p) { context.reopenGui(); }, Collections.emptyList()).open(p); } - + @Override public void edit(T stage) { super.edit(stage); @@ -140,7 +136,7 @@ public void edit(T stage) { }).collect(Collectors.toList())); setComparisons(stage.comparisons.clone()); } - + @Override public final T finishStage(StageController controller) { List<CountableObject<ItemStack>> itemsMap = new ArrayList<>(); @@ -152,10 +148,10 @@ public final T finishStage(StageController controller) { } return finishStage(controller, itemsMap, comparisons); } - + protected abstract T finishStage(@NotNull StageController controller, @NotNull List<@NotNull CountableObject<ItemStack>> items, @NotNull ItemComparisonMap comparisons); - + } } \ No newline at end of file diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java index bd5e9ad5..1c1732ca 100755 --- a/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/progress/ProgressPlaceholders.java @@ -26,11 +26,14 @@ public final class ProgressPlaceholders { .registerIndexedContextual("done", ProgressPlaceholderContext.class, context -> Integer.toString(context.getProgress().getTotalAmount() - context.getProgress().getPlayerAmount(context.getPlayerAccount()))) - .registerIndexedContextual("amount", ProgressPlaceholderContext.class, + .registerIndexedContextual("total", ProgressPlaceholderContext.class, context -> Integer.toString(context.getProgress().getTotalAmount())) .registerIndexedContextual("percentage", ProgressPlaceholderContext.class, - context -> Integer.toString((int) (context.getProgress().getPlayerAmount(context.getPlayerAccount()) - * 100D / context.getProgress().getTotalAmount()))); + context -> { + int perc = (int) (100D - context.getProgress().getPlayerAmount(context.getPlayerAccount()) * 100D + / context.getProgress().getTotalAmount()); + return Integer.toString(perc); + }); private static final PlaceholderRegistry DESCRIPTION_REGISTRY = PROGRESS_REGISTRY.with(new PlaceholderRegistry() .registerIndexedContextual("name", ProgressObjectPlaceholderContext.class, context -> context.getProgress().getObjectName())); @@ -39,7 +42,7 @@ private ProgressPlaceholders() {} public static void registerProgress(@NotNull PlaceholderRegistry placeholders, @NotNull String key, @NotNull HasProgress progress) { - placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|amount|percentage)", + placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|total|percentage)", PlayerPlaceholdersContext.class, (matcher, context) -> { return PROGRESS_REGISTRY.resolve(matcher.group(1), new ProgressPlaceholderContext( context.getActor(), context.replacePluginPlaceholders(), progress)); @@ -51,7 +54,7 @@ public static void registerObject(@NotNull PlaceholderRegistry placeholders, @No placeholders.registerIndexedContextual(key, PlayerPlaceholdersContext.class, context -> formatObject(object, context)); - placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|amount|percentage|name)", + placeholders.register(Placeholder.ofPatternContextual(key + "_(remaining|done|total|percentage|name)", PlayerPlaceholdersContext.class, (matcher, context) -> { return DESCRIPTION_REGISTRY.resolve(matcher.group(1), new ProgressObjectPlaceholderContext( context.getActor(), context.replacePluginPlaceholders(), object)); @@ -71,7 +74,7 @@ public static <T> void registerObjects(@NotNull PlaceholderRegistry placeholders objectsDescription); }); - placeholders.register(Placeholder.ofPatternContextual(key + "_(\\d+)(?:_(remaining|done|amount|percentage))?", + placeholders.register(Placeholder.ofPatternContextual(key + "_(\\d+)(?:_(remaining|done|total|percentage))?", PlayerPlaceholdersContext.class, (matcher, context) -> { int index = Integer.parseInt(matcher.group(1)); CountableObject<T> object = objects.getObject(index); @@ -126,9 +129,11 @@ public int getObjectAmount() { @NotNull ItemsDescriptionConfiguration configuration, @NotNull String @NotNull... elements) { if (elements.length == 0) return Lang.Unknown.toString(); - if ((elements.length == 1 && configuration.isAloneSplitInlined()) || configuration.isSourceSplit(source)) - return MessageUtils.itemsToFormattedString(elements, "§r"); - return String.join(configuration.getSplitPrefix(), elements); + if (elements.length == 1 && configuration.isAloneSplitInlined()) + return elements[0]; + if (configuration.isSourceSplit(source)) + return configuration.getSplitPrefix() + String.join(configuration.getSplitPrefix(), elements); + return MessageUtils.itemsToFormattedString(elements, "§r"); } private static class ProgressPlaceholderContext implements PlayerPlaceholdersContext { diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index dda48136..64d988f0 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -184,6 +184,7 @@ public void run() { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Migrating from " + lastVersion + " to " + pluginVersion); int updated = quests.updateAll(); if (updated > 0) logger.info("Updated " + updated + " quests during migration."); + pools.updateAll(); saveAllConfig(false); } }catch (Throwable e) { diff --git a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java index fcac004f..07856a6f 100644 --- a/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java +++ b/core/src/main/java/fr/skytasul/quests/DefaultQuestFeatures.java @@ -292,7 +292,8 @@ public static void registerMessageProcessors() { PlaceholderRegistry defaultPlaceholders = new PlaceholderRegistry() .registerContextual("player", PlaceholdersContext.class, context -> context.getActor().getName()) .registerContextual("PLAYER", PlaceholdersContext.class, context -> context.getActor().getName()) - .register("prefix", () -> BeautyQuests.getInstance().getPrefix()); + .register("prefix", () -> BeautyQuests.getInstance().getPrefix()) + .register("nl", "\n"); QuestsAPI.getAPI().registerMessageProcessor("default_message_type", 1, new MessageProcessor() { @Override diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index fc03cecd..37ed6acd 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -613,7 +613,7 @@ private void init() { itemSingleFormat = config.getString("item formats.single"); itemMultipleFormat = config.getString("item formats.multiple"); stageDescriptionFormat = config.getString("description format"); - descPrefix = "{nl}" + config.getString("prefix"); + descPrefix = "{nl}" + config.getString("line prefix"); inlineAlone = config.getBoolean("inline alone"); for (String s : config.getStringList("split sources")) { try { diff --git a/core/src/main/java/fr/skytasul/quests/editor/SelectNPC.java b/core/src/main/java/fr/skytasul/quests/editor/SelectNPC.java index febb67e9..86196d2a 100644 --- a/core/src/main/java/fr/skytasul/quests/editor/SelectNPC.java +++ b/core/src/main/java/fr/skytasul/quests/editor/SelectNPC.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.InventoryClear; import fr.skytasul.quests.api.localization.Lang; @@ -13,7 +14,7 @@ import fr.skytasul.quests.npcs.BQNPCClickEvent; import fr.skytasul.quests.utils.QuestUtils; -public class SelectNPC extends InventoryClear{ +public class SelectNPC extends InventoryClear implements Listener { private Consumer<BqNpc> run; diff --git a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java index 128b797c..99532620 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/mobs/MobsListGUI.java @@ -29,7 +29,7 @@ public MobsListGUI(Collection<MutableCountableObject<Mob<?>>> objects, super(Lang.INVENTORY_MOBS.toString(), DyeColor.ORANGE, objects); this.end = end; } - + @Override public void finish(List<MutableCountableObject<Mob<?>>> objects) { end.accept(objects); @@ -81,7 +81,7 @@ public ItemStack getObjectItemStack(MutableCountableObject<Mob<?>> mob) { .addDescription(Lang.Amount.format(mob)) .addClick(ClickType.LEFT, Lang.editAmount.toString()) .addClick(ClickType.RIGHT, Lang.editMobName.toString()) - .addClick(ClickType.SHIFT_RIGHT, (mob.getObject().getFactory() instanceof LeveledMobFactory ? "" : "§8§n") + .addClick(ClickType.SHIFT_RIGHT, (mob.getObject().getFactory() instanceof LeveledMobFactory ? "" : "§8§m") + Lang.setLevel.toString()); ItemStack item = ItemUtils.item(mob.getObject().getMobItem(), mob.getObject().getName(), loreBuilder.toLoreArray()); item.setAmount(Math.min(mob.getAmount(), 64)); 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 3f04f408..2bf2282b 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 @@ -18,6 +18,7 @@ import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayerQuestDatas; import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.types.Dialogable; import fr.skytasul.quests.api.utils.ChatColorUtils; import fr.skytasul.quests.api.utils.XMaterial; @@ -80,9 +81,10 @@ public CloseBehavior onClose(Player p) { public static Stream<Dialogable> getDialogableStream(PlayerQuestDatas datas, Quest quest) { return datas.getQuestFlowStages() - .filter(Dialogable.class::isInstance) - .map(Dialogable.class::cast) - .filter(Dialogable::hasDialog); + .map(StageController::getStage) + .filter(Dialogable.class::isInstance) + .map(Dialogable.class::cast) + .filter(Dialogable::hasDialog); } class WrappedDialogable { 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 7b12f140..c8faea4a 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -96,21 +96,13 @@ public boolean isNPC(@NotNull Entity entity) { @Override public @Nullable BqNpcImplementation getById(String id) { - return npcs.computeIfAbsent(id, this::registerNPC); - } - - public @Nullable BqNpcImplementation getById(BqInternalNpcFactory npcFactory, int id) { - return npcs.computeIfAbsent(getNpcId(npcFactory, id), this::registerNPC); - } - - private @Nullable BqNpcImplementation registerNPC(String id) { BqInternalNpcFactory factory; int npcId; int separatorIndex = id.indexOf(SEPARATOR); if (separatorIndex == -1) { // TODO migration 1.0 QuestsPlugin.getPlugin().getLoggerExpanded() - .warning("Loading NPC with id " + id + " from a previous version of the plugin."); + .debug("Loading NPC with id " + id + " from a previous version of the plugin."); factory = getMigrationFactory(); npcId = Integer.parseInt(id); } else { @@ -122,11 +114,17 @@ public boolean isNPC(@NotNull Entity entity) { if (factory == null) throw new IllegalArgumentException("Cannot find factory for NPC " + id + ". Is your NPC plugin installed?"); - BqInternalNpc npc = factory.fetchNPC(npcId); - if (npc == null) - return null; + return getByFactoryAndId(factory, npcId); + } + + public @Nullable BqNpcImplementation getByFactoryAndId(@NotNull BqInternalNpcFactory factory, int id) { + return npcs.computeIfAbsent(getNpcId(factory, id), strId -> { + BqInternalNpc npc = factory.fetchNPC(id); + if (npc == null) + return null; - return new BqNpcImplementation(new WrappedInternalNpc(factory, npc)); + return new BqNpcImplementation(new WrappedInternalNpc(factory, npc)); + }); } @Override @@ -143,7 +141,7 @@ public void npcClicked(BqInternalNpcFactory npcFactory, @Nullable Cancellable ev @NotNull NpcClickType click) { if (event != null && event.isCancelled()) return; - BQNPCClickEvent newEvent = new BQNPCClickEvent(getById(npcFactory, npcID), p, click); + BQNPCClickEvent newEvent = new BQNPCClickEvent(getByFactoryAndId(npcFactory, npcID), p, click); Bukkit.getPluginManager().callEvent(newEvent); if (event != null) event.setCancelled(newEvent.isCancelled()); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java index 62db759f..0baa055e 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageBringBack.java @@ -110,7 +110,7 @@ public int getPlayerAmount(@NotNull PlayerAccount account) { @Override public @NotNull String getObjectName() { - return ItemUtils.getName(item); + return ItemUtils.getName(item, true); } @Override @@ -223,7 +223,7 @@ public void setupLine(@NotNull StageGuiLine line) { public void setItems(List<ItemStack> items) { this.items = Utils.combineItems(items); getLine().refreshItemLore(5, - QuestOption.formatNullableValue(Lang.AmountItems.quickFormat("amount", this.items.size()))); + QuestOption.formatNullableValue(Lang.AmountItems.quickFormat("items_amount", this.items.size()))); } public void setMessage(String message) { @@ -235,7 +235,7 @@ public void setComparisons(ItemComparisonMap comparisons) { this.comparisons = comparisons; getLine().refreshItemLore(10, QuestOption.formatNullableValue( - Lang.AmountComparisons.quickFormat("amount", this.comparisons.getEffective().size()), + Lang.AmountComparisons.quickFormat("comparisons_amount", this.comparisons.getEffective().size()), comparisons.isDefault())); } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java index fc349eed..6a35c550 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageMobs.java @@ -83,7 +83,7 @@ protected boolean objectApplies(Mob<?> object, Object other) { @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { - return Lang.SCOREBOARD_NONE.toString(); + return Lang.SCOREBOARD_MOBS.toString(); } @Override @@ -92,7 +92,6 @@ public void started(PlayerAccount acc) { if (acc.isCurrent() && sendStartMessage()) { MessageUtils.sendRawMessage(acc.getPlayer(), Lang.STAGE_MOBSLIST.toString(), getPlaceholdersRegistry(), StageDescriptionPlaceholdersContext.of(true, acc, DescriptionSource.FORCELINE, MessageType.DefaultMessageType.PREFIXED)); - Lang.STAGE_MOBSLIST.send(acc.getPlayer(), this); } } 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 544f7c6d..34cf9608 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageNPC.java @@ -134,7 +134,8 @@ public void setNPC(String npcID) { if (npcID != null) npc = QuestsPlugin.getPlugin().getNpcManager().getById(npcID); if (npc == null) { - QuestsPlugin.getPlugin().getLoggerExpanded().warning("The NPC " + npcID + " does not exist for " + toString()); + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("The NPC " + npcID + " does not exist for " + getController().toString()); } else { this.npcID = npc.getId(); // TODO migration 1.0 initDialogRunner(); @@ -359,11 +360,10 @@ public void setNPCId(String npcID) { public void setDialog(Dialog dialog) { this.dialog = dialog; - getLine() - .refreshItemLore(SLOT_DIALOG, - dialog == null ? Lang.NotSet.toString() - : QuestOption.formatDescription( - Lang.AmountDialogLines.quickFormat("amount", dialog.getMessages().size()))); + getLine().refreshItemLore(SLOT_DIALOG, + dialog == null ? Lang.NotSet.toString() + : QuestOption.formatDescription( + Lang.AmountDialogLines.quickFormat("lines_amount", dialog.getMessages().size()))); } public void setHidden(boolean hidden) { diff --git a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java index bfa31c4a..1988185c 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/pools/QuestPoolsManagerImplementation.java @@ -56,6 +56,13 @@ public void save(@NotNull QuestPoolImplementation pool) { } } + public void updateAll() throws IOException { + for (QuestPoolImplementation pool : pools.values()) { + pool.save(config.createSection(Integer.toString(pool.getId()))); + } + config.save(file); + } + @Override public @NotNull QuestPoolImplementation createPool(@Nullable QuestPool editing, @Nullable String npcID, @Nullable String hologram, int maxQuests, int questsPerLaunch, boolean redoAllowed, long timeDiff, diff --git a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java index 08fbcffb..19856079 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/types/Command.java +++ b/core/src/main/java/fr/skytasul/quests/utils/types/Command.java @@ -68,7 +68,8 @@ public Map<String, Object> serialize(){ } public static Command deserialize(Map<String, Object> map){ - return new Command((String) map.get("label"), (boolean) map.get("console"), (boolean) map.getOrDefault("parse", Boolean.FALSE), (int) map.getOrDefault("delay", 0)); + return new Command((String) map.get("label"), (boolean) map.get("console"), + (boolean) map.getOrDefault("parse", Boolean.TRUE), (int) map.getOrDefault("delay", 0)); } } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index d471d4db..55040357 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -157,9 +157,9 @@ stage description: # Show boss bars for stages with progress boss bars: true # Format of the boss bar for stages with progress. - # Available placeholders are: {progress_done}, {progress_remaining}, {progress_amount}, {progress_percentage} + # Available placeholders are: {progress_done}, {progress_remaining}, {progress_total}, {progress_percentage} # and all other placeholders from quest and stage (i.e. {quest_name}) - boss bar format: "§6{quest_name}: §e{progress_done}/{progress_amount}" + boss bar format: "§6{quest_name}: §e{progress_done}/{progress_total}" # Seconds before the progress bar disappear (set it to 0 to make it persistent) boss bar timeout: 15 diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java index 8ce1d52b..3d7c9dc8 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java @@ -11,7 +11,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.api.editors.CancellableEditor; +import fr.skytasul.quests.api.editors.InventoryClear; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.mobs.MobFactory; @@ -41,7 +41,7 @@ public void itemClick(Player p, Consumer<NPC> run) { Lang.SELECT_KILL_NPC.send(p); // we cannot use the SelectNPC editor as it uses the BQNPCManager // and if it is registered to another NPC plugin it wouldn't work - new CancellableEditor(p, () -> run.accept(null)) { + new InventoryClear(p, () -> run.accept(null)) { @EventHandler(priority = EventPriority.LOW) private void onNPCClick(NPCRightClickEvent e) { @@ -65,7 +65,7 @@ public void begin() { public NPC fromValue(String value) { return CitizensAPI.getNPCRegistry().getById(Integer.parseInt(value)); } - + @Override public boolean bukkitMobApplies(NPC first, Entity entity) { return first.isSpawned() && first.getEntity().equals(entity); diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java index 6ebaf390..4b440dd0 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java @@ -8,6 +8,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; @@ -24,60 +25,60 @@ import net.citizensnpcs.trait.LookClose; import net.citizensnpcs.trait.SkinTrait; -public class BQCitizens implements BqInternalNpcFactoryCreatable { - +public class BQCitizens implements BqInternalNpcFactoryCreatable, Listener { + @Override public int getTimeToWaitForNPCs() { return 2; } - + @Override public boolean isNPC(Entity entity) { return CitizensAPI.getNPCRegistry().isNPC(entity); } - + @Override public BqInternalNpc fetchNPC(int id) { NPC npc = CitizensAPI.getNPCRegistry().getById(id); return npc == null ? null : new BQCitizensNPC(npc); } - + @Override public Collection<Integer> getIDs() { return StreamSupport.stream(CitizensAPI.getNPCRegistry().sorted().spliterator(), false).map(NPC::getId).collect(Collectors.toList()); } - + @EventHandler (priority = EventPriority.HIGHEST) public void onNPCRightClick(NPCRightClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; npcClicked(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_RIGHT : NpcClickType.RIGHT); } - + @EventHandler (priority = EventPriority.HIGHEST) public void onNPCLeftClick(NPCLeftClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; npcClicked(e, e.getNPC().getId(), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_LEFT : NpcClickType.LEFT); } - + @EventHandler public void onNPCRemove(NPCRemoveEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; npcRemoved(e.getNPC().getId()); } - + @EventHandler public void onCitizensReload(CitizensReloadEvent e) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("Citizens has been reloaded whereas it is highly not recommended for plugins compatibilities. Unexpected behaviors may happen."); npcsReloaded(); } - + @Override public boolean isValidEntityType(EntityType type) { return true; } - + @Override public BqInternalNpc create(Location location, EntityType type, String name, @Nullable String skin) { NPC npc = CitizensAPI.getNPCRegistry().createNPC(type, name); @@ -93,51 +94,51 @@ public BqInternalNpc create(Location location, EntityType type, String name, @Nu return new BQCitizensNPC(npc); } - + public static class BQCitizensNPC implements BqInternalNpc { - + private NPC npc; - + private BQCitizensNPC(NPC npc) { this.npc = npc; } - + public NPC getCitizensNPC() { return npc; } - + @Override public int getInternalId() { return npc.getId(); } - + @Override public String getName() { return npc.getName(); } - + @Override public boolean isSpawned() { return npc.isSpawned(); } - + @Override public @NotNull Entity getEntity() { return npc.getEntity(); } - + @Override public @NotNull Location getLocation() { return npc.getStoredLocation(); } - + @Override public boolean setNavigationPaused(boolean paused) { boolean b = npc.getNavigator().isPaused(); npc.getNavigator().setPaused(paused); return b; } - + } - + } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java index ade0d2d0..475df8ca 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java @@ -9,6 +9,7 @@ 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 com.google.common.cache.Cache; @@ -24,20 +25,20 @@ import io.github.gonalez.znpcs.npc.NPCType; import io.github.gonalez.znpcs.npc.event.NPCInteractEvent; -public class BQServerNPCs implements BqInternalNpcFactoryCreatable { - +public class BQServerNPCs implements BqInternalNpcFactoryCreatable, Listener { + private Cache<Integer, Boolean> cachedNpcs = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); @Override public int getTimeToWaitForNPCs() { return 45; } - + @Override public Collection<Integer> getIDs() { return NPC.all().stream().map(x -> x.getNpcPojo().getId()).collect(Collectors.toList()); } - + @Override public boolean isNPC(Entity entity) { Boolean result = cachedNpcs.getIfPresent(entity.getEntityId()); @@ -47,18 +48,18 @@ public boolean isNPC(Entity entity) { } return result; } - + @Override public BqInternalNpc fetchNPC(int id) { NPC npc = NPC.find(id); return npc == null ? null : new BQServerNPC(npc); } - + @Override public boolean isValidEntityType(EntityType type) { return Arrays.stream(NPCType.values()).map(NPCType::name).anyMatch(name -> name.equals(type.name())); } - + @Override public @NotNull BqInternalNpc create(Location location, EntityType type, String name, @Nullable String skin) { List<Integer> ids = ConfigurationConstants.NPC_LIST.stream().map(NPCModel::getId).collect(Collectors.toList()); @@ -72,56 +73,56 @@ public boolean isValidEntityType(EntityType type) { return new BQServerNPC(npc); } - + @EventHandler public void onInteract(NPCInteractEvent e) { npcClicked(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), NpcClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); } - + public static class BQServerNPC implements BqInternalNpc { - + private final NPC npc; - + private BQServerNPC(NPC npc) { this.npc = npc; } - + public NPC getServerNPC() { return npc; } - + @Override public int getInternalId() { return npc.getNpcPojo().getId(); } - + @Override public String getName() { return npc.getNpcPojo().getHologramLines().isEmpty() ? "ID: " + npc.getNpcPojo().getId() : npc.getNpcPojo().getHologramLines().get(0); } - + @Override public boolean isSpawned() { return npc.getBukkitEntity() != null; } - + @Override public Entity getEntity() { return (Entity) npc.getBukkitEntity(); } - + @Override public Location getLocation() { return npc.getLocation(); } - + @Override public boolean setNavigationPaused(boolean paused) { return true; } - + } - + } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java index d63945a2..0bf3f699 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java @@ -9,6 +9,7 @@ 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 com.google.common.cache.Cache; @@ -24,7 +25,7 @@ import io.github.znetworkw.znpcservers.npc.interaction.NPCInteractEvent; import lol.pyr.znpcsplus.ZNPCsPlus; -public class BQZNPCsPlus implements BqInternalNpcFactoryCreatable { +public class BQZNPCsPlus implements BqInternalNpcFactoryCreatable, Listener { private Cache<Integer, Boolean> cachedNpcs = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); From 33a9ed865db1f4616e07a48d8758e2c22effa2cb Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 16 Sep 2023 23:28:58 +0200 Subject: [PATCH 51/95] :globe_with_meridians: Updated all locales + added turkish, romanian, dutch, korean, danish and czech --- core/src/main/resources/locales/cs_CZ.yml | 178 ++ core/src/main/resources/locales/da_DK.yml | 59 + core/src/main/resources/locales/de_DE.yml | 1369 ++++++++-------- core/src/main/resources/locales/en_US.yml | 1792 +++++++++++---------- core/src/main/resources/locales/es_ES.yml | 1448 ++++++++--------- core/src/main/resources/locales/fr_FR.yml | 1461 ++++++++--------- core/src/main/resources/locales/hu_HU.yml | 565 ++++--- core/src/main/resources/locales/it_IT.yml | 914 +++++------ core/src/main/resources/locales/ko_KR.yml | 222 +++ core/src/main/resources/locales/lt_LT.yml | 874 +++++----- core/src/main/resources/locales/nl_NL.yml | 43 + core/src/main/resources/locales/pl_PL.yml | 1460 ++++++++--------- core/src/main/resources/locales/pt_BR.yml | 1452 ++++++++--------- core/src/main/resources/locales/pt_PT.yml | 874 +++++----- core/src/main/resources/locales/ro_RO.yml | 91 ++ core/src/main/resources/locales/ru_RU.yml | 1380 ++++++++-------- core/src/main/resources/locales/sv_SE.yml | 348 ++-- core/src/main/resources/locales/th_TH.yml | 1066 ++++++------ core/src/main/resources/locales/tr_TR.yml | 799 +++++++++ core/src/main/resources/locales/uk_UA.yml | 1457 ++++++++--------- core/src/main/resources/locales/vi_VN.yml | 1409 ++++++++-------- core/src/main/resources/locales/zh_CN.yml | 1461 ++++++++--------- core/src/main/resources/locales/zh_HK.yml | 1109 ++++++------- 23 files changed, 11415 insertions(+), 10416 deletions(-) create mode 100755 core/src/main/resources/locales/cs_CZ.yml create mode 100755 core/src/main/resources/locales/da_DK.yml create mode 100755 core/src/main/resources/locales/ko_KR.yml create mode 100755 core/src/main/resources/locales/nl_NL.yml create mode 100755 core/src/main/resources/locales/ro_RO.yml create mode 100755 core/src/main/resources/locales/tr_TR.yml diff --git a/core/src/main/resources/locales/cs_CZ.yml b/core/src/main/resources/locales/cs_CZ.yml new file mode 100755 index 00000000..2b0a42bd --- /dev/null +++ b/core/src/main/resources/locales/cs_CZ.yml @@ -0,0 +1,178 @@ +--- +inv: + create: + bringBack: '§aPřinést zpět předměty' + bucket: '§aVyplnit kbelíky' + craft: '§aVyrobit předmět' + findNPC: '§aNajít NPC' + findRegion: '§aNajít region' + fish: '§aChytat ryby' + killMobs: '§aZabít monstra' + mineBlocks: '§aRozbít bloky' + placeBlocks: '§aPostav bloky' + talkChat: '§aPsát do chatu' +msg: + bringBackObjects: Přineste mě zpět {items}. + command: + adminModeEntered: '§aSpustil jsi režim správce.' + adminModeLeft: '§aOpustil jsi režim správce.' + backupCreated: '§6Úspěšně jsi vytvořil zálohy všech úkolů a informací o hráči.' + backupPlayersFailed: '§cVytváření zálohy pro všechny hráčské informace se nezdařilo.' + backupQuestsFailed: '§cVytváření zálohy pro všechny úkoly se nezdařilo.' + cancelQuest: '§6Zrušil jsi úkol {quest}.' + cancelQuestUnavailable: '§cQuest {quest} nemůže být zrušen.' + checkpoint: + noCheckpoint: '§cNebyl nalezen žádný kontrolní bod pro úkol {quest}.' + questNotStarted: '§cTento úkol aktuálně neděláš.' + help: + adminMode: '§6/{label} adminMod: §ePřepni režim správce. (Pouze pro zobrazení malých zpráv v logech.)' + create: '§6/{label} vytvořit: §eVytvoř úkol.' + edit: '§6/{label} editace: §eEdituj úkol.' + finishAll: '§6/{label} dokončil všechny <player>: §eDokonči všechny questy hráče.' + header: '§6§lBeautyQuests — Nápověda' + list: '§6/{label} seznam: §ePodívejte se na seznam úkolů. (Pouze pro podporované verze)' + remove: '§6/{label} remove <id>: §eVymazat úkol se zadaným id nebo kliknout na NPC pokud není definováno.' + resetPlayer: '§6/{label} resetPlayer <player>: §eOdstraňte všechny informace o hráči.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eVymazat informace o hledání pro hráče.' + save: '§6/{label} save: §eVytvoří manuální uložení pluginu.' + seePlayer: '§6/{label} seePlayer <player>: §eZobrazit informace o hráči.' + setItem: '§6/{label} setItem <talk|launch>: §eSave položku hologramu.' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §ePřeskočit aktuální scénu/spustit větev/nastavit scénu pro větev.' + start: '§6/{label} start <player> [id]: §eVynutit spuštění úkolu.' + version: '§6/{label} verze: §ePodívejte se na aktuální verzi pluginu.' + invalidCommand: + simple: '§cTento příkaz neexistuje, napište §ehelp§c.' + itemChanged: '§aPředmět byl upraven. Změny se projeví po restartu.' + itemRemoved: '§aHologramový předmět byl odstraněn.' + leaveAll: '§aVynutil jsi konec {success} úkolů. Chyby: {errors}' + removed: '§aQuest {quest_name} byl úspěšně odstraněn.' + resetPlayer: + player: '§6Všechny informace o tvých {quest_amount} úkol(ech) byly smazány hráčem {deleter_name}.' + remover: '§6{quest_amount} informace o úkolu {player} byla smazány.' + resetPlayerQuest: + player: '§6Všechny informace o výpravě {quest} byly smazány hráčem {deleter_name}.' + remover: '§6{player} informace o úkolu {quest} byla smazány.' + resetQuest: '§6Odstraněna data hledání pro {player_amount} hráčů.' + scoreboard: + hidden: '§6Scoreboard hráče {player_name} byl schován.' + lineInexistant: '§cŘádek {line_id} neexistuje.' + lineRemoved: '§6Úspěšně jsi odstranil řádek {line_id}.' + lineReset: '§6Úspěšně jsi resetoval řádek {line_id}.' + lineSet: '§6Řádek {line_id} byl úspěšně upraven.' + resetAll: '§6Úspěšně jsi obnovil tabulku skóre hráče {player_name}.' + shown: '§6Scoreboard hráče {player_name} byl zobrazen.' + setStage: + branchDoesntExist: '§cVětev s ID {branch_id} neexistuje.' + doesntExist: '§cStage s ID {stage_id} neexistuje.' + next: '§aFáze byla přeskočena.' + nextUnavailable: '§cMožnost "přeskočit" není k dispozici, když je hráč na konci větve.' + set: '§aFáze {stage_id} byla spuštěna.' + startQuest: '§6Vynutil jsi spuštění Questu {quest} (UUID: {player}).' + editor: + already: '§cJiž jsi v editoru.' + blockAmount: '§aNapiš množství bloků:' + blockData: '§aNapište bloková data (dostupná bloková data: {available_datas}):' + blockName: '§aNapište název bloku:' + dialog: + cleared: '§a{amount} odstranilo zprávy.' + help: + header: '§6§lBeautyQuests - nápověda pro editor dialogů' + list: '§6Seznam: §evšech zpráv.' + remove: '§6remove <id>: §eOdebrat zprávu.' + syntaxRemove: '§cSprávná sytax: odstranit <id>' + enter: + subtitle: '§6Napiš "/quests exitEditor" pro vynucení ukončení editoru.' + title: '§6~ Mód editoru ~' + goToLocation: '§aPřejít na požadovanou polohu pro stage.' + itemCreator: + invalidBlockType: '§cNeplatný typ bloku.' + itemName: '§aNapiš název předmětu:' + unknownBlockType: '§cNeznámý typ bloku.' + unknownItemType: '§cNeznámý typ předmětu.' + mythicmobs: + disabled: '§cMythicMobs jsou vypnuty.' + npc: + choseStarter: '§aVyberte NPC u kterého začíná Quest.' + enter: '§aKlikni na NPC, nebo napiš "cancel".' + notStarter: '§cU tohoto NPC quest nezačíná.' + text: + argNotSupported: '§cArgument {arg} není podporován.' + chooseJobRequired: '§aNapiš jméno požadované práce:' + chooseLvlRequired: '§aNapiš požadované množství úrovní:' + chooseMoneyRequired: '§aNapište částku požadovaných peněz:' + chooseObjectiveRequired: '§aNapiš název objektu.' + reward: + permissionName: '§aNapiš jméno oprávnění.' + textList: + syntax: '§cSprávná syntaxe: ' + typeBucketAmount: '§aNapiš množství kbelíků k naplnění:' + typeGameTicks: '§aNapište požadované herní ticks' + typeLocationRadius: '§aNapsat požadovanou vzdálenost od polohy:' + errorOccurred: '§cDošlo k chybě, obraťte se na adminstrátor! §4§lChybový kód: {error}' + experience: + edited: '§aZměnil jsi zisk z {old_xp_amount} na {xp_amount} bodů.' + indexOutOfBounds: '§cČíslo {index} je mimo hranice! Musí být mezi {min} a {max}.' + invalidBlockData: '§cBlokdata {block_data}jsou neplatné nebo nekompatibilní s blokem {block_material}.' + inventoryFull: '§cTvůj inventář je plný, předmět byl vyhozen na zem.' + moveToTeleportPoint: '§aJdi na místo určení teleportu.' + npcDoesntExist: '§cNPC s ID {npc_id} neexistuje.' + number: + invalid: '§c{input} není platné číslo.' + negative: '§cMusíš zadat kladné číslo!' + zero: '§cMusíte zadat jiné číslo než 0!' + pools: + allCompleted: '§7Všechny úkoly byly dokončeny!' + maxQuests: '§cNemůžeš mít zároveň více než {pool_max_quests} úkol(ů)...' + noAvailable: '§7Žádný další úkol není k dispozici...' + noTime: '§cMusíš počkat {time_left} než budeš dělat jiný úkol.' + quest: + alreadyStarted: '§cTvůj úkol byl už zahájen!' + cancelling: '§cProces vytváření úkolu byl zrušen.' + createCancelled: '§cVytváření nebo úprava úkolu byla přerušena jiným pluginem!' + created: '§aBlahopřejeme! Vytvořil jsi nový úkol §e{quest}§a, který obsahuje {quest_branches} větev(e)!' + editCancelling: '§cProces úpravy úkolu byl zrušen.' + edited: '§aBlahopřejeme! Upravil jsi úkol §e{quest}§a, který obsahuje nyní {quest_branches} větev(e)!' + finished: + base: '§aBlahopřejeme! Dokončil jsi svůj úkol §e{quest_name}§a!' + obtain: '§aObdržel jsi {rewards}!' + invalidID: '§cÚkol s ID {quest_id} neexistuje.' + started: '§aTvůj úkol právě začíná §r§e{quest_name}§o§6!' + questItem: + craft: '§cNemůžeš použít item z úkolu k výrobě!' + drop: '§cPředmět, který je součástí tvého úkolu, není možné zahodit!' + quests: + checkpoint: '§7Dosáhl jsi kontrolního bodu úkolu!' + failed: '§cSelhal jsi v plnění úkolu {quest_name}' + maxLaunched: '§cNemůžeš mít více než {quests_max_amount} úkol zároveň...' + updated: '§7Úkol §e{quest_name}§7 a jeho nastavení bylo aktualizováno.' + regionDoesntExists: '§cTento region neexistuje. (Musíš být ve stejném světě.)' + requirements: + combatLevel: '§cTvoje bojová úroveň musí být {long_level}!' + job: '§cTvá úroveň pro úkol §e{job_name}§c musí být {long_level}!' + level: '§cTvůj level musí být {long_level}!' + money: '§cMusíš mít {money}!' + quest: '§cMusíš dokončit Quest §e{quest_name}§c!' + skill: '§cTvá úroveň pro dovednost §e{skill_name}§c musí být {long_level}!' + waitTime: '§cMusis počkat {time_left} , než budeš moci restartovat tento úkol!' + selectNPCToKill: '§aVyberte NPC pro zabíjení.' + stageMobs: + listMobs: '§aMusíš zabít {mobs}' + typeCancel: '§aNapište "cancel" pro návrat k poslednímu textu.' + writeChatMessage: '§aNapiš povinnou zprávu: (Přidat "{SLASH}na začátek, pokud chceš příkaz.)' + writeCommand: '§aNapište požadovaný příkaz: (Příkaz je bez "/" a zástupného znaku "{PLAYER}je podporován. Bude nahrazeno jménem vykonavatele.)' + writeConfirmMessage: '§aNapiš potvrzovací zprávu zobrazenou když se hráč chystá spustit úkol: (Write "null", pokud chceš výchozí zprávu.)' + writeDescriptionText: '§aNapiš text, který popisuje cíl fáze:' + writeHologramText: '§aNapište text hologramu: (Napište „none“, pokud nechcete hologram, a „null“, pokud chcete výchozí text.)' + writeMobAmount: '§aNapiš počet mobů, k zabíjení:' + writeMobName: '§aNapiš vlastní jméno moba, kterého budeš zabíjet:' + writeNPCText: '§aNapiš dialog který NPC řekně hráči: (Napiš "help" pro získání pomoci)' + writeNpcName: '§aNapiš jméno NPC:' + writeNpcSkinName: '§aNapiš jméno skinu, který má být použit na NPC:' + writeQuestDescription: '§aNapiš popis úkolu, který bude zobrazen v GUI úkolu hráče.' + writeQuestMaterial: '§aNapiš jméno materiálu pro předmět úkolu.' + writeQuestName: '§aNapiš jméno úkolu:' + writeQuestTimer: '§aNapište požadovaný čas (v minutách), než budete moci úlohu znovu spustit: (Pokud chcete výchozí časovač, napište „null“.)' + writeRegionName: '§aNapiš název regionu vyžadovaného pro krok:' + writeStageText: '§aNapiš text, který bude odeslán hráči na začátku kroku:' + writeStartMessage: '§aNapište zprávu, která bude odeslána na začátku úkolu, „null“, pokud chcete výchozí, nebo „none“, pokud nechcete žádnou:' + writeXPGain: '§aNapiš množství bodů zkušenosti, které hráč získá: (poslední hodnota: {xp_amount})' diff --git a/core/src/main/resources/locales/da_DK.yml b/core/src/main/resources/locales/da_DK.yml new file mode 100755 index 00000000..48f2c34b --- /dev/null +++ b/core/src/main/resources/locales/da_DK.yml @@ -0,0 +1,59 @@ +--- +msg: + dialogs: + skipped: '§8§o Dialog sprunget over.' + tooFar: '§7§oDu er for langt væk fra {npc_name}...' + experience: + edited: '§aDu har ændret XP vundet, fra {old_xp_amount} til {xp_amount} points.' + moveToTeleportPoint: '§aGå til den ønskede teleporterings placering.' + npcDoesntExist: '§cDen NPC med id {npc_id} eksisterer ikke.' + number: + negative: '§cDu skal indtaste et positivt tal!' + pools: + allCompleted: '§7Du har afsluttet alle quests!' + maxQuests: '§cDu kan ikke have mere end {pool_max_quests} quest(s) på samme tid...' + noAvailable: '§7Der er ikke flere quests tilgængelig...' + noTime: '§cDu skal vente {time_left} før du laver en anden quest.' + quest: + alreadyStarted: '§cDu har allerede startet questen!' + cancelling: '§cProces for quest oprettelse annulleret.' + createCancelled: '§cOprettelsen eller redigeringen er blevet annulleret af et andet plugin!' + created: '§aTillykke! Du har oprettet questen §e{quest}§a som inkluderer {quest_branches} gren(e)!' + editCancelling: '§cProces for quest redigering annulleret.' + edited: '§aTillykke! Du har redigeret questen §e{quest}§a som inkluderer nu {quest_branches} gren(e)!' + finished: + base: '§aTillykke! Du er færdig med questen §e{quest_name}§a!' + obtain: '§aDu får {rewards}!' + invalidID: '§cQuesten med id {quest_id} eksisterer ikke.' + invalidPoolID: '§cPoolen {pool_id} eksisterer ikke.' + notStarted: '§cDu er ikke på dennne quest i øjeblikket.' + started: '§aDu har startet questen §r§e{quest_name}§o§6!' + questItem: + craft: '§cDu kan ikke bruge et quest element til at crafte!' + drop: '§cDu kan ikke smide et quest element!' + eat: '§cDu kan ikke spise et quest element!' + quests: + checkpoint: '§7Quest checkpoint nået!' + failed: '§cDu har fejlet questen {quest_name}...' + maxLaunched: '§cDu kan ikke have mere end {quests_max_amount} quest(s) på samme tid...' + updated: '§7Quest §e{quest_name}§7 opdateret.' + regionDoesntExists: '§cDette område eksisterer ikke. (Du skal være i den samme verden. "WorldGuard region")' + requirements: + money: '§cDu skal have {money}!' + waitTime: '§cDu skal vente {time_left} før du kan genstarte denne quest!' + restartServer: '§7Genstart din server for at se modifikationerne.' + selectNPCToKill: '§aVælg den NPC at dræbe.' + stageMobs: + listMobs: '§aDu skal dræbe {mobs}.' + versionRequired: 'Version påkrævet: §l{version}' + writeChatMessage: '§aSkriv krævet besked: (Tilføj "{SLASH}" til begyndelsen, hvis du vil have en kommando.)' + writeMessage: '§aSkriv den besked, der vil blive sendt til spilleren' + writeMobAmount: '§aSkriv mængden af væsner at dræbe:' + writeMobName: '§aSkriv det brugerdefinerede navn på væsnet til at dræbe:' + writeNPCText: '§aSkriv den dialog, der vil blive sagt til spilleren af NPC''en: (Skriv "help" for at modtage hjælp.)' + writeNpcName: '§aSkriv navnet på NPC''en:' + writeNpcSkinName: '§aSkriv navnet på udseendet på NPC''en:' + writeQuestName: '§aSkriv navnet på din quest:' + writeRegionName: '§aSkriv navnet på den region der kræves for trinet:' + writeStartMessage: '§aSkriv den besked, der vil blive sendt i begyndelsen af questen, "null", hvis du ønsker standard eller "none", hvis du ønsker ingen:' + writeXPGain: '§aSkriv mængden af erfaringspoint spilleren vil få: (mindste værdi: {xp_amount})' diff --git a/core/src/main/resources/locales/de_DE.yml b/core/src/main/resources/locales/de_DE.yml index 0c1ab366..c2f34aaa 100644 --- a/core/src/main/resources/locales/de_DE.yml +++ b/core/src/main/resources/locales/de_DE.yml @@ -1,750 +1,765 @@ --- -msg: - quest: - finished: - base: '§aGlückwunsch! Du hast die Quest §e{0}§a abgeschlossen!' - obtain: '§aDu erhälst {0}!' - started: '§aDu hast die Quest §r§e{0}§o§6 gestartet!' - created: '§aGlückwunsch! Du hast die Quest §e{0}§a mit {1} Zweig(en) erstellt!' - edited: '§aGlückwunsch! Du hast die Quest §e{0}§a bearbeitet, die jetzt {1} Zweig(e) enthält!' - createCancelled: '§cDie Erstellung oder Bearbeitung wurde von einem anderen Plugin abgebrochen!' - cancelling: '§cErstellung der Quest abgebrochen.' - editCancelling: '§cBearbeitung der Quest abgebrochen.' - invalidID: '§cDie Quest mit der ID {0} existiert nicht.' - invalidPoolID: '§cDie Gruppe {0} existiert nicht.' - alreadyStarted: '§cDu hast die Quest bereits gestartet!' - notStarted: '§cDu machst diese Quest momentan nicht.' - quests: - maxLaunched: '§cDu kannst nicht mehr als {0} Quest(s) gleichzeitig haben...' - nopStep: '§cDiese Quest hat keinen Schritt.' - updated: '§7Quest §e{0}§7 aktualisiert.' - checkpoint: '§7Quest-Checkpoint erreicht!' - failed: '§cDu hast die Quest {0} fehlgeschlagen...' - pools: - noTime: '§cDu musst warten, bevor du eine andere Quest absolvieren kannst.' - allCompleted: '§7Du hast alle Quests abgeschlossen!' - noAvailable: '§7Es ist keine Quest mehr verfügbar...' - maxQuests: '§cDu kannst nicht mehr als {0} Quest(s) gleichzeitig haben...' - questItem: - drop: '§cDu kannst einen Questgegenstand nicht fallen lassen!' - craft: '§cDu kannst keinen Questgegenstand zum Craften verwenden!' - eat: Du kannst Quest Items nicht Essen! - stageMobs: - noMobs: '§cDer Schritt beinhaltet nicht das Töten von Mobs.' - listMobs: '§aDu musst {0} töten.' - writeNPCText: '§aSchreibe den Dialog, den der NPC mit dem Spieler führt: (Schreibe „help”, um Hilfe zu erhalten.)' - writeRegionName: '§aSchreibe den für den Schritt benötigten Namen der Region:' - writeXPGain: '§aSchreibe die Menge an Erfahrungspunkten, die der Spieler erhalten wird: (Letzter Wert: {0})' - writeMobAmount: '§aSchreibe die zu tötende Mob‐Menge:' - writeMobName: '§aSchreibe den benutzerdefinierten Namen des zu tötenden Mobs:' - writeChatMessage: '§aSchreibe die benötigte Nachricht: (Füge „{SLASH}” zum Anfang hinzu, wenn du einen Befehl ausdrücken möchtest.)' - writeMessage: '§aSchreibe die Nachricht die an den Spieler gesendet wird' - writeStartMessage: '§aSchreibe die Nachricht, die zu Beginn der Quest gesendet wird, "null", wenn du die Standardnachricht wünschst, oder "none", wenn du dir keine Nachricht wünschst:' - writeEndMsg: '§aSchreibe die Nachricht, die am Ende der Quest gesendet wird, "null", wenn du die Standardnachricht wünschst, oder "none", wenn du dir keine Nachricht wünschst. Du kannst "{0}" verwenden, das dann durch die erhaltenen Belohnungen ersetzt wird.' - writeEndSound: '§aSchreibe den Tonnamen, der am Ende der Quest dem Spieler abgespielt wird, "null" wenn Sie die Standardeinstellung oder "keine" wollen, wenn Sie keine wollen:' - writeDescriptionText: '§aSchreibe einen Text, der das Ziel des Schrittes beschreibt:' - writeStageText: '§aSchreibe den am Anfang des Schrittes zum Spieler gesendete Text:' - moveToTeleportPoint: '§aGehe zur gewünschten Teleportationsposition.' - writeNpcName: '§aSchreibe den Namen des NPCs:' - writeNpcSkinName: '§aSchreibe den Namen des NPC‐Skins:' - writeQuestName: '§a Schreibe den Namen der Quest:' - writeCommand: '§aSchreibe den gewünschten Befehl: (Den Befehl ohne den Schrägstrich schreiben. Unterstützter Platzhalter: „{PLAYER}“; welcher mit dem Namen des Spielers, der den Befehl ausgeführt hat, ersetzt wird.)' - writeHologramText: '§aSchreibe den Text des Hologramms: (Schreibe „none”, wenn du kein Hologramm haben möchtest und „null”, wenn du den Standard‐Text verwenden willst.)' - writeQuestTimer: '§aSchreibe die benötigte Zeit (in Minuten), bevor ein Spieler die Quest erneut starten kann: (Schreibe „null“, wenn der Standard‐Timer verwendet werden soll.)' - writeConfirmMessage: '§aSchreibe die Bestätigungsnachricht, die beim Startversuch der Quest dem Spieler gezeigt wird: (Schreibe „null“, wenn die Standard‐Nachricht verwendet werden soll.)' - writeQuestDescription: '§aGebe die Beschreibung der Quest ein, welche in der Quest-GUI des Spielers angezeigt werden soll.' - writeQuestMaterial: '§aSchreibe das Material des Questgegenstandes.' - requirements: - quest: '§cDu musst die Quest §e{0}§c abgeschlossen haben!' - level: '§cDein Level muss {0} sein!' - job: '§cDein Level für den Job §e{1}§c muss {0} sein!' - skill: '§cDein Level für die Fertigkeit §e{1}§c muss {0} sein!' - combatLevel: '§cDein Kampflevel muss {0} sein!' - money: '§cDu benötigst {0}!' - waitTime: '§cDu musst {0} warten, bevor du die Quest erneut starten kannst!' - experience: - edited: '§aDu hast die Erfahrungsgewinnung von {0} auf {1} Punkt(e) gesetzt.' - selectNPCToKill: '§aWähle den zu tötenden NPC.' - npc: - remove: '§aNPC gelöscht.' - talk: '§aGehe und rede mit dem NPC namens §e{0}§a.' - regionDoesntExists: '§cDie Region existiert nicht. (Du musst dich in der selben Welt befinden.)' - npcDoesntExist: '§cDer NPC mit der ID {0} existiert nicht.' - objectDoesntExist: '§cDas angegebene Item mit der ID {0} existiert nicht.' - number: - negative: '§cDu musst eine positive Zahl eingeben!' - zero: '§cDie Zahl darf nicht 0 sein!' - invalid: '§c{0} ist keine gültige Zahl.' - notInBounds: '§cDeine Zahl muss zwischen {0} und {1} liegen.' - errorOccurred: '§cEin Fehler ist aufgetreten; kontaktiere einen Administrator! §4§lFehlercode: {0}' - commandsDisabled: '§cDu kannst zurzeit keine Befehle ausführen!' - indexOutOfBounds: '§cDie Zahl {0} ist außerhalb der Grenze! Sie muss zwischen {1} und {2} liegen.' - invalidBlockData: '§cDie Blockdaten {0} sind ungültig oder inkompatibel mit dem Block {1}.' - invalidBlockTag: '§cNicht verfügbarer Blocktag {0}.' - bringBackObjects: Bring mir {0} zurück. - inventoryFull: '§cDein Inventar ist voll, das Item wurde auf den Boden gelegt.' - playerNeverConnected: '§cKann keine Informationen über den Spieler {0} finden.' - playerNotOnline: '§cDer Spieler {0} ist offline.' - playerDataNotFound: '§cDaten des Spielers {0} nicht gefunden.' - versionRequired: 'Benötigte Version: §l{0}' - restartServer: '§7Starte deinen Server neu, um die Änderungen zu sehen.' - dialogs: - skipped: 'Dialog übersprungen.' - tooFar: '§7§oDu bist zu weit von {0}...' - command: - downloadTranslations: - syntax: "§cDu musst eine Sprache auswählen zum downloaden.\nBeispiel: \"/quests downloadTranslations en_US\"." - notFound: '§cSprache {0} nicht gefunden für die Version {1}.' - exists: '§cDie Datei {0} existiert bereits. Füge "-Overwrite "true" an deinen Befehl an, um ihn zu überschreiben. (/quests downloadTranslations <lang> -overwrite true)' - downloaded: '§aSprache {0} wurde heruntergeladen! §7Du musst nun die Datei "/plugins/BeautyQuests/config.yml" bearbeiten, um den Wert von §ominecraftTranslationsFile§7 mit {0} zu ändern. Der Server muss anschliessend neu gestartet werden.' - checkpoint: - noCheckpoint: '§cKein Checkpoint für die Quest {0} gefunden.' - questNotStarted: '§cDu machst diese Quest nicht.' - setStage: - branchDoesntExist: '§cDer Zweig mit der ID {0} existiert nicht.' - doesntExist: '§cDer Schritt mit der ID {0} existiert nicht.' - next: '§aDer Schritt wurde übersprungen.' - nextUnavailable: '§cDie „Überspringen“‐Option ist nicht verfügbar, wenn der Spieler am Ende eines Zweiges ist.' - set: '§aSchritt {0} gestartet.' - startDialog: - impossible: '§cKann den Dialog jetzt nicht starten.' - noDialog: '§cDer Spieler hat keinen ausstehenden Dialog.' - alreadyIn: '§cDer Spieler spielt bereits einen Dialog.' - success: '§aStartete Dialog für Spieler {0} in Quest {1}!' - playerNeeded: '§cDu musst ein Spieler sein, um diesen Befehl ausführen zu können.' - incorrectSyntax: '§cFalsche Syntax.' - noPermission: '§cDu hast nicht die benötigte Berechtigung „{0}“, um diesen Befehl auszuführen!' - invalidCommand: - quests: '§cDieser Befehl existiert nicht, schreibe §e/quests help§c.' - simple: '§cDieser Befehl existiert nicht, schreibe §ehelp§c.' - needItem: '§cDu musst ein Item in deiner Haupthand halten!' - itemChanged: '§aDas Item wurde bearbeitet. Die Änderungen werden nach einem Neustart angewendet.' - itemRemoved: '§aDas Hologramm‐Item wurde entfernt.' - removed: '§aDie Quest {0} wurde erfolgreich entfernt.' - leaveAll: '§aDu hast das Ende von {0} Quest(s) erzwungen. Fehler: {1}' - resetPlayer: - player: '§6Alle Informationen deiner {0} Quest(s) wurde/wurden von {1} gelöscht.' - remover: '§6{0} Questinformation(en) (und {2} Gruppen) von {1} wurde(n) gelöscht.' - resetPlayerQuest: - player: '§6Alle Informationen über die Quest {0} wurden von {1} gelöscht.' - remover: '§6{0} Questinformation(en) von {1} wurde(n) gelöscht.' - resetQuest: '§6Quest Daten wurden für {0} Spieler entfernt.' - startQuest: '§6Du hast den Start der Quest {0} erzwungen. (Spieler‐UUID: {1})' - startQuestNoRequirements: '§cDer Spieler erfüllt nicht die Anforderungen für die Quest {0}... Füge "-OverrideRequirements am Ende deines Befehls hinzu, um die Anforderungsüberprüfung zu umgehen.' - cancelQuest: '§6Du hast die Quest {0} abgebrochen.' - cancelQuestUnavailable: '§cDie Quest {0} kann nicht abgebrochen werden.' - backupCreated: '§6Du hast erfolgreich Sicherungen aller Quests und Spielerinformationen erstellt.' - backupPlayersFailed: '§cDas Sichern von allen Spielerinformationen ist fehlgeschlagen.' - backupQuestsFailed: '§cDas Sichern von allen Quests ist fehlgeschlagen.' - adminModeEntered: '§aDu hast den Admin‐Modus betreten.' - adminModeLeft: '§aDu hast den Admin‐Modus verlassen.' - resetPlayerPool: - timer: '§aDu hast den {0} Gruppentimer auf {1} zurückgesetzt.' - full: '§aDu hast die {0} Gruppendaten auf {1} zurückgesetzt.' - scoreboard: - lineSet: '§6Du hast die Zeile {0} erfolgreich bearbeitet.' - lineReset: '§6Du hast die Zeile {0} erfolgreich zurückgesetzt.' - lineRemoved: '§6Du hast die Zeile {0} erfolgreich entfernt.' - lineInexistant: '§cDie Zeile {0} existiert nicht.' - resetAll: '§6Du hast das Scoreboard des Spielers {0} erfolgreich zurückgesetzt.' - hidden: '§6Das Scoreboard des Spielers {0} wurde versteckt.' - shown: '§6Das Scoreboard des Spielers {0} wurde angezeigt.' - own: - hidden: '§6Dein Scoreboard ist jetzt versteckt.' - shown: Dein Scoreboard wird wieder angezeigt. - help: - header: '§6§lBeautyQuests — Hilfe' - create: '§6/{0} create: §eErstelle eine Quest.' - edit: '§6/{0} edit: §eBearbeite eine Quest.' - remove: '§6/{0} remove <ID>: §eLösche eine Quest mit der angegebenen ID oder klicke auf den NPC, wenn nicht definiert.' - finishAll: '§6/{0} finishAll <Spieler>: §eBeende alle Quests eines Spielers.' - setStage: '§6/{0} setStage <Spieler> <ID> [neuer Zweig] [neuer Schritt]: §eÜberspringe den aktuellen Schritt/starte einen Zweig/setze einen Schritt für einen Zweig.' - startDialog: '§6/{0} startDialog <player> <quest id>: §eStartet den ausstehenden Dialog für eine NPC-Stufe oder den Startdialog für eine Quest.' - resetPlayer: '§6/{0} resetPlayer <Spieler>: §eEntferne alle Informationen eines Spielers.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <Spieler> [ID]: §eLösche Informationen einer Quest für einen Spieler.' - seePlayer: '§6/{0} seePlayer <Spieler>: §eSieh dir die Informationen eines Spielers an.' - reload: '§6/{0} reload: §eSpeichere und und lade alle Konfigurationen und Dateien neu. (§cveraltet§e)' - start: '§6/{0} start <Spieler> [ID]: §eErzwinge das Starten einer Quest.' - setItem: '§6/{0} setItem <talk|launch>: §eSpeichere das Hologramm‐Item.' - setFirework: '§6/{0} SetFeuerwerk: §eBearbeite das standardmäßig end Feuerwerk.' - adminMode: '§6/{0} adminMode: §eSchalte den Admin‐Modus (für die Anzeige von Protokollnachrichten) für dich um.' - version: '§6/{0} version: §eLass dir die aktuelle Plugin‐Version anzeigen.' - downloadTranslations: '§6/{0} heruntergeladene Übersetzung <language>: §eDownloads einer Vanille-Übersetzungsdatei' - save: '§6/{0} save: §eFühre eine manuelle Plugin‐Speicherung durch.' - list: '§6/{0} list: §eSieh dir die Questliste an. (Funktioniert nur bei unterstützten Versionen.)' - typeCancel: '§aSchreibe „cancel“, um zum letzten Text zurückzukehren.' - editor: - blockAmount: '§aSchreibe die Anzahl der Blöcke:' - blockName: '§aSchreibe den Namen des Blocks:' - blockData: '§aSchreibe die Blockdaten (verfügbare Blockdaten: {0}):' - blockTag: '§aSchreibe den Blocktag (verfügbare Blocktags: §7{0}§a):' - typeBucketAmount: '§aSchreibe die Anzahl an zu füllenden Eimern:' - typeDamageAmount: 'Schreibe die Menge an Schaden, die der Spieler zufügen muss:' - goToLocation: '§aGehe zur gewünschten Position für den Schritt.' - typeLocationRadius: '§aSchreibe die benötigte Distanz von der Position:' - typeGameTicks: '§aSchreibe die benötigten Spiel-Ticks:' - already: '§cDu befindest dich bereits im Editor.' - stage: - location: - typeWorldPattern: '§aSchreibe einen Regex für Weltnamen:' - enter: - title: '§6~ Editor‐Modus ~' - subtitle: '§6Schreibe „/quests exitEditor”, um das Verlassen zu erzwingen.' - list: '§c⚠ §7Du befindest dich in einem "Listen"-Editor. Verwende "add", um Zeilen hinzuzufügen. Siehe "help" (ohne Schrägstrich) für Hilfe. §e§lTippe "close", um den Editor zu verlassen.' - chat: '§6Du bist zurzeit im Editor‐Modus. Schreibe „/quests exitEditor“, um das Verlassen des Editors zu erzwingen. (Nicht empfohlen, erwäge die Verwendung von Befehlen wie „close“ oder „cancel“, um zum vorherigen Inventar zurückzukehren.)' - npc: - enter: '§aKlicke auf einen NPC oder schreibe „cancel”.' - choseStarter: '§aWähle den NPC, der die Quest startet.' - notStarter: '§cDieser NPC ist kein Queststarter.' - text: - argNotSupported: '§cDas Argument {0} wird nicht unterstützt.' - chooseLvlRequired: '§aSchreibe die Anzahl der benötigten Level:' - chooseJobRequired: '§aSchreibe den Namen des gewünschten Jobs:' - choosePermissionRequired: '§aSchreibe die benötigte Berechtigung, um die Quest zu starten:' - choosePermissionMessage: '§aDu kannst eine Verweigerungs‐Nachricht für Spieler ohne ausreichende Berechtigungen festlegen. (Um diesen Schritt zu überspringen, schreibe „null”.)' - choosePlaceholderRequired: - identifier: '§aSchreibe den Namen des benötigten Platzhalters ohne die Prozentzeichen:' - value: '§aSchreibe den erforderlichen Wert für den Platzhalter §e%§e{0}§e%§a:' - chooseSkillRequired: '§aSchreibe den Namen der benötigten Fähigkeit:' - chooseMoneyRequired: '§aSchreibe die Menge an benötigtem Geld:' - reward: - permissionName: '§aGebe den Namen der Berechtigung ein.' - permissionWorld: '§aGebe die Welt an, in welcher die Berechtigung bearbeitet werden soll, oder "null" wenn es Global gelten soll.' - money: '§aSchreibe die zu bekommende Menge an Geld:' - wait: '§aSchreibe die Anzahl von Game Ticks, zum warten: (1 Sekunde = 20 Game Ticks)' - random: - min: '§aSchreibe die minimale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' - max: '§aSchreibe die maximale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' - chooseObjectiveRequired: '§aGebe den Namen des Ziels an.' - chooseObjectiveTargetScore: '§aGebe den benötigten Punktestand für das Ziel an.' - chooseRegionRequired: '§aSchreibe den Namen der benötigten Region (du musst in der gleichen Welt sein).' - selectWantedBlock: '§aKlicke mit dem Stock auf den gewünschten Block für diesen Schritt.' - itemCreator: - itemType: '§aSchreibe den Namen des gewünschten Items:' - itemAmount: '§aSchreibe die Menge des/der Item(s):' - itemName: '§aSchreibe den Item‐Namen:' - itemLore: '§aÄndere die Item‐Beschreibung: (Schreibe „help“ für Hilfe.)' - unknownItemType: '§cUnbekanntes Item.' - invalidItemType: '§cUngültiges Item. (Das Item darf kein Block sein.)' - unknownBlockType: '§cUnbekannter Blocktyp.' - invalidBlockType: '§cUngültiger Blocktyp.' - dialog: - syntax: '§cKorrekte Syntax: {0}{1} <Nachricht>' - syntaxRemove: '§cKorrekte Syntax: remove <ID>' - player: '§aNachricht "§7{0}§a" für den Spieler hinzugefügt.' - npc: '§aNachricht "§7{0}§a" für den NPC hinzugefügt.' - noSender: '§aNachricht "§7{0}§a" ohne einen Absender hinzugefügt.' - messageRemoved: '§aNachricht "§7{0}§a" entfernt.' - edited: '§aNachricht "§7{0}§a" bearbeitet.' - soundAdded: '§aTon "§7{0}§a" für die Nachricht "§7{1}§a" hinzugefügt.' - cleared: '§a{0} entfernte Nachricht(en).' - help: - header: '§6§lBeautyQuests — Dialogbearbeitungs‐Hilfe' - npc: '§6npc <Nachricht>: §eFüge eine vom NPC gesagte Nachricht hinzu.' - player: '§6player <Nachricht>: §eFüge eine vom Spieler gesagte Nachricht hinzu.' - nothing: '§6noSender <Nachricht>: §eFüge eine Nachricht ohne Absender hinzu.' - remove: '§6remove <ID>: §eEntferne eine Nachricht.' - list: '§6list: §eSchaue dir alle Nachrichten an.' - npcInsert: '§6npcInsert <ID> <Nachricht>: §eFüge eine vom NPC gesagte Nachricht ein.' - playerInsert: '§6playerInsert <ID> <Nachricht>: §eFüge eine vom Spieler gesagte Nachricht ein.' - nothingInsert: '§6nothingInsert <ID> <Nachricht>: §eFüge eine Nachricht ohne Präfix ein.' - edit: '§6edit <id> <message>: §eBearbeite eine Nachricht.' - addSound: '§6addSound <ID> <Geräusch>: §eFüge ein Geräusch einer Nachricht hinzu.' - clear: '§6clear: §eEntferne alle Nachrichten.' - close: '§6close: §eBestätige alle Nachrichten.' - setTime: '§6setTime <id> <time>: §eSetze die Zeit (in Ticks) bevor die nächste automatische Nachricht gesendet wird.' - npcName: '§6npcName [benutzerdefinierter NPC-Name]: §eSetze (oder zurücksetzen auf Standard) des benutzerdefinierten Namens des NPCs im Dialog' - skippable: '§6Überspringbar [true|falsch]: §eLegen Sie fest, ob der Dialog übersprungen werden kann oder nicht' - timeSet: '§aDie Zeit für die Nachricht {0} wurde bearbeitet: jetzt {1} Ticks.' - timeRemoved: '§aDie Zeit wurde für die Nachricht {0} entfernt.' - npcName: - set: '§aBenutzerdefinierter NPC-Name wurde zu §7{1}§a gesetzt (alter Name war §7{0}§a)' - unset: '§aBenutzerdefinierter NPC-Name wurde auf Standard gesetzt (alter Name war §7{0}§a)' - skippable: - set: '§aDer dialogbare Status ist nun auf §7{1}§a gesetzt (war §7{0}§a)' - mythicmobs: - list: '§aEine Liste aller Mythic Mobs:' - isntMythicMob: '§cDieser Mythic Mob existiert nicht.' - disabled: '§cMythicMob ist deaktiviert.' - textList: - syntax: '§cKorrekte Syntax: ' - added: '§aText "§7{0}§a" hinzugefügt.' - removed: '§aText "§7{0}§a" entfernt.' - help: - header: '§6§lBeautyQuests — Listen‐Editor‐Hilfe' - add: '§6add <message>: §eFüge einen Text hinzu.' - remove: '§6remove <ID>: §eEntferne einen Text.' - list: '§6list: §eSieh dir alle hinzugefügten Texte an.' - close: '§6close: §eBestätige die hinzugefügten Texte.' - noSuchElement: '§cDieses Element existiert nicht. Erlaubte Elemente sind: §e{0}' - scoreboardObjectiveNotFound: '§cUnbekanntes Scoreboard Ziel.' - pool: - hologramText: 'Schreibe den benutzerdefinierten Hologramm-Text für diese Gruppe (oder "null", wenn du den Standardtext möchtest).' - maxQuests: 'Lege die maximale Anzahl an Quests fest, die aus dieser Gruppe gestartet werden können.' - questsPerLaunch: 'Schreibe die Anzahl der Quests, die du bei einem Klick auf den NPC erhalten hast.' - timeMsg: 'Schreibe die Zeit, bevor Spieler eine neue Quest annehmen können (Standardeinheit: Tage).' - title: - title: 'Schreibe den Titeltext (oder "null", wenn du keinen möchtest).' - subtitle: 'Schreibe den Untertiteltext (oder "null", wenn du keinen möchtest).' - fadeIn: 'Schreibe die "Einblende"-Dauer, in Ticks (20 ticks = 1 Sekunde).' - stay: 'Schreibe die "Bleibe"-Dauer, in Ticks (20 Ticks = 1 Sekunde).' - fadeOut: 'Schreibe die "Ausblende"-Dauer, in Ticks (20 ticks = 1 Sekunde).' - firework: - invalidHand: 'Du musst ein Feuerwerk in deiner Main Hand halten.' - edited: 'Feuerwerk Quest bearbeitet!' - writeCommandDelay: '§aGebe die gewünschte Befehl Verzögerung in Ticks an.' advancement: finished: Abgeschlossen notStarted: Nicht gestartet +description: + requirement: + class: Klasse {class_name} + combatLevel: Kampflevel {short_level} + faction: Fraktion {faction_name} + jobLevel: Level {short_level} für {job_name} + quest: Quest beenden §e{quest_name} + skillLevel: Level {short_level} für {skill_name} + title: '§8§lAnforderungen:' + reward: + title: '§8§lBelohnungen:' +indication: + cancelQuest: '§7Bist du sicher, dass du die Quest {quest_name} abbrechen möchtest?' + closeInventory: '§7Bist du sicher, dass du die GUI schließen möchtest?' + removeQuest: '§7Bist du sicher, dass du die Quest {quest} entfernen möchtest?' + startQuest: '§7Möchtest du die Quest {quest_name} starten?' inv: - validate: '§b§lBestätigen' - cancel: '§c§lAbbrechen' - search: '§e§lSuche' addObject: '§aFüge ein Ziel hinzu' + block: + blockData: '§dBlockdaten (fortgeschritten)' + blockName: '§bEigener Blockname' + blockTag: '§dTag (Erweitert)' + blockTagLore: Wähle einen Tag, welcher eine Liste von möglichen Blöcken beschreibt. Tags können durch Datapacks angepasst werden. Du kannst eine Liste von Tags im Minecraft Wiki finden. + materialNotItemLore: Dieser Block kann momentan nicht als Item angezeigt werden. Er wird immer noch korrekt als {block_material} gespeichert. + name: Block auswählen + blockAction: + location: '§eWähle einen genauen Ort aus' + material: '§eWähle ein Blockmaterial' + name: Blockaktion auswählen + blocksList: + addBlock: '§aKlicke, um einen Block hinzuzufügen.' + name: Blöcke auswählen + buckets: + name: Eimertyp + cancel: '§c§lAbbrechen' + cancelActions: + name: Aktionen abbrechen + checkpointActions: + name: Checkpoint-Aktionen + chooseAccount: + name: Welcher Account? + chooseQuest: + menu: '§aQuests Menu' + menuLore: Ruft dich zu deinem Quest-Menü zurück. + name: Welche Quest? + classesList.name: Klassenliste + classesRequired.name: Klassen erforderlich + command: + console: Konsole + delay: '§bVerzögerung' + name: Befehl + parse: Platzhalter analysieren + value: '§eBefehl' + commandsList: + console: '§eKonsole: {command_console}' + name: Befehlliste + value: '§eBefehl: {command_label}' confirm: name: Bist du sicher? - 'yes': '§aBestätigen' 'no': '§cAbbrechen' + 'yes': '§aBestätigen' create: - stageCreate: '§aNeuen Schritt erstellen' - stageRemove: '§cDiesen Schritt löschen' - stageUp: Eins höher - stageDown: Eins runter - stageType: '§7Stufentyp: §e{0}' + NPCSelect: '§eNPC auswählen oder erstellen' + NPCText: '§eDialog bearbeiten' + breedAnimals: '§aZüchte Tiere' + bringBack: '§aItems zurückbringen' + bucket: '§aEimer befüllen' + cancelMessage: Senden abbrechen cantFinish: '§7Du musst mindestens eine Stufe erstellen, bevor du die Questerstellung fertigstellen kannst!' + changeEntityType: '§eObjekttyp ändern' + changeTicksRequired: '§eÄndere die erforderlichen gespielten Ticks' + craft: '§aItem herstellen' + currentRadius: '§eAktuelle Entfernung: §6{radius}' + dealDamage: '§cSchaden an Mobs zufügen' + death: '§csterben' + eatDrink: '§aEssen oder trinken Sie Essen oder Tränke' + editBlocksMine: '§eDie zu zerstörenden Blöcke bearbeiten' + editBlocksPlace: '§eDie zu plazierenden Blöcke bearbeiten' + editBucketAmount: '§eAnzahl an zu befüllenden Eimern bearbeiten' + editBucketType: '§eTyp des zu befüllenden Eimers bearbeiten' + editFishes: '§eDie zu fangenden Fische bearbeiten' + editItem: '§eHerzustellendes Item bearbeiten' + editItemsToEnchant: '§eBearbeite Items zum Verzaubern' + editItemsToMelt: '§eBearbeite Items zum Schmelzen' + editLocation: '§ePosition bearbeiten' + editMessageType: '§eDie zu schreibende Nachricht bearbeiten' + editMobsKill: '§eDie zu tötenden Mobs bearbeiten' + editRadius: '§eEntfernung von Position bearbeiten' + enchant: '§dVerzauberte Gegenstände' findNPC: '§aNPC finden' - bringBack: '§aItems zurückbringen' findRegion: '§aRegion finden' + fish: '§aFische fangen' + hideClues: Partikel und Hologramme verstecken + ignoreCase: Fall der Nachricht ignorieren + interact: '§aMit Block interagieren' killMobs: '§aMobs töten' + leftClick: Muss Linksklick sein + location: '§aZu Position gehen' + melt: '§6Schmelze Elemente' mineBlocks: '§aBlöcke zerstören' + mobsKillFromAFar: Muss mit Projektil getötet werden placeBlocks: '§aPlatziere Blöcke' - talkChat: '§aIm Chat schreiben' - interact: '§aMit Block interagieren' - fish: '§aFische fangen' - craft: '§aItem herstellen' - bucket: '§aEimer befüllen' - location: '§aZu Position gehen' playTime: '§eSpielzeit' - breedAnimals: '§aZüchte Tiere' - tameAnimals: '§aZähme Tiere' - NPCText: '§eDialog bearbeiten' - dialogLines: '{0} Zeilen' - NPCSelect: '§eNPC auswählen oder erstellen' - hideClues: Partikel und Hologramme verstecken - gps: Zeigt einen Kompass zum Ziel an - editMobsKill: '§eDie zu tötenden Mobs bearbeiten' - mobsKillFromAFar: Muss mit Projektil getötet werden - editBlocksMine: '§eDie zu zerstörenden Blöcke bearbeiten' preventBlockPlace: Spieler daran hindern, ihre eigenen Blöcke zu zerstören - editBlocksPlace: '§eDie zu plazierenden Blöcke bearbeiten' - editMessageType: '§eDie zu schreibende Nachricht bearbeiten' - cancelMessage: Senden abbrechen - ignoreCase: Fall der Nachricht ignorieren replacePlaceholders: Ersetze {PLAYER} und Platzhalter von PAPI + selectBlockLocation: '§eBlockposition auswählen' + selectBlockMaterial: '§eWähle Blockmaterial' selectItems: '§eBenötigte Items auswählen' - selectItemsMessage: '§eFragenachricht bearbeiten' selectItemsComparisons: '§eWähle Gegenstandsvergleiche (ERWEITERT)' + selectItemsMessage: '§eFragenachricht bearbeiten' selectRegion: '§7Region auswählen' - toggleRegionExit: Beim Verlassen + stage: + dealDamage: + damage: '§eSchaden zu erledigen' + targetMobs: '§cMobs zu Schaden' + death: + anyCause: Jede Todesursache + causes: '§aSetze Todesursache §d(FORTGESCHRITTEN)' + setCauses: '{causes_amount} Todesursache(n)' + eatDrink: + items: '§eBearbeite Items um zu essen oder zu trinken' + location: + worldPattern: '§aSetze Weltennamenmuster §d(FORTGESCHRITTEN)' + worldPatternLore: Wenn du möchtest, dass die Stage für eine Welt, die einem bestimmten Muster entspricht, abgeschlossen wird, gib hier einen Regex (regulärer Ausdruck) ein. + stageCreate: '§aNeuen Schritt erstellen' + stageDown: Eins runter + stageRemove: '§cDiesen Schritt löschen' stageStartMsg: '§eStartnachricht bearbeiten' - selectBlockLocation: '§eBlockposition auswählen' - selectBlockMaterial: '§eWähle Blockmaterial' - leftClick: Muss Linksklick sein - editFishes: '§eDie zu fangenden Fische bearbeiten' - editItem: '§eHerzustellendes Item bearbeiten' - editBucketType: '§eTyp des zu befüllenden Eimers bearbeiten' - editBucketAmount: '§eAnzahl an zu befüllenden Eimern bearbeiten' - editLocation: '§ePosition bearbeiten' - editRadius: '§eEntfernung von Position bearbeiten' - currentRadius: '§eAktuelle Entfernung: §6{0}' - changeTicksRequired: '§eÄndere die erforderlichen gespielten Ticks' - changeEntityType: '§eObjekttyp ändern' - stages: - name: Schritte erstellen - nextPage: '§eNächste Seite' - laterPage: '§eVorherige Seite' - endingItem: '§eAbschlussbelohnung bearbeiten' - descriptionTextItem: '§eBeschreibung bearbeiten' - regularPage: '§aReguläre Schritte' - branchesPage: '§dZweig‐Schritte' - previousBranch: '§eZurück zum vorherigen Zweig' - newBranch: '§eZum neuen Zweig gehen' - validationRequirements: '§eValidierungsanforderungen' - validationRequirementsLore: Alle Anforderungen müssen dem Spieler entsprechen, der versucht, den Schritt zu beenden. Ist dies nicht der Fall, kann der Schritt nicht beendet werden. + stageType: '§7Stufentyp: §e{stage_type}' + stageUp: Eins höher + talkChat: '§aIm Chat schreiben' + tameAnimals: '§aZähme Tiere' + toggleRegionExit: Beim Verlassen details: - hologramLaunch: '§e„Starten“‐Hologramm‐Item bearbeiten' - hologramLaunchLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest starten kann. - hologramLaunchNo: '§e„Starten nicht verfügbar“‐Hologramm‐Item bearbeiten' - hologramLaunchNoLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest NICHT starten kann. + actions: '{amount} Aktion(en)' + auto: Beim ersten Beitritt automatisch starten + autoLore: Wenn aktiviert, wird die Quest automatisch gestartet, wenn der Spieler zum ersten Mal den Server betritt. + bypassLimit: Questlimit nicht zählen + bypassLimitLore: Wenn aktiviert, ist die Quest startbar, auch wenn der Spieler seine maximale Anzahl an begonnenen Quests erreicht hat. + cancelRewards: '§cAbbrechen von Aktionen' + cancelRewardsLore: Aktionen wenn Spieler diese Quest abbrechen. + cancellable: Vom Spieler abbrechbar + cancellableLore: Ermöglicht dem Spieler, die Quest durch das Quest-Menü abzubrechen. + createQuestLore: Du musst einen Questnamen definieren. + createQuestName: '§lQuest erstellen' customConfirmMessage: '§eQuestbestätigungsnachricht bearbeiten' customConfirmMessageLore: Meldung, die in der Bestätigungs-GUI angezeigt wird, wenn ein Spieler die Quest startet. customDescription: '§eBearbeite Quest Beschreibung' customDescriptionLore: Beschreibung, die unter dem Namen der Quest in GUIs steht. - name: Letzte Questdetails - multipleTime: - itemName: Wiederholbar ein-/ausschalten - itemLore: "Kann die Quest mehrmals\nabgeschlossen werden?" - cancellable: Vom Spieler abbrechbar - cancellableLore: Ermöglicht dem Spieler, die Quest durch das Quest-Menü abzubrechen. - startableFromGUI: Über GUI startbar - startableFromGUILore: Ermöglicht dem Spieler, die Quest aus dem Quest-Menü zu starten. - scoreboardItem: Scoreboard aktivieren - scoreboardItemLore: Wenn deaktiviert, wird die Quest nicht über das Scoreboard verfolgt. + customMaterial: '§eBearbeite das Material des Questgegenstandes' + customMaterialLore: Angezeigter Gegenstand dieser Quest im Questmenü. + defaultValue: '§8(Standardwert)' + editQuestName: '§lQuest bearbeiten' + editRequirements: '§eAnforderungen bearbeiten' + editRequirementsLore: Alle Anforderungen müssen auf den Spieler zutreffen, bevor er mit der Quest beginnen kann. + endMessage: '§eAbschlussnachricht bearbeiten' + endMessageLore: Nachricht, die am Ende der Quest an den Spieler gesendet wird. + endSound: '§eBearbeite den end sound' + endSoundLore: Ton, der am Ende einer Quest abgespielt wird. + failOnDeath: Im Todesfall fehlschlagen + failOnDeathLore: Wird die Quest abgebrochen, wenn der Spieler stirbt? + firework: '§dEnding Feuerwerk' + fireworkLore: Feuerwerk startet, wenn der Spieler die Quest beendet hat + fireworkLoreDrop: Lege dein eigenes Feuerwerk hierher hideNoRequirementsItem: Verstecken, wenn die Anforderungen nicht erfüllt sind hideNoRequirementsItemLore: Wenn aktiviert, wird die Quest nicht im Questmenü angezeigt, wenn die Anforderungen nicht erfüllt sind. - bypassLimit: Questlimit nicht zählen - bypassLimitLore: Wenn aktiviert, ist die Quest startbar, auch wenn der Spieler seine maximale Anzahl an begonnenen Quests erreicht hat. - auto: Beim ersten Beitritt automatisch starten - autoLore: Wenn aktiviert, wird die Quest automatisch gestartet, wenn der Spieler zum ersten Mal den Server betritt. + hologramLaunch: '§e„Starten“‐Hologramm‐Item bearbeiten' + hologramLaunchLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest starten kann. + hologramLaunchNo: '§e„Starten nicht verfügbar“‐Hologramm‐Item bearbeiten' + hologramLaunchNoLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest NICHT starten kann. + hologramText: '§eHologrammtext' + hologramTextLore: Text, der auf dem Hologramm über dem Kopf des Starter NPCs angezeigt wird. + keepDatas: Spielerdaten beibehalten + keepDatasLore: 'Erzwinge das Plugin die Daten der Spieler zu speichern, obwohl Stufen bearbeitet wurden. §c§lWARNUNG §c- Aktivieren dieser Option kann die Daten deiner Spieler zerstören.' + loreReset: '§e§lDer Fortschritt aller Spieler wird zurückgesetzt' + multipleTime: + itemLore: Kann die Quest mehrmals abgeschlossen werden? + itemName: Wiederholbar ein-/ausschalten + name: Letzte Questdetails + optionValue: '§8Wert: §7{value}' questName: '§a§lQuestname bearbeiten' questNameLore: Ein Name muss gesetzt werden, um die Questerstellung abzuschließen. - setItemsRewards: '§eBelohnungs‐Items bearbeiten' + questPool: '§eQuestgruppe' + questPoolLore: Füge diese Quest einer Questgruppe hinzu removeItemsReward: '§eEntferne Items vom Inventar' - setXPRewards: '§eBelohnungserfahrungspunkte bearbeiten' + requiredParameter: '§7Benötigter Parameter' + requirements: '{amount} Anforderung(en)' + rewards: '{amount} Belohnung(en)' + rewardsLore: Aktionen die durchgeführt werden wenn die Quest endet. + scoreboardItem: Scoreboard aktivieren + scoreboardItemLore: Wenn deaktiviert, wird die Quest nicht über das Scoreboard verfolgt. + selectStarterNPC: '§e§lNPC‐Starter auswählen' + selectStarterNPCLore: Ein Klick auf den ausgewählten NPC startet die Quest + selectStarterNPCPool: '§c⚠: Eine Questgruppe ist ausgewählt' setCheckpointReward: '§eBearbeite Checkpoint Belohnungen' + setItemsRewards: '§eBelohnungs‐Items bearbeiten' + setMoneyReward: '§eGeldbelohnung bearbeiten' + setPermReward: '§eBerechtigungen bearbeiten' setRewardStopQuest: '§cQuest stoppen' - setRewardsWithRequirements: '§eBelohnungen mit Voraussetzungen' setRewardsRandom: '§dZufällige Belohnungen' - setPermReward: '§eBerechtigungen bearbeiten' - setMoneyReward: '§eGeldbelohnung bearbeiten' - setWaitReward: '§e"Warte"-Belohnung bearbeiten' + setRewardsWithRequirements: '§eBelohnungen mit Voraussetzungen' setTitleReward: '§eTitelbelohnung bearbeiten' - selectStarterNPC: '§e§lNPC‐Starter auswählen' - selectStarterNPCLore: Ein Klick auf den ausgewählten NPC startet die Quest - selectStarterNPCPool: '§c⚠: Eine Questgruppe ist ausgewählt' - createQuestName: '§lQuest erstellen' - createQuestLore: Du musst einen Questnamen definieren. - editQuestName: '§lQuest bearbeiten' - endMessage: '§eAbschlussnachricht bearbeiten' - endMessageLore: Nachricht, die am Ende der Quest an den Spieler gesendet wird. - startMessage: '§eStartnachricht bearbeiten' - startMessageLore: Nachricht, die am Anfang der Quest an den Spieler gesendet wird. + setWaitReward: '§e"Warte"-Belohnung bearbeiten' + setXPRewards: '§eBelohnungserfahrungspunkte bearbeiten' startDialog: '§eStart‐Dialog bearbeiten' startDialogLore: Dialog, der vor dem Start der Quests angezeigt wird, wenn Spieler auf den Starter NPC klicken. - editRequirements: '§eAnforderungen bearbeiten' - editRequirementsLore: Alle Anforderungen müssen auf den Spieler zutreffen, bevor er mit der Quest beginnen kann. + startMessage: '§eStartnachricht bearbeiten' + startMessageLore: Nachricht, die am Anfang der Quest an den Spieler gesendet wird. startRewards: '§6Startbelohnungen' startRewardsLore: Aktionen die durchgeführt werden wenn die Quest startet. - hologramText: '§eHologrammtext' - hologramTextLore: Text, der auf dem Hologramm über dem Kopf des Starter NPCs angezeigt wird. + startableFromGUI: Über GUI startbar + startableFromGUILore: Ermöglicht dem Spieler, die Quest aus dem Quest-Menü zu starten. timer: '§bNeustart Timer' timerLore: Zeit, bis der Spieler die Quest wieder starten kann. - requirements: '{0} Anforderung(en)' - rewards: '{0} Belohnung(en)' - actions: '{0} Aktion(en)' - rewardsLore: Aktionen die durchgeführt werden wenn die Quest endet. - customMaterial: '§eBearbeite das Material des Questgegenstandes' - customMaterialLore: Angezeigter Gegenstand dieser Quest im Questmenü. - failOnDeath: Im Todesfall fehlschlagen - failOnDeathLore: Wird die Quest abgebrochen, wenn der Spieler stirbt? - questPool: '§eQuestgruppe' - questPoolLore: Füge diese Quest einer Questgruppe hinzu - keepDatas: Spielerdaten beibehalten - keepDatasLore: |- - Erzwinge das Plugin die Daten der Spieler zu speichern, obwohl Stufen bearbeitet wurden. - §c§lWARNUNG §c- Aktivieren dieser Option kann die Daten deiner Spieler zerstören. - loreReset: '§e§lDer Fortschritt aller Spieler wird zurückgesetzt' - optionValue: '§8Wert: §7{0}' - defaultValue: '§8(Standardwert)' - requiredParameter: '§7Benötigter Parameter' - itemsSelect: - name: Items bearbeiten - none: |- - §aBewege ein Item hierher oder - klicke, um den Item‐Editor zu öffnen. + visibility: '§bQuest Sichtbarkeit' + visibilityLore: Legen Sie fest, in welchen Tabs des Menüs die Quest angezeigt wird und ob die Quest auf dynamischen Karten sichtbar ist. + editTitle: + fadeIn: '§aEinblendedauer' + fadeOut: '§aAusblendedauer' + name: Titel bearbeiten + stay: '§bEinblendedauer' + subtitle: '§eUntertitel' + title: '§6Titel' + entityType: + name: Objekttyp auswählen + factionsList.name: Fraktionsliste + factionsRequired.name: Fraktionen benötigt + itemComparisons: + bukkit: Bukkit nativer Vergleich + bukkitLore: Nutzt das Standard Bukkit Gegenstandsvergleichsystem. Vergleicht Material, Haltbarkeit, NBT Tags... + customBukkit: Bukkit nativer Vergleich - KEIN NBT + customBukkitLore: Nutzt das Standard Bukkit Gegenstandsvergleichsystem, aber löscht NBT Tags. Vergleicht Material, Haltbarkeit... + enchants: Gegenstände verzaubert + enchantsLore: Vergleicht Gegenstandsverzauberungen + itemLore: Gegenstands-Beschreibung + itemLoreLore: Vergleicht Gegenstands-Beschreibungen + itemName: Gegenstandsname + itemNameLore: Vergleicht Gegenstandsnamen + itemsAdder: ItemsAdder + itemsAdderLore: Vergleicht ItemsAdder-IDs + material: Gegenstandsmaterial + materialLore: Vergleicht Gegenstandsmaterial (z.B Stein, Eisenschwert...) + name: Itemvergleiche + repairCost: Reparaturkosten + repairCostLore: Vergleicht Reparaturkosten für Rüstungen und Schwerter + itemCreator: + isQuestItem: '§bQuest‐Item:' + itemFlags: Item‐Flags umschalten + itemLore: '§bItem‐Beschreibung' + itemName: '§bItem‐Name' + itemType: '§bItem‐Typ' + name: Item‐Ersteller itemSelect: name: Item auswählen + itemsSelect: + name: Items bearbeiten + none: '§aBewege ein Item hierher oder klicke, um den Item‐Editor zu öffnen.' + listAllQuests: + name: Quests + listBook: + noQuests: Es wurden zuvor keine Quests erstellt. + questMultiple: Mehrfachverwendung + questName: Name + questRewards: Belohnungen + questStages: Schritte + questStarter: Starter + requirements: Vorraussetzungen + listPlayerQuests: + name: 'Quests von {player_name}' + listQuests: + canRedo: '§3§oDu kannst diese Quest erneut starten!' + finished: Abgeschlossene Quests + inProgress: Laufende Quests + loreCancelClick: '§cQuest abbrechen' + loreDialogsHistoryClick: '§7Dialoge anzeigen' + loreStart: '§a§oKlicke, um die Quest zu starten.' + loreStartUnavailable: '§c§oDu erfüllst nicht die Anforderungen, um die Quest zu starten.' + notStarted: Nicht gestartete Quests + timeToWaitRedo: '§3§oDu kannst diese Quest in {time_left} erneut starten.' + timesFinished: '§3Quest {times_finished} mal(e) erledigt.' + mobSelect: + boss: '§6Wähle einen Boss' + bukkitEntityType: '§eObjekttyp auswählen' + epicBoss: '§6Wähle einen Epic Boss' + mythicMob: '§6Mythic Mob auswählen' + name: Wähle den Mobtyp + mobs: + name: Mobs auswählen + none: '§aKlicke, um ein Mob hinzuzufügen.' + setLevel: Mindestlevel festlegen npcCreate: + move: + itemLore: '§aDie NPC‐Position ändern.' + itemName: '§eBewegen' + moveItem: '§a§lPosition bestätigen' name: NPC erstellen setName: '§eNPC‐Name bearbeiten' setSkin: '§eNPC‐Skin bearbeiten' setType: '§eNPC‐Typ bearbeiten' - move: - itemName: '§eBewegen' - itemLore: '§aDie NPC‐Position ändern.' - moveItem: '§a§lPosition bestätigen' npcSelect: + createStageNPC: '§eNPC erstellen' name: Auswählen oder erstellen? selectStageNPC: '§eExistierenden NPC auswählen' - createStageNPC: '§eNPC erstellen' - entityType: - name: Objekttyp auswählen - chooseQuest: - name: Welche Quest? - mobs: - name: Mobs auswählen - none: '§aKlicke, um ein Mob hinzuzufügen.' - clickLore: |- - §a§lLinksklick§a, um Anzahl zu bearbeiten. - §a§l§nShift§a§l + Linksklick§a, um Mob-Namen zu bearbeiten. - §c§lRechtsklick§c zum Löschen. - mobSelect: - name: Wähle den Mobtyp - bukkitEntityType: '§eObjekttyp auswählen' - mythicMob: '§6Mythic Mob auswählen' - epicBoss: '§6Wähle einen Epic Boss' - boss: '§6Wähle einen Boss' - stageEnding: - locationTeleport: '§eTeleportationsposition bearbeiten' - command: '§eAuszuführenden Befehl bearbeiten' + particleEffect: + color: '§bPartikelfarbe' + name: Erstelle einen Partikeleffekt + shape: '§dPartikel Muster' + type: '§ePartikel Typ' + particleList: + colored: Farbige Partikel + name: Partikel Liste + permission: + name: Berechtigung auswählen + perm: '§aBerechtigung' + remove: Berechtigung entfernen + removeLore: '§7Berechtigung wird genommen\n§7statt zu geben.' + world: '§aWelt' + worldGlobal: '§b§lGlobal' + permissionList: + name: Berechtigungsliste + removed: '§eGenommen: §6{permission_removed}' + world: '§eWelt: §6{permission_world}' + poolCreation: + avoidDuplicates: Duplikate vermeiden + avoidDuplicatesLore: '§8> §7Versuche es zu vermeiden,\n immer wieder die gleiche Quest zu absolvieren' + hologramText: '§eBenutzerdefiniertes Hologramm der Gruppe' + maxQuests: '§aMax. Quests' + name: Questgruppen Erstellung + questsPerLaunch: '§aPro Start gestartete Quests' + redoAllowed: Ist Wiederholen erlaubt + requirements: '§bAnforderungen, um eine Quest zu starten' + time: '§bLege die Zeit zwischen Quests fest' + poolsList.name: Questgruppen + poolsManage: + choose: '§e> §6§oWähle diese Gruppe §e<' + create: '§aErstelle eine Questgruppe' + edit: '§e> §6§oBearbeite die Gruppe... §e<' + itemName: '§aGruppe #{pool}' + name: Questgruppen + poolAvoidDuplicates: '§8Duplikate vermeiden: §7{pool_duplicates}' + poolHologram: '§8Hologramm-Text: §7{pool_hologram}' + poolMaxQuests: '§8Max. Quests: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8Quest(s): §7{pool_quests}' + poolQuestsPerLaunch: '§8Quests pro Start vergeben: §7{pool_quests_per_launch}' + poolRedo: '§8Kann abgeschlossene Quests wiederholen: §7{pool_redo}' + poolTime: '§8Zeit zwischen Quests: §7{pool_time}' requirements: name: Anforderungen rewards: + commands: 'Befehle: {amount}' name: Belohnungen - commands: 'Befehle: {0}' - teleportation: |- - §aAusgewählt: - X: {0} - Y: {1} - Z: {2} - Welt: {3} random: - rewards: Belohnungen bearbeiten minMax: Bearbeite das min und max - checkpointActions: - name: Checkpoint-Aktionen + rewards: Belohnungen bearbeiten rewardsWithRequirements: name: Belohnungen mit Voraussetzungen - listAllQuests: - name: Quests - listPlayerQuests: - name: 'Quests von {0}' - listQuests: - notStarted: Nicht gestartete Quests - finished: Abgeschlossene Quests - inProgress: Laufende Quests - loreDialogsHistoryClick: '§7Dialoge anzeigen' - loreCancelClick: '§cQuest abbrechen' - loreStart: '§a§oKlicke, um die Quest zu starten.' - loreStartUnavailable: '§c§oDu erfüllst nicht die Anforderungen, um die Quest zu starten.' - timeToWaitRedo: '§3§oDu kannst diese Quest in {0} erneut starten.' - canRedo: '§3§oDu kannst diese Quest erneut starten!' - timesFinished: '§3Quest {0} mal(e) erledigt.' - itemCreator: - name: Item‐Ersteller - itemType: '§bItem‐Typ' - itemFlags: Item‐Flags umschalten - itemName: '§bItem‐Name' - itemLore: '§bItem‐Beschreibung' - isQuestItem: '§bQuest‐Item:' - command: - name: Befehl - value: '§eBefehl' - console: Konsole - delay: '§bVerzögerung' - chooseAccount: - name: Welcher Account? - listBook: - questName: Name - questStarter: Starter - questRewards: Belohnungen - questMultiple: Mehrfachverwendung - requirements: Vorraussetzungen - questStages: Schritte - noQuests: Es wurden zuvor keine Quests erstellt. - commandsList: - name: Befehlliste - value: '§eBefehl: {0}' - console: '§eKonsole: {0}' - block: - name: Block auswählen - material: '§eMaterial: {0}' - materialNotItemLore: 'Dieser Block kann momentan nicht als Item angezeigt werden. Er wird immer noch korrekt als {0} gespeichert.' - blockData: '§dBlockdaten (fortgeschritten)' - blockTag: '§dTag (Erweitert)' - blockTagLore: 'Wähle einen Tag, welcher eine Liste von möglichen Blöcken beschreibt. Tags können durch Datapacks angepasst werden. Du kannst eine Liste von Tags im Minecraft Wiki finden.' - blocksList: - name: Blöcke auswählen - addBlock: '§aKlicke, um einen Block hinzuzufügen.' - blockAction: - name: Blockaktion auswählen - location: '§eWähle einen genauen Ort aus' - material: '§eWähle ein Blockmaterial' - buckets: - name: Eimertyp - permission: - name: Berechtigung auswählen - perm: '§aBerechtigung' - world: '§aWelt' - worldGlobal: '§b§lGlobal' - remove: Berechtigung entfernen - removeLore: '§7Berechtigung wird genommen\n§7statt zu geben.' - permissionList: - name: Berechtigungsliste - removed: '§eGenommen: §6{0}' - world: '§eWelt: §6{0}' - classesRequired.name: Klassen erforderlich - classesList.name: Klassenliste - factionsRequired.name: Fraktionen benötigt - factionsList.name: Fraktionsliste - poolsManage: - name: Questgruppen - itemName: '§aGruppe #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Max. Quests: §7{0}' - poolQuestsPerLaunch: '§8Quests pro Start vergeben: §7{0}' - poolRedo: '§8Kann abgeschlossene Quests wiederholen: §7{0}' - poolTime: '§8Zeit zwischen Quests: §7{0}' - poolHologram: '§8Hologramm-Text: §7{0}' - poolAvoidDuplicates: '§8Duplikate vermeiden: §7{0}' - poolQuestsList: '§7{0} §8Quest(s): §7{1}' - create: '§aErstelle eine Questgruppe' - edit: '§e> §6§oBearbeite die Gruppe... §e<' - choose: '§e> §6§oWähle diese Gruppe §e<' - poolCreation: - name: Questgruppen Erstellung - hologramText: '§eBenutzerdefiniertes Hologramm der Gruppe' - maxQuests: '§aMax. Quests' - questsPerLaunch: '§aPro Start gestartete Quests' - time: '§bLege die Zeit zwischen Quests fest' - redoAllowed: Ist Wiederholen erlaubt - avoidDuplicates: Duplikate vermeiden - avoidDuplicatesLore: '§8> §7Versuche es zu vermeiden,\n immer wieder die gleiche Quest zu absolvieren' - requirements: '§bAnforderungen, um eine Quest zu starten' - poolsList.name: Questgruppen - itemComparisons: - name: Itemvergleiche - bukkit: Bukkit nativer Vergleich - bukkitLore: "Nutzt das Standard Bukkit Gegenstandsvergleichsystem.\nVergleicht Material, Haltbarkeit, NBT Tags..." - customBukkit: Bukkit nativer Vergleich - KEIN NBT - customBukkitLore: "Nutzt das Standard Bukkit Gegenstandsvergleichsystem, aber löscht NBT Tags.\nVergleicht Material, Haltbarkeit..." - material: Gegenstandsmaterial - materialLore: 'Vergleicht Gegenstandsmaterial (z.B Stein, Eisenschwert...)' - itemName: Gegenstandsname - itemNameLore: Vergleicht Gegenstandsnamen - itemLore: Gegenstands-Beschreibung - itemLoreLore: Vergleicht Gegenstands-Beschreibungen - enchants: Gegenstände verzaubert - enchantsLore: Vergleicht Gegenstandsverzauberungen - repairCost: Reparaturkosten - repairCostLore: Vergleicht Reparaturkosten für Rüstungen und Schwerter - editTitle: - name: Titel bearbeiten - title: '§6Titel' - subtitle: '§eUntertitel' - fadeIn: '§aEinblendedauer' - stay: '§bEinblendedauer' - fadeOut: '§aAusblendedauer' -scoreboard: - name: '§6§lQuests' - noLaunched: '§cKeine laufenden Quests.' - noLaunchedName: '&c&lLaden' - noLaunchedDescription: '§c§oLaden' - textBetwteenBranch: '§e oder' - asyncEnd: '§ex' - stage: - region: '§eFinde Region §6{0}' - npc: '§eSprich mit dem NPC §6{0}' - items: '§eBringe Items zu §6{0}§e:' - mobs: '§eTöte §6{0}' - mine: '§eBaue {0} ab' - placeBlocks: '§ePlatziere {0}' - chat: '§eSchreibe §6{0}' - interact: '§eKlicke auf den Block bei §6{0}' - interactMaterial: '§eKlicke auf einen §6{0}§e Block' - fish: '§eAngle §6{0}' - craft: '§eStelle §6{0} §eher' - bucket: '§eBefülle §6{0}' - location: '§eGehe zu: §6{0}§e, §6{1}§e, §6{2}§e in §6{3}' - breed: '§eZüchte §6{0}' - tame: '§eZähme §6{0}' -indication: - startQuest: '§7Möchtest du die Quest {0} starten?' - closeInventory: '§7Bist du sicher, dass du die GUI schließen möchtest?' - cancelQuest: '§7Bist du sicher, dass du die Quest {0} abbrechen möchtest?' - removeQuest: '§7Bist du sicher, dass du die Quest {0} entfernen möchtest?' -description: - requirement: - title: '§8§lAnforderungen:' - level: 'Level {0}' - jobLevel: 'Level {0} für {1}' - combatLevel: 'Kampflevel {0}' - skillLevel: 'Level {0} für {1}' - class: 'Klasse {0}' - faction: 'Fraktion {0}' - quest: 'Quest beenden §e{0}' - reward: - title: '§8§lBelohnungen:' + search: '§e§lSuche' + stageEnding: + command: '§eAuszuführenden Befehl bearbeiten' + locationTeleport: '§eTeleportationsposition bearbeiten' + stages: + branchesPage: '§dZweig‐Schritte' + descriptionTextItem: '§eBeschreibung bearbeiten' + endingItem: '§eAbschlussbelohnung bearbeiten' + laterPage: '§eVorherige Seite' + name: Schritte erstellen + newBranch: '§eZum neuen Zweig gehen' + nextPage: '§eNächste Seite' + previousBranch: '§eZurück zum vorherigen Zweig' + regularPage: '§aReguläre Schritte' + validationRequirements: '§eValidierungsanforderungen' + validationRequirementsLore: Alle Anforderungen müssen dem Spieler entsprechen, der versucht, den Schritt zu beenden. Ist dies nicht der Fall, kann der Schritt nicht beendet werden. + validate: '§b§lBestätigen' misc: + amount: '§eAnzahl: {amount}' + and: und + bucket: + lava: Lavaeimer + milk: Milcheimer + water: Wassereimer + click: + left: Linksklick + middle: Mittelklick + right: Rechtsklick + shift-left: Shift-Linksklick + shift-right: Shift-Rechtsklick + comparison: + different: anders als {number} + equals: gleich wie {number} + greater: strikt größer als {number} + greaterOrEquals: größer als {number} + less: strikt weniger als {number} + lessOrEquals: weniger als {number} + disabled: Deaktiviert + enabled: Aktiviert + entityType: '§eObjekttyp: {entity_type}' + entityTypeAny: '§eJedes Objekt' format: - prefix: '§6<§e§lQuests§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - offText: '§r§e{0}' editorPrefix: '§a' - time: - weeks: '{0} Wochen' - days: '{0} Tage' - hours: '{0} Stunden' - minutes: '{0} Minuten' - lessThanAMinute: 'weniger als eine Minute' - stageType: - region: Region finden - npc: NPC finden - items: Items zurückbringen - mobs: Mobs töten - mine: Blöcke zerstören - placeBlocks: Blöcke platzieren - chat: Im Chat schreiben - interact: Mit Block interagieren - Fish: Fische fangen - Craft: Item herstellen - Bucket: Eimer befüllen - location: Position finden - playTime: Spielzeit - breedAnimals: Züchte Tiere - tameAnimals: Zähme Tiere - comparison: - equals: gleich wie {0} - different: anders als {0} - less: strikt weniger als {0} - lessOrEquals: weniger als {0} - greater: strikt größer als {0} - greaterOrEquals: größer als {0} + prefix: '§6<§e§lQuests§r§6> §r' + hologramText: '§8§lQuest‐NPC' + 'no': 'Nein' + notSet: '§cnicht gesetzt' + or: oder + poolHologramText: '§eNeue Quest verfügbar!' + questItemLore: '§e§oQuest‐Item' + removeRaw: Entfernen requirement: - logicalOr: '§dLogisch ODER (Voraussetzungen)' - skillAPILevel: '§bAPI-Level benötigt' class: '§bBenötigte Klasse(n)' - faction: '§bBenötigte Fraktion(en)' - jobLevel: '§bJob‐Level benötigt' combatLevel: '§bKampflevel benötigt' experienceLevel: '§bErfahrungslevel benötigt' + faction: '§bBenötigte Fraktion(en)' + jobLevel: '§bJob‐Level benötigt' + logicalOr: '§dLogisch ODER (Voraussetzungen)' + mcMMOSkillLevel: '§dBenötigtes Fertigkeitslevel' + money: '§dGeld benötigt' permissions: '§3Benötigte Berechtigung(en)' - scoreboard: '§dPunktestand erforderlich' - region: '§dRegion erforderlich' placeholder: '§bPlatzhalter‐Wert benötigt' quest: '§aQuest benötigt' - mcMMOSkillLevel: '§dBenötigtes Fertigkeitslevel' - money: '§dGeld benötigt' - bucket: - water: Wassereimer - lava: Lavaeimer - milk: Milcheimer - click: - right: Rechtsklick - left: Linksklick - shift-right: Shift-Rechtsklick - shift-left: Shift-Linksklick - middle: Mittelklick - ticks: '{0} Ticks' - questItemLore: '§e§oQuest‐Item' - hologramText: '§8§lQuest‐NPC' - poolHologramText: '§eNeue Quest verfügbar!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eObjekttyp: {0}' - entityTypeAny: '§eJedes Objekt' - enabled: Aktiviert - disabled: Deaktiviert + region: '§dRegion erforderlich' + scoreboard: '§dPunktestand erforderlich' + skillAPILevel: '§bAPI-Level benötigt' + stageType: + Bucket: Eimer befüllen + Craft: Item herstellen + Fish: Fische fangen + breedAnimals: Züchte Tiere + chat: Im Chat schreiben + interact: Mit Block interagieren + items: Items zurückbringen + location: Position finden + mine: Blöcke zerstören + mobs: Mobs töten + npc: NPC finden + placeBlocks: Blöcke platzieren + playTime: Spielzeit + region: Region finden + tameAnimals: Zähme Tiere + ticks: '{ticks} Ticks' + time: + days: '{days_amount} Tage' + hours: '{hours_amount} Stunden' + lessThanAMinute: weniger als eine Minute + minutes: '{minutes_amount} Minuten' + weeks: '{weeks_amount} Wochen' unknown: unbekannt - notSet: '§cnicht gesetzt' - unused: '§2§lUnbenutzt' - used: '§a§lBenutzt' - remove: '§7Mittelklicke zum Entfernen' - removeRaw: Entfernen - or: oder - amount: '§eAnzahl: {0}' - items: Items - expPoints: Erfahrungspunkte 'yes': 'Ja' - 'no': 'Nein' - and: und +msg: + bringBackObjects: Bring mir {items} zurück. + command: + adminModeEntered: '§aDu hast den Admin‐Modus betreten.' + adminModeLeft: '§aDu hast den Admin‐Modus verlassen.' + backupCreated: '§6Du hast erfolgreich Sicherungen aller Quests und Spielerinformationen erstellt.' + backupPlayersFailed: '§cDas Sichern von allen Spielerinformationen ist fehlgeschlagen.' + backupQuestsFailed: '§cDas Sichern von allen Quests ist fehlgeschlagen.' + cancelQuest: '§6Du hast die Quest {quest} abgebrochen.' + cancelQuestUnavailable: '§cDie Quest {quest} kann nicht abgebrochen werden.' + checkpoint: + noCheckpoint: '§cKein Checkpoint für die Quest {quest} gefunden.' + questNotStarted: '§cDu machst diese Quest nicht.' + downloadTranslations: + downloaded: '§aSprache {lang} wurde heruntergeladen! §7Du musst nun die Datei "/plugins/BeautyQuests/config.yml" bearbeiten, um den Wert von §ominecraftTranslationsFile§7 mit {lang} zu ändern. Der Server muss anschliessend neu gestartet werden.' + exists: '§cDie Datei {file_name} existiert bereits. Füge "-Overwrite "true" an deinen Befehl an, um ihn zu überschreiben. (/quests downloadTranslations <lang> -overwrite true)' + notFound: '§cSprache {lang} nicht gefunden für die Version {version}.' + syntax: '§cDu musst eine Sprache auswählen zum downloaden. Beispiel: "/quests downloadTranslations en_US".' + help: + adminMode: '§6/{label} adminMode: §eSchalte den Admin‐Modus (für die Anzeige von Protokollnachrichten) für dich um.' + create: '§6/{label} create: §eErstelle eine Quest.' + downloadTranslations: '§6/{label} heruntergeladene Übersetzung <language>: §eDownloads einer Vanille-Übersetzungsdatei' + edit: '§6/{label} edit: §eBearbeite eine Quest.' + finishAll: '§6/{label} finishAll <Spieler>: §eBeende alle Quests eines Spielers.' + header: '§6§lBeautyQuests — Hilfe' + list: '§6/{label} list: §eSieh dir die Questliste an. (Funktioniert nur bei unterstützten Versionen.)' + reload: '§6/{label} reload: §eSpeichere und und lade alle Konfigurationen und Dateien neu. (§cveraltet§e)' + remove: '§6/{label} remove <ID>: §eLösche eine Quest mit der angegebenen ID oder klicke auf den NPC, wenn nicht definiert.' + resetPlayer: '§6/{label} resetPlayer <Spieler>: §eEntferne alle Informationen eines Spielers.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <Spieler> [ID]: §eLösche Informationen einer Quest für einen Spieler.' + save: '§6/{label} save: §eFühre eine manuelle Plugin‐Speicherung durch.' + seePlayer: '§6/{label} seePlayer <Spieler>: §eSieh dir die Informationen eines Spielers an.' + setFirework: '§6/{label} SetFeuerwerk: §eBearbeite das standardmäßig end Feuerwerk.' + setItem: '§6/{label} setItem <talk|launch>: §eSpeichere das Hologramm‐Item.' + setStage: '§6/{label} setStage <Spieler> <ID> [neuer Zweig] [neuer Schritt]: §eÜberspringe den aktuellen Schritt/starte einen Zweig/setze einen Schritt für einen Zweig.' + start: '§6/{label} start <Spieler> [ID]: §eErzwinge das Starten einer Quest.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eStartet den ausstehenden Dialog für eine NPC-Stufe oder den Startdialog für eine Quest.' + version: '§6/{label} version: §eLass dir die aktuelle Plugin‐Version anzeigen.' + invalidCommand: + simple: '§cDieser Befehl existiert nicht, schreibe §ehelp§c.' + itemChanged: '§aDas Item wurde bearbeitet. Die Änderungen werden nach einem Neustart angewendet.' + itemRemoved: '§aDas Hologramm‐Item wurde entfernt.' + leaveAll: '§aDu hast das Ende von {success} Quest(s) erzwungen. Fehler: {errors}' + removed: '§aDie Quest {quest_name} wurde erfolgreich entfernt.' + resetPlayer: + player: '§6Alle Informationen deiner {quest_amount} Quest(s) wurde/wurden von {deleter_name} gelöscht.' + remover: '§6{quest_amount} Questinformation(en) (und {quest_pool} Gruppen) von {player} wurde(n) gelöscht.' + resetPlayerPool: + full: '§aDu hast die {pool} Gruppendaten auf {player} zurückgesetzt.' + timer: '§aDu hast den {pool} Gruppentimer auf {player} zurückgesetzt.' + resetPlayerQuest: + player: '§6Alle Informationen über die Quest {quest} wurden von {deleter_name} gelöscht.' + remover: '§6{player} Questinformation(en) von {quest} wurde(n) gelöscht.' + resetQuest: '§6Quest Daten wurden für {player_amount} Spieler entfernt.' + scoreboard: + hidden: '§6Das Scoreboard des Spielers {player_name} wurde versteckt.' + lineInexistant: '§cDie Zeile {line_id} existiert nicht.' + lineRemoved: '§6Du hast die Zeile {line_id} erfolgreich entfernt.' + lineReset: '§6Du hast die Zeile {line_id} erfolgreich zurückgesetzt.' + lineSet: '§6Du hast die Zeile {line_id} erfolgreich bearbeitet.' + own: + hidden: '§6Dein Scoreboard ist jetzt versteckt.' + shown: Dein Scoreboard wird wieder angezeigt. + resetAll: '§6Du hast das Scoreboard des Spielers {player_name} erfolgreich zurückgesetzt.' + shown: '§6Das Scoreboard des Spielers {player_name} wurde angezeigt.' + setStage: + branchDoesntExist: '§cDer Zweig mit der ID {branch_id} existiert nicht.' + doesntExist: '§cDer Schritt mit der ID {stage_id} existiert nicht.' + next: '§aDer Schritt wurde übersprungen.' + nextUnavailable: '§cDie „Überspringen“‐Option ist nicht verfügbar, wenn der Spieler am Ende eines Zweiges ist.' + set: '§aSchritt {stage_id} gestartet.' + startDialog: + alreadyIn: '§cDer Spieler spielt bereits einen Dialog.' + impossible: '§cKann den Dialog jetzt nicht starten.' + noDialog: '§cDer Spieler hat keinen ausstehenden Dialog.' + success: '§aStartete Dialog für Spieler {player} in Quest {quest}!' + startPlayerPool: + error: Der Pool {pool} für {player} konnte nicht gestartet werden. + success: 'Pool {pool} bis {player}gestartet. Ergebnis: {result}' + startQuest: '§6Du hast den Start der Quest {quest} erzwungen. (Spieler‐UUID: {player})' + startQuestNoRequirements: '§cDer Spieler erfüllt nicht die Anforderungen für die Quest {quest}... Füge "-OverrideRequirements am Ende deines Befehls hinzu, um die Anforderungsüberprüfung zu umgehen.' + dialogs: + skipped: Dialog übersprungen. + tooFar: '§7§oDu bist zu weit von {npc_name}...' + editor: + advancedSpawnersMob: 'Schreibe den Namen des benutzerdefinierten Spawnermob zum Töten:' + already: '§cDu befindest dich bereits im Editor.' + availableElements: 'Verfügbare Elemente: §e{available_elements}' + blockAmount: '§aSchreibe die Anzahl der Blöcke:' + blockData: '§aSchreibe die Blockdaten (verfügbare Blockdaten: {available_datas}):' + blockName: '§aSchreibe den Namen des Blocks:' + blockTag: '§aSchreibe den Blocktag (verfügbare Blocktags: §7{available_tags}§a):' + chat: '§6Du bist zurzeit im Editor‐Modus. Schreibe „/quests exitEditor“, um das Verlassen des Editors zu erzwingen. (Nicht empfohlen, erwäge die Verwendung von Befehlen wie „close“ oder „cancel“, um zum vorherigen Inventar zurückzukehren.)' + color: 'Geben Sie eine Farbe im Hexadezimalformat (#XXXXX) oder RGB Format (RED GRE BLU) ein.' + colorNamed: Geben Sie den Namen einer Farbe ein. + comparisonTypeDefault: '§aWählen Sie den Vergleichstyp unter {available}aus. Der Standardvergleich ist: §e§l{default}§r§a. Geben Sie §onull§r§a ein, um ihn zu verwenden.' + dialog: + cleared: '§a{amount} entfernte Nachricht(en).' + edited: '§aNachricht "§7{msg}§a" bearbeitet.' + help: + addSound: '§6addSound <ID> <Geräusch>: §eFüge ein Geräusch einer Nachricht hinzu.' + clear: '§6clear: §eEntferne alle Nachrichten.' + close: '§6close: §eBestätige alle Nachrichten.' + edit: '§6edit <id> <message>: §eBearbeite eine Nachricht.' + header: '§6§lBeautyQuests — Dialogbearbeitungs‐Hilfe' + list: '§6list: §eSchaue dir alle Nachrichten an.' + nothing: '§6noSender <Nachricht>: §eFüge eine Nachricht ohne Absender hinzu.' + nothingInsert: '§6nothingInsert <ID> <Nachricht>: §eFüge eine Nachricht ohne Präfix ein.' + npc: '§6npc <Nachricht>: §eFüge eine vom NPC gesagte Nachricht hinzu.' + npcInsert: '§6npcInsert <ID> <Nachricht>: §eFüge eine vom NPC gesagte Nachricht ein.' + npcName: '§6npcName [benutzerdefinierter NPC-Name]: §eSetze (oder zurücksetzen auf Standard) des benutzerdefinierten Namens des NPCs im Dialog' + player: '§6player <Nachricht>: §eFüge eine vom Spieler gesagte Nachricht hinzu.' + playerInsert: '§6playerInsert <ID> <Nachricht>: §eFüge eine vom Spieler gesagte Nachricht ein.' + remove: '§6remove <ID>: §eEntferne eine Nachricht.' + setTime: '§6setTime <id> <time>: §eSetze die Zeit (in Ticks) bevor die nächste automatische Nachricht gesendet wird.' + skippable: '§6Überspringbar [true|falsch]: §eLegen Sie fest, ob der Dialog übersprungen werden kann oder nicht' + messageRemoved: '§aNachricht "§7{msg}§a" entfernt.' + noSender: '§aNachricht "§7{msg}§a" ohne einen Absender hinzugefügt.' + npc: '§aNachricht "§7{msg}§a" für den NPC hinzugefügt.' + npcName: + set: '§aBenutzerdefinierter NPC-Name wurde zu §7{new_name}§a gesetzt (alter Name war §7{old_name}§a)' + unset: '§aBenutzerdefinierter NPC-Name wurde auf Standard gesetzt (alter Name war §7{old_name}§a)' + player: '§aNachricht "§7{msg}§a" für den Spieler hinzugefügt.' + skippable: + set: '§aDer dialogbare Status ist nun auf §7{new_state}§a gesetzt (war §7{old_state}§a)' + unset: '§aDer überspringbare Status wird auf Standard zurückgesetzt (war §7{old_state}§a)' + soundAdded: '§aTon "§7{sound}§a" für die Nachricht "§7{msg}§a" hinzugefügt.' + syntaxRemove: '§cKorrekte Syntax: remove <ID>' + timeRemoved: '§aDie Zeit wurde für die Nachricht {msg} entfernt.' + timeSet: '§aDie Zeit für die Nachricht {msg} wurde bearbeitet: jetzt {time} Ticks.' + enter: + list: '§c⚠ §7Du befindest dich in einem "Listen"-Editor. Verwende "add", um Zeilen hinzuzufügen. Siehe "help" (ohne Schrägstrich) für Hilfe. §e§lTippe "close", um den Editor zu verlassen.' + subtitle: '§6Schreibe „/quests exitEditor”, um das Verlassen zu erzwingen.' + title: '§6~ Editor‐Modus ~' + firework: + edited: Feuerwerk Quest bearbeitet! + invalid: Dieser Gegenstand ist kein gültiges Feuerwerk. + invalidHand: Du musst ein Feuerwerk in deiner Main Hand halten. + removed: Das Questfeuerwerk entfernt! + goToLocation: '§aGehe zur gewünschten Position für den Schritt.' + invalidColor: Die eingegebene Farbe ist ungültig. Sie muss entweder Hexadezimal- oder RGB sein. + invalidPattern: '§cUngültiges regex-Muster §4{input}§c.' + itemCreator: + invalidBlockType: '§cUngültiger Blocktyp.' + invalidItemType: '§cUngültiges Item. (Das Item darf kein Block sein.)' + itemAmount: '§aSchreibe die Menge des/der Item(s):' + itemLore: '§aÄndere die Item‐Beschreibung: (Schreibe „help“ für Hilfe.)' + itemName: '§aSchreibe den Item‐Namen:' + itemType: '§aSchreibe den Namen des gewünschten Items:' + unknownBlockType: '§cUnbekannter Blocktyp.' + unknownItemType: '§cUnbekanntes Item.' + mythicmobs: + disabled: '§cMythicMob ist deaktiviert.' + isntMythicMob: '§cDieser Mythic Mob existiert nicht.' + list: '§aEine Liste aller Mythic Mobs:' + noSuchElement: '§cDieses Element existiert nicht. Erlaubte Elemente sind: §e{available_elements}' + npc: + choseStarter: '§aWähle den NPC, der die Quest startet.' + enter: '§aKlicke auf einen NPC oder schreibe „cancel”.' + notStarter: '§cDieser NPC ist kein Queststarter.' + pool: + hologramText: Schreibe den benutzerdefinierten Hologramm-Text für diese Gruppe (oder "null", wenn du den Standardtext möchtest). + maxQuests: Lege die maximale Anzahl an Quests fest, die aus dieser Gruppe gestartet werden können. + questsPerLaunch: Schreibe die Anzahl der Quests, die du bei einem Klick auf den NPC erhalten hast. + timeMsg: 'Schreibe die Zeit, bevor Spieler eine neue Quest annehmen können (Standardeinheit: Tage).' + scoreboardObjectiveNotFound: '§cUnbekanntes Scoreboard Ziel.' + selectWantedBlock: '§aKlicke mit dem Stock auf den gewünschten Block für diesen Schritt.' + stage: + location: + typeWorldPattern: '§aSchreibe einen Regex für Weltnamen:' + text: + argNotSupported: '§cDas Argument {arg} wird nicht unterstützt.' + chooseJobRequired: '§aSchreibe den Namen des gewünschten Jobs:' + chooseLvlRequired: '§aSchreibe die Anzahl der benötigten Level:' + chooseMoneyRequired: '§aSchreibe die Menge an benötigtem Geld:' + chooseObjectiveRequired: '§aGebe den Namen des Ziels an.' + chooseObjectiveTargetScore: '§aGebe den benötigten Punktestand für das Ziel an.' + choosePermissionMessage: '§aDu kannst eine Verweigerungs‐Nachricht für Spieler ohne ausreichende Berechtigungen festlegen. (Um diesen Schritt zu überspringen, schreibe „null”.)' + choosePermissionRequired: '§aSchreibe die benötigte Berechtigung, um die Quest zu starten:' + choosePlaceholderRequired: + identifier: '§aSchreibe den Namen des benötigten Platzhalters ohne die Prozentzeichen:' + value: '§aSchreibe den erforderlichen Wert für den Platzhalter §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aSchreibe den Namen der benötigten Region (du musst in der gleichen Welt sein).' + chooseSkillRequired: '§aSchreibe den Namen der benötigten Fähigkeit:' + reward: + money: '§aSchreibe die zu bekommende Menge an Geld:' + permissionName: '§aGebe den Namen der Berechtigung ein.' + permissionWorld: '§aGebe die Welt an, in welcher die Berechtigung bearbeitet werden soll, oder "null" wenn es Global gelten soll.' + random: + max: '§aSchreibe die maximale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' + min: '§aSchreibe die minimale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' + wait: '§aSchreibe die Anzahl von Game Ticks, zum warten: (1 Sekunde = 20 Game Ticks)' + textList: + added: '§aText "§7{msg}§a" hinzugefügt.' + help: + add: '§6add <message>: §eFüge einen Text hinzu.' + close: '§6close: §eBestätige die hinzugefügten Texte.' + header: '§6§lBeautyQuests — Listen‐Editor‐Hilfe' + list: '§6list: §eSieh dir alle hinzugefügten Texte an.' + remove: '§6remove <ID>: §eEntferne einen Text.' + removed: '§aText "§7{msg}§a" entfernt.' + syntax: '§cKorrekte Syntax: ' + title: + fadeIn: Schreibe die "Einblende"-Dauer, in Ticks (20 ticks = 1 Sekunde). + fadeOut: Schreibe die "Ausblende"-Dauer, in Ticks (20 ticks = 1 Sekunde). + stay: Schreibe die "Bleibe"-Dauer, in Ticks (20 Ticks = 1 Sekunde). + subtitle: Schreibe den Untertiteltext (oder "null", wenn du keinen möchtest). + title: Schreibe den Titeltext (oder "null", wenn du keinen möchtest). + typeBucketAmount: '§aSchreibe die Anzahl an zu füllenden Eimern:' + typeDamageAmount: 'Schreibe die Menge an Schaden, die der Spieler zufügen muss:' + typeGameTicks: '§aSchreibe die benötigten Spiel-Ticks:' + typeLocationRadius: '§aSchreibe die benötigte Distanz von der Position:' + errorOccurred: '§cEin Fehler ist aufgetreten; kontaktiere einen Administrator! §4§lFehlercode: {error}' + experience: + edited: '§aDu hast die Erfahrungsgewinnung von {old_xp_amount} auf {xp_amount} Punkt(e) gesetzt.' + indexOutOfBounds: '§cDie Zahl {index} ist außerhalb der Grenze! Sie muss zwischen {min} und {max} liegen.' + invalidBlockData: '§cDie Blockdaten {block_data} sind ungültig oder inkompatibel mit dem Block {block_material}.' + invalidBlockTag: '§cNicht verfügbarer Blocktag {block_tag}.' + inventoryFull: '§cDein Inventar ist voll, das Item wurde auf den Boden gelegt.' + moveToTeleportPoint: '§aGehe zur gewünschten Teleportationsposition.' + npcDoesntExist: '§cDer NPC mit der ID {npc_id} existiert nicht.' + number: + invalid: '§c{input} ist keine gültige Zahl.' + negative: '§cDu musst eine positive Zahl eingeben!' + notInBounds: '§cDeine Zahl muss zwischen {min} und {max} liegen.' + zero: '§cDie Zahl darf nicht 0 sein!' + pools: + allCompleted: '§7Du hast alle Quests abgeschlossen!' + maxQuests: '§cDu kannst nicht mehr als {pool_max_quests} Quest(s) gleichzeitig haben...' + noAvailable: '§7Es ist keine Quest mehr verfügbar...' + noTime: '§cDu musst warten, bevor du eine andere Quest absolvieren kannst.' + quest: + alreadyStarted: '§cDu hast die Quest bereits gestartet!' + cancelling: '§cErstellung der Quest abgebrochen.' + createCancelled: '§cDie Erstellung oder Bearbeitung wurde von einem anderen Plugin abgebrochen!' + created: '§aGlückwunsch! Du hast die Quest §e{quest}§a mit {quest_branches} Zweig(en) erstellt!' + editCancelling: '§cBearbeitung der Quest abgebrochen.' + edited: '§aGlückwunsch! Du hast die Quest §e{quest}§a bearbeitet, die jetzt {quest_branches} Zweig(e) enthält!' + finished: + base: '§aGlückwunsch! Du hast die Quest §e{quest_name}§a abgeschlossen!' + obtain: '§aDu erhälst {rewards}!' + invalidID: '§cDie Quest mit der ID {quest_id} existiert nicht.' + invalidPoolID: '§cDie Gruppe {pool_id} existiert nicht.' + notStarted: '§cDu machst diese Quest momentan nicht.' + started: '§aDu hast die Quest §r§e{quest_name}§o§6 gestartet!' + questItem: + craft: '§cDu kannst keinen Questgegenstand zum Craften verwenden!' + drop: '§cDu kannst einen Questgegenstand nicht fallen lassen!' + eat: Du kannst Quest Items nicht Essen! + quests: + checkpoint: '§7Quest-Checkpoint erreicht!' + failed: '§cDu hast die Quest {quest_name} fehlgeschlagen...' + maxLaunched: '§cDu kannst nicht mehr als {quests_max_amount} Quest(s) gleichzeitig haben...' + updated: '§7Quest §e{quest_name}§7 aktualisiert.' + regionDoesntExists: '§cDie Region existiert nicht. (Du musst dich in der selben Welt befinden.)' + requirements: + combatLevel: '§cDein Kampflevel muss {long_level} sein!' + job: '§cDein Level für den Job §e{job_name}§c muss {long_level} sein!' + level: '§cDein Level muss {long_level} sein!' + money: '§cDu benötigst {money}!' + quest: '§cDu musst die Quest §e{quest_name}§c abgeschlossen haben!' + skill: '§cDein Level für die Fertigkeit §e{skill_name}§c muss {long_level} sein!' + waitTime: '§cDu musst {time_left} warten, bevor du die Quest erneut starten kannst!' + restartServer: '§7Starte deinen Server neu, um die Änderungen zu sehen.' + selectNPCToKill: '§aWähle den zu tötenden NPC.' + stageMobs: + listMobs: '§aDu musst {mobs} töten.' + typeCancel: '§aSchreibe „cancel“, um zum letzten Text zurückzukehren.' + versionRequired: 'Benötigte Version: §l{version}' + writeChatMessage: '§aSchreibe die benötigte Nachricht: (Füge „{SLASH}” zum Anfang hinzu, wenn du einen Befehl ausdrücken möchtest.)' + writeCommand: '§aSchreibe den gewünschten Befehl: (Den Befehl ohne den Schrägstrich schreiben. Unterstützter Platzhalter: „{PLAYER}“; welcher mit dem Namen des Spielers, der den Befehl ausgeführt hat, ersetzt wird.)' + writeCommandDelay: '§aGebe die gewünschte Befehl Verzögerung in Ticks an.' + writeConfirmMessage: '§aSchreibe die Bestätigungsnachricht, die beim Startversuch der Quest dem Spieler gezeigt wird: (Schreibe „null“, wenn die Standard‐Nachricht verwendet werden soll.)' + writeDescriptionText: '§aSchreibe einen Text, der das Ziel des Schrittes beschreibt:' + writeEndMsg: '§aSchreibe die Nachricht, die am Ende der Quest gesendet wird, "null", wenn du die Standardnachricht wünschst, oder "none", wenn du dir keine Nachricht wünschst. Du kannst "{rewards}" verwenden, das dann durch die erhaltenen Belohnungen ersetzt wird.' + writeEndSound: '§aSchreibe den Tonnamen, der am Ende der Quest dem Spieler abgespielt wird, "null" wenn Sie die Standardeinstellung oder "keine" wollen, wenn Sie keine wollen:' + writeHologramText: '§aSchreibe den Text des Hologramms: (Schreibe „none”, wenn du kein Hologramm haben möchtest und „null”, wenn du den Standard‐Text verwenden willst.)' + writeMessage: '§aSchreibe die Nachricht die an den Spieler gesendet wird' + writeMobAmount: '§aSchreibe die zu tötende Mob‐Menge:' + writeMobName: '§aSchreibe den benutzerdefinierten Namen des zu tötenden Mobs:' + writeNPCText: '§aSchreibe den Dialog, den der NPC mit dem Spieler führt: (Schreibe „help”, um Hilfe zu erhalten.)' + writeNpcName: '§aSchreibe den Namen des NPCs:' + writeNpcSkinName: '§aSchreibe den Namen des NPC‐Skins:' + writeQuestDescription: '§aGebe die Beschreibung der Quest ein, welche in der Quest-GUI des Spielers angezeigt werden soll.' + writeQuestMaterial: '§aSchreibe das Material des Questgegenstandes.' + writeQuestName: '§a Schreibe den Namen der Quest:' + writeQuestTimer: '§aSchreibe die benötigte Zeit (in Minuten), bevor ein Spieler die Quest erneut starten kann: (Schreibe „null“, wenn der Standard‐Timer verwendet werden soll.)' + writeRegionName: '§aSchreibe den für den Schritt benötigten Namen der Region:' + writeStageText: '§aSchreibe den am Anfang des Schrittes zum Spieler gesendete Text:' + writeStartMessage: '§aSchreibe die Nachricht, die zu Beginn der Quest gesendet wird, "null", wenn du die Standardnachricht wünschst, oder "none", wenn du dir keine Nachricht wünschst:' + writeXPGain: '§aSchreibe die Menge an Erfahrungspunkten, die der Spieler erhalten wird: (Letzter Wert: {xp_amount})' +scoreboard: + asyncEnd: '§ex' + name: '§6§lQuests' + noLaunched: '§cKeine laufenden Quests.' + noLaunchedDescription: '§c§oLaden' + noLaunchedName: '&c&lLaden' + stage: + breed: '§eZüchte §6{mobs}' + bucket: '§eBefülle §6{buckets}' + chat: '§eSchreibe §6{text}' + craft: '§eStelle §6{items} §eher' + fish: '§eAngle §6{items}' + interact: '§eKlicke auf den Block bei §6{x}' + interactMaterial: '§eKlicke auf einen §6{block}§e Block' + items: '§eBringe Items zu §6{dialog_npc_name}§e:' + location: '§eGehe zu: §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world}' + mine: '§eBaue {blocks} ab' + mobs: '§eTöte §6{mobs}' + npc: '§eSprich mit dem NPC §6{dialog_npc_name}' + placeBlocks: '§ePlatziere {blocks}' + region: '§eFinde Region §6{region_id}' + tame: '§eZähme §6{mobs}' + textBetwteenBranch: '§e oder' diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 1f31217a..53701a95 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -1,877 +1,915 @@ -msg: - quest: - finished: - base: §aCongratulations! You have finished the quest §e{quest_name}§a! - obtain: §aYou obtain {rewards}! - started: §aYou have started the quest §r§e{quest_name}§o§6! - created: §aCongratulations! You have created the quest §e{quest}§a which includes - {quest_branches} branch(es)! - edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes - {quest_branches} branch(es)! - createCancelled: §cThe creation or edition has been cancelled by another plugin! - cancelling: §cProcess of quest creation cancelled. - editCancelling: §cProcess of quest edition cancelled. - invalidID: §cThe quest with the id {quest_id} doesn't exist. - invalidPoolID: §cThe pool {pool_id} does not exist. - alreadyStarted: §cYou have already started the quest! - notStarted: §cYou are not currently doing this quest. - quests: - maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same time... - updated: §7Quest §e{quest_name}§7 updated. - checkpoint: §7Quest checkpoint reached! - failed: §cYou have failed the quest {quest_name}... - pools: - noTime: §cYou must wait {time_left} before doing another quest. - allCompleted: §7You have completed all the quests! - noAvailable: §7There is no more quest available... - maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same time... - questItem: - drop: §cYou can't drop a quest item! - craft: §cYou can't use a quest item to craft! - eat: §cYou cannot eat a quest item! - stageMobs: - listMobs: §aYou must kill {mobs}. - writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write - "help" to receive help.)' - writeRegionName: '§aWrite the name of the region required for the step:' - writeXPGain: '§aWrite the amount of experience points the player will obtain: (Last - value: {xp_amount})' - writeMobAmount: '§aWrite the amount of mobs to kill:' - writeMobName: '§aWrite the custom name of the mob to kill:' - writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if - you want a command.)' - writeMessage: '§aWrite the message that will be sent to the player' - writeStartMessage: '§aWrite the message that will be sent at the beginning of the quest, - "null" if you want the default one or "none" if you want none:' - writeEndMsg: '§aWrite the message that will be sent at the end of the quest, - "null" if you want the default one or "none" if you want none. You can use "{0}" which - will be replaced with the rewards obtained.' - writeEndSound: '§aWrite the sound name that will be played to the player at the end of - the quest, "null" if you want the default one or "none" if you want none:' - writeDescriptionText: '§aWrite the text which describes the goal of the stage:' - writeStageText: '§aWrite the text that will be sent to the player at the beginning - of the step:' - moveToTeleportPoint: §aGo to the wanted teleport location. - writeNpcName: '§aWrite the name of the NPC:' - writeNpcSkinName: '§aWrite the name of the skin of the NPC:' - writeQuestName: '§aWrite the name of your quest:' - writeCommand: '§aWrite the wanted command: (The command is without the "/" and the - placeholder "{PLAYER}" is supported. It will be replaced with the name of the - executor.)' - writeHologramText: '§aWrite text of the hologram: (Write "none" if you don''t want - a hologram and "null" if you want the default text.)' - writeQuestTimer: '§aWrite the required time (in minutes) before you can restart - the quest: (Write "null" if you want the default timer.)' - writeConfirmMessage: '§aWrite the confirmation message shown when a player is about - to start the quest: (Write "null" if you want the default message.)' - writeQuestDescription: '§aWrite the description of the quest, shown in the player''s quest GUI.' - writeQuestMaterial: '§aWrite the material of the quest item.' - requirements: - quest: §cYou must have finished the quest §e{quest_name}§c! - level: §cYour level must be {long_level}! - job: §cYour level for the job §e{job_name}§c must be {long_level}! - skill: §cYour level for the skill §e{skill_name}§c must be {long_level}! - combatLevel: §cYour combat level must be {long_level}! - money: §cYou must have {money}! - waitTime: §cYou must wait {time_left} before you can restart this quest! - experience: - edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} points. - selectNPCToKill: §aSelect the NPC to kill. - regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) - npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. - number: - negative: §cYou must enter a positive number! - zero: §cYou must enter a number other than 0! - invalid: §c{input} isn't a valid number. - notInBounds: §cYour number must be between {min} and {max}. - errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: {error}' - indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} and - {max}. - invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the block {block_material}. - invalidBlockTag: §cUnavailable block tag {block_tag}. - bringBackObjects: Bring me back {items}. - inventoryFull: §cYour inventory is full, the item has been dropped on the floor. - versionRequired: 'Version required: §l{version}' - restartServer: '§7Restart your server to see the modifications.' - dialogs: - skipped: '§8§o Dialog skipped.' - tooFar: '§7§oYou are too far away from {npc_name}...' - command: - downloadTranslations: - syntax: '§cYou must specify a language to download. Example: "/quests downloadTranslations en_US".' - notFound: '§cLanguage {lang} not found for version {version}.' - exists: '§cThe file {file_name} already exists. Append "-overwrite" to your command to overwrite it. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§aLanguage {lang} has been downloaded! §7You must now edit the - file "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 with {lang}, then restart the server.' - checkpoint: - noCheckpoint: §cNo checkpoint found for the quest {quest}. - questNotStarted: §cYou are not doing this quest. - setStage: - branchDoesntExist: §cThe branch with the id {branch_id} doesn't exist. - doesntExist: §cThe stage with the id {stage_id} doesn't exist. - next: §aThe stage has been skipped. - nextUnavailable: §cThe "skip" option is not available when the player is at - the end of a branch. - set: §aStage {stage_id} launched. - startDialog: - impossible: §cImpossible to start the dialog now. - noDialog: §cThe player has no pending dialog. - alreadyIn: §cThe player is already playing a dialog. - success: §aStarted dialog for player {player} in quest {quest}! - invalidCommand: - simple: §cThis command doesn't exist, write §ehelp§c. - itemChanged: §aThe item has been edited. The changes will affect after a restart. - itemRemoved: §aThe hologram item has been removed. - removed: §aThe quest {quest_name} has successfully been removed. - leaveAll: '§aYou have forced the end of {success} quest(s). Errors: {errors}' - resetPlayer: - player: §6All informations of your {quest_amount} quest(s) has/have been deleted by {deleter_name}. - remover: §6{quest_amount} quest information(s) (and {quest_pool} pools) of {player} has/have been deleted. - resetPlayerQuest: - player: §6All informations about the quest {quest} have been deleted by {deleter_name}. - remover: §6{player} informations of quest {quest} has/have been deleted. - resetQuest: §6Removed datas of the quest for {player_amount} players. - startQuest: '§6You have forced starting of quest {quest} for {player}.' - startQuestNoRequirements: '§cThe player does not meet the requirements for the quest {quest}... - Append "-overrideRequirements" at the end of your command to bypass the requirements check.' - cancelQuest: §6You have cancelled the quest {quest}. - cancelQuestUnavailable: §cThe quest {quest} can't be cancelled. - backupCreated: §6You have successfully created backups of all quests and player - informations. - backupPlayersFailed: §cCreating a backup for all the player informations has failed. - backupQuestsFailed: §cCreating a backup for all the quests has failed. - adminModeEntered: §aYou have entered the Admin Mode. - adminModeLeft: §aYou have left the Admin Mode. - resetPlayerPool: - timer: §aYou have reset the {pool} pool timer of {player}. - full: §aYou have reset the {pool} pool datas of {player}. - startPlayerPool: - error: 'Failed to start the pool {pool} for {player}.' - success: 'Started pool {pool} to {player}. Result: {result}' - scoreboard: - lineSet: §6You have successfully edited the line {line_id}. - lineReset: §6You have successfully reset the line {line_id}. - lineRemoved: §6You have successfully removed the line {line_id}. - lineInexistant: §cThe line {line_id} doesn't exist. - resetAll: §6You have successfully reset the scoreboard of the player {player_name}. - hidden: §6The scoreboard of the player {player_name} has been hidden. - shown: §6The scoreboard of the player {player_name} has been shown. - own: - hidden: §6Your scoreboard is now hidden. - shown: §6Your scoreboard is shown again. - help: - header: §6§lBeautyQuests — Help - create: '§6/{label} create: §eCreate a quest.' - edit: '§6/{label} edit: §eEdit a quest.' - remove: '§6/{label} remove <id>: §eDelete a quest with a specified id or click on - the NPC when not defined.' - finishAll: '§6/{label} finishAll <player>: §eFinish all quests of a player.' - setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eSkip the - current stage/start the branch/set a stage for a branch.' - startDialog: '§6/{label} startDialog <player> <quest id>: §eStarts the pending dialog - for a NPC stage or the starting dialog for a quest.' - resetPlayer: '§6/{label} resetPlayer <player>: §eRemove all informations about a - player.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete informations - of a quest for a player.' - seePlayer: '§6/{label} seePlayer <player>: §eView informations about a player.' - reload: '§6/{label} reload: §eSave and reload all configurations and files. (§cdeprecated§e)' - start: '§6/{label} start <player> [id]: §eForce the starting of a quest.' - setItem: '§6/{label} setItem <talk|launch>: §eSave the hologram item.' - setFirework: '§6/{label} setFirework: §eEdit the default ending firework.' - adminMode: '§6/{label} adminMode: §eToggle the Admin Mode. (Useful for displaying - little log messages.)' - version: '§6/{label} version: §eSee the current plugin version.' - downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownloads a vanilla translation file' - save: '§6/{label} save: §eMake a manual plugin save.' - list: '§6/{label} list: §eSee the quest list. (Only for supported versions.)' - typeCancel: §aWrite "cancel" to come back to the last text. - editor: - blockAmount: '§aWrite the amount of blocks:' - blockName: '§aWrite the name of the block:' - blockData: '§aWrite the blockdata (available blockdatas: §7{available_datas}§a):' - blockTag: '§aWrite the block tag (available tags: §7{available_tags}§a):' - typeBucketAmount: '§aWrite the amount of buckets to fill:' - typeDamageAmount: 'Write the amount of damage player have to deal:' - goToLocation: §aGo to the wanted location for the stage. - typeLocationRadius: '§aWrite the required distance from the location:' - typeGameTicks: '§aWrite the required game ticks:' - already: §cYou are already in the editor. - stage: - location: - typeWorldPattern: '§aWrite a regex for world names:' - enter: - title: §6~ Editor Mode ~ - subtitle: §6Write "/quests exitEditor" to force quit the editor. - list: '§c⚠ §7You have entered a "list" editor. Use "add" to add lines. Refer to "help" (without slash) for help. §e§lType "close" to exit editor.' - chat: §6You are currently in the Editor Mode. Write "/quests exitEditor" to force - leaving the editor. (Highly not recommended, consider using commands such as - "close" or "cancel" to come back to the previous inventory.) - npc: - enter: §aClick on a NPC, or write "cancel". - choseStarter: §aChoose the NPC which starts the quest. - notStarter: §cThis NPC isn't a quest starter. - text: - argNotSupported: §cThe argument {arg} not supported. - chooseLvlRequired: '§aWrite the required amount of levels:' - chooseJobRequired: '§aWrite name of the wanted job:' - choosePermissionRequired: '§aWrite the required permission to start the quest:' - choosePermissionMessage: §aYou can choose a rejection message if the player - doesn't have the required permission. (To skip this step, write "null".) - choosePlaceholderRequired: - identifier: '§aWrite the name of the required placeholder without the percent - characters:' - value: '§aWrite the required value for the placeholder §e%§e{placeholder}§e%§a:' - chooseSkillRequired: '§aWrite the name of the required skill:' - chooseMoneyRequired: '§aWrite the amount of required money:' - reward: - permissionName: §aWrite the permission name. - permissionWorld: §aWrite the world in which the permission will be edited, - or "null" if you want to be global. - money: '§aWrite the amount of the received money:' - wait: '§aWrite the amount of game ticks to wait: (1 second = 20 game ticks)' - random: - min: '§aWrite the minimum amount of rewards given to the player (inclusive).' - max: '§aWrite the maximum amount of rewards given to the player (inclusive).' - chooseObjectiveRequired: §aWrite the objective name. - chooseObjectiveTargetScore: §aWrite the target score for the objective. - chooseRegionRequired: §aWrite the name of the required region (you must be in the same world). - chooseRequirementCustomReason: 'Write the custom reason for this requirement. If the player does - not meet the requirement but tries to start the quest anyway, this message will appear in the chat.' - chooseRequirementCustomDescription: 'Write the custom description for this requirement. It will appear - in the description of the quest in the menu.' - chooseRewardCustomDescription: 'Write the custom description for this reward. It will appear - in the description of the quest in the menu.' - selectWantedBlock: §aClick with the stick on the wanted block for the stage. - itemCreator: - itemType: '§aWrite the name of the wanted item type:' - itemAmount: '§aWrite the amount of item(s):' - itemName: '§aWrite the item name:' - itemLore: '§aModify the item lore: (Write "help" for help.)' - unknownItemType: §cUnknown item type. - invalidItemType: §cInvalid item type. (The item can't be a block.) - unknownBlockType: §cUnknown block type. - invalidBlockType: §cInvalid block type. - dialog: - syntaxMessage: '§cCorrect syntax: {command} <message>' - syntaxRemove: '§cCorrect sytax: remove <id>' - player: §aMessage "§7{msg}§a" added for the player. - npc: §aMessage "§7{msg}§a" added for the NPC. - noSender: §aMessage "§7{msg}§a" added without a sender. - messageRemoved: §aMessage "§7{msg}§a" removed. - edited: §aMessage "§7{msg}§a" edited. - soundAdded: §aSound "§7{sound}§a" added for the message "§7{msg}§a". - cleared: §aRemoved §2§l{amount}§a message(s). - help: - header: §6§lBeautyQuests — Dialog editor help - npc: '§6npc <message>: §eAdd a message said by the NPC.' - player: '§6player <message>: §eAdd a message said by the player.' - nothing: '§6noSender <message>: §eAdd a message without a sender.' - remove: '§6remove <id>: §eRemove a message.' - list: '§6list: §eView all messages.' - npcInsert: '§6npcInsert <id> <message>: §eInsert a message said by the NPC.' - playerInsert: '§6playerInsert <id> <message>: §eInsert a message said by player.' - nothingInsert: '§6nothingInsert <id> <message>: §eInsert a message without - any prefix.' - edit: '§6edit <id> <message>: §eEdit a message.' - addSound: '§6addSound <id> <sound>: §eAdd a sound to a message.' - clear: '§6clear: §eRemove all messages.' - close: '§6close: §eValidate all messages.' - setTime: '§6setTime <id> <time>: §eSet the time (in ticks) before the next msg plays automatically.' - npcName: '§6npcName [custom NPC name]: §eSet (or reset to default) custom name of the NPC in the dialog' - skippable: '§6skippable [true|false]: §eSet if the dialog can be skipped or not' - timeSet: '§aTime has been edited for message {msg}: now {time} ticks.' - timeRemoved: '§aTime has been removed for message {msg}.' - npcName: - set: '§aCustom NPC name set to §7{new_name}§a (was §7{old_name}§a)' - unset: '§aCustom NPC name reset to default (was §7{old_name}§a)' - skippable: - set: '§aThe dialog skippable status is now set to §7{new_state}§a (was §7{old_state}§a)' - unset: '§aThe dialog skippable status is reset to default (was §7{old_state}§a)' - mythicmobs: - list: '§aA list of all Mythic Mobs:' - isntMythicMob: §cThis Mythic Mob doesn't exist. - disabled: §cMythicMob is disabled. - advancedSpawnersMob: 'Write the name of the custom spawner mob to kill:' - textList: - syntax: '§cCorrect syntax: {command}' - added: §aText "§7{msg}§a" added. - removed: §aText "§7{msg}§a" removed. - help: - header: §6§lBeautyQuests — List editor help - add: '§6add <message>: §eAdd a text.' - remove: '§6remove <id>: §eRemove a text.' - list: '§6list: §eView all added texts.' - close: '§6close: §eValidate the added texts.' - availableElements: 'Available elements: §e{available_elements}' - noSuchElement: '§cThere is no such element. Allowed elements are: §e{available_elements}' - invalidPattern: '§cInvalid regex pattern §4{input}§c.' - comparisonTypeDefault: '§aChoose the comparison type you want among {available}. Default comparison is: §e§l{default}§r§a. Type §onull§r§a to use it.' - scoreboardObjectiveNotFound: '§cUnknown scoreboard objective.' - pool: - hologramText: 'Write the custom hologram text for this pool (or "null" if you want the default one).' - maxQuests: 'Write the maximum amount of quests launcheable from this pool.' - questsPerLaunch: 'Write the amount of quests given when players click on the NPC.' - timeMsg: 'Write the time before players can take a new quest. (default unit: days)' - title: - title: 'Write the title text (or "null" if you want none).' - subtitle: 'Write the subtitle text (or "null" if you want none).' - fadeIn: 'Write the "fade-in" duration, in ticks (20 ticks = 1 second).' - stay: 'Write the "stay" duration, in ticks (20 ticks = 1 second).' - fadeOut: 'Write the "fade-out" duration, in ticks (20 ticks = 1 second).' - colorNamed: 'Enter the name of a color.' - color: 'Enter a color in the hexadecimal format (#XXXXX) or RGB format (RED GRE BLU).' - invalidColor: 'The color you entered is invalid. It must be either hexadecimal or RGB.' - firework: - invalid: 'This item is not a valid firework.' - invalidHand: 'You must hold a firework in your main hand.' - edited: 'Edited the quest firework!' - removed: 'Removed the quest firework!' - writeCommandDelay: '§aWrite the desired command delay, in ticks.' -advancement: - finished: Finished - notStarted: Not started -inv: - validate: §b§lValidate - cancel: §c§lCancel - search: §e§lSearch - addObject: §aAdd an object - confirm: - name: Are you sure? - 'yes': §aConfirm - 'no': §cCancel - create: - stageCreate: §aCreate new step - stageRemove: §cDelete this step - stageUp: Move up - stageDown: Move down - stageType: '§7Stage type: §e{stage_type}' - cantFinish: §7You must create at least one stage before finishing quest creation! - findNPC: §aFind NPC - bringBack: §aBring back items - findRegion: §aFind region - killMobs: §aKill mobs - mineBlocks: §aBreak blocks - placeBlocks: §aPlace blocks - talkChat: §aWrite in chat - interact: §aInteract with a type of block - interactLocation: §aInteract with block at location - fish: §aCatch fishes - melt: §6Melt items - enchant: §dEnchant items - craft: §aCraft item - bucket: §aFill buckets - location: §aGo to location - playTime: §ePlay time - breedAnimals: §aBreed animals - tameAnimals: §aTame animals - death: §cDie - dealDamage: §cDeal damage to mobs - eatDrink: §aEat or drink food or potions - NPCText: §eEdit dialog - NPCSelect: §eChoose or create NPC - hideClues: Hide particles and holograms - editMobsKill: §eEdit mobs to kill - mobsKillFromAFar: Needs to be killed with projectile - editBlocksMine: §eEdit blocks to break - preventBlockPlace: Prevent players to break their own blocks - editBlocksPlace: §eEdit blocks to place - editMessageType: §eEdit message to write - cancelMessage: Cancel sending - ignoreCase: Ignore the case of the message - replacePlaceholders: Replace {PLAYER} and placeholders from PAPI - selectItems: §eEdit required items - selectItemsMessage: §eEdit asking message - selectItemsComparisons: §eSelect items comparisons (ADVANCED) - selectRegion: §7Choose region - toggleRegionExit: On exit - stageStartMsg: §eEdit starting message - selectBlockLocation: §eSelect block location - selectBlockMaterial: §eSelect block material - leftClick: Click must be left-click - editFishes: §eEdit fishes to catch - editItemsToMelt: §eEdit items to melt - editItemsToEnchant: §eEdit items to enchant - editItem: §eEdit item to craft - editBucketType: §eEdit type of bucket to fill - editBucketAmount: §eEdit amount of buckets to fill - editLocation: §eEdit location - editRadius: §eEdit distance from location - currentRadius: '§eCurrent distance: §6{radius}' - changeTicksRequired: '§eChange played ticks required' - changeEntityType: '§eChange entity type' - stage: - location: - worldPattern: '§aSet world name pattern §d(ADVANCED)' - worldPatternLore: 'If you want the stage to be completed for any world matching a specific pattern, enter a regex (regular expression) here.' - death: - causes: '§aSet death causes §d(ADVANCED)' - anyCause: Any death cause - setCauses: '{causes_amount} death cause(s)' - dealDamage: - damage: '§eDamage to deal' - targetMobs: '§cMobs to damage' - eatDrink: - items: '§eEdit items to eat or drink' - stages: - name: Create stages - nextPage: §eNext page - laterPage: §ePrevious page - endingItem: §eEdit end rewards - descriptionTextItem: §eEdit description - regularPage: §aRegular stages - branchesPage: §dBranch stages - previousBranch: §eBack to previous branch - newBranch: §eGo to new branch - validationRequirements: §eValidation requirements - validationRequirementsLore: All the requirements must match the player that tries to complete the stage. If not, the stage can not be completed. - details: - hologramLaunch: §eEdit "launch" hologram item - hologramLaunchLore: Hologram displayed above Starter NPC's head when the player can start the quest. - hologramLaunchNo: §eEdit "launch unavailable" hologram item - hologramLaunchNoLore: Hologram displayed above Starter NPC's head when the player can NOT start the quest. - customConfirmMessage: §eEdit quest confirmation message - customConfirmMessageLore: Message displayed in the Confirmation GUI when a player is about to start the quest. - customDescription: §eEdit quest description - customDescriptionLore: Description shown below the name of the quest in GUIs. - name: Last quest details - multipleTime: - itemName: Toggle repeatable - itemLore: Can the quest be done several times? - cancellable: Cancellable by player - cancellableLore: Allows the player to cancel the quest through its Quests Menu. - startableFromGUI: Startable from GUI - startableFromGUILore: Allows the player to start the quest from the Quests Menu. - scoreboardItem: Enable scoreboard - scoreboardItemLore: If disabled, the quest will not be tracked through the scoreboard. - hideNoRequirementsItem: Hide when requirements not met - hideNoRequirementsItemLore: If enabled, the quest will not be displayed in the Quests Menu when the requirements are not met. - bypassLimit: Don't count quest limit - bypassLimitLore: If enabled, the quest will be startable even if the player has reached its maximum amount of started quests. - auto: Start automatically on first join - autoLore: If enabled, the quest will be started automatically when the player joins the server for the first time. - questName: §a§lEdit quest name - questNameLore: A name must be set to complete quest creation. - setItemsRewards: §eEdit reward items - removeItemsReward: §eRemove items from inventory - setXPRewards: §eEdit reward experience - setCheckpointReward: §eEdit checkpoint rewards - setRewardStopQuest: §cStop the quest - setRewardsWithRequirements: §eRewards with requirements - setRewardsRandom: §dRandom rewards - setPermReward: §eEdit permissions - setMoneyReward: §eEdit money reward - setWaitReward: '§eEdit "wait" reward' - setTitleReward: '§eEdit title reward' - selectStarterNPC: §e§lSelect NPC starter - selectStarterNPCLore: Clicking on the selected NPC will start the quest. - selectStarterNPCPool: §c⚠ A quest pool is selected - createQuestName: §lCreate quest - createQuestLore: You must define a quest name. - editQuestName: §lEdit quest - endMessage: §eEdit end message - endMessageLore: Message which will be sent to the player at the end of the quest. - endSound: §eEdit end sound - endSoundLore: Sound which will be played at the end of the quest. - startMessage: §eEdit start message - startMessageLore: Message which will be sent to the player at the beginning of the quest. - startDialog: §eEdit start dialog - startDialogLore: Dialog which will be played before the quests start when players click on the Starter NPC. - editRequirements: §eEdit requirements - editRequirementsLore: Every requirements must apply to the player before it can start the quest. - startRewards: §6Start rewards - startRewardsLore: Actions performed when the quest starts. - cancelRewards: §cCancel actions - cancelRewardsLore: Actions performed when players cancel this quest. - hologramText: §eHologram text - hologramTextLore: Text displayed on the hologram above the Starter NPC's head. - timer: §bRestart timer - timerLore: Time before the player can start the quest again. - requirements: '{amount} requirement(s)' - rewards: '{amount} reward(s)' - actions: '{amount} action(s)' - rewardsLore: Actions performed when the quest ends. - customMaterial: '§eEdit quest item material' - customMaterialLore: Item representative of this quest in the Quests Menu. - failOnDeath: Fail on death - failOnDeathLore: Will the quest be cancelled when the player dies? - questPool: §eQuest Pool - questPoolLore: Attach this quest to a quest pool - firework: §dEnding Firework - fireworkLore: Firework launched when the player finishes the quest - fireworkLoreDrop: Drop your custom firework here - visibility: §bQuest visibility - visibilityLore: Choose in which tabs of the menu will the quest be shown, and if - the quest is visible on dynamic maps. - keepDatas: Preserve players datas - keepDatasLore: |- - Force the plugin to preserve players datas, even though stages have been edited. - §c§lWARNING §c- enabling this option may break your players datas. - loreReset: '§e§lAll players'' advancement will be reset' - optionValue: '§8Value: §7{value}' - defaultValue: '§8(default value)' - requiredParameter: '§7Required parameter' - itemsSelect: - name: Edit items - none: |- - §aMove an item to here or - click to open the item editor. - itemSelect: - name: Choose item - npcCreate: - name: Create NPC - setName: §eEdit NPC name - setSkin: §eEdit NPC skin - setType: §eEdit NPC type - move: - itemName: §eMove - itemLore: §aChange the NPC location. - moveItem: §a§lValidate place - npcSelect: - name: Select or create? - selectStageNPC: §eSelect existing NPC - createStageNPC: §eCreate NPC - entityType: - name: Choose entity type - chooseQuest: - name: Which quest? - menu: §aQuests Menu - menuLore: Gets you to your Quests Menu. - mobs: - name: Select mobs - none: §aClick to add a mob. - editAmount: Edit amount - editMobName: Edit mob name - setLevel: Set minimum level - mobSelect: - name: Select mob type - bukkitEntityType: §eSelect entity type - mythicMob: §6Select Mythic Mob - epicBoss: §6Select Epic Boss - boss: §6Select a Boss - advancedSpawners: §6Select an AdvancedSpawners mob - stageEnding: - locationTeleport: §eEdit teleport location - command: §eEdit executed command - requirements: - name: Requirements - setReason: Set custom reason - reason: '§8Custom reason: §7{reason}' - rewards: - name: Rewards - commands: 'Commands: {amount}' - random: - rewards: Edit rewards - minMax: Edit min and max - checkpointActions: - name: Checkpoint actions - cancelActions: - name: Cancel actions - rewardsWithRequirements: - name: Rewards with requirements - listAllQuests: - name: Quests - listPlayerQuests: - name: '{player_name}''s quests' - listQuests: - notStarted: Not started quests - finished: Finished quests - inProgress: Quests in progress - loreDialogsHistoryClick: §7View the dialogs - loreCancelClick: §cCancel the quest - loreStart: §a§oClick to start the quest. - loreStartUnavailable: §c§oYou do not meet requirements to start the quest. - timeToWaitRedo: §7§oYou can restart this quest in {time_left}... - canRedo: §e§oYou can restart this quest! - timesFinished: §eCompleted §6{times_finished} x§e. - format: - normal: §6§l§o{quest_name} - withId: §6§l§o{quest_name}§r §e#{quest_id} - itemCreator: - name: Item creator - itemType: §bItem type - itemFlags: Toggle item flags - itemName: §bItem name - itemLore: §bItem lore - isQuestItem: '§bQuest item:' - command: - name: Command - value: §eCommand - console: Console - parse: Parse placeholders - delay: §bDelay - chooseAccount: - name: What account? - listBook: - questName: Name - questStarter: Starter - questRewards: Rewards - questMultiple: Several times - requirements: Requirements - questStages: Stages - noQuests: No quests have previously been created. - commandsList: - name: Command list - value: '§eCommand: {command_label}' - console: '§eConsole: {command_console}' - block: - name: Choose block - material: '§eMaterial: {block_type}' - materialNotItemLore: 'The block chosen cannot be displayed as an item. It is still correctly stored as {block_material}.' - blockName: '§bCustom block name' - blockData: '§dBlockdata (advanced)' - blockTag: '§dTag (advanced)' - blockTagLore: 'Choose a tag which describes a list of possible blocks. - Tags can be customized using datapacks. - You can find list of tags on the Minecraft wiki.' - blocksList: - name: Select blocks - addBlock: §aClick to add a block. - blockAction: - name: Select block action - location: §eSelect a precise location - material: §eSelect a block material - buckets: - name: Bucket type - permission: - name: Choose permission - perm: §aPermission - world: §aWorld - worldGlobal: §b§lGlobal - remove: Remove permission - removeLore: §7Permission will be taken off\n§7instead of given. - permissionList: - name: Permissions list - removed: '§eTaken off: §6{permission_removed}' - world: '§eWorld: §6{permission_world}' - classesRequired.name: Classes required - classesList.name: Classes list - factionsRequired.name: Factions required - factionsList.name: Factions list - poolsManage: - name: Quest Pools - itemName: '§aPool {pool}' - poolNPC: '§8NPC: §7{pool_npc_id}' - poolMaxQuests: '§8Max quests: §7{pool_max_quests}' - poolQuestsPerLaunch: '§8Quests given per launch: §7{pool_quests_per_launch}' - poolRedo: '§8Can redo completed quests: §7{pool_redo}' - poolTime: '§8Time between quests: §7{pool_time}' - poolHologram: '§8Hologram text: §7{pool_hologram}' - poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' - poolQuestsList: '§7{pool_quests_amount} §8quest(s): §7{pool_quests}' - create: §aCreate a quest pool - edit: §e> §6§oEdit the pool... §e< - choose: §e> §6§oChoose this pool §e< - poolCreation: - name: Quest pool creation - hologramText: §ePool custom hologram - maxQuests: §aMax quests - questsPerLaunch: §aQuests started per launch - time: §bSet time between quests - redoAllowed: Is redo allowed - avoidDuplicates: Avoid duplicates - avoidDuplicatesLore: §8> §7Try to avoid doing\n the same quest over and over - requirements: §bRequirements to start a quest - poolsList.name: Quest pools - itemComparisons: - name: Item Comparisons - bukkit: Bukkit native comparison - bukkitLore: 'Uses Bukkit default item comparison system.\nCompares material, durability, nbt tags...' - customBukkit: Bukkit native comparison - NO NBT - customBukkitLore: 'Uses Bukkit default item comparison system, but wipes out NBT tags.\nCompares material, durability...' - material: Item material - materialLore: 'Compares item material (i. e. stone, iron sword...)' - itemName: Item name - itemNameLore: Compares items names - itemLore: Item lore - itemLoreLore: Compares items lores - enchants: Items enchants - enchantsLore: Compares items enchants - repairCost: Repair cost - repairCostLore: Compares repair cost for armors and swords - itemsAdder: ItemsAdder - itemsAdderLore: Compares ItemsAdder IDs - mmoItems: MMOItems item - mmoItemsLore: Compares MMOItems types and IDs - editTitle: - name: Edit Title - title: §6Title - subtitle: §eSubtitle - fadeIn: §aFade-in duration - stay: §bStay duration - fadeOut: §aFade-out duration - particleEffect: - name: Create particle effect - shape: §dParticle shape - type: §eParticle type - color: §bParticle color - particleList: - name: Particles list - colored: Colored particle - damageCause: - name: Damage cause - damageCausesList: - name: Damage causes list - visibility: - name: Quest visibility - notStarted: '"Not started" menu tab' - inProgress: '"In progress" menu tab' - finished: '"Finished" menu tab' - maps: 'Maps (such as dynmap or BlueMap)' - equipmentSlots: - name: Equipment slots - questObjects: - setCustomDescription: 'Set custom description' - description: '§8Description: §7{description}' - -scoreboard: - name: §6§lQuests - noLaunched: §cNo quests in progress. - noLaunchedName: §c§lLoading - noLaunchedDescription: §c§oLoading - textBetwteenBranch: §e or - asyncEnd: §ex - stage: - region: §eFind region §6{region_id} - npc: §eTalk with NPC §6{dialog_npc_name} - items: '§eBring items to §6{dialog_npc_name}§e: {items}' - mobs: §eKill §6{mobs} - mine: §eMine {blocks} - placeBlocks: §ePlace {blocks} - chat: §eWrite §6{text} - interact: §eClick on the block at §6{x} {y} {z} - interactMaterial: §eClick on a §6{block}§e block - fish: §eFish §6{items} - melt: §eMelt §6{items} - enchant: §eEnchant §6{items} - craft: §eCraft §6{items} - bucket: §eFill §6{buckets} - location: §eGo to §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world} - playTimeFormatted: §ePlay §6{time_remaining_human} - breed: §eBreed §6{mobs} - tame: §eTame §6{mobs} - die: §cDie - dealDamage: - any: §cDeal {damage_remaining} damage - mobs: §cDeal {damage_remaining} damage to {target_mobs} - eatDrink: §eConsume §6{items} -indication: - startQuest: §7Do you want to start the quest {quest_name}? - closeInventory: §7Are you sure you want to close the GUI? - cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? - removeQuest: §7Are you sure you want to remove the quest {quest}? - removePool: §7Are you sure you want to remove the pool {quest}? -description: - requirement: - title: '§8§lRequirements:' - level: 'Level {short_level}' - jobLevel: 'Level {short_level} for {job_name}' - combatLevel: 'Combat level {short_level}' - skillLevel: 'Level {short_level} for {skill_name}' - class: 'Class {class_name}' - faction: 'Faction {faction_name}' - quest: 'Finish quest §e{quest_name}' - reward: - title: '§8§lRewards:' - -misc: - format: - prefix: §6<§e§lQuests§r§6> §r - npcText: §6[{message_id}/{message_count}] §e§l{npc_name_message}:§r§e {text} - selfText: §6[{message_id}/{message_count}] §e§l{player_name}:§r§e {text} - offText: §r§e{message} - editorPrefix: §a - errorPrefix: §4✖ §c - successPrefix: §2✔ §a - requirementNotMetPrefix: §c - time: - weeks: '{weeks_amount} weeks' - days: '{days_amount} days' - hours: '{hours_amount} hours' - minutes: '{minutes_amount} minutes' - lessThanAMinute: 'a few seconds' - stageType: - region: Find region - npc: Find NPC - items: Bring back items - mobs: Kill mobs - mine: Break blocks - placeBlocks: Place blocks - chat: Write in chat - interact: Interact with block - interactLocation: Interact with block at location - Fish: Catch fishes - Melt: Melt items - Enchant: Enchant items - Craft: Craft item - Bucket: Fill bucket - location: Find location - playTime: Play time - breedAnimals: Breed animals - tameAnimals: Tame animals - die: Die - dealDamage: Deal damage - eatDrink: Eat or drink - comparison: - equals: equal to {number} - different: different to {number} - less: strictly less than {number} - lessOrEquals: less than {number} - greater: strictly greater than {number} - greaterOrEquals: greater than {number} - requirement: - logicalOr: §dLogical OR (requirements) - skillAPILevel: §bSkillAPI level required - class: §bClass(es) required - faction: §bFaction(s) required - jobLevel: §bJob level required - combatLevel: §bCombat level required - experienceLevel: §bExperience levels required - permissions: §3Permission(s) required - scoreboard: §dScore required - region: §dRegion required - placeholder: §bPlaceholder value required - quest: §aQuest required - mcMMOSkillLevel: §dSkill level required - money: §dMoney required - equipment: §eEquipment required - reward: - skillApiXp: SkillAPI XP reward - bucket: - water: Water bucket - lava: Lava bucket - milk: Milk bucket - snow: Snow bucket - click: - right: Right click - left: Left click - shift-right: Shift-right click - shift-left: Shift-left click - middle: Middle click - amounts: - items: '{items_amount} item(s)' - comparisons: '{comparisons_amount} comparaison(s)' - dialogLines: '{lines_amount} line(s)' - permissions: '{permissions_amount} permission(s)' - mobs: '{mobs_amount} mob(s)' - xp: '{xp_amount} experience point(s)' - ticks: '{ticks} ticks' - location: |- - Location: {x} {y} {z} - World: {world} - questItemLore: §e§oQuest Item - hologramText: §8§lQuest NPC - poolHologramText: §eNew quest available! - entityType: '§eEntity type: {entity_type}' - entityTypeAny: §eAny entity - enabled: Enabled - disabled: Disabled - unknown: unknown - notSet: §cnot set - removeRaw: Remove - reset: Reset - or: or - amount: '§eAmount: {amount}' - 'yes': 'Yes' - 'no': 'No' - and: and +advancement: + finished: Finished + notStarted: Not started +description: + requirement: + class: Class {class_name} + combatLevel: Combat level {short_level} + faction: Faction {faction_name} + jobLevel: Level {short_level} for {job_name} + level: Level {short_level} + quest: Finish quest §e{quest_name} + skillLevel: Level {short_level} for {skill_name} + title: '§8§lRequirements:' + reward: + title: '§8§lRewards:' +indication: + cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? + closeInventory: §7Are you sure you want to close the GUI? + removePool: §7Are you sure you want to remove the pool {quest}? + removeQuest: §7Are you sure you want to remove the quest {quest}? + startQuest: §7Do you want to start the quest {quest_name}? +inv: + addObject: §aAdd an object + block: + blockData: §dBlockdata (advanced) + blockName: §bCustom block name + blockTag: §dTag (advanced) + blockTagLore: Choose a tag which describes a list of possible blocks. Tags can + be customized using datapacks. You can find list of tags on the Minecraft wiki. + material: '§eMaterial: {block_type}' + materialNotItemLore: The block chosen cannot be displayed as an item. It is still + correctly stored as {block_material}. + name: Choose block + blockAction: + location: §eSelect a precise location + material: §eSelect a block material + name: Select block action + blocksList: + addBlock: §aClick to add a block. + name: Select blocks + buckets: + name: Bucket type + cancel: §c§lCancel + cancelActions: + name: Cancel actions + checkpointActions: + name: Checkpoint actions + chooseAccount: + name: What account? + chooseQuest: + menu: §aQuests Menu + menuLore: Gets you to your Quests Menu. + name: Which quest? + classesList.name: Classes list + classesRequired.name: Classes required + command: + console: Console + delay: §bDelay + name: Command + parse: Parse placeholders + value: §eCommand + commandsList: + console: '§eConsole: {command_console}' + name: Command list + value: '§eCommand: {command_label}' + confirm: + name: Are you sure? + 'no': §cCancel + 'yes': §aConfirm + create: + NPCSelect: §eChoose or create NPC + NPCText: §eEdit dialog + breedAnimals: §aBreed animals + bringBack: §aBring back items + bucket: §aFill buckets + cancelMessage: Cancel sending + cantFinish: §7You must create at least one stage before finishing quest creation! + changeEntityType: §eChange entity type + changeTicksRequired: §eChange played ticks required + craft: §aCraft item + currentRadius: '§eCurrent distance: §6{radius}' + dealDamage: §cDeal damage to mobs + death: §cDie + eatDrink: §aEat or drink food or potions + editBlocksMine: §eEdit blocks to break + editBlocksPlace: §eEdit blocks to place + editBucketAmount: §eEdit amount of buckets to fill + editBucketType: §eEdit type of bucket to fill + editFishes: §eEdit fishes to catch + editItem: §eEdit item to craft + editItemsToEnchant: §eEdit items to enchant + editItemsToMelt: §eEdit items to melt + editLocation: §eEdit location + editMessageType: §eEdit message to write + editMobsKill: §eEdit mobs to kill + editRadius: §eEdit distance from location + enchant: §dEnchant items + findNPC: §aFind NPC + findRegion: §aFind region + fish: §aCatch fishes + hideClues: Hide particles and holograms + ignoreCase: Ignore the case of the message + interact: §aInteract with a type of block + interactLocation: §aInteract with block at location + killMobs: §aKill mobs + leftClick: Click must be left-click + location: §aGo to location + melt: §6Melt items + mineBlocks: §aBreak blocks + mobsKillFromAFar: Needs to be killed with projectile + placeBlocks: §aPlace blocks + playTime: §ePlay time + preventBlockPlace: Prevent players to break their own blocks + replacePlaceholders: Replace {PLAYER} and placeholders from PAPI + selectBlockLocation: §eSelect block location + selectBlockMaterial: §eSelect block material + selectItems: §eEdit required items + selectItemsComparisons: §eSelect items comparisons (ADVANCED) + selectItemsMessage: §eEdit asking message + selectRegion: §7Choose region + stage: + dealDamage: + damage: §eDamage to deal + targetMobs: §cMobs to damage + death: + anyCause: Any death cause + causes: §aSet death causes §d(ADVANCED) + setCauses: '{causes_amount} death cause(s)' + eatDrink: + items: §eEdit items to eat or drink + location: + worldPattern: §aSet world name pattern §d(ADVANCED) + worldPatternLore: If you want the stage to be completed for any world matching + a specific pattern, enter a regex (regular expression) here. + stageCreate: §aCreate new step + stageDown: Move down + stageRemove: §cDelete this step + stageStartMsg: §eEdit starting message + stageType: '§7Stage type: §e{stage_type}' + stageUp: Move up + talkChat: §aWrite in chat + tameAnimals: §aTame animals + toggleRegionExit: On exit + damageCause: + name: Damage cause + damageCausesList: + name: Damage causes list + details: + actions: '{amount} action(s)' + auto: Start automatically on first join + autoLore: If enabled, the quest will be started automatically when the player + joins the server for the first time. + bypassLimit: Don't count quest limit + bypassLimitLore: If enabled, the quest will be startable even if the player has + reached its maximum amount of started quests. + cancelRewards: §cCancel actions + cancelRewardsLore: Actions performed when players cancel this quest. + cancellable: Cancellable by player + cancellableLore: Allows the player to cancel the quest through its Quests Menu. + createQuestLore: You must define a quest name. + createQuestName: §lCreate quest + customConfirmMessage: §eEdit quest confirmation message + customConfirmMessageLore: Message displayed in the Confirmation GUI when a player + is about to start the quest. + customDescription: §eEdit quest description + customDescriptionLore: Description shown below the name of the quest in GUIs. + customMaterial: §eEdit quest item material + customMaterialLore: Item representative of this quest in the Quests Menu. + defaultValue: §8(default value) + editQuestName: §lEdit quest + editRequirements: §eEdit requirements + editRequirementsLore: Every requirements must apply to the player before it can + start the quest. + endMessage: §eEdit end message + endMessageLore: Message which will be sent to the player at the end of the quest. + endSound: §eEdit end sound + endSoundLore: Sound which will be played at the end of the quest. + failOnDeath: Fail on death + failOnDeathLore: Will the quest be cancelled when the player dies? + firework: §dEnding Firework + fireworkLore: Firework launched when the player finishes the quest + fireworkLoreDrop: Drop your custom firework here + hideNoRequirementsItem: Hide when requirements not met + hideNoRequirementsItemLore: If enabled, the quest will not be displayed in the + Quests Menu when the requirements are not met. + hologramLaunch: §eEdit "launch" hologram item + hologramLaunchLore: Hologram displayed above Starter NPC's head when the player + can start the quest. + hologramLaunchNo: §eEdit "launch unavailable" hologram item + hologramLaunchNoLore: Hologram displayed above Starter NPC's head when the player + can NOT start the quest. + hologramText: §eHologram text + hologramTextLore: Text displayed on the hologram above the Starter NPC's head. + keepDatas: Preserve players datas + keepDatasLore: 'Force the plugin to preserve players datas, even though stages + have been edited. + + §c§lWARNING §c- enabling this option may break your players datas.' + loreReset: §e§lAll players' advancement will be reset + multipleTime: + itemLore: Can the quest be done several times? + itemName: Toggle repeatable + name: Last quest details + optionValue: '§8Value: §7{value}' + questName: §a§lEdit quest name + questNameLore: A name must be set to complete quest creation. + questPool: §eQuest Pool + questPoolLore: Attach this quest to a quest pool + removeItemsReward: §eRemove items from inventory + requiredParameter: §7Required parameter + requirements: '{amount} requirement(s)' + rewards: '{amount} reward(s)' + rewardsLore: Actions performed when the quest ends. + scoreboardItem: Enable scoreboard + scoreboardItemLore: If disabled, the quest will not be tracked through the scoreboard. + selectStarterNPC: §e§lSelect NPC starter + selectStarterNPCLore: Clicking on the selected NPC will start the quest. + selectStarterNPCPool: §c⚠ A quest pool is selected + setCheckpointReward: §eEdit checkpoint rewards + setItemsRewards: §eEdit reward items + setMoneyReward: §eEdit money reward + setPermReward: §eEdit permissions + setRewardStopQuest: §cStop the quest + setRewardsRandom: §dRandom rewards + setRewardsWithRequirements: §eRewards with requirements + setTitleReward: §eEdit title reward + setWaitReward: §eEdit "wait" reward + setXPRewards: §eEdit reward experience + startDialog: §eEdit start dialog + startDialogLore: Dialog which will be played before the quests start when players + click on the Starter NPC. + startMessage: §eEdit start message + startMessageLore: Message which will be sent to the player at the beginning of + the quest. + startRewards: §6Start rewards + startRewardsLore: Actions performed when the quest starts. + startableFromGUI: Startable from GUI + startableFromGUILore: Allows the player to start the quest from the Quests Menu. + timer: §bRestart timer + timerLore: Time before the player can start the quest again. + visibility: §bQuest visibility + visibilityLore: Choose in which tabs of the menu will the quest be shown, and + if the quest is visible on dynamic maps. + editTitle: + fadeIn: §aFade-in duration + fadeOut: §aFade-out duration + name: Edit Title + stay: §bStay duration + subtitle: §eSubtitle + title: §6Title + entityType: + name: Choose entity type + equipmentSlots: + name: Equipment slots + factionsList.name: Factions list + factionsRequired.name: Factions required + itemComparisons: + bukkit: Bukkit native comparison + bukkitLore: Uses Bukkit default item comparison system.\nCompares material, durability, + nbt tags... + customBukkit: Bukkit native comparison - NO NBT + customBukkitLore: Uses Bukkit default item comparison system, but wipes out NBT + tags.\nCompares material, durability... + enchants: Items enchants + enchantsLore: Compares items enchants + itemLore: Item lore + itemLoreLore: Compares items lores + itemName: Item name + itemNameLore: Compares items names + itemsAdder: ItemsAdder + itemsAdderLore: Compares ItemsAdder IDs + material: Item material + materialLore: Compares item material (i. e. stone, iron sword...) + mmoItems: MMOItems item + mmoItemsLore: Compares MMOItems types and IDs + name: Item Comparisons + repairCost: Repair cost + repairCostLore: Compares repair cost for armors and swords + itemCreator: + isQuestItem: '§bQuest item:' + itemFlags: Toggle item flags + itemLore: §bItem lore + itemName: §bItem name + itemType: §bItem type + name: Item creator + itemSelect: + name: Choose item + itemsSelect: + name: Edit items + none: '§aMove an item to here or + + click to open the item editor.' + listAllQuests: + name: Quests + listBook: + noQuests: No quests have previously been created. + questMultiple: Several times + questName: Name + questRewards: Rewards + questStages: Stages + questStarter: Starter + requirements: Requirements + listPlayerQuests: + name: '{player_name}''s quests' + listQuests: + canRedo: §e§oYou can restart this quest! + finished: Finished quests + format: + normal: §6§l§o{quest_name} + withId: §6§l§o{quest_name}§r §e#{quest_id} + inProgress: Quests in progress + loreCancelClick: §cCancel the quest + loreDialogsHistoryClick: §7View the dialogs + loreStart: §a§oClick to start the quest. + loreStartUnavailable: §c§oYou do not meet requirements to start the quest. + notStarted: Not started quests + timeToWaitRedo: §7§oYou can restart this quest in {time_left}... + timesFinished: §eCompleted §6{times_finished} x§e. + mobSelect: + advancedSpawners: §6Select an AdvancedSpawners mob + boss: §6Select a Boss + bukkitEntityType: §eSelect entity type + epicBoss: §6Select Epic Boss + mythicMob: §6Select Mythic Mob + name: Select mob type + mobs: + editAmount: Edit amount + editMobName: Edit mob name + name: Select mobs + none: §aClick to add a mob. + setLevel: Set minimum level + npcCreate: + move: + itemLore: §aChange the NPC location. + itemName: §eMove + moveItem: §a§lValidate place + name: Create NPC + setName: §eEdit NPC name + setSkin: §eEdit NPC skin + setType: §eEdit NPC type + npcSelect: + createStageNPC: §eCreate NPC + name: Select or create? + selectStageNPC: §eSelect existing NPC + particleEffect: + color: §bParticle color + name: Create particle effect + shape: §dParticle shape + type: §eParticle type + particleList: + colored: Colored particle + name: Particles list + permission: + name: Choose permission + perm: §aPermission + remove: Remove permission + removeLore: §7Permission will be taken off\n§7instead of given. + world: §aWorld + worldGlobal: §b§lGlobal + permissionList: + name: Permissions list + removed: '§eTaken off: §6{permission_removed}' + world: '§eWorld: §6{permission_world}' + poolCreation: + avoidDuplicates: Avoid duplicates + avoidDuplicatesLore: §8> §7Try to avoid doing\n the same quest over and over + hologramText: §ePool custom hologram + maxQuests: §aMax quests + name: Quest pool creation + questsPerLaunch: §aQuests started per launch + redoAllowed: Is redo allowed + requirements: §bRequirements to start a quest + time: §bSet time between quests + poolsList.name: Quest pools + poolsManage: + choose: §e> §6§oChoose this pool §e< + create: §aCreate a quest pool + edit: §e> §6§oEdit the pool... §e< + itemName: §aPool {pool} + name: Quest Pools + poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' + poolHologram: '§8Hologram text: §7{pool_hologram}' + poolMaxQuests: '§8Max quests: §7{pool_max_quests}' + poolNPC: '§8NPC: §7{pool_npc_id}' + poolQuestsList: '§7{pool_quests_amount} §8quest(s): §7{pool_quests}' + poolQuestsPerLaunch: '§8Quests given per launch: §7{pool_quests_per_launch}' + poolRedo: '§8Can redo completed quests: §7{pool_redo}' + poolTime: '§8Time between quests: §7{pool_time}' + questObjects: + description: '§8Description: §7{description}' + setCustomDescription: Set custom description + requirements: + name: Requirements + reason: '§8Custom reason: §7{reason}' + setReason: Set custom reason + rewards: + commands: 'Commands: {amount}' + name: Rewards + random: + minMax: Edit min and max + rewards: Edit rewards + rewardsWithRequirements: + name: Rewards with requirements + search: §e§lSearch + stageEnding: + command: §eEdit executed command + locationTeleport: §eEdit teleport location + stages: + branchesPage: §dBranch stages + descriptionTextItem: §eEdit description + endingItem: §eEdit end rewards + laterPage: §ePrevious page + name: Create stages + newBranch: §eGo to new branch + nextPage: §eNext page + previousBranch: §eBack to previous branch + regularPage: §aRegular stages + validationRequirements: §eValidation requirements + validationRequirementsLore: All the requirements must match the player that tries + to complete the stage. If not, the stage can not be completed. + validate: §b§lValidate + visibility: + finished: '"Finished" menu tab' + inProgress: '"In progress" menu tab' + maps: Maps (such as dynmap or BlueMap) + name: Quest visibility + notStarted: '"Not started" menu tab' +misc: + amount: '§eAmount: {amount}' + amounts: + comparisons: '{comparisons_amount} comparison(s)' + dialogLines: '{lines_amount} line(s)' + items: '{items_amount} item(s)' + mobs: '{mobs_amount} mob(s)' + permissions: '{permissions_amount} permission(s)' + xp: '{xp_amount} experience point(s)' + and: and + bucket: + lava: Lava bucket + milk: Milk bucket + snow: Snow bucket + water: Water bucket + click: + left: Left click + middle: Middle click + right: Right click + shift-left: Shift-left click + shift-right: Shift-right click + comparison: + different: different to {number} + equals: equal to {number} + greater: strictly greater than {number} + greaterOrEquals: greater than {number} + less: strictly less than {number} + lessOrEquals: less than {number} + disabled: Disabled + enabled: Enabled + entityType: '§eEntity type: {entity_type}' + entityTypeAny: §eAny entity + format: + editorPrefix: §a + errorPrefix: §4✖ §c + npcText: §6[{message_id}/{message_count}] §e§l{npc_name_message}:§r§e {text} + offText: §r§e{message} + prefix: §6<§e§lQuests§r§6> §r + requirementNotMetPrefix: §c + selfText: §6[{message_id}/{message_count}] §e§l{player_name}:§r§e {text} + successPrefix: §2✔ §a + hologramText: §8§lQuest NPC + location: 'Location: {x} {y} {z} + + World: {world}' + 'no': 'No' + notSet: §cnot set + or: or + poolHologramText: §eNew quest available! + questItemLore: §e§oQuest Item + removeRaw: Remove + requirement: + class: §bClass(es) required + combatLevel: §bCombat level required + equipment: §eEquipment required + experienceLevel: §bExperience levels required + faction: §bFaction(s) required + jobLevel: §bJob level required + logicalOr: §dLogical OR (requirements) + mcMMOSkillLevel: §dSkill level required + money: §dMoney required + permissions: §3Permission(s) required + placeholder: §bPlaceholder value required + quest: §aQuest required + region: §dRegion required + scoreboard: §dScore required + skillAPILevel: §bSkillAPI level required + reset: Reset + reward: + skillApiXp: SkillAPI XP reward + stageType: + Bucket: Fill bucket + Craft: Craft item + Enchant: Enchant items + Fish: Catch fishes + Melt: Melt items + breedAnimals: Breed animals + chat: Write in chat + dealDamage: Deal damage + die: Die + eatDrink: Eat or drink + interact: Interact with block + interactLocation: Interact with block at location + items: Bring back items + location: Find location + mine: Break blocks + mobs: Kill mobs + npc: Find NPC + placeBlocks: Place blocks + playTime: Play time + region: Find region + tameAnimals: Tame animals + ticks: '{ticks} ticks' + time: + days: '{days_amount} days' + hours: '{hours_amount} hours' + lessThanAMinute: a few seconds + minutes: '{minutes_amount} minutes' + weeks: '{weeks_amount} weeks' + unknown: unknown + 'yes': 'Yes' +msg: + bringBackObjects: Bring me back {items}. + command: + adminModeEntered: §aYou have entered the Admin Mode. + adminModeLeft: §aYou have left the Admin Mode. + backupCreated: §6You have successfully created backups of all quests and player + informations. + backupPlayersFailed: §cCreating a backup for all the player informations has failed. + backupQuestsFailed: §cCreating a backup for all the quests has failed. + cancelQuest: §6You have cancelled the quest {quest}. + cancelQuestUnavailable: §cThe quest {quest} can't be cancelled. + checkpoint: + noCheckpoint: §cNo checkpoint found for the quest {quest}. + questNotStarted: §cYou are not doing this quest. + downloadTranslations: + downloaded: §aLanguage {lang} has been downloaded! §7You must now edit the file + "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 + with {lang}, then restart the server. + exists: §cThe file {file_name} already exists. Append "-overwrite" to your command + to overwrite it. (/quests downloadTranslations <lang> -overwrite) + notFound: §cLanguage {lang} not found for version {version}. + syntax: '§cYou must specify a language to download. Example: "/quests downloadTranslations + en_US".' + help: + adminMode: '§6/{label} adminMode: §eToggle the Admin Mode. (Useful for displaying + little log messages.)' + create: '§6/{label} create: §eCreate a quest.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownloads + a vanilla translation file' + edit: '§6/{label} edit: §eEdit a quest.' + finishAll: '§6/{label} finishAll <player>: §eFinish all quests of a player.' + header: §6§lBeautyQuests — Help + list: '§6/{label} list: §eSee the quest list. (Only for supported versions.)' + reload: '§6/{label} reload: §eSave and reload all configurations and files. + (§cdeprecated§e)' + remove: '§6/{label} remove <id>: §eDelete a quest with a specified id or click + on the NPC when not defined.' + resetPlayer: '§6/{label} resetPlayer <player>: §eRemove all informations about + a player.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete informations + of a quest for a player.' + save: '§6/{label} save: §eMake a manual plugin save.' + seePlayer: '§6/{label} seePlayer <player>: §eView informations about a player.' + setFirework: '§6/{label} setFirework: §eEdit the default ending firework.' + setItem: '§6/{label} setItem <talk|launch>: §eSave the hologram item.' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eSkip + the current stage/start the branch/set a stage for a branch.' + start: '§6/{label} start <player> [id]: §eForce the starting of a quest.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eStarts the pending + dialog for a NPC stage or the starting dialog for a quest.' + version: '§6/{label} version: §eSee the current plugin version.' + invalidCommand: + simple: §cThis command doesn't exist, write §ehelp§c. + itemChanged: §aThe item has been edited. The changes will affect after a restart. + itemRemoved: §aThe hologram item has been removed. + leaveAll: '§aYou have forced the end of {success} quest(s). Errors: {errors}' + removed: §aThe quest {quest_name} has successfully been removed. + resetPlayer: + player: §6All informations of your {quest_amount} quest(s) has/have been deleted + by {deleter_name}. + remover: §6{quest_amount} quest information(s) (and {quest_pool} pools) of {player} + has/have been deleted. + resetPlayerPool: + full: §aYou have reset the {pool} pool datas of {player}. + timer: §aYou have reset the {pool} pool timer of {player}. + resetPlayerQuest: + player: §6All informations about the quest {quest} have been deleted by {deleter_name}. + remover: §6{player} informations of quest {quest} has/have been deleted. + resetQuest: §6Removed datas of the quest for {player_amount} players. + scoreboard: + hidden: §6The scoreboard of the player {player_name} has been hidden. + lineInexistant: §cThe line {line_id} doesn't exist. + lineRemoved: §6You have successfully removed the line {line_id}. + lineReset: §6You have successfully reset the line {line_id}. + lineSet: §6You have successfully edited the line {line_id}. + own: + hidden: §6Your scoreboard is now hidden. + shown: §6Your scoreboard is shown again. + resetAll: §6You have successfully reset the scoreboard of the player {player_name}. + shown: §6The scoreboard of the player {player_name} has been shown. + setStage: + branchDoesntExist: §cThe branch with the id {branch_id} doesn't exist. + doesntExist: §cThe stage with the id {stage_id} doesn't exist. + next: §aThe stage has been skipped. + nextUnavailable: §cThe "skip" option is not available when the player is at + the end of a branch. + set: §aStage {stage_id} launched. + startDialog: + alreadyIn: §cThe player is already playing a dialog. + impossible: §cImpossible to start the dialog now. + noDialog: §cThe player has no pending dialog. + success: §aStarted dialog for player {player} in quest {quest}! + startPlayerPool: + error: Failed to start the pool {pool} for {player}. + success: 'Started pool {pool} to {player}. Result: {result}' + startQuest: §6You have forced starting of quest {quest} for {player}. + startQuestNoRequirements: §cThe player does not meet the requirements for the + quest {quest}... Append "-overrideRequirements" at the end of your command to + bypass the requirements check. + dialogs: + skipped: §8§o Dialog skipped. + tooFar: §7§oYou are too far away from {npc_name}... + editor: + advancedSpawnersMob: 'Write the name of the custom spawner mob to kill:' + already: §cYou are already in the editor. + availableElements: 'Available elements: §e{available_elements}' + blockAmount: '§aWrite the amount of blocks:' + blockData: '§aWrite the blockdata (available blockdatas: §7{available_datas}§a):' + blockName: '§aWrite the name of the block:' + blockTag: '§aWrite the block tag (available tags: §7{available_tags}§a):' + chat: §6You are currently in the Editor Mode. Write "/quests exitEditor" to force + leaving the editor. (Highly not recommended, consider using commands such as + "close" or "cancel" to come back to the previous inventory.) + color: Enter a color in the hexadecimal format (#XXXXX) or RGB format (RED GRE + BLU). + colorNamed: Enter the name of a color. + comparisonTypeDefault: '§aChoose the comparison type you want among {available}. + Default comparison is: §e§l{default}§r§a. Type §onull§r§a to use it.' + dialog: + cleared: §aRemoved §2§l{amount}§a message(s). + edited: §aMessage "§7{msg}§a" edited. + help: + addSound: '§6addSound <id> <sound>: §eAdd a sound to a message.' + clear: '§6clear: §eRemove all messages.' + close: '§6close: §eValidate all messages.' + edit: '§6edit <id> <message>: §eEdit a message.' + header: §6§lBeautyQuests — Dialog editor help + list: '§6list: §eView all messages.' + nothing: '§6noSender <message>: §eAdd a message without a sender.' + nothingInsert: '§6nothingInsert <id> <message>: §eInsert a message without + any prefix.' + npc: '§6npc <message>: §eAdd a message said by the NPC.' + npcInsert: '§6npcInsert <id> <message>: §eInsert a message said by the NPC.' + npcName: '§6npcName [custom NPC name]: §eSet (or reset to default) custom + name of the NPC in the dialog' + player: '§6player <message>: §eAdd a message said by the player.' + playerInsert: '§6playerInsert <id> <message>: §eInsert a message said by player.' + remove: '§6remove <id>: §eRemove a message.' + setTime: '§6setTime <id> <time>: §eSet the time (in ticks) before the next + msg plays automatically.' + skippable: '§6skippable [true|false]: §eSet if the dialog can be skipped or + not' + messageRemoved: §aMessage "§7{msg}§a" removed. + noSender: §aMessage "§7{msg}§a" added without a sender. + npc: §aMessage "§7{msg}§a" added for the NPC. + npcName: + set: §aCustom NPC name set to §7{new_name}§a (was §7{old_name}§a) + unset: §aCustom NPC name reset to default (was §7{old_name}§a) + player: §aMessage "§7{msg}§a" added for the player. + skippable: + set: §aThe dialog skippable status is now set to §7{new_state}§a (was §7{old_state}§a) + unset: §aThe dialog skippable status is reset to default (was §7{old_state}§a) + soundAdded: §aSound "§7{sound}§a" added for the message "§7{msg}§a". + syntaxMessage: '§cCorrect syntax: {command} <message>' + syntaxRemove: '§cCorrect sytax: remove <id>' + timeRemoved: §aTime has been removed for message {msg}. + timeSet: '§aTime has been edited for message {msg}: now {time} ticks.' + enter: + list: §c⚠ §7You have entered a "list" editor. Use "add" to add lines. Refer + to "help" (without slash) for help. §e§lType "close" to exit editor. + subtitle: §6Write "/quests exitEditor" to force quit the editor. + title: §6~ Editor Mode ~ + firework: + edited: Edited the quest firework! + invalid: This item is not a valid firework. + invalidHand: You must hold a firework in your main hand. + removed: Removed the quest firework! + goToLocation: §aGo to the wanted location for the stage. + invalidColor: The color you entered is invalid. It must be either hexadecimal + or RGB. + invalidPattern: §cInvalid regex pattern §4{input}§c. + itemCreator: + invalidBlockType: §cInvalid block type. + invalidItemType: §cInvalid item type. (The item can't be a block.) + itemAmount: '§aWrite the amount of item(s):' + itemLore: '§aModify the item lore: (Write "help" for help.)' + itemName: '§aWrite the item name:' + itemType: '§aWrite the name of the wanted item type:' + unknownBlockType: §cUnknown block type. + unknownItemType: §cUnknown item type. + mythicmobs: + disabled: §cMythicMob is disabled. + isntMythicMob: §cThis Mythic Mob doesn't exist. + list: '§aA list of all Mythic Mobs:' + noSuchElement: '§cThere is no such element. Allowed elements are: §e{available_elements}' + npc: + choseStarter: §aChoose the NPC which starts the quest. + enter: §aClick on a NPC, or write "cancel". + notStarter: §cThis NPC isn't a quest starter. + pool: + hologramText: Write the custom hologram text for this pool (or "null" if you + want the default one). + maxQuests: Write the maximum amount of quests launcheable from this pool. + questsPerLaunch: Write the amount of quests given when players click on the + NPC. + timeMsg: 'Write the time before players can take a new quest. (default unit: + days)' + scoreboardObjectiveNotFound: §cUnknown scoreboard objective. + selectWantedBlock: §aClick with the stick on the wanted block for the stage. + stage: + location: + typeWorldPattern: '§aWrite a regex for world names:' + text: + argNotSupported: §cThe argument {arg} not supported. + chooseJobRequired: '§aWrite name of the wanted job:' + chooseLvlRequired: '§aWrite the required amount of levels:' + chooseMoneyRequired: '§aWrite the amount of required money:' + chooseObjectiveRequired: §aWrite the objective name. + chooseObjectiveTargetScore: §aWrite the target score for the objective. + choosePermissionMessage: §aYou can choose a rejection message if the player + doesn't have the required permission. (To skip this step, write "null".) + choosePermissionRequired: '§aWrite the required permission to start the quest:' + choosePlaceholderRequired: + identifier: '§aWrite the name of the required placeholder without the percent + characters:' + value: '§aWrite the required value for the placeholder §e%§e{placeholder}§e%§a:' + chooseRegionRequired: §aWrite the name of the required region (you must be in + the same world). + chooseRequirementCustomDescription: Write the custom description for this requirement. + It will appear in the description of the quest in the menu. + chooseRequirementCustomReason: Write the custom reason for this requirement. + If the player does not meet the requirement but tries to start the quest anyway, + this message will appear in the chat. + chooseRewardCustomDescription: Write the custom description for this reward. + It will appear in the description of the quest in the menu. + chooseSkillRequired: '§aWrite the name of the required skill:' + reward: + money: '§aWrite the amount of the received money:' + permissionName: §aWrite the permission name. + permissionWorld: §aWrite the world in which the permission will be edited, + or "null" if you want to be global. + random: + max: §aWrite the maximum amount of rewards given to the player (inclusive). + min: §aWrite the minimum amount of rewards given to the player (inclusive). + wait: '§aWrite the amount of game ticks to wait: (1 second = 20 game ticks)' + textList: + added: §aText "§7{msg}§a" added. + help: + add: '§6add <message>: §eAdd a text.' + close: '§6close: §eValidate the added texts.' + header: §6§lBeautyQuests — List editor help + list: '§6list: §eView all added texts.' + remove: '§6remove <id>: §eRemove a text.' + removed: §aText "§7{msg}§a" removed. + syntax: '§cCorrect syntax: {command}' + title: + fadeIn: Write the "fade-in" duration, in ticks (20 ticks = 1 second). + fadeOut: Write the "fade-out" duration, in ticks (20 ticks = 1 second). + stay: Write the "stay" duration, in ticks (20 ticks = 1 second). + subtitle: Write the subtitle text (or "null" if you want none). + title: Write the title text (or "null" if you want none). + typeBucketAmount: '§aWrite the amount of buckets to fill:' + typeDamageAmount: 'Write the amount of damage player have to deal:' + typeGameTicks: '§aWrite the required game ticks:' + typeLocationRadius: '§aWrite the required distance from the location:' + errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: + {error}' + experience: + edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} + points. + indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} + and {max}. + invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the + block {block_material}. + invalidBlockTag: §cUnavailable block tag {block_tag}. + inventoryFull: §cYour inventory is full, the item has been dropped on the floor. + moveToTeleportPoint: §aGo to the wanted teleport location. + npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. + number: + invalid: §c{input} isn't a valid number. + negative: §cYou must enter a positive number! + notInBounds: §cYour number must be between {min} and {max}. + zero: §cYou must enter a number other than 0! + pools: + allCompleted: §7You have completed all the quests! + maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same + time... + noAvailable: §7There is no more quest available... + noTime: §cYou must wait {time_left} before doing another quest. + quest: + alreadyStarted: §cYou have already started the quest! + cancelling: §cProcess of quest creation cancelled. + createCancelled: §cThe creation or edition has been cancelled by another plugin! + created: §aCongratulations! You have created the quest §e{quest}§a which includes + {quest_branches} branch(es)! + editCancelling: §cProcess of quest edition cancelled. + edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes + {quest_branches} branch(es)! + finished: + base: §aCongratulations! You have finished the quest §e{quest_name}§a! + obtain: §aYou obtain {rewards}! + invalidID: §cThe quest with the id {quest_id} doesn't exist. + invalidPoolID: §cThe pool {pool_id} does not exist. + notStarted: §cYou are not currently doing this quest. + started: §aYou have started the quest §r§e{quest_name}§o§6! + questItem: + craft: §cYou can't use a quest item to craft! + drop: §cYou can't drop a quest item! + eat: §cYou cannot eat a quest item! + quests: + checkpoint: §7Quest checkpoint reached! + failed: §cYou have failed the quest {quest_name}... + maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same + time... + updated: §7Quest §e{quest_name}§7 updated. + regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) + requirements: + combatLevel: §cYour combat level must be {long_level}! + job: §cYour level for the job §e{job_name}§c must be {long_level}! + level: §cYour level must be {long_level}! + money: §cYou must have {money}! + quest: §cYou must have finished the quest §e{quest_name}§c! + skill: §cYour level for the skill §e{skill_name}§c must be {long_level}! + waitTime: §cYou must wait {time_left} before you can restart this quest! + restartServer: §7Restart your server to see the modifications. + selectNPCToKill: §aSelect the NPC to kill. + stageMobs: + listMobs: §aYou must kill {mobs}. + typeCancel: §aWrite "cancel" to come back to the last text. + versionRequired: 'Version required: §l{version}' + writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if + you want a command.)' + writeCommand: '§aWrite the wanted command: (The command is without the "/" and the + placeholder "{PLAYER}" is supported. It will be replaced with the name of the + executor.)' + writeCommandDelay: §aWrite the desired command delay, in ticks. + writeConfirmMessage: '§aWrite the confirmation message shown when a player is about + to start the quest: (Write "null" if you want the default message.)' + writeDescriptionText: '§aWrite the text which describes the goal of the stage:' + writeEndMsg: §aWrite the message that will be sent at the end of the quest, "null" + if you want the default one or "none" if you want none. You can use "{rewards}" + which will be replaced with the rewards obtained. + writeEndSound: '§aWrite the sound name that will be played to the player at the + end of the quest, "null" if you want the default one or "none" if you want none:' + writeHologramText: '§aWrite text of the hologram: (Write "none" if you don''t want + a hologram and "null" if you want the default text.)' + writeMessage: §aWrite the message that will be sent to the player + writeMobAmount: '§aWrite the amount of mobs to kill:' + writeMobName: '§aWrite the custom name of the mob to kill:' + writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write + "help" to receive help.)' + writeNpcName: '§aWrite the name of the NPC:' + writeNpcSkinName: '§aWrite the name of the skin of the NPC:' + writeQuestDescription: §aWrite the description of the quest, shown in the player's + quest GUI. + writeQuestMaterial: §aWrite the material of the quest item. + writeQuestName: '§aWrite the name of your quest:' + writeQuestTimer: '§aWrite the required time (in minutes) before you can restart + the quest: (Write "null" if you want the default timer.)' + writeRegionName: '§aWrite the name of the region required for the step:' + writeStageText: '§aWrite the text that will be sent to the player at the beginning + of the step:' + writeStartMessage: '§aWrite the message that will be sent at the beginning of the + quest, "null" if you want the default one or "none" if you want none:' + writeXPGain: '§aWrite the amount of experience points the player will obtain: (Last + value: {xp_amount})' +scoreboard: + asyncEnd: §ex + name: §6§lQuests + noLaunched: §cNo quests in progress. + noLaunchedDescription: §c§oLoading + noLaunchedName: §c§lLoading + stage: + breed: §eBreed §6{mobs} + bucket: §eFill §6{buckets} + chat: §eWrite §6{text} + craft: §eCraft §6{items} + dealDamage: + any: §cDeal {damage_remaining} damage + mobs: §cDeal {damage_remaining} damage to {target_mobs} + die: §cDie + eatDrink: §eConsume §6{items} + enchant: §eEnchant §6{items} + fish: §eFish §6{items} + interact: §eClick on the block at §6{x} {y} {z} + interactMaterial: §eClick on a §6{block}§e block + items: '§eBring items to §6{dialog_npc_name}§e: {items}' + location: §eGo to §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world} + melt: §eMelt §6{items} + mine: §eMine {blocks} + mobs: §eKill §6{mobs} + npc: §eTalk with NPC §6{dialog_npc_name} + placeBlocks: §ePlace {blocks} + playTimeFormatted: §ePlay §6{time_remaining_human} + region: §eFind region §6{region_id} + tame: §eTame §6{mobs} + textBetwteenBranch: §e or diff --git a/core/src/main/resources/locales/es_ES.yml b/core/src/main/resources/locales/es_ES.yml index bc6c9501..a7bed459 100644 --- a/core/src/main/resources/locales/es_ES.yml +++ b/core/src/main/resources/locales/es_ES.yml @@ -1,836 +1,788 @@ --- -msg: - quest: - finished: - base: '§a¡Felicitaciones! ¡Has finalizado la misión §e{0}§a!' - obtain: '§a¡Obtuviste {0}!' - started: '§a¡Has comenzado la misión §r§e{0}§o§6!' - created: '§a¡Felicitaciones! ¡Has creado la misión §e{0}§a el cual incluye {1} rama(s)!' - edited: '§a¡Felicitaciones! ¡Has editado la misión §e{0}§a el cual incluye ahora {1} rama(s)!' - createCancelled: '§c¡La creación o edición a sido cancelada por otro plugin!' - cancelling: '§cProceso de creación de la misión cancelada.' - editCancelling: '§cProceso de edición de misión cancelada.' - invalidID: '§cLa misión con la id {0} no existe.' - invalidPoolID: '§cEl grupo {0} no existe.' - alreadyStarted: '§cYa has comenzado la misión!' - notStarted: '§cActualmente no estás haciendo esta misión.' - quests: - maxLaunched: '§cNo puedes tener mas de {0} Misiones al mismo tiempo...' - nopStep: '§cEsta misión no tiene ningún paso.' - updated: '§7Misión §e{0}§7 actualizada.' - checkpoint: El punto de control de tarea ha sido alcanzado - failed: Has fallado en la búsquedast {0} - pools: - noTime: '§cDebes esperar {0} antes de hacer otra misión.' - allCompleted: '§7¡Has completado todas las misiones!' - noAvailable: '§7No hay más misiones disponibles...' - maxQuests: '§cNo puedes tener más de {0} mision(es) al mismo tiempo...' - questItem: - drop: '§c¡No puedes soltar un objeto de misión!' - craft: '§c¡No puedes usar un objeto de misión para fabricar!' - eat: '§c¡No puedes comer un objeto de misión!' - stageMobs: - noMobs: '§cEsta etapa no necesita ningún mob para matar.' - listMobs: '§aDebes matar {0}.' - writeNPCText: '§aEscribe el dialogo que se le dirá al jugador por el NPC: (Escribe "help" para recibir ayuda.)' - writeRegionName: '§aEscribe el nombre de la región requerida para este paso:' - writeXPGain: '§aEscribe la cantidad de puntos de experiencia que el jugador obtendrá: (Último valor: {0})' - writeMobAmount: '§aEscribe la cantidad de mobs a matar:' - writeMobName: '§aEscribe el nombre personalizado del mob para matar:' - writeChatMessage: '§aEscribir mensaje requerido: (Añadir "{SLASH}" al principio si quieres un comando)' - writeMessage: '§aEscribe el mensaje que se enviará al jugador' - writeStartMessage: '§aEscribe el mensaje que será enviado al iniciar la misión, "null" si quieres el predeterminado o "none" si no quieres ninguno' - writeEndMsg: '§aEscribe el mensaje que se enviará al final de la misión, "null" si quieres el predeterminado o "none" si no quieres ninguno. Puedes usar "{0}" que será reemplazado por las recompensas obtenidas.' - writeEndSound: '§aEscribe el nombre del sonido que se reproducirá al jugador al final de la misión, "null" si quieres el predeterminado o "none" si no quieres ninguno:' - writeDescriptionText: '§aEscribe el texto que describe el objetivo de la etapa:' - writeStageText: '§aEscribe el texto que será enviado al jugador al comienzo del paso:' - moveToTeleportPoint: '§aIr a la ubicación de teletransporte deseada.' - writeNpcName: '§aEscribe el nombre del NPC:' - writeNpcSkinName: '§aEscribe el nombre de la skin del NPC:' - writeQuestName: '§aEscribe el nombre de tu misión:' - writeCommand: '§aEscribe el comando deseado: (El comando es sin "/" y la variable "{PLAYER}" es compatible. Será reemplazado por el nombre del ejecutador.)' - writeHologramText: '§aEscribe el texto del holograma: (Escribe "none" si no quieres un holograma y "null" si quieres el texto por defecto.)' - writeQuestTimer: '§aEscriba el tiempo requerido (en minutos) antes de reiniciar la misión: (Escriba "null" si desea el temporizador predeterminado.)' - writeConfirmMessage: '§aEscribe el mensaje de confirmación que se muestra cuando un jugador está a punto de iniciar la misión: (Escribe "null" si quieres el mensaje por defecto.)' - writeQuestDescription: '§aEscribe la descripción de la misión, mostrado en la GUI de misiones del jugador.' - writeQuestMaterial: '§aEscribe el material del item de la misión.' - requirements: - quest: '§cDebes haber terminado la misión §e{0}§c!' - level: '§c¡Tu nivel debe ser {0}!' - job: '§c¡Tu nivel para el trabajo §e{1}§c debe ser {0}!' - skill: '§cTu nivel para la habilidad §e{1}§c debe ser {0}!' - combatLevel: '§cTu nivel de combate debe ser {0}!' - money: '§cDebes tener {0}!' - waitTime: '§cDebes esperar {0} para poder reiniciar esta misión!' - experience: - edited: '§aHas cambiado la ganancia de la experiencia de {0} a {1} puntos.' - selectNPCToKill: '§aSelecciona el NPC para matar.' - npc: - remove: '§aNPC eliminado.' - talk: '§aVe y habla con el NPC llamado §e{0}§a.' - regionDoesntExists: '§cEsta región no existe. (Tienes que estar en el mismo mundo.)' - npcDoesntExist: '§cEl NPC con la id {0} no existe.' - objectDoesntExist: '§cEl elemento especificado con el id {0} no existe.' - number: - negative: '§cDebes introducir un número positivo!' - zero: '§cDebes introducir un número distinto de 0!' - invalid: '§c{0} no es un número válido.' - notInBounds: '§cTu número debe estar entre {0} y {1}.' - errorOccurred: '§cHa ocurrido un error, ¡contacta con un administrador! §4§lError: {0}' - commandsDisabled: '§cActualmente no tienes permisos para ejecutar comandos!' - indexOutOfBounds: '§cEl número {0} está fuera de límites! Debe estar entre {1} y {2}.' - invalidBlockData: '§cLos datos del bloque {0} no son válidos o son incompatibles con el bloque {1}.' - invalidBlockTag: '§cEtiqueta de bloque {0} no disponible.' - bringBackObjects: Tráeme de nuevo {0}. - inventoryFull: '§cTu inventario está lleno, el objeto ha sido abandonado en el suelo.' - playerNeverConnected: '§cNo se puede encontrar información sobre el jugador {0}.' - playerNotOnline: '§cEl jugador {0} está desconectado.' - playerDataNotFound: '§cDatas del jugador {0} no encontrados.' - versionRequired: 'Versión requerida: §l{0}' - restartServer: '§7Reinicia tu servidor para ver las modificaciones.' - dialogs: - skipped: '§8§o Diálogo omitido.' - tooFar: '§7§oEstás demasiado lejos de {0}...' - command: - downloadTranslations: - syntax: '§cDebes especificar un idioma para descargar. Ejemplo: "/quests downloadTranslations en_US".' - notFound: '§cIdioma {0} no encontrado para la versión {1}.' - exists: '§cEl archivo {0} ya existe. Añade "-overwrite" a tu comando para sobrescribirlo. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§a¡El idioma {0} ha sido descargado! §7Ahora debes editar el archivo "/plugins/BeautyQuests/config.yml" para cambiar el valor de §ominecraftTranslationsFile§7 con {0}, y luego reiniciar el servidor.' - checkpoint: - noCheckpoint: '§cNo se ha encontrado ningún punto de control para la misión {0}.' - questNotStarted: '§cNo estás haciendo esta misión.' - setStage: - branchDoesntExist: '§cLa rama con el id {0} no existe.' - doesntExist: '§cLa etapa con el id {0} no existe.' - next: '§aLa etapa ha sido omitida.' - nextUnavailable: '§cLa opción "skip" no está disponible cuando el jugador está al final de una rama.' - set: '§aFase {0} lanzada.' - startDialog: - impossible: '§cNo es posible iniciar el diálogo ahora.' - noDialog: '§cEl jugador no tiene un diálogo pendiente.' - alreadyIn: '§cEl jugador ya está reproduciendo un diálogo.' - success: '§aEmpezó el diálogo para el jugador {0} en la misión {1}!' - playerNeeded: '§cDebes ser un jugador para ejecutar este comando!' - incorrectSyntax: '§cSintaxis incorrecta.' - noPermission: '§cNo tienes suficientes permisos para ejecutar este comando! (Requiere: {0})' - invalidCommand: - quests: '§cEste comando no existe, escribe §e/quest help§c.' - simple: '§cEste comando no existe, escribe §ehelp§c.' - needItem: '§cDebes mantener un objeto en tu mano principal!' - itemChanged: '§aEl elemento ha sido editado. Los cambios afectarán después de un reinicio.' - itemRemoved: '§aEl elemento holograma ha sido eliminado.' - removed: '§aLa misión {0} se ha eliminado correctamente.' - leaveAll: '§aHas forzado el final de {0} misión(s). Errores: {1}' - resetPlayer: - player: '§6Todas las informaciones de tu misión(s) {0} han sido eliminadas por {1}.' - remover: '§6{0} información(es) de misiones (y {2} pool) de {1} ha sido eliminada.' - resetPlayerQuest: - player: '§6Toda la información sobre la misión {0} fue borrada por {1}.' - remover: '§6{0} información de {1} ha sido eliminado.' - resetQuest: '§6Removida información de misiones de {0} jugadores.' - startQuest: '§6Obligaste a empezar la misión {0} (UUID de Jugador: {1}).' - startQuestNoRequirements: '§cEl jugador no cumple con los requisitos para la misión {0}... Añade "-overrideRequirements" al final de tu comando para evitar la comprobación de requisitos.' - cancelQuest: '§6Cancelaste la misión {0}.' - cancelQuestUnavailable: '&cLa misión {0} no puede ser cancelada.' - backupCreated: '&6Creaste correctamente copias de seguridad de misiones e información.' - backupPlayersFailed: '§cLa creación de la copia de seguridad para toda la información de los jugadores ha fallado.' - backupQuestsFailed: '§cLa creación de la copia de seguridad para todas las misiones ha fallado.' - adminModeEntered: '&aEntraste en el modo Admin.' - adminModeLeft: '&aSaliste del modo Admin.' - resetPlayerPool: - timer: '§aHas reiniciado el {0} contador del grupo en {1}.' - full: '§aHas reiniciado la {0} información del grupo en {1}.' - scoreboard: - lineSet: '§6Has editado con éxito la línea {0}.' - lineReset: '§6Has restablecido con éxito la línea {0}.' - lineRemoved: '§6Has eliminado con éxito la línea {0}.' - lineInexistant: '§cLa línea {0} no existe.' - resetAll: '§6Has restablecido el marcador del jugador {0} con éxito.' - hidden: '§6El marcador del jugador {0} ha sido ocultado.' - shown: '§6El marcador del jugador {0} ha sido mostrado.' - own: - hidden: Su marcador ahora está oculto. - shown: Su marcador se muestra de nuevo - help: - header: '§6§lBeautyQuests — Ayuda' - create: '§6/{0} create: §eCrea una misión.' - edit: '§6/{0} edit: §eEditar una misión.' - remove: '§6/{0} remove <id>: §eElimina una misión con un id especificado o haz clic en el NPC cuando no se haya definido.' - finishAll: '§6/{0} finishAll <player>: §eFinish all quests of a player.' - setStage: '§6/{0} setStage <player> <id> [new branch] [new stage]: §eSkip the current stage/start the branch/set a stage for a branch.' - startDialog: '§6/{0} startDialog <player> <quest id>: §eComienza el diálogo pendiente para una etapa del NPC o el diálogo de inicio para una misión.' - resetPlayer: '§6/{0} restablecido jugador <player>: §eElimina toda la información sobre un jugador.' - resetPlayerQuest: '§6/{0} restablecida la Misión de Jugador <player> [id]: §eElimina información de una misión para un jugador.' - seePlayer: '§6/{0} seePlayer <player>: §eVer la informacion sobre un jugador' - reload: '§6/{0} reload: §eGuarda y recarga todas las configuraciones y archivos. (§cdeprecado§e)' - start: '§6/{0} start <player> [id]: §eForzar el inicio de una mision' - setItem: '§6/{0} setItem <talk|launch>: §eGuarda el elemento del holograma.' - setFirework: '§6/{0} setFirework: §eEdita el fuego artificial por defecto al finalizar.' - adminMode: '§6/{0} adminMode: §eActiva el Modo de administración. (Útil para mostrar mensajes de poco registro.)' - version: '§6/{0} version: §eVer la versión actual del plugin.' - downloadTranslations: '§6/{0} descargaTraducciones <language>: §eDescargas un archivo de traducción de vaina' - save: '§6/{0} save: §eHacer un guardado manual.' - list: '§6/{0} list: §eVer la lista de misiones. (Sólo para versiones soportadas.)' - typeCancel: '§aEscribe "cancel" para volver al último texto.' - editor: - blockAmount: '§aEscribe la cantidad de bloques:' - blockName: '§aEscribe el nombre del bloque:' - blockData: '§aEscribe los datos de bloque (datos de bloques disponibles: {0}):' - blockTag: '§aEscribe la etiqueta de bloque (etiquetas disponibles: §7{0}§a):' - typeBucketAmount: '§aEscribe la cantidad de cubos a rellenar:' - typeDamageAmount: 'Escribe la cantidad de daño que tiene que hacer el jugador:' - goToLocation: '§aVe a la ubicación deseada para la etapa y click a la esmeralda.' - typeLocationRadius: '§aEscribe la distancia requerida de la ubicación:' - typeGameTicks: '§aEscribe los ticks requeridos:' - already: '§cYa estás en el editor.' - stage: - location: - typeWorldPattern: '§aEscribe una expresión para nombres de mundo:' - enter: - title: '§6~ Modo editor ~' - subtitle: '§2♣§d§kii§a§lSkyblock§d§kii§2♣ §aEscribe "/quests exitEditor" para forzar la salida del editor.' - list: '§c⚠ §7Has introducido un editor de "lista". Usa "add" para añadir líneas. Consulta "help" (sin barra) para ayuda. §eEscribe "close" para salir del editor.' - chat: '§2♣§d§kii§a§lSkyblock§d§kii§2♣ §2Estás actualmente en modo editor. Escribe "/quests exitEditor" para forzar la salida del editor. (No se recomienda, considere usar comandos como "close" o "cancelar" para volver al inventario anterior.)' - npc: - enter: '§aHas click en un NPC, o escribe "cancel".' - choseStarter: '§aElige el NPC que inicia la misión.' - notStarter: '§cEste NPC no es un iniciador de misiones.' - text: - argNotSupported: '§cEl argumento {0} no es compatible.' - chooseLvlRequired: '§aEscribe la cantidad requerida de niveles:' - chooseJobRequired: '§aEscribir nombre del trabajo deseado:' - choosePermissionRequired: '§aEscribe el permiso requerido para iniciar la misión:' - choosePermissionMessage: '§aPuedes elegir un mensaje de rechazo si el jugador no tiene el permiso requerido. (Para saltar este paso, escribe "null".)' - choosePlaceholderRequired: - identifier: '§aEscribe el nombre de la variable sin el símbolo de porcentaje:' - value: '§aEscribe el valor requerido para la variable §e%§e{0}§e%§a:' - chooseSkillRequired: '§aEscribe el nombre de la habilidad requerida:' - chooseMoneyRequired: '§aEscribe la cantidad de dinero necesario:' - reward: - permissionName: '§aEscribe el nombre del permiso.' - permissionWorld: '§aEscribe el mundo en el que el permiso será editado, o "nulo" si quieres ser global.' - money: '§aEscribe la cantidad del dinero recibido:' - wait: '§aEscribe la cantidad de ticks del juego para esperar: (1 segundo = 20 ticks del juego)' - random: - min: '§aEscribe la cantidad mínima de recompensas entregadas al jugador (inclusive).' - max: '§aEscribe la cantidad máxima de recompensas entregadas al jugador (inclusive).' - chooseObjectiveRequired: '§aEscribe el nombre del objetivo.' - chooseObjectiveTargetScore: '§aEscribe la puntuación objetivo para el objetivo.' - chooseRegionRequired: '§aEscribe el nombre de la región requerida (debes estar en el mismo mundo).' - selectWantedBlock: '§aHaz clic con el palo en el bloque deseado para la etapa.' - itemCreator: - itemType: '§aEscribe el nombre del tipo de elemento deseado:' - itemAmount: '§aEscribe la cantidad de objeto(s):' - itemName: '§aEscribe el nombre del item:' - itemLore: '§aModificar la descripción del objeto: (Escribe "help" para ayuda.)' - unknownItemType: '§cTipo de elemento desconocido.' - invalidItemType: '§cTipo de elemento inválido. (El elemento no puede ser un bloque.)' - unknownBlockType: '§cTipo de bloque desconocido.' - invalidBlockType: '§cTipo de bloque inválido.' - dialog: - syntax: '§cSintaxis correctas: {0}{1} <message>' - syntaxRemove: '§cSytaxis correcta: remove <id>' - player: '§aMensaje "§7{0}§a" añadido por el jugador.' - npc: '§aMensaje "§7{0}§a" añadido al NPC.' - noSender: '§aMensaje "§7{0}§a" añadido sin remitente.' - messageRemoved: '§aMensaje "§7{0}§a" eliminado.' - edited: '§aMensaje "§7{0}§a" editado.' - soundAdded: '§aSonido "§7{0}§a" agregado al mensaje "§7{1}§a".' - cleared: '§a{0} mensaje(s) removido.' - help: - header: '§6§lBeautyQuests — Ayuda del editor de diálogo' - npc: '§6npc <message>: §eAgrega un mensaje dicho por el NPC.' - player: '§6player <message>: §eAgrega un mensaje dicho por el jugador.' - nothing: '§6noSender <message>: §eAgrega un mensaje sin remitente.' - remove: '§6remove <id>: §eRemover un mensaje.' - list: '§6list: §eVer todos los mensajes.' - npcInsert: '§6npcInsert <id> <message>: §eInsertar un mensaje dicho por el NPC.' - playerInsert: '§6playerInsert <id> <message>: §eInsertar un mensaje dicho por el jugador' - nothingInsert: '§6nothingInsert <id> <message>: §eInserta un mensaje sin ningún prefijo.' - edit: '§6edit <id> <message>: §eEditar un mensaje.' - addSound: '§6addSound <id> <sound>: §eAñade un sonido a un mensaje' - clear: '§6clear: §eBorra todos los mensajes.' - close: '&6close: &eGuardas y validas los mensajes.' - setTime: '§6setTime <id> <time>: §eEstablece el tiempo (en ticks) despues de que el siguiente mensaje aparezca automaticamente' - npcName: '§6Nombre del npc [custom NPC name]: §eEstablecido (o restablecido a default) nombre personalizado del NPC en el diálogo' - skippable: '§6skippable [true|false]: §eEstablecer si el diálogo puede ser omitido o no.' - timeSet: '§aTiempo ha sido editado para el mensaje {0}: ahora {1} ticks.' - timeRemoved: '§aTiempo eliminado para el mensaje {0}.' - npcName: - set: '§aNombre de NPC establecido a §7{1}§a (era §7{0}§a)' - unset: '§aNombre de NPC personalizado restablecido por defecto (§7{0}§a)' - skippable: - set: '§aEl estado del diálogo ignorable se modificó a §7{1}§a (era §7{0}§a)' - unset: '§aEl estado del diálogo ignorable se restableció al original (era §7{0}§a)' - mythicmobs: - list: '&aToda la lista de "Mythic Mobs":' - isntMythicMob: '§cEste Mob Mítico no existe.' - disabled: '§cMythicMob está deshabilitado.' - advancedSpawnersMob: 'Escribe el nombre del spawner personalizado para matar:' - textList: - syntax: '§cSintaxis correcta: ' - added: '§aTexto "§7{0}§a" añadido.' - removed: '§aTexto "§7{0}§a" eliminado.' - help: - header: '§6§lBeautyQuests — Ayuda del editor de listas' - add: '§6add <message>: §eAgrega un texto.' - remove: '§6remove <id>: §eEliminar un texto.' - list: '§6list: §eVer todos los textos añadidos' - close: '§6close: §eValida los textos añadidos' - availableElements: 'Elementos disponibles: §e{0}' - noSuchElement: '§cNo hay tal elemento. Los elementos permitidos son: §e{0}' - invalidPattern: '§cPatrón de expresión inválido §4{0}§c.' - comparisonTypeDefault: '§aElige el tipo de comparación que quieres entre {0}. La comparación predeterminada es: §e§l{1}§r§a. Escribe §onull§r§a para usarlo.' - scoreboardObjectiveNotFound: '§cObjetivo desconocido del marcador.' - pool: - hologramText: 'Escriba el texto personalizado del holograma para este grupo (o "null" si desea el predeterminado).' - maxQuests: 'Escribe la cantidad máxima de misiones lanzables desde este conjunto' - questsPerLaunch: 'Escribe la cantidad de misiones que se dan cuando los jugadores hacen clic en el NPC.' - timeMsg: 'Escribe el tiempo antes de que los jugadores puedan tomar una nueva misión. (Unidad predeterminada: días)' - title: - title: 'Escribe el texto del título (o "null" si quieres ninguno).' - subtitle: 'Escribe el texto de subtítulos (o "null" si no quieres ninguno).' - fadeIn: 'Escriba la duración de "fade-in", en ticks (20 ticks = 1 segundo).' - stay: 'Escriba la duración de la estancia, en ticks (20 ticks = 1 segundo).' - fadeOut: 'Escriba la duración de "desvanecer", en ticks (20 ticks = 1 segundo).' - colorNamed: 'Introduzca el nombre de un color.' - color: 'Introduzca un color en formato hexadecimal (#XXXXX) o formato RGB (RED GRE BLU).' - invalidColor: 'El color introducido no es válido. Debe ser hexadecimal o RGB.' - firework: - invalid: 'Este objeto no es un fuego artificial válido.' - invalidHand: 'Debes sostener un fuego artificial en tu mano principal.' - edited: '¡El fuego artificial de la misión fue editado!' - removed: '¡El fuego artificial de la misión fue eliminado!' - writeCommandDelay: '§aEscriba el retardo de comando deseado, en ticks.' advancement: finished: Finalizado notStarted: No comenzado +description: + requirement: + class: Clase {class_name} + combatLevel: Nivel de combate {short_level} + faction: Facción {faction_name} + jobLevel: Nivel {short_level} de {job_name} + level: Nivel {short_level} + quest: Finalizar misión §e{quest_name} + skillLevel: Nivel {short_level} de {skill_name} + title: '§8§lRequisitos:' + reward: + title: '§8§lRecompensas:' +indication: + cancelQuest: '§7Estás seguro de que quieres cancelar la misión {quest_name}?' + closeInventory: '§7¿Estás seguro de que quieres cerrar la GUI?' + removeQuest: '§7¿Estás seguro de que quieres eliminar la misión {quest}?' + startQuest: '§7Quieres iniciar la misión {quest_name}?' inv: - validate: '§b§lValidar' - cancel: '§c§lCancelar' - search: '§e§lBuscar' addObject: '§aAñadir un objeto' + block: + blockData: '§dBlockdata (avanzado)' + blockTag: '§dEtiqueta (avanzado)' + blockTagLore: Elija una etiqueta que describa una lista de posibles bloques. Las etiquetas se pueden personalizar usando datapacks. Puedes encontrar la lista de etiquetas en la wiki de Minecraft. + materialNotItemLore: El bloque elegido no puede mostrarse como objeto. Todavía se almacena correctamente como {block_material}. + name: Elegir bloque + blockAction: + location: '§eSelecciona una ubicación precisa' + material: '§eSelecciona un material de bloque' + name: Seleccionar acción de bloque + blocksList: + addBlock: '§aClick para añadir un bloque.' + name: Seleccionar bloques + buckets: + name: Tipo de cubo + cancel: '§c§lCancelar' + cancelActions: + name: Cancelar acciones + checkpointActions: + name: Acciones de puntos de control + chooseAccount: + name: '¿Qué cuenta?' + chooseQuest: + menu: '§aMenú de Misiones' + menuLore: Te lleva a tu Menú de Misiones. + name: '¿Qué misión?' + classesList.name: Lista de clases + classesRequired.name: Clases requeridas + command: + console: Consola + delay: '§bRetraso' + name: Comando + parse: Analizar marcadores de posición (placeholders) + value: '§eComando' + commandsList: + name: Lista de comandos + value: '§Comando: {command_label}' confirm: name: Estas seguro? + 'no': Cancelar 'yes': '§aConfirmar' - 'no': "Cancelar\n" create: - stageCreate: '§aCrear nuevo paso' - stageRemove: '§cBorrar este paso' - stageUp: Mover arriba - stageDown: Mover abajo - stageType: '§7Tipo de etapa: §e{0}' - cantFinish: '§7¡Debes crear al menos una etapa antes de terminar la creación de misión!' - findNPC: "Encuentra al NPC\n" + NPCSelect: '§eElegir o crear NPC' + NPCText: '§eEditar dialogo' + breedAnimals: '§aReproducir Animales' bringBack: Trae devuelta ciertos items - findRegion: "Encuentra una región\n" - killMobs: "Asesina mobs\n" - mineBlocks: Rompe bloques - placeBlocks: "Coloca bloques\n" - talkChat: Escribe en el chat - interact: Interactúa con el bloque - fish: "Pesca peces\n" - melt: '§6Cocinar objetos' - enchant: '§dEncantar objetos' + bucket: Llena cubetas + cancelMessage: Cancelar envío + cantFinish: '§7¡Debes crear al menos una etapa antes de terminar la creación de misión!' + changeEntityType: '§eCambiar tipo de entidad' + changeTicksRequired: '§eCambiar ticks reproducidos requeridos' craft: Craftea items - bucket: Llena cubetas - location: Dirígete a la localización - playTime: '§eTiempo de juego' - breedAnimals: '§aReproducir Animales' - tameAnimals: '§aDomesticar animales' - death: '§cMuerte' + currentRadius: '§eDistancia actual: §6{radius}' dealDamage: '§cInflige daño a los mobs' + death: '§cMuerte' eatDrink: '§aIngiere o bebe alimentos o pociones' - NPCText: '§eEditar dialogo' - dialogLines: '{0} líneas' - NPCSelect: '§eElegir o crear NPC' - hideClues: Ocultar partículas y hologramas - gps: Muestra una brújula hacia el objetivo - editMobsKill: '§eEditar mobs a matar' - mobsKillFromAFar: Necesita ser asesinado con proyectil editBlocksMine: '§eEditar bloques a romper' - preventBlockPlace: Evita que los jugadores rompan sus propios bloques editBlocksPlace: '§eEditar bloques a colocar' + editBucketAmount: '§eEditar cantidad de cubos a rellenar' + editBucketType: '§eEditar tipo de cubo para rellenar' + editFishes: '§eEditar peces para capturar' + editItem: '§eEditar elemento a crear' + editItemsToEnchant: '§eEditar objetos para encantar' + editItemsToMelt: '§eEditar objetos para cocinar' + editLocation: '§eEditar ubicación' editMessageType: '§eEditar mensaje a escribir' - cancelMessage: Cancelar envío - ignoreCase: Ignorar el caso del mensaje - replacePlaceholders: Reemplazar {PLAYER} y marcadores de posición de PAPI + editMobsKill: '§eEditar mobs a matar' + editRadius: '§eEditar distancia de la ubicación' + enchant: '§dEncantar objetos' + findNPC: Encuentra al NPC + findRegion: Encuentra una región + fish: Pesca peces + hideClues: Ocultar partículas y hologramas + ignoreCase: Ignorar el caso del mensaje + interact: Interactúa con el bloque + killMobs: Asesina mobs + leftClick: Haga clic izquierdo + location: Dirígete a la localización + melt: '§6Cocinar objetos' + mineBlocks: Rompe bloques + mobsKillFromAFar: Necesita ser asesinado con proyectil + placeBlocks: Coloca bloques + playTime: '§eTiempo de juego' + preventBlockPlace: Evita que los jugadores rompan sus propios bloques + replacePlaceholders: Reemplazar {PLAYER} y marcadores de posición de PAPI + selectBlockLocation: '§eSelecciona la ubicación del bloque' + selectBlockMaterial: '§eSeleccionar material de bloque' selectItems: '§eEditar elementos requeridos' - selectItemsMessage: '§eEditar mensaje preguntando' selectItemsComparisons: '§eSeleccionar comparaciones de objetos (AVANZADO)' + selectItemsMessage: '§eEditar mensaje preguntando' selectRegion: '§7Elegir región' - toggleRegionExit: Al salir - stageStartMsg: '§eEditar mensaje inicial' - selectBlockLocation: '§eSelecciona la ubicación del bloque' - selectBlockMaterial: '§eSeleccionar material de bloque' - leftClick: Haga clic izquierdo - editFishes: '§eEditar peces para capturar' - editItemsToMelt: '§eEditar objetos para cocinar' - editItemsToEnchant: '§eEditar objetos para encantar' - editItem: '§eEditar elemento a crear' - editBucketType: '§eEditar tipo de cubo para rellenar' - editBucketAmount: '§eEditar cantidad de cubos a rellenar' - editLocation: '§eEditar ubicación' - editRadius: '§eEditar distancia de la ubicación' - currentRadius: '§eDistancia actual: §6{0}' - changeTicksRequired: '§eCambiar ticks reproducidos requeridos' - changeEntityType: '§eCambiar tipo de entidad' stage: - location: - worldPattern: '§aEstablecer un patrón del nombre del mundo §d(AVANZADO)' - worldPatternLore: 'Si desea que el escenario se complete para cualquier mundo que coincida con un patrón específico, ingrese aquí una expresión regular.' - death: - causes: '§aEstablecer causas de muerte §d(AVANZADO)' - anyCause: Cualquier causa de muerte - setCauses: '{0} causa(s) de muerte' dealDamage: damage: '§eDaño para infligir' targetMobs: '§cMobs para dañar' + death: + anyCause: Cualquier causa de muerte + causes: '§aEstablecer causas de muerte §d(AVANZADO)' + setCauses: '{causes_amount} causa(s) de muerte' eatDrink: items: '§eEditar items para comer o beber' - stages: - name: Crear etapas - nextPage: '§eSiguiente página' - laterPage: '§ePágina anterior' - endingItem: '§eEditar recompensas finales' - descriptionTextItem: '§eEditar descripción' - regularPage: '§aEtapas regulares' - branchesPage: '§dRamas de las etapas' - previousBranch: '§eRegresa a la rama anterior' - newBranch: '§eIr a una nueva rama' - validationRequirements: '§eRequisitos de validación' - validationRequirementsLore: Todos los requisitos deben coincidir con el jugador que intenta completar la etapa. Si no, la etapa no se puede completar. + location: + worldPattern: '§aEstablecer un patrón del nombre del mundo §d(AVANZADO)' + worldPatternLore: Si desea que el escenario se complete para cualquier mundo que coincida con un patrón específico, ingrese aquí una expresión regular. + stageCreate: '§aCrear nuevo paso' + stageDown: Mover abajo + stageRemove: '§cBorrar este paso' + stageStartMsg: '§eEditar mensaje inicial' + stageType: '§7Tipo de etapa: §e{stage_type}' + stageUp: Mover arriba + talkChat: Escribe en el chat + tameAnimals: '§aDomesticar animales' + toggleRegionExit: Al salir + damageCause: + name: Causa de daño + damageCausesList: + name: Lista de causas de daño details: - hologramLaunch: '§eEditar "launch" item del holograma' - hologramLaunchLore: El Holograma se muestra sobre la cabeza de Starter NPC cuando el jugador puede comenzar la misión. - hologramLaunchNo: '§eEditar "launch unavailable" holograma no disponible"' - hologramLaunchNoLore: El Holograma se muestra sobre la cabeza de Starter NPC cuando el jugador NO puede iniciar la misión. + actions: '{amount} acción(es)' + auto: Iniciar automáticamente en el primer ingreso + autoLore: Si está activado, la misión se iniciará automáticamente cuando el jugador se una al servidor por primera vez. + bypassLimit: No cuente el límite de misiones + bypassLimitLore: Si está activado, la misión será iniciada incluso si el jugador ha alcanzado la cantidad máxima de misiones iniciadas. + cancelRewards: '§cCancelar acciones' + cancelRewardsLore: Acciones realizadas cuando los jugadores cancelan esta misión. + cancellable: Cancelar por jugador + cancellableLore: Permite al jugador cancelar la misión a través de su Menú de misiones. + createQuestLore: Debes definir un nombre de misión. + createQuestName: '§lCrear misión' customConfirmMessage: '§eEditar mensaje de confirmación de búsqueda' customConfirmMessageLore: Mensaje mostrado en la interfaz de usuario de confirmación cuando un jugador está a punto de comenzar la misión. customDescription: '§eEditar descripción de la misión' customDescriptionLore: Descripción mostrada a continuación el nombre de la misión en GUIs. - name: Últimos detalles de la misión - multipleTime: - itemName: Alternar repetible - itemLore: "¿Puede hacerse la misión\nvarias veces?" - cancellable: Cancelar por jugador - cancellableLore: Permite al jugador cancelar la misión a través de su Menú de misiones. - startableFromGUI: Empezable desde GUI - startableFromGUILore: Permite al jugador comenzar la misión desde el Menú de Misiones. - scoreboardItem: Habilitar el scoreboard - scoreboardItemLore: Si está desactivado, la misión no será rastreada a través del marcador. + customMaterial: '§eEditar material del objeto de la misión' + customMaterialLore: Artículo representativo de esta misión en el Menú de Misiones. + defaultValue: '§8(valor predeterminado)' + editQuestName: '§lEditar misión' + editRequirements: '§eEditar requisitos' + editRequirementsLore: Todos los requisitos deben aplicarse al jugador antes de que pueda comenzar la misión. + endMessage: '§eEditar mensaje final' + endMessageLore: Mensaje que se enviará al jugador al final de la misión. + endSound: '§eEditar sonido final' + endSoundLore: Sonido que se reproducirá al final de la misión. + failOnDeath: Fracaso al morir + failOnDeathLore: '¿Se cancelará la misión cuando el jugador muera?' + firework: '§dFuego artificial de finalización' + fireworkLore: Fuegos artificiales lanzados cuando el jugador termine la misión + fireworkLoreDrop: Arrastra aquí tu fuego artificial personalizado hideNoRequirementsItem: Ocultar cuando no se cumplan los requisitos hideNoRequirementsItemLore: Si está activado, la misión no se mostrará en el menú de misiones cuando no se cumplan los requisitos. - bypassLimit: No cuente el límite de misiones - bypassLimitLore: Si está activado, la misión será iniciada incluso si el jugador ha alcanzado la cantidad máxima de misiones iniciadas. - auto: Iniciar automáticamente en el primer ingreso - autoLore: Si está activado, la misión se iniciará automáticamente cuando el jugador se una al servidor por primera vez. + hologramLaunch: '§eEditar "launch" item del holograma' + hologramLaunchLore: El Holograma se muestra sobre la cabeza de Starter NPC cuando el jugador puede comenzar la misión. + hologramLaunchNo: '§eEditar "launch unavailable" holograma no disponible"' + hologramLaunchNoLore: El Holograma se muestra sobre la cabeza de Starter NPC cuando el jugador NO puede iniciar la misión. + hologramText: '§eTexto del holograma' + hologramTextLore: Texto mostrado en el holograma sobre la cabeza del NPC de inicio. + keepDatas: Conservar datos de los jugadores + keepDatasLore: 'Forzar el plugin para preservar los datos de los jugadores, aunque las etapas han sido editadas. §c§lADVERTENCIA §c- habilitar esta opción puede dañar los datos de tus jugadores.' + loreReset: '§e§lTodos los avances de los jugadores serán reiniciados' + multipleTime: + itemLore: '¿Puede hacerse la misión varias veces?' + itemName: Alternar repetible + name: Últimos detalles de la misión + optionValue: '§8Valor: §7{value}' questName: '§a§lEditar nombre de misión' questNameLore: Debe establecer un nombre para completar la creación de misión. - setItemsRewards: '§eEditar objetos de recompensa' + questPool: '§eHerramienta de Misión' + questPoolLore: Adjuntar esta misión a un grupo de misiones removeItemsReward: '§eEliminar items del inventario' - setXPRewards: '§eEditar experiencia de recompensa' + requiredParameter: '§7Parámetro requerido' + requirements: '{amount} requisito(s)' + rewards: '{amount} recompensa(s)' + rewardsLore: Acciones realizadas cuando termina la misión. + scoreboardItem: Habilitar el scoreboard + scoreboardItemLore: Si está desactivado, la misión no será rastreada a través del marcador. + selectStarterNPC: '§e§lSelecciona el NPC iniciador' + selectStarterNPCLore: Al hacer clic en el PNJ seleccionado comenzará la misión. + selectStarterNPCPool: '§c⚠ Un grupo de misiones está seleccionado' setCheckpointReward: '§eEditar recompensas de puntos de control' + setItemsRewards: '§eEditar objetos de recompensa' + setMoneyReward: '§eEditar recompensa de dinero' + setPermReward: '§eEditar permisos' setRewardStopQuest: '§cDetener la misión' - setRewardsWithRequirements: '§eRecompensas con requerimientos' setRewardsRandom: '§dRecompensas aleatorias' - setPermReward: '§eEditar permisos' - setMoneyReward: '§eEditar recompensa de dinero' - setWaitReward: '§eEditar recompensa "esperar"' + setRewardsWithRequirements: '§eRecompensas con requerimientos' setTitleReward: '§eEditar recompensa del título' - selectStarterNPC: '§e§lSelecciona el NPC iniciador' - selectStarterNPCLore: Al hacer clic en el PNJ seleccionado comenzará la misión. - selectStarterNPCPool: '§c⚠ Un grupo de misiones está seleccionado' - createQuestName: '§lCrear misión' - createQuestLore: Debes definir un nombre de misión. - editQuestName: '§lEditar misión' - endMessage: '§eEditar mensaje final' - endMessageLore: Mensaje que se enviará al jugador al final de la misión. - endSound: '§eEditar sonido final' - endSoundLore: Sonido que se reproducirá al final de la misión. - startMessage: '§eEditar mensaje de inicio' - startMessageLore: Mensaje que se enviará al jugador al comienzo de la misión. + setWaitReward: '§eEditar recompensa "esperar"' + setXPRewards: '§eEditar experiencia de recompensa' startDialog: '§eEditar diálogo de inicio' startDialogLore: Diálogo que se reproducira antes de que las misiones comiencen cuando los jugadores hagan clic en el Inicio NPC. - editRequirements: '§eEditar requisitos' - editRequirementsLore: Todos los requisitos deben aplicarse al jugador antes de que pueda comenzar la misión. + startMessage: '§eEditar mensaje de inicio' + startMessageLore: Mensaje que se enviará al jugador al comienzo de la misión. startRewards: '§6Recompensas de inicio' startRewardsLore: Acciones realizadas cuando comienza la misión. - cancelRewards: '§cCancelar acciones' - cancelRewardsLore: Acciones realizadas cuando los jugadores cancelan esta misión. - hologramText: '§eTexto del holograma' - hologramTextLore: Texto mostrado en el holograma sobre la cabeza del NPC de inicio. + startableFromGUI: Empezable desde GUI + startableFromGUILore: Permite al jugador comenzar la misión desde el Menú de Misiones. timer: '§bReiniciar temporizador' timerLore: Tiempo antes de que el jugador pueda volver a empezar la misión. - requirements: '{0} requisito(s)' - rewards: '{0} recompensa(s)' - actions: '{0} acción(es)' - rewardsLore: Acciones realizadas cuando termina la misión. - customMaterial: '§eEditar material del objeto de la misión' - customMaterialLore: Artículo representativo de esta misión en el Menú de Misiones. - failOnDeath: Fracaso al morir - failOnDeathLore: '¿Se cancelará la misión cuando el jugador muera?' - questPool: '§eHerramienta de Misión' - questPoolLore: Adjuntar esta misión a un grupo de misiones - firework: '§dFuego artificial de finalización' - fireworkLore: Fuegos artificiales lanzados cuando el jugador termine la misión - fireworkLoreDrop: Arrastra aquí tu fuego artificial personalizado visibility: Visibilidad de la misión visibilityLore: Elige en qué pestañas del menú se mostrará la misión, y si la misión es visible en los mapas dinámicos. - keepDatas: Conservar datos de los jugadores - keepDatasLore: |- - Forzar el plugin para preservar los datos de los jugadores, aunque las etapas han sido editadas. - §c§lADVERTENCIA §c- habilitar esta opción puede dañar los datos de tus jugadores. - loreReset: '§e§lTodos los avances de los jugadores serán reiniciados' - optionValue: '§8Valor: §7{0}' - defaultValue: '§8(valor predeterminado)' - requiredParameter: '§7Parámetro requerido' - itemsSelect: - name: Editar elementos - none: |- - §aMueve un elemento aquí o - haz click para abrir el editor de objetos. + editTitle: + fadeIn: '§aDuración del Fade-in' + fadeOut: '§aDuración del Fade-out' + name: Editar título + stay: '§bDuración' + subtitle: '§eSubtítulo' + title: '§6Título' + entityType: + name: Elija el tipo de entidad + equipmentSlots: + name: Ranuras de equipamiento + factionsList.name: Lista de facciones + factionsRequired.name: Facciones requeridas + itemComparisons: + bukkit: Comparación nativa de Bukkit + bukkitLore: Utiliza el sistema predeterminado de comparación de artículos de Bukkit. Compara material, durabilidad, etiquetas... + customBukkit: Comparación nativa de bukkit - NO NBT + customBukkitLore: Utiliza el sistema de comparación de artículos por defecto de Bukkit, pero elimina las etiquetas NBT. Compara material, durabilidad... + enchants: Encantamientos de los articulos + enchantsLore: Comparar los encantamientos de los articulos + itemLore: Descripcion del objeto + itemLoreLore: Comparar descripcion de los artículos + itemName: Nombre del artículo + itemNameLore: Comparar nombres de artículos + material: Material del artículo + materialLore: Compara el material del objeto (i.e. piedra, espada de hierro...) + name: Comparaciones de artículos + repairCost: Coste de reparación + repairCostLore: Compara el coste de reparación de armaduras y espadas + itemCreator: + isQuestItem: '§bObjeto de misión:' + itemFlags: Alternar variables de elementos + itemLore: '§bDescripcion del objeto' + itemName: '§bNombre del objeto' + itemType: '§bTipo de artículo' + name: Creador de objetos itemSelect: name: Elegir elemento + itemsSelect: + name: Editar elementos + none: '§aMueve un elemento aquí o haz click para abrir el editor de objetos.' + listAllQuests: + name: Misiones + listBook: + noQuests: No se han creado misiones previamente. + questMultiple: Varias veces + questName: Nombre + questRewards: Recompensas + questStages: Etapas + questStarter: Interruptor + requirements: Requisitos + listPlayerQuests: + name: 'Misiones de {player_name}' + listQuests: + canRedo: '§3§oPuedes reiniciar esta misión!' + finished: Misiones finalizadas + inProgress: Misiones en progreso + loreCancelClick: '§cCancela la misión' + loreDialogsHistoryClick: '§7Ver los diálogos' + loreStart: '§a§oClic para comenzar la misión.' + loreStartUnavailable: '§c§oNo cumples los requisitos para empezar la misión.' + notStarted: Misiones no comenzadas + timeToWaitRedo: '§3§oPuedes reiniciar esta misión en {time_left}.' + timesFinished: '§3Mision Finalizada {times_finished} veces.' + mobSelect: + boss: '§6Selecciona un Boss' + bukkitEntityType: '§eSeleccionar tipo de entidad' + epicBoss: '§6Selecciona un Epic Boss' + mythicMob: '§6Selecciona un mob mítico' + name: Seleccionar tipo de mob + mobs: + name: Seleccionar mobs + none: '§aClic para añadir un Mob.' + setLevel: Nivel mínimo npcCreate: + move: + itemLore: '§aCambiar la ubicación del NPC.' + itemName: '§eMover' + moveItem: '§a§lValidar lugar' name: Crear NPC setName: '§eEditar nombre NPC' setSkin: '§eEdit NPC skin' setType: '§eEditar tipo NPC' - move: - itemName: '§eMover' - itemLore: '§aCambiar la ubicación del NPC.' - moveItem: '§a§lValidar lugar' npcSelect: + createStageNPC: '&eCrea un NPC' name: '¿Seleccionar o crear?' selectStageNPC: '§eSeleccionar NPC existente' - createStageNPC: '&eCrea un NPC' - entityType: - name: Elija el tipo de entidad - chooseQuest: - name: '¿Qué misión?' - menu: '§aMenú de Misiones' - menuLore: Te lleva a tu Menú de Misiones. - mobs: - name: Seleccionar mobs - none: '§aClic para añadir un Mob.' - clickLore: |- - §a§lHaz clic izquierdo§a para editar la cantidad. - §a§l§nShift§l + clic izquierdo§l para editar el nombre del ratón. - §c§lHaz clic derecho§c para eliminar. - setLevel: Nivel mínimo - mobSelect: - name: Seleccionar tipo de mob - bukkitEntityType: '§eSeleccionar tipo de entidad' - mythicMob: '§6Selecciona un mob mítico' - epicBoss: '§6Selecciona un Epic Boss' - boss: '§6Selecciona un Boss' - stageEnding: - locationTeleport: '§eEditar lugar de teletransportación' - command: '§eEditar comando ejecutado' - requirements: - name: Requerimientos - rewards: - name: Recompensas - commands: 'Comandos: {0}' - teleportation: |- - §aSeleccionado: - X: {0} - Y: {1} - Z: {2} - Mundo: {3} - random: - rewards: Editar recompensas - minMax: Editar mínimo y máximo - checkpointActions: - name: Acciones de puntos de control - cancelActions: - name: Cancelar acciones - rewardsWithRequirements: - name: Recompensas con requisitos - listAllQuests: - name: Misiones - listPlayerQuests: - name: 'Misiones de {0}' - listQuests: - notStarted: Misiones no comenzadas - finished: Misiones finalizadas - inProgress: Misiones en progreso - loreDialogsHistoryClick: '§7Ver los diálogos' - loreCancelClick: '§cCancela la misión' - loreStart: '§a§oClic para comenzar la misión.' - loreStartUnavailable: '§c§oNo cumples los requisitos para empezar la misión.' - timeToWaitRedo: '§3§oPuedes reiniciar esta misión en {0}.' - canRedo: '§3§oPuedes reiniciar esta misión!' - timesFinished: '§3Mision Finalizada {0} veces.' - itemCreator: - name: Creador de objetos - itemType: '§bTipo de artículo' - itemFlags: Alternar variables de elementos - itemName: '§bNombre del objeto' - itemLore: '§bDescripcion del objeto' - isQuestItem: '§bObjeto de misión:' - command: - name: Comando - value: '§eComando' - console: Consola - parse: Analizar marcadores de posición (placeholders) - delay: '§bRetraso' - chooseAccount: - name: '¿Qué cuenta?' - listBook: - questName: Nombre - questStarter: Interruptor - questRewards: Recompensas - questMultiple: Varias veces - requirements: Requisitos - questStages: Etapas - noQuests: No se han creado misiones previamente. - commandsList: - name: Lista de comandos - value: '§Comando: {0}' - console: '§eConsole: {0}' - block: - name: Elegir bloque - material: '§eMaterial: {0}' - materialNotItemLore: 'El bloque elegido no puede mostrarse como objeto. Todavía se almacena correctamente como {0}.' - blockData: '§dBlockdata (avanzado)' - blockTag: '§dEtiqueta (avanzado)' - blockTagLore: 'Elija una etiqueta que describa una lista de posibles bloques. Las etiquetas se pueden personalizar usando datapacks. Puedes encontrar la lista de etiquetas en la wiki de Minecraft.' - blocksList: - name: Seleccionar bloques - addBlock: '§aClick para añadir un bloque.' - blockAction: - name: Seleccionar acción de bloque - location: '§eSelecciona una ubicación precisa' - material: '§eSelecciona un material de bloque' - buckets: - name: Tipo de cubo + particleEffect: + color: '§bColor de partícula' + name: Crear efecto de partículas + shape: '§dForma de partícula' + type: '§eTipo de partícula' + particleList: + colored: Partícula de color + name: Lista de partículas permission: name: Elegir permiso perm: '§aPermiso' - world: '§aMundo' - worldGlobal: '§b§lGlobal' remove: Quitar permiso removeLore: '§7El permiso será retirado de\n§7en lugar de dado.' + world: '§aMundo' + worldGlobal: '§b§lGlobal' permissionList: name: Lista de permisos - removed: '§eDesactivado: §6{0}' - world: '§eMundo: §6{0}' - classesRequired.name: Clases requeridas - classesList.name: Lista de clases - factionsRequired.name: Facciones requeridas - factionsList.name: Lista de facciones - poolsManage: - name: Grupos de Misiones - itemName: '§aGrupo #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Misiones máximas: §7{0}' - poolQuestsPerLaunch: '§8Misiones dadas por lanzamiento: §7{0}' - poolRedo: '§8Puede rehacer misiones completadas: §7{0}' - poolTime: '§8Tiempo entre misiones: §7{0}' - poolHologram: '§8Texto del Holograma: §7{0}' - poolAvoidDuplicates: '§8Evitar duplicados: §7{0}' - poolQuestsList: '§7{0} §8Misión(s): §7{1}' - create: '§aCrear conjunto de misiones' - edit: '§e> §6§oEditar el conjunto... §e<' - choose: '§e> §6§oElige este grupo §e<' + removed: '§eDesactivado: §6{permission_removed}' + world: '§eMundo: §6{permission_world}' poolCreation: - name: Creación del conjunto de misiones + avoidDuplicates: Evitar duplicados + avoidDuplicatesLore: '§8> §7Intenta evitar hacer\n la misma misión una y otra vez.' hologramText: '§eHolograma personalizado grupal' maxQuests: '§aMximas misiones' + name: Creación del conjunto de misiones questsPerLaunch: '§aMisiones iniciadas por lanzamiento' - time: '§bEstablecer tiempo entre misiones' redoAllowed: Está permitido rehacer - avoidDuplicates: Evitar duplicados - avoidDuplicatesLore: '§8> §7Intenta evitar hacer\n la misma misión una y otra vez.' requirements: '§bRequerimientos para iniciar una misión' + time: '§bEstablecer tiempo entre misiones' poolsList.name: Grupos de misiones - itemComparisons: - name: Comparaciones de artículos - bukkit: Comparación nativa de Bukkit - bukkitLore: "Utiliza el sistema predeterminado de comparación de artículos de Bukkit.\nCompara material, durabilidad, etiquetas..." - customBukkit: Comparación nativa de bukkit - NO NBT - customBukkitLore: "Utiliza el sistema de comparación de artículos por defecto de Bukkit, pero elimina las etiquetas NBT.\nCompara material, durabilidad..." - material: Material del artículo - materialLore: 'Compara el material del objeto (i.e. piedra, espada de hierro...)' - itemName: Nombre del artículo - itemNameLore: Comparar nombres de artículos - itemLore: Descripcion del objeto - itemLoreLore: Comparar descripcion de los artículos - enchants: Encantamientos de los articulos - enchantsLore: Comparar los encantamientos de los articulos - repairCost: Coste de reparación - repairCostLore: Compara el coste de reparación de armaduras y espadas - editTitle: - name: Editar título - title: '§6Título' - subtitle: '§eSubtítulo' - fadeIn: '§aDuración del Fade-in' - stay: '§bDuración' - fadeOut: '§aDuración del Fade-out' - particleEffect: - name: Crear efecto de partículas - shape: '§dForma de partícula' - type: '§eTipo de partícula' - color: '§bColor de partícula' - particleList: - name: Lista de partículas - colored: Partícula de color - damageCause: - name: Causa de daño - damageCausesList: - name: Lista de causas de daño + poolsManage: + choose: '§e> §6§oElige este grupo §e<' + create: '§aCrear conjunto de misiones' + edit: '§e> §6§oEditar el conjunto... §e<' + itemName: '§aGrupo #{pool}' + name: Grupos de Misiones + poolAvoidDuplicates: '§8Evitar duplicados: §7{pool_duplicates}' + poolHologram: '§8Texto del Holograma: §7{pool_hologram}' + poolMaxQuests: '§8Misiones máximas: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8Misión(s): §7{pool_quests}' + poolQuestsPerLaunch: '§8Misiones dadas por lanzamiento: §7{pool_quests_per_launch}' + poolRedo: '§8Puede rehacer misiones completadas: §7{pool_redo}' + poolTime: '§8Tiempo entre misiones: §7{pool_time}' + requirements: + name: Requerimientos + rewards: + commands: 'Comandos: {amount}' + name: Recompensas + random: + minMax: Editar mínimo y máximo + rewards: Editar recompensas + rewardsWithRequirements: + name: Recompensas con requisitos + search: '§e§lBuscar' + stageEnding: + command: '§eEditar comando ejecutado' + locationTeleport: '§eEditar lugar de teletransportación' + stages: + branchesPage: '§dRamas de las etapas' + descriptionTextItem: '§eEditar descripción' + endingItem: '§eEditar recompensas finales' + laterPage: '§ePágina anterior' + name: Crear etapas + newBranch: '§eIr a una nueva rama' + nextPage: '§eSiguiente página' + previousBranch: '§eRegresa a la rama anterior' + regularPage: '§aEtapas regulares' + validationRequirements: '§eRequisitos de validación' + validationRequirementsLore: Todos los requisitos deben coincidir con el jugador que intenta completar la etapa. Si no, la etapa no se puede completar. + validate: '§b§lValidar' visibility: + finished: 'Pestaña de menú: "Finalizado"' + inProgress: 'Pestaña de menú: "En progreso"' + maps: Mapas (como dynmap o BlueMap) name: Visibilidad de la misión notStarted: 'Pestaña de menú: "No iniciado"' - inProgress: 'Pestaña de menú: "En progreso"' - finished: 'Pestaña de menú: "Finalizado"' - maps: 'Mapas (como dynmap o BlueMap)' - equipmentSlots: - name: Ranuras de equipamiento -scoreboard: - name: '§6§lMisión' - noLaunched: '§cNo hay misiones en curso.' - noLaunchedName: '§c§lCargando' - noLaunchedDescription: '§c§oCargando' - textBetwteenBranch: '§e o' - asyncEnd: '§ex' - stage: - region: '§eEncontrar región §6{0}' - npc: '§eHablar con NPC §6{0}' - items: '§eTrae objetos a §6{0}§e:' - mobs: '§eMata §6{0}' - mine: '§eMina {0}' - placeBlocks: '§eColocar {0}' - chat: '§eEscribir §6{0}' - interact: '§eClick en el bloque en §6{0}' - interactMaterial: '§eHaz clic en un bloque §6{0}§e' - fish: '§ePez §6{0}' - melt: '§eCocinar §6{0}' - enchant: '§eEncantar §6{0}' - craft: '§eCraftear §6{0}' - bucket: '§eRellenar §6{0}' - location: '§eIr a §6{0}§e, §6{1}§e, §6{2}§e en §6{3}' - playTimeFormatted: '§eComenzar §6{0}' - breed: '§eReproducir §6{0}' - tame: '§eDomar §6{0}' - die: '§cMuerte' - dealDamage: - any: '§cCausa {0} de daño' - mobs: '§cCausa {0} de daño a {1}' - eatDrink: '§eConsumir §6{0}' -indication: - startQuest: '§7Quieres iniciar la misión {0}?' - closeInventory: '§7¿Estás seguro de que quieres cerrar la GUI?' - cancelQuest: '§7Estás seguro de que quieres cancelar la misión {0}?' - removeQuest: '§7¿Estás seguro de que quieres eliminar la misión {0}?' -description: - requirement: - title: '§8§lRequisitos:' - level: 'Nivel {0}' - jobLevel: 'Nivel {0} de {1}' - combatLevel: 'Nivel de combate {0}' - skillLevel: 'Nivel {0} de {1}' - class: 'Clase {0}' - faction: 'Facción {0}' - quest: 'Finalizar misión §e{0}' - reward: - title: '§8§lRecompensas:' misc: - format: - prefix: '§6<§e§lMisiones§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - offText: '§r§e{0}' - time: - weeks: '{0} semanas' - days: '{0} días' - hours: '{0} horas' - minutes: '{0} minutos' - lessThanAMinute: 'menos de un minuto' - stageType: - region: Buscar región - npc: Buscar NPC - items: Traer elementos - mobs: Mata mobs - mine: Romper bloques - placeBlocks: Colocar bloques - chat: Escribir en el chat - interact: Interactuar con el bloque - Fish: Captura de peces - Melt: Cocinar objetos - Enchant: Encantar objetos - Craft: Fabrica objetos - Bucket: Rellenar cubo - location: Buscar ubicación - playTime: Tiempo de juego - breedAnimals: Reproducir Animales - tameAnimals: Domar animales - die: Morir - dealDamage: Inflige daño. - eatDrink: Comer o beber - comparison: - equals: igual a {0} - different: diferente a {0} - less: estrictamente menos de {0} - lessOrEquals: menos de {0} - greater: estrictamente mayor que {0} - greaterOrEquals: mayor que {0} - requirement: - logicalOr: '§dLógica O (requerimientos)' - skillAPILevel: '§bSkillAPI nivel requerido' - class: '§bClase(s) requerida' - faction: '§bFacción(es) requerida(s)' - jobLevel: '§bNivel de trabajo requerido' - combatLevel: '§bNivel de combate requerido' - experienceLevel: '§bNivel de experiencia requerida' - permissions: '§3Permiso(s) requeridos' - scoreboard: '§dPuntuación requerida' - region: '§dRequiere una Region' - placeholder: '§bValor de placeholder requerido' - quest: '§aMisión requerida' - mcMMOSkillLevel: '§dNivel de habilidad requerida' - money: '§dDinero requerido' - equipment: '§eEquipamiento requerido' + amount: '§eCantidad: {amount}' + amounts: + comparisons: '{comparisons_amount} comparación(es)' + dialogLines: '{lines_amount} línea(s)' + items: '{items_amount} objeto(s)' + permissions: '{permissions_amount} permiso(s)' + and: "y" bucket: - water: Balde de agua lava: Balde de lava milk: Balde de leche snow: Cubo de nieve + water: Balde de agua click: - right: Click derecho left: Clic izquierdo - shift-right: Mayús-Clic derecho - shift-left: Mayús-Clic izquierdo middle: Clic central - amounts: - items: '{0} objeto(s)' - comparisons: '{0} comparación(es)' - dialogLines: '{0} línea(s)' - permissions: '{0} permiso(s)' - mobs: '{0} mob(s)' - ticks: '{0} ticks' - questItemLore: '§e§oObjeto de la misión' - hologramText: '§8§lNPC de la misión' - poolHologramText: '§e¡Nueva misión disponible!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eTipo de entidad: {0}' - entityTypeAny: '§eCualquier entidad' - enabled: Activado + right: Click derecho + shift-left: Mayús-Clic izquierdo + shift-right: Mayús-Clic derecho + comparison: + different: diferente a {number} + equals: igual a {number} + greater: estrictamente mayor que {number} + greaterOrEquals: mayor que {number} + less: estrictamente menos de {number} + lessOrEquals: menos de {number} disabled: Desactivado - unknown: desconocido + enabled: Activado + entityType: '§eTipo de entidad: {entity_type}' + entityTypeAny: '§eCualquier entidad' + format: + prefix: '§6<§e§lMisiones§r§6> §r' + hologramText: '§8§lNPC de la misión' + 'no': 'No' notSet: '§cno colocado' - unused: '§a§lSin usar' - used: '§a§lUsado' - remove: '§7Click central para eliminar' + or: o + poolHologramText: '§e¡Nueva misión disponible!' + questItemLore: '§e§oObjeto de la misión' removeRaw: Eliminar + requirement: + class: '§bClase(s) requerida' + combatLevel: '§bNivel de combate requerido' + equipment: '§eEquipamiento requerido' + experienceLevel: '§bNivel de experiencia requerida' + faction: '§bFacción(es) requerida(s)' + jobLevel: '§bNivel de trabajo requerido' + logicalOr: '§dLógica O (requerimientos)' + mcMMOSkillLevel: '§dNivel de habilidad requerida' + money: '§dDinero requerido' + permissions: '§3Permiso(s) requeridos' + placeholder: '§bValor de placeholder requerido' + quest: '§aMisión requerida' + region: '§dRequiere una Region' + scoreboard: '§dPuntuación requerida' + skillAPILevel: '§bSkillAPI nivel requerido' reset: Reiniciar - or: o - amount: '§eCantidad: {0}' - items: Objetos - expPoints: Puntos de experiencia + stageType: + Bucket: Rellenar cubo + Craft: Fabrica objetos + Enchant: Encantar objetos + Fish: Captura de peces + Melt: Cocinar objetos + breedAnimals: Reproducir Animales + chat: Escribir en el chat + dealDamage: Inflige daño. + die: Morir + eatDrink: Comer o beber + interact: Interactuar con el bloque + items: Traer elementos + location: Buscar ubicación + mine: Romper bloques + mobs: Mata mobs + npc: Buscar NPC + placeBlocks: Colocar bloques + playTime: Tiempo de juego + region: Buscar región + tameAnimals: Domar animales + time: + days: '{days_amount} días' + hours: '{hours_amount} horas' + lessThanAMinute: menos de un minuto + minutes: '{minutes_amount} minutos' + weeks: '{weeks_amount} semanas' + unknown: desconocido 'yes': 'Si' - 'no': 'No' - and: "y" +msg: + bringBackObjects: Tráeme de nuevo {items}. + command: + adminModeEntered: '&aEntraste en el modo Admin.' + adminModeLeft: '&aSaliste del modo Admin.' + backupCreated: '&6Creaste correctamente copias de seguridad de misiones e información.' + backupPlayersFailed: '§cLa creación de la copia de seguridad para toda la información de los jugadores ha fallado.' + backupQuestsFailed: '§cLa creación de la copia de seguridad para todas las misiones ha fallado.' + cancelQuest: '§6Cancelaste la misión {quest}.' + cancelQuestUnavailable: '&cLa misión {quest} no puede ser cancelada.' + checkpoint: + noCheckpoint: '§cNo se ha encontrado ningún punto de control para la misión {quest}.' + questNotStarted: '§cNo estás haciendo esta misión.' + downloadTranslations: + downloaded: '§a¡El idioma {lang} ha sido descargado! §7Ahora debes editar el archivo "/plugins/BeautyQuests/config.yml" para cambiar el valor de §ominecraftTranslationsFile§7 con {lang}, y luego reiniciar el servidor.' + exists: '§cEl archivo {file_name} ya existe. Añade "-overwrite" a tu comando para sobrescribirlo. (/quests downloadTranslations <lang> -overwrite)' + notFound: '§cIdioma {lang} no encontrado para la versión {version}.' + syntax: '§cDebes especificar un idioma para descargar. Ejemplo: "/quests downloadTranslations en_US".' + help: + adminMode: '§6/{label} adminMode: §eActiva el Modo de administración. (Útil para mostrar mensajes de poco registro.)' + create: '§6/{label} create: §eCrea una misión.' + downloadTranslations: '§6/{label} descargaTraducciones <language>: §eDescargas un archivo de traducción de vaina' + edit: '§6/{label} edit: §eEditar una misión.' + header: '§6§lBeautyQuests — Ayuda' + list: '§6/{label} list: §eVer la lista de misiones. (Sólo para versiones soportadas.)' + reload: '§6/{label} reload: §eGuarda y recarga todas las configuraciones y archivos. (§cdeprecado§e)' + remove: '§6/{label} remove <id>: §eElimina una misión con un id especificado o haz clic en el NPC cuando no se haya definido.' + resetPlayer: '§6/{label} restablecido jugador <player>: §eElimina toda la información sobre un jugador.' + resetPlayerQuest: '§6/{label} restablecida la Misión de Jugador <player> [id]: §eElimina información de una misión para un jugador.' + save: '§6/{label} save: §eHacer un guardado manual.' + seePlayer: '§6/{label} seePlayer <player>: §eVer la informacion sobre un jugador' + setFirework: '§6/{label} setFirework: §eEdita el fuego artificial por defecto al finalizar.' + setItem: '§6/{label} setItem <talk|launch>: §eGuarda el elemento del holograma.' + start: '§6/{label} start <player> [id]: §eForzar el inicio de una mision' + startDialog: '§6/{label} startDialog <player> <quest id>: §eComienza el diálogo pendiente para una etapa del NPC o el diálogo de inicio para una misión.' + version: '§6/{label} version: §eVer la versión actual del plugin.' + invalidCommand: + simple: '§cEste comando no existe, escribe §ehelp§c.' + itemChanged: '§aEl elemento ha sido editado. Los cambios afectarán después de un reinicio.' + itemRemoved: '§aEl elemento holograma ha sido eliminado.' + leaveAll: '§aHas forzado el final de {success} misión(s). Errores: {errors}' + removed: '§aLa misión {quest_name} se ha eliminado correctamente.' + resetPlayer: + player: '§6Todas las informaciones de tu misión(s) {quest_amount} han sido eliminadas por {deleter_name}.' + remover: '§6{quest_amount} información(es) de misiones (y {quest_pool} pool) de {player} ha sido eliminada.' + resetPlayerPool: + full: '§aHas reiniciado la {pool} información del grupo en {player}.' + timer: '§aHas reiniciado el {pool} contador del grupo en {player}.' + resetPlayerQuest: + player: '§6Toda la información sobre la misión {quest} fue borrada por {deleter_name}.' + remover: '§6{player} información de {quest} ha sido eliminado.' + resetQuest: '§6Removida información de misiones de {player_amount} jugadores.' + scoreboard: + hidden: '§6El marcador del jugador {player_name} ha sido ocultado.' + lineInexistant: '§cLa línea {line_id} no existe.' + lineRemoved: '§6Has eliminado con éxito la línea {line_id}.' + lineReset: '§6Has restablecido con éxito la línea {line_id}.' + lineSet: '§6Has editado con éxito la línea {line_id}.' + own: + hidden: Su marcador ahora está oculto. + shown: Su marcador se muestra de nuevo + resetAll: '§6Has restablecido el marcador del jugador {player_name} con éxito.' + shown: '§6El marcador del jugador {player_name} ha sido mostrado.' + setStage: + branchDoesntExist: '§cLa rama con el id {branch_id} no existe.' + doesntExist: '§cLa etapa con el id {stage_id} no existe.' + next: '§aLa etapa ha sido omitida.' + nextUnavailable: '§cLa opción "skip" no está disponible cuando el jugador está al final de una rama.' + set: '§aFase {stage_id} lanzada.' + startDialog: + alreadyIn: '§cEl jugador ya está reproduciendo un diálogo.' + impossible: '§cNo es posible iniciar el diálogo ahora.' + noDialog: '§cEl jugador no tiene un diálogo pendiente.' + success: '§aEmpezó el diálogo para el jugador {player} en la misión {quest}!' + startQuest: '§6Obligaste a empezar la misión {quest} (UUID de Jugador: {player}).' + startQuestNoRequirements: '§cEl jugador no cumple con los requisitos para la misión {quest}... Añade "-overrideRequirements" al final de tu comando para evitar la comprobación de requisitos.' + dialogs: + skipped: '§8§o Diálogo omitido.' + tooFar: '§7§oEstás demasiado lejos de {npc_name}...' + editor: + advancedSpawnersMob: 'Escribe el nombre del spawner personalizado para matar:' + already: '§cYa estás en el editor.' + availableElements: 'Elementos disponibles: §e{available_elements}' + blockAmount: '§aEscribe la cantidad de bloques:' + blockData: '§aEscribe los datos de bloque (datos de bloques disponibles: {available_datas}):' + blockName: '§aEscribe el nombre del bloque:' + blockTag: '§aEscribe la etiqueta de bloque (etiquetas disponibles: §7{available_tags}§a):' + chat: '§2♣§d§kii§a§lSkyblock§d§kii§2♣ §2Estás actualmente en modo editor. Escribe "/quests exitEditor" para forzar la salida del editor. (No se recomienda, considere usar comandos como "close" o "cancelar" para volver al inventario anterior.)' + color: 'Introduzca un color en formato hexadecimal (#XXXXX) o formato RGB (RED GRE BLU).' + colorNamed: Introduzca el nombre de un color. + comparisonTypeDefault: '§aElige el tipo de comparación que quieres entre {available}. La comparación predeterminada es: §e§l{default}§r§a. Escribe §onull§r§a para usarlo.' + dialog: + cleared: '§a{amount} mensaje(s) removido.' + edited: '§aMensaje "§7{msg}§a" editado.' + help: + addSound: '§6addSound <id> <sound>: §eAñade un sonido a un mensaje' + clear: '§6clear: §eBorra todos los mensajes.' + close: '&6close: &eGuardas y validas los mensajes.' + edit: '§6edit <id> <message>: §eEditar un mensaje.' + header: '§6§lBeautyQuests — Ayuda del editor de diálogo' + list: '§6list: §eVer todos los mensajes.' + nothing: '§6noSender <message>: §eAgrega un mensaje sin remitente.' + nothingInsert: '§6nothingInsert <id> <message>: §eInserta un mensaje sin ningún prefijo.' + npc: '§6npc <message>: §eAgrega un mensaje dicho por el NPC.' + npcInsert: '§6npcInsert <id> <message>: §eInsertar un mensaje dicho por el NPC.' + npcName: '§6Nombre del npc [custom NPC name]: §eEstablecido (o restablecido a default) nombre personalizado del NPC en el diálogo' + player: '§6player <message>: §eAgrega un mensaje dicho por el jugador.' + playerInsert: '§6playerInsert <id> <message>: §eInsertar un mensaje dicho por el jugador' + remove: '§6remove <id>: §eRemover un mensaje.' + setTime: '§6setTime <id> <time>: §eEstablece el tiempo (en ticks) despues de que el siguiente mensaje aparezca automaticamente' + skippable: '§6skippable [true|false]: §eEstablecer si el diálogo puede ser omitido o no.' + messageRemoved: '§aMensaje "§7{msg}§a" eliminado.' + noSender: '§aMensaje "§7{msg}§a" añadido sin remitente.' + npc: '§aMensaje "§7{msg}§a" añadido al NPC.' + npcName: + set: '§aNombre de NPC establecido a §7{new_name}§a (era §7{old_name}§a)' + unset: '§aNombre de NPC personalizado restablecido por defecto (§7{old_name}§a)' + player: '§aMensaje "§7{msg}§a" añadido por el jugador.' + skippable: + set: '§aEl estado del diálogo ignorable se modificó a §7{new_state}§a (era §7{old_state}§a)' + unset: '§aEl estado del diálogo ignorable se restableció al original (era §7{old_state}§a)' + soundAdded: '§aSonido "§7{sound}§a" agregado al mensaje "§7{msg}§a".' + syntaxRemove: '§cSytaxis correcta: remove <id>' + timeRemoved: '§aTiempo eliminado para el mensaje {msg}.' + timeSet: '§aTiempo ha sido editado para el mensaje {msg}: ahora {time} ticks.' + enter: + list: '§c⚠ §7Has introducido un editor de "lista". Usa "add" para añadir líneas. Consulta "help" (sin barra) para ayuda. §eEscribe "close" para salir del editor.' + subtitle: '§2♣§d§kii§a§lSkyblock§d§kii§2♣ §aEscribe "/quests exitEditor" para forzar la salida del editor.' + title: '§6~ Modo editor ~' + firework: + edited: '¡El fuego artificial de la misión fue editado!' + invalid: Este objeto no es un fuego artificial válido. + invalidHand: Debes sostener un fuego artificial en tu mano principal. + removed: '¡El fuego artificial de la misión fue eliminado!' + goToLocation: '§aVe a la ubicación deseada para la etapa y click a la esmeralda.' + invalidColor: El color introducido no es válido. Debe ser hexadecimal o RGB. + invalidPattern: '§cPatrón de expresión inválido §4{input}§c.' + itemCreator: + invalidBlockType: '§cTipo de bloque inválido.' + invalidItemType: '§cTipo de elemento inválido. (El elemento no puede ser un bloque.)' + itemAmount: '§aEscribe la cantidad de objeto(s):' + itemLore: '§aModificar la descripción del objeto: (Escribe "help" para ayuda.)' + itemName: '§aEscribe el nombre del item:' + itemType: '§aEscribe el nombre del tipo de elemento deseado:' + unknownBlockType: '§cTipo de bloque desconocido.' + unknownItemType: '§cTipo de elemento desconocido.' + mythicmobs: + disabled: '§cMythicMob está deshabilitado.' + isntMythicMob: '§cEste Mob Mítico no existe.' + list: '&aToda la lista de "Mythic Mobs":' + noSuchElement: '§cNo hay tal elemento. Los elementos permitidos son: §e{available_elements}' + npc: + choseStarter: '§aElige el NPC que inicia la misión.' + enter: '§aHas click en un NPC, o escribe "cancel".' + notStarter: '§cEste NPC no es un iniciador de misiones.' + pool: + hologramText: Escriba el texto personalizado del holograma para este grupo (o "null" si desea el predeterminado). + maxQuests: Escribe la cantidad máxima de misiones lanzables desde este conjunto + questsPerLaunch: Escribe la cantidad de misiones que se dan cuando los jugadores hacen clic en el NPC. + timeMsg: 'Escribe el tiempo antes de que los jugadores puedan tomar una nueva misión. (Unidad predeterminada: días)' + scoreboardObjectiveNotFound: '§cObjetivo desconocido del marcador.' + selectWantedBlock: '§aHaz clic con el palo en el bloque deseado para la etapa.' + stage: + location: + typeWorldPattern: '§aEscribe una expresión para nombres de mundo:' + text: + argNotSupported: '§cEl argumento {arg} no es compatible.' + chooseJobRequired: '§aEscribir nombre del trabajo deseado:' + chooseLvlRequired: '§aEscribe la cantidad requerida de niveles:' + chooseMoneyRequired: '§aEscribe la cantidad de dinero necesario:' + chooseObjectiveRequired: '§aEscribe el nombre del objetivo.' + chooseObjectiveTargetScore: '§aEscribe la puntuación objetivo para el objetivo.' + choosePermissionMessage: '§aPuedes elegir un mensaje de rechazo si el jugador no tiene el permiso requerido. (Para saltar este paso, escribe "null".)' + choosePermissionRequired: '§aEscribe el permiso requerido para iniciar la misión:' + choosePlaceholderRequired: + identifier: '§aEscribe el nombre de la variable sin el símbolo de porcentaje:' + value: '§aEscribe el valor requerido para la variable §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aEscribe el nombre de la región requerida (debes estar en el mismo mundo).' + chooseSkillRequired: '§aEscribe el nombre de la habilidad requerida:' + reward: + money: '§aEscribe la cantidad del dinero recibido:' + permissionName: '§aEscribe el nombre del permiso.' + permissionWorld: '§aEscribe el mundo en el que el permiso será editado, o "nulo" si quieres ser global.' + random: + max: '§aEscribe la cantidad máxima de recompensas entregadas al jugador (inclusive).' + min: '§aEscribe la cantidad mínima de recompensas entregadas al jugador (inclusive).' + wait: '§aEscribe la cantidad de ticks del juego para esperar: (1 segundo = 20 ticks del juego)' + textList: + added: '§aTexto "§7{msg}§a" añadido.' + help: + add: '§6add <message>: §eAgrega un texto.' + close: '§6close: §eValida los textos añadidos' + header: '§6§lBeautyQuests — Ayuda del editor de listas' + list: '§6list: §eVer todos los textos añadidos' + remove: '§6remove <id>: §eEliminar un texto.' + removed: '§aTexto "§7{msg}§a" eliminado.' + syntax: '§cSintaxis correcta: ' + title: + fadeIn: Escriba la duración de "fade-in", en ticks (20 ticks = 1 segundo). + fadeOut: Escriba la duración de "desvanecer", en ticks (20 ticks = 1 segundo). + stay: Escriba la duración de la estancia, en ticks (20 ticks = 1 segundo). + subtitle: Escribe el texto de subtítulos (o "null" si no quieres ninguno). + title: Escribe el texto del título (o "null" si quieres ninguno). + typeBucketAmount: '§aEscribe la cantidad de cubos a rellenar:' + typeDamageAmount: 'Escribe la cantidad de daño que tiene que hacer el jugador:' + typeGameTicks: '§aEscribe los ticks requeridos:' + typeLocationRadius: '§aEscribe la distancia requerida de la ubicación:' + errorOccurred: '§cHa ocurrido un error, ¡contacta con un administrador! §4§lError: {error}' + experience: + edited: '§aHas cambiado la ganancia de la experiencia de {old_xp_amount} a {xp_amount} puntos.' + indexOutOfBounds: '§cEl número {index} está fuera de límites! Debe estar entre {min} y {max}.' + invalidBlockData: '§cLos datos del bloque {block_data} no son válidos o son incompatibles con el bloque {block_material}.' + invalidBlockTag: '§cEtiqueta de bloque {block_tag} no disponible.' + inventoryFull: '§cTu inventario está lleno, el objeto ha sido abandonado en el suelo.' + moveToTeleportPoint: '§aIr a la ubicación de teletransporte deseada.' + npcDoesntExist: '§cEl NPC con la id {npc_id} no existe.' + number: + invalid: '§c{input} no es un número válido.' + negative: '§cDebes introducir un número positivo!' + notInBounds: '§cTu número debe estar entre {min} y {max}.' + zero: '§cDebes introducir un número distinto de 0!' + pools: + allCompleted: '§7¡Has completado todas las misiones!' + maxQuests: '§cNo puedes tener más de {pool_max_quests} mision(es) al mismo tiempo...' + noAvailable: '§7No hay más misiones disponibles...' + noTime: '§cDebes esperar {time_left} antes de hacer otra misión.' + quest: + alreadyStarted: '§cYa has comenzado la misión!' + cancelling: '§cProceso de creación de la misión cancelada.' + createCancelled: '§c¡La creación o edición a sido cancelada por otro plugin!' + created: '§a¡Felicitaciones! ¡Has creado la misión §e{quest}§a el cual incluye {quest_branches} rama(s)!' + editCancelling: '§cProceso de edición de misión cancelada.' + edited: '§a¡Felicitaciones! ¡Has editado la misión §e{quest}§a el cual incluye ahora {quest_branches} rama(s)!' + finished: + base: '§a¡Felicitaciones! ¡Has finalizado la misión §e{quest_name}§a!' + obtain: '§a¡Obtuviste {rewards}!' + invalidID: '§cLa misión con la id {quest_id} no existe.' + invalidPoolID: '§cEl grupo {pool_id} no existe.' + notStarted: '§cActualmente no estás haciendo esta misión.' + started: '§a¡Has comenzado la misión §r§e{quest_name}§o§6!' + questItem: + craft: '§c¡No puedes usar un objeto de misión para fabricar!' + drop: '§c¡No puedes soltar un objeto de misión!' + eat: '§c¡No puedes comer un objeto de misión!' + quests: + checkpoint: El punto de control de tarea ha sido alcanzado + failed: Has fallado en la búsquedast {quest_name} + maxLaunched: '§cNo puedes tener mas de {quests_max_amount} Misiones al mismo tiempo...' + updated: '§7Misión §e{quest_name}§7 actualizada.' + regionDoesntExists: '§cEsta región no existe. (Tienes que estar en el mismo mundo.)' + requirements: + combatLevel: '§cTu nivel de combate debe ser {long_level}!' + job: '§c¡Tu nivel para el trabajo §e{job_name}§c debe ser {long_level}!' + level: '§c¡Tu nivel debe ser {long_level}!' + money: '§cDebes tener {money}!' + quest: '§cDebes haber terminado la misión §e{quest_name}§c!' + skill: '§cTu nivel para la habilidad §e{skill_name}§c debe ser {long_level}!' + waitTime: '§cDebes esperar {time_left} para poder reiniciar esta misión!' + restartServer: '§7Reinicia tu servidor para ver las modificaciones.' + selectNPCToKill: '§aSelecciona el NPC para matar.' + stageMobs: + listMobs: '§aDebes matar {mobs}.' + typeCancel: '§aEscribe "cancel" para volver al último texto.' + versionRequired: 'Versión requerida: §l{version}' + writeChatMessage: '§aEscribir mensaje requerido: (Añadir "{SLASH}" al principio si quieres un comando)' + writeCommand: '§aEscribe el comando deseado: (El comando es sin "/" y la variable "{PLAYER}" es compatible. Será reemplazado por el nombre del ejecutador.)' + writeCommandDelay: '§aEscriba el retardo de comando deseado, en ticks.' + writeConfirmMessage: '§aEscribe el mensaje de confirmación que se muestra cuando un jugador está a punto de iniciar la misión: (Escribe "null" si quieres el mensaje por defecto.)' + writeDescriptionText: '§aEscribe el texto que describe el objetivo de la etapa:' + writeEndMsg: '§aEscribe el mensaje que se enviará al final de la misión, "null" si quieres el predeterminado o "none" si no quieres ninguno. Puedes usar "{rewards}" que será reemplazado por las recompensas obtenidas.' + writeEndSound: '§aEscribe el nombre del sonido que se reproducirá al jugador al final de la misión, "null" si quieres el predeterminado o "none" si no quieres ninguno:' + writeHologramText: '§aEscribe el texto del holograma: (Escribe "none" si no quieres un holograma y "null" si quieres el texto por defecto.)' + writeMessage: '§aEscribe el mensaje que se enviará al jugador' + writeMobAmount: '§aEscribe la cantidad de mobs a matar:' + writeMobName: '§aEscribe el nombre personalizado del mob para matar:' + writeNPCText: '§aEscribe el dialogo que se le dirá al jugador por el NPC: (Escribe "help" para recibir ayuda.)' + writeNpcName: '§aEscribe el nombre del NPC:' + writeNpcSkinName: '§aEscribe el nombre de la skin del NPC:' + writeQuestDescription: '§aEscribe la descripción de la misión, mostrado en la GUI de misiones del jugador.' + writeQuestMaterial: '§aEscribe el material del item de la misión.' + writeQuestName: '§aEscribe el nombre de tu misión:' + writeQuestTimer: '§aEscriba el tiempo requerido (en minutos) antes de reiniciar la misión: (Escriba "null" si desea el temporizador predeterminado.)' + writeRegionName: '§aEscribe el nombre de la región requerida para este paso:' + writeStageText: '§aEscribe el texto que será enviado al jugador al comienzo del paso:' + writeStartMessage: '§aEscribe el mensaje que será enviado al iniciar la misión, "null" si quieres el predeterminado o "none" si no quieres ninguno' + writeXPGain: '§aEscribe la cantidad de puntos de experiencia que el jugador obtendrá: (Último valor: {xp_amount})' +scoreboard: + asyncEnd: '§ex' + name: '§6§lMisión' + noLaunched: '§cNo hay misiones en curso.' + noLaunchedDescription: '§c§oCargando' + noLaunchedName: '§c§lCargando' + stage: + breed: '§eReproducir §6{mobs}' + bucket: '§eRellenar §6{buckets}' + chat: '§eEscribir §6{text}' + craft: '§eCraftear §6{items}' + dealDamage: + any: '§cCausa {damage_remaining} de daño' + mobs: '§cCausa {damage_remaining} de daño a {target_mobs}' + die: '§cMuerte' + eatDrink: '§eConsumir §6{items}' + enchant: '§eEncantar §6{items}' + fish: '§ePez §6{items}' + interact: '§eClick en el bloque en §6{x}' + interactMaterial: '§eHaz clic en un bloque §6{block}§e' + items: '§eTrae objetos a §6{dialog_npc_name}§e:' + location: '§eIr a §6{target_x}§e, §6{target_y}§e, §6{target_z}§e en §6{target_world}' + melt: '§eCocinar §6{items}' + mine: '§eMina {blocks}' + mobs: '§eMata §6{mobs}' + npc: '§eHablar con NPC §6{dialog_npc_name}' + placeBlocks: '§eColocar {blocks}' + playTimeFormatted: '§eComenzar §6{time_remaining_human}' + region: '§eEncontrar región §6{region_id}' + tame: '§eDomar §6{mobs}' + textBetwteenBranch: '§e o' diff --git a/core/src/main/resources/locales/fr_FR.yml b/core/src/main/resources/locales/fr_FR.yml index 92defc65..d440797b 100644 --- a/core/src/main/resources/locales/fr_FR.yml +++ b/core/src/main/resources/locales/fr_FR.yml @@ -1,842 +1,795 @@ --- -msg: - quest: - finished: - base: '§aFélicitations ! Vous avez complété la quête §e{0}§r§a !' - obtain: '§aVous remportez {0} !' - started: '§aVous commencez la quête §r§e{0}§o§6 !' - created: '§aFélicitations ! Vous avez créé la quête §e{0}§a, qui comporte {1} branche(s) !' - edited: '§aFélicitations ! Vous avez modifié la quête §e{0}§a, qui comporte désormais {1} branche(s) !' - createCancelled: '§cLa création (ou l''édition) de votre quête a été annulée par un plugin tiers.' - cancelling: '§cAnnulation du processus de création de quête.' - editCancelling: '§cAnnulation du processus d''édition de la quête.' - invalidID: '§cLa quête avec l''id {0} n''existe pas.' - invalidPoolID: '§cLe groupe {0} n''existe pas.' - alreadyStarted: '§cVous avez déjà commencé cette quête !' - notStarted: '§cVous ne faites pas cette quête en ce moment.' - quests: - maxLaunched: '§cVous ne pouvez pas avoir plus de {0} quête(s) simultanément...' - nopStep: '§cCette quête ne comporte aucune étape.' - updated: '§7Quête §e{0}§7 actualisée.' - checkpoint: '§7Checkpoint de quête atteint !' - failed: '§cVous avez échoué à la quête {0}...' - pools: - noTime: '§cVous devez attendre {0} avant de faire une autre quête.' - allCompleted: '§7Vous avez terminé toutes les quêtes !' - noAvailable: '§7Il n''y a plus de quête disponible...' - maxQuests: '§cVous ne pouvez pas avoir plus de {0} quête(s) simultanément...' - questItem: - drop: '§cVous ne pouvez pas jeter un objet de quête !' - craft: '§cVous ne pouvez pas utiliser un objet de quête pour crafter !' - eat: '§cVous ne pouvez pas manger un objet de quête !' - stageMobs: - noMobs: '§cCette étape ne nécessite de tuer aucun mob.' - listMobs: '§aIl faut que vous tuiez {0}.' - writeNPCText: '§aÉcrivez le dialogue qui sera dit au joueur par le NPC : (Tapez "help" pour recevoir de l''aide.)' - writeRegionName: '§aEcrivez le nom de la région voulue pour l''étape :' - writeXPGain: '§aÉcrivez le nombre de points d’expérience que le joueur va remporter. (Ancien gain : {0})' - writeMobAmount: '§aEcrivez le nombre de mobs à tuer :' - writeMobName: '§aÉcrivez le nom personnalisé du mob à tuer :' - writeChatMessage: '§aÉcrivez le message requis (rajoutez "{SLASH}" au début pour en faire une commande.)' - writeMessage: '§aÉcrivez le message qui sera envoyé au joueur' - writeStartMessage: '§aÉcrivez le message qui sera envoyé au début de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas :' - writeEndMsg: '§aÉcrivez le message qui sera envoyé à la fin de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas. Vous pouvez utiliser "{0}" qui sera remplacé par les récompenses obtenues.' - writeEndSound: '§aÉcrivez le nom du son qui sera joué au joueur à la fin de la quête, "null" si vous voulez le son par défaut ou "none" si vous n''en voulez pas :' - writeDescriptionText: '§aEcrivez le texte qui décrira le but de l''étape :' - writeStageText: '§aEcrivez le texte qui sera transmis au joueur au début de l''étape :' - moveToTeleportPoint: '§aAllez au lieu de téléportation désiré.' - writeNpcName: '§aEcrivez le nom du NPC :' - writeNpcSkinName: '§aEcrivez le nom du skin du NPC :' - writeQuestName: '§aEcrivez le nom de votre quête :' - writeCommand: '§aÉcrivez la commande : (n''écrivez pas le "/" ; le placeholder "{PLAYER}" est pris en charge. Il sera remplacée par le nom du joueur exécuteur.)' - writeHologramText: '§aEcrivez le texte de l''hologramme. (tapez "none" si vous ne voulez pas d''hologramme, et "null" si vous voulez le texte par défaut.)' - writeQuestTimer: '§aRenseignez le temps nécessaire (en minutes) avant de pouvoir refaire la quête. (Tapez "null" si vous voulez le temps par défaut)' - writeConfirmMessage: '§aÉcrivez le message de confirmation affiché lorsqu''un joueur est sur le point de démarrer la quête : (Tapez "null" si vous voulez le message par défaut).' - writeQuestDescription: '§aÉcrivez la description de la quête, affichée dans l''interface des quêtes du joueur.' - writeQuestMaterial: '§aIndiquez le type d''item pour la quête.' - requirements: - quest: '§cVous devez avoir terminé la quête §e{0}§c !' - level: '§cVotre niveau doit être {0}!' - job: '§cVotre niveau pour le métier §e{1}§c doit être {0}!' - skill: '§cVotre niveau pour la compétence §e{1}§c doit être {0}!' - combatLevel: '§cVotre niveau de combat doit être {0}!' - money: '§cVous devez avoir {0} !' - waitTime: '§cVous devez encore attendre {0} avant de pouvoir recommencer cette quête !' - experience: - edited: '§aVous avez changé le gain d''expérience de {0} à {1} points.' - selectNPCToKill: '§aSélectionnez le NPC à tuer.' - npc: - remove: '§aSuppression du NPC.' - talk: '§aVa parler à un NPC nommé §e{0}§a.' - regionDoesntExists: '§cCette région n''existe pas. (Vous devez être dans le même monde.)' - npcDoesntExist: '§cLa quête avec l''id {0} n''existe pas.' - objectDoesntExist: '§cL''objet avec l''id {0} n''existe pas.' - number: - negative: '§cTu dois entrer un nombre positif !' - zero: '§cTu dois entrer un nombre autre que 0 !' - invalid: '§c{0} n''est pas un nombre valide.' - notInBounds: '§cLa valeur doit être comprise entre {0} et {1}.' - errorOccurred: '§cUne erreur est survenue, prévenez un administrateur ! §4§lCode d''erreur : {0}' - commandsDisabled: '§cVous n''êtes actuellement pas autorisé à exécuter des commandes !' - indexOutOfBounds: '§cLe numéro {0} est hors des limites ! Il doit se trouver entre {1} et {2}.' - invalidBlockData: '§cLa blockdata {0} est invalide ou incompatible avec le bloc {1}.' - invalidBlockTag: '§cTag de bloc {0} indisponible.' - bringBackObjects: Rapporte-moi {0}. - inventoryFull: '§cVotre inventaire est plein, l''item a été jeté au sol.' - playerNeverConnected: '§cImpossible de trouver les informations sur le joueur {0}.' - playerNotOnline: '§cLe joueur {0} n''est pas en ligne.' - playerDataNotFound: '§cLes données du joueur {0} sont introuvables.' - versionRequired: 'Version requise : §l{0}' - restartServer: '§7Redémarrez votre serveur pour voir les modifications.' - dialogs: - skipped: '§8§o Le dialogue a été passé.' - tooFar: '§7§oVous êtes trop loin de {0}...' - command: - downloadTranslations: - syntax: '§cVous devez spécifier une langue à télécharger. Exemple: "/quests downloadTranslations fr_FR".' - notFound: '§cLangue {0} introuvable pour la version {1}.' - exists: '§cLe fichier {0} existe déjà. Ajoutez "-overwrite" à votre commande pour l''écraser. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§aLa langue {0} a été téléchargée ! §7Vous devez maintenant modifier le fichier "/plugins/BeautyQuests/config.yml" pour changer la valeur de §ominecraftTranslationsFile§7 avec {0}, puis redémarrer le serveur.' - checkpoint: - noCheckpoint: '§cAucun checkpoint trouvé pour la quête {0}.' - questNotStarted: '§cVous ne faites pas cette quête.' - setStage: - branchDoesntExist: '§cLa branche avec l''id {0} n''existe pas.' - doesntExist: '§cL''étape avec l''id {0} n''existe pas.' - next: '§aL''étape a été passée.' - nextUnavailable: '§cL''option "passer l''étape" n''est pas disponible quand le joueur est à la fin d''une branche.' - set: '§aL''étape {0} a été lancée.' - startDialog: - impossible: '§cImpossible de démarrer le dialogue maintenant.' - noDialog: '§cLe joueur n''a aucun dialogue en attente.' - alreadyIn: '§cLe joueur est déjà dans un dialogue.' - success: '§aDébut du dialogue pour le joueur {0} dans la quête {1}!' - playerNeeded: '§cVous devez être un joueur pour effectuer cette commande!' - incorrectSyntax: '§cSyntaxe incorrecte.' - noPermission: '§cVous devez disposer de la permission "{0}" pour pouvoir exécuter cette commande !' - invalidCommand: - quests: '§cCette commande n''existe pas, tapez §e/quests help§c.' - simple: '§cCette commande n''existe pas, tapez §ehelp§c.' - needItem: '§cVous devez tenir un item dans votre main principale !' - itemChanged: '§aL''item a été modifié. Le changement prendra effet après redémarrage.' - itemRemoved: '§aL''item de l''hologramme a été supprimé.' - removed: '§aLa quête {0} a bien été supprimée.' - leaveAll: '§aVous avez forcé la fin de {0} quête(s). §c{1} erreur(s).' - resetPlayer: - player: '§6Les données de vos {0} quêtes ont été supprimées par {1}.' - remover: '§6Les données de {0} quête(s) (et {2} pools) pour le joueur {1} ont bien été supprimées.' - resetPlayerQuest: - player: '§6Les données de la quête {0} ont été supprimées par {1}.' - remover: '§6Les données de la quête {1} du joueur {0} ont bien été supprimées.' - resetQuest: '§6Les données de la quête ont été supprimées pour {0} joueurs.' - startQuest: '§6Vous avez forcé le début de la quête {0} (UUID du joueur : {1}).' - startQuestNoRequirements: '§cLe joueur ne remplit pas les conditions pour la quête {0}... Ajoutez "-overrideRequirements" à la fin de votre commande pour ne pas effectuer la vérification des conditions.' - cancelQuest: '§6Vous avez annulé la quête {0}.' - cancelQuestUnavailable: '§cLa quête {0} ne peut être annulée.' - backupCreated: '§6Vous avez créé une sauvegarde des quêtes et des données joueurs avec succès.' - backupPlayersFailed: '§cLa création d''une sauvegarde des données joueur a échoué.' - backupQuestsFailed: '§cLa création d''une sauvegarde des quêtes a échoué.' - adminModeEntered: '§aVous entrez dans le mode Administrateur.' - adminModeLeft: '§aVous sortez du mode Administrateur.' - resetPlayerPool: - timer: '§aVous avez réinitialisé le minuteur de {1} pour le groupe {0}.' - full: '§aVous avez réinitialisé les données de {1} pour le groupe {0}.' - startPlayerPool: - error: 'Impossible de démarrer le groupe {0} pour {1}.' - success: 'Groupe {0} démarré pour {1}. Résultat: {2}' - scoreboard: - lineSet: '§6Vous avez modifié la ligne {0}.' - lineReset: '§6Vous avez réinitialisé la ligne {0}.' - lineRemoved: '§6Vous avez supprimé la ligne {0}.' - lineInexistant: '§cLa ligne {0} n''existe pas.' - resetAll: '§6Vous avez réinitialisé le scoreboard du joueur {0}.' - hidden: '§6Le scoreboard du joueur {0} a été masqué.' - shown: '§6Le scoreboard du joueur {0} est maintenant affiché.' - own: - hidden: '§6Votre scoreboard est désormais caché.' - shown: '§6Votre scoreboard est de nouveau visible.' - help: - header: '§6§lBeautyQuests — Aide' - create: '§6/{0} create : §eCréer une quête.' - edit: '§6/{0} edit : §eModifier une quête.' - remove: '§6/{0} remove <id> : §eSupprimer une quête avec un ID spécifié ou en cliquant sur son NPC.' - finishAll: '§6/{0} finishAll <joueur> : §eFinir toutes les quêtes d''un joueur.' - setStage: '§6/{0} setStage <joueur> <id> [nouvelle branche] [nouvelle étape]: §ePasser l''étape en cours/lancer une branche/lancer une étape pour une branche.' - startDialog: '§6/{0} startDialog <joueur> <id de quête>: §eDémarre le dialogue en attente pour une étape "NPC" ou le dialogue de début d''une quête.' - resetPlayer: '§6/{0} resetPlayer <joueur> : §eSupprimer les données d''un joueur.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <joueur> [id] : §eSupprimer les données d''une seule quête pour un joueur.' - seePlayer: '§6/{0} seePlayer <joueur> : §eVoir les données d''un joueur.' - reload: '§6/{0} reload : §eSauvegarder et recharger les fichiers de configuration/sauvegarde. (§cdéconseillé§e)' - start: '§6/{0} start <joueur> [id] : §eForcer le lancement d''une quête.' - setItem: '§6/{0} setItem <talk|launch> : §eSauvegarder l''item de l''hologramme dans le fichier de données.' - setFirework: '§6/{0} setFirework : §eModifie le feu d''artifice de fin par défaut.' - adminMode: '§6/{0} adminMode : §eMode administrateur (réception d''informations journal)' - version: '§6/{0} version : §eVoir la version du plugin.' - downloadTranslations: '§6/{0} downloadTranslations <langage>: §eTélécharge un fichier de traductions vanilla' - save: '§6/{0} save: §eFaire une sauvegarde manuelles des données.' - list: '§6/{0} list : §eVoir la liste des quêtes (seulement pour les versions supportées).' - typeCancel: '§aTapez "cancel" pour revenir à l''ancien texte.' - editor: - blockAmount: '§aÉcrivez le nombre de blocs :' - blockName: '§aÉcrivez le nom du bloc :' - blockData: '§aÉcrivez la blockdata (blockdatas disponibles : {0}) :' - blockTag: '§aÉcrivez le tag de bloc (tagsdisponibles: §7{0}§a):' - typeBucketAmount: '§aÉcrivez la quantité de seaux à remplir :' - typeDamageAmount: 'Écrivez le nombre de dégâts que le joueur doit infliger :' - goToLocation: '§aAllez à l''emplacement souhaité pour l''étape.' - typeLocationRadius: '§aÉcrivez la distance requise à partir de cet endroit :' - typeGameTicks: '§aEcrivez la quantité de ticks requis :' - already: '§cVous êtes déjà dans un éditeur.' - stage: - location: - typeWorldPattern: '§aÉcrivez une expression régulière (regex) pour les noms de monde :' - enter: - title: '§6~ mode éditeur ~' - subtitle: '§6Entrez "/quests exitEditor" pour forcer la sortie.' - list: '§c⚠ §7Vous êtes entré dans un éditeur "liste". Utilisez "add" pour ajouter des lignes. Tapez "help" (sans slash) pour obtenir de l''aide. §e§lTapez "close" pour quitter l''éditeur.' - chat: '§6Vous êtes actuellement dans le mode éditeur. Entrez "/quests exitEditor" pour forcer la sortie de ce mode (peu recommandé, préférez l''usage de mots-clés tels que "close" ou "cancel" pour revenir à l''inventaire précédent).' - npc: - enter: '§aCliquez sur un NPC, ou tapez "cancel" pour annuler.' - choseStarter: '§aSélectionnez le NPC qui commence la quête.' - notStarter: '§cCe NPC n''est pas lanceur de quête.' - text: - argNotSupported: '§cArgument {0} non supporté.' - chooseLvlRequired: '§aEntrez la quantité de niveaux requise :' - chooseJobRequired: '§aEntrez le nom du le métier voulu :' - choosePermissionRequired: '§aEntrez les permissions requises pour commencer la quête :' - choosePermissionMessage: '§aVous pouvez choisir un message de refus si le joueur n''a pas la permission requise. (pour passer cette étape, entrez "null" et aucun message ne sera envoyé)' - choosePlaceholderRequired: - identifier: '§aEntrez le nom du placeholder requis, sans les pourcentages de début et de fin :' - value: '§aEntrez la valeur requise pour le placeholder §e%§e{0}§e%§a :' - chooseSkillRequired: '§aEntrez le nom de la compétence requise :' - chooseMoneyRequired: '§aEntrez la quantité de monnaie nécessaire :' - reward: - permissionName: '§aIndiquez le nom de la permission.' - permissionWorld: '§aIndiquez le monde dans lequel la permission sera mise à jour, ou "null" si vous voulez que ça le soit partout.' - money: '§aEntrez la quantité de monnaie gagnée :' - wait: '§aÉcrivez le nombre de ticks à attendre : (1 seconde = 20 ticks)' - random: - min: '§aÉcrivez le nombre minimum de récompenses données au joueur (inclus).' - max: '§aÉcrivez le nombre maximum de récompenses données au joueur (inclus).' - chooseObjectiveRequired: '§aÉcrivez le nom de l''objectif.' - chooseObjectiveTargetScore: '§aIndiquez le score visé pour cet objectif.' - chooseRegionRequired: '§aÉcrivez le nom de la région requise (vous devez être dans le même monde).' - selectWantedBlock: '§aCliquez avec le bâton sur le bloc voulu pour l''étape.' - itemCreator: - itemType: '§aEntrez le nom du type d''item voulu :' - itemAmount: '§aÉcrivez le nombre d''item(s) :' - itemName: '§aEntrez le nom de l''item :' - itemLore: '§aModifiez la description de l''item. (Tapez "help" pour obtenir de l''aide.)' - unknownItemType: '§cType d''item inconnu.' - invalidItemType: '§cType d''item invalide (il doit être un item et non un bloc).' - unknownBlockType: '§cType de bloc inconnu.' - invalidBlockType: '§cType de bloc invalide.' - dialog: - syntax: '§cSyntaxe correcte : {0}{1} <message>' - syntaxRemove: '§cSyntaxe correcte : remove <id>' - player: '§aMessage "§7{0}§a" ajouté pour le joueur.' - npc: '§aMessage "§7{0}§a" ajouté pour le NPC.' - noSender: '§aMessage "§7{0}§a" ajouté pour aucune entité parlante.' - messageRemoved: '§aMessage "§7{0}§a" supprimé.' - edited: '§aMessage "§7{0}§a" modifié.' - soundAdded: '§aSon "§7{0}§a" ajouté pour le message "§7{1}§a".' - cleared: '§a{0} messages supprimés.' - help: - header: '§e§lBeautyQuests — §6Aide de l''éditeur de dialogues' - npc: '§6npc <message> : §aAjouter un message dit par le NPC.' - player: '§6player <message> : §eAjouter un message dit par le joueur.' - nothing: '§6noSender <message> : §eAjouter un message exempt d''entité parlante.' - remove: '§6remove <id> : §eSupprimer un message.' - list: '§6list: §eVoir une liste des messages.' - npcInsert: '§6npcInsert <id> <message> : §eInsérer un message dit par le NPC.' - playerInsert: '§6playerInsert <id> <message> : §eInsérer un message dit par le joueur.' - nothingInsert: '§6nothingInsert <id> <message> : §eInsérer un message sans préfixe.' - edit: '§6edit <id> <message>: §eModifier un message.' - addSound: '§6addSound <id> <son> : §eAjouter un son sur un message.' - clear: '§6clear: §eSupprimer tous les messages.' - close: '§6close: §eValider les messages.' - setTime: '§6setTime <id> <time>: §eModifie le temps (en ticks) avant que le message suivant ne se lance.' - npcName: '§6npcName [nom du NPC] : §eModifie (ou remet au nom par défaut) le nom personnalisé du NPC dans le dialogue' - skippable: '§6skippable [true|false] : §eDéfinir si le dialogue peut être ignoré ou non' - timeSet: '§aLe temps a été modifié pour le message {0}: il est maintenant de {1} tick(s).' - timeRemoved: '§aLe temps a été supprimé du message {0}.' - npcName: - set: '§aNom du NPC personnalisé modifié pour §7{1}§a (avant: §7{0}§a)' - unset: '§aNom du NPC personnalisé réinitialisé à la valeur par défaut (était §7{0}§a)' - skippable: - set: '§aStatut "ignorable" du dialogue modifié pour §7{1}§a (avant: §7{0}§a)' - unset: '§aStatut "ignorable" du dialogue remis à la valeur par défaut (était §7{0}§a)' - mythicmobs: - list: '§aListe de tous les MythicMobs :' - isntMythicMob: '§cCe Mythic Mob n''existe pas.' - disabled: '§cMythicMob est désactivé.' - advancedSpawnersMob: 'Écrivez le nom du mob de AdvancedSpawners à tuer :' - textList: - syntax: '§cSyntaxe correcte : ' - added: '§aTexte "§7{0}§a" ajouté.' - removed: '§aTexte "§7{0}§a" supprimé.' - help: - header: '§6§lBeautyQuests — Aide de l''éditeur de liste' - add: '§6add <message> : §eAjouter un texte.' - remove: '§6remove <id> : §eSupprimer un texte.' - list: '§6list: §eVoir tout les textes.' - close: '§6close: §eValider les textes.' - availableElements: 'Éléments disponibles : §e{0}' - noSuchElement: '§cIl n''y a pas d’élément correspondant. Les éléments permis sont : §e{0}' - invalidPattern: '§cRegex invalide: §4{0}§c.' - comparisonTypeDefault: '§aChoissez le type de comparaison que vous voulez parmi {0}. La comparaison par défaut est: §e§l{1}§r§a. Tapez §onull§r§a pour l''utiliser.' - scoreboardObjectiveNotFound: '§cObjectif de scoreboard inconnu.' - pool: - hologramText: 'Écrivez le texte personnalisé de l''hologramme pour ce groupe (ou "null" si vous voulez le texte par défaut).' - maxQuests: 'Écrivez le nombre maximum de quêtes lancées dans ce groupe.' - questsPerLaunch: 'Écrivez le nombre de quêtes données lorsque les joueurs cliquent sur le NPC.' - timeMsg: 'Écrivez le temps avant que les joueurs puissent prendre une nouvelle quête. (Unité par défaut: jours)' - title: - title: 'Écrivez le titre (ou "null" si vous n''en voulez pas).' - subtitle: 'Écrivez le sous-titre (ou "null" si vous n''en voulez pas).' - fadeIn: 'Écrivez la durée du fondu d''entrée, en ticks (20 ticks = 1 seconde).' - stay: 'Écrivez la durée où le titre reste affiché, en ticks (20 ticks = 1 seconde).' - fadeOut: 'Écrivez la durée du fondu de sortie, en ticks (20 ticks = 1 seconde).' - colorNamed: 'Saisissez le nom de la couleur :' - color: 'Entrez une couleur au format hexadécimal (#XXXXX) ou RVB (ROUGE VERT BLEU).' - invalidColor: 'La couleur que vous avez saisie n''est pas valide. Elle doit être hexadécimale ou RVB.' - firework: - invalid: 'Cet objet n''est pas un feu d''artifice valide.' - invalidHand: 'Vous devez tenir un feu d''artifice dans votre main principale.' - edited: 'Feu d''artifice de quête modifié !' - removed: 'Feu d''artifice de quête supprimé !' - writeCommandDelay: '§aIndiquez le délai de commande désiré, en ticks.' advancement: finished: Terminée notStarted: Pas commencée +description: + requirement: + class: Classe {class_name} + combatLevel: Niveau de combat {short_level} + jobLevel: Niveau {short_level} pour {job_name} + level: Niveau {short_level} + quest: Terminer la quête §e{quest_name} + skillLevel: Niveau {short_level} pour {skill_name} + title: '§8§lConditions :' + reward: + title: '§8§lRécompenses :' +indication: + cancelQuest: '§7Êtes-vous sûr de vouloir annuler la quête {quest_name} ?' + closeInventory: '§7Êtes-vous sûr de vouloir fermer l''interface graphique ?' + removeQuest: '§7Êtes-vous sûr de vouloir supprimer la quête {quest} ?' + startQuest: '§7Voulez-vous commencer la quête {quest_name} ?' inv: - validate: '§b§lValider' - cancel: '§c§lAnnuler' - search: '§e§lRechercher' addObject: '§aAjouter un objet' + block: + blockData: '§dBlockdata (avancé)' + blockName: '§bNom de bloc personnalisé' + blockTag: '§dTag (avancé)' + blockTagLore: Choisissez un tag qui décrit une liste de blocs possibles. Les tags peuvent être personnalisés en utilisant des datapacks. Vous pouvez trouver une liste des tags sur le Minecraft Wiki. + material: '§eType de bloc : {block_type}' + materialNotItemLore: Le bloc choisi ne peut pas être affiché comme un item. Il est toujours correctement sauvegardé comme {block_material}. + name: Choisir un bloc + blockAction: + location: '§eSélectionner un emplacement précis' + material: '§eSélectionner un type de bloc' + name: Sélectionner l'action + blocksList: + addBlock: '§aCliquez pour ajouter un block.' + name: Sélectionner des blocs + buckets: + name: Type de seau + cancel: '§c§lAnnuler' + cancelActions: + name: Actions d'annulation + checkpointActions: + name: Actions du checkpoint + chooseAccount: + name: Quel compte ? + chooseQuest: + menu: '§aMenu des Quêtes' + menuLore: Vous ouvre votre menu de Quêtes. + name: Quelle quête ? + classesList.name: Liste des classes + classesRequired.name: Classes requises + command: + console: Console + delay: '§bDélai' + name: Commande + parse: Remplacer les placeholders + value: '§eCommande' + commandsList: + console: '§eConsole : {command_console}' + name: Liste des commandes + value: '§eCommande : {command_label}' confirm: name: Êtes-vous sûr ? - 'yes': '§aConfirmer' 'no': '§cAnnuler' + 'yes': '§aConfirmer' create: - stageCreate: '§aCréer une nouvelle étape' - stageRemove: '§cSupprimer cette étape' - stageUp: Monter - stageDown: Descendre - stageType: '§7Type d''étape: §e{0}' - cantFinish: '§7Vous devez créer au moins une étape avant de terminer la création de la quête !' - findNPC: '§aTrouver un NPC' + NPCSelect: '§eChoisir ou créer un NPC' + NPCText: '§eModifier le dialogue' + breedAnimals: '§aFaire reproduire des animaux' bringBack: '§aRapporter des objets' - findRegion: '§aTrouver une région' - killMobs: '§aTuer des mobs' - mineBlocks: '§aCasser des blocs' - placeBlocks: '§aPoser des blocs' - talkChat: '§aEcrire dans le chat' - interact: '§aCliquez sur un bloc' - fish: '§aPêcher' - melt: '§6Cuire des items' - enchant: '§dEnchanter des items' - craft: '§aFabriquer un objet' bucket: '§aRemplir des seaux' - location: '§aAller à un endroit' - playTime: '§eTemps de jeu' - breedAnimals: '§aFaire reproduire des animaux' - tameAnimals: '§aApprivoiser des animaux' - death: '§cMourir' + cancelMessage: Annuler l'envoi + cantFinish: '§7Vous devez créer au moins une étape avant de terminer la création de la quête !' + changeEntityType: '§eSélectionner un type d''entité' + changeTicksRequired: '§eChanger la quantité de ticks requis' + craft: '§aFabriquer un objet' + currentRadius: '§eDistance actuelle : §6{radius}' dealDamage: '§cInfliger des dégâts à des mobs' + death: '§cMourir' eatDrink: '§aManger ou boire de la nourriture ou des potions' - NPCText: '§eModifier le dialogue' - dialogLines: '{0} lignes' - NPCSelect: '§eChoisir ou créer un NPC' - hideClues: Cacher les particules et les hologrammes - gps: Affiche une boussole vers l'objectif - editMobsKill: '§eModifier les mobs à tuer' - mobsKillFromAFar: Doit être tué de loin editBlocksMine: '§eModifier les blocs à casser' - preventBlockPlace: Empêcher les joueurs de casser leurs propres blocs editBlocksPlace: '§eModifier les blocs à poser' + editBucketAmount: '§eModifier la quantité de seaux à remplir' + editBucketType: '§eModifier le type de seau à remplir' + editFishes: '§eModifier les poissons nécessaires' + editItem: '§eEditer l''objet à fabriquer' + editItemsToEnchant: '§eModifier les items à enchanter' + editItemsToMelt: '§eModifier les items à cuire' + editLocation: '§eModifier l''endroit' editMessageType: '§eModifier le message à écrire' - cancelMessage: Annuler l'envoi + editMobsKill: '§eModifier les mobs à tuer' + editRadius: '§eModifier la distance à partir de l''endroit' + enchant: '§dEnchanter des items' + findNPC: '§aTrouver un NPC' + findRegion: '§aTrouver une région' + fish: '§aPêcher' + hideClues: Cacher les particules et les hologrammes ignoreCase: Ignorer la casse du message + interact: '§aCliquez sur un bloc' + killMobs: '§aTuer des mobs' + leftClick: Clic gauche nécessaire + location: '§aAller à un endroit' + melt: '§6Cuire des items' + mineBlocks: '§aCasser des blocs' + mobsKillFromAFar: Doit être tué de loin + placeBlocks: '§aPoser des blocs' + playTime: '§eTemps de jeu' + preventBlockPlace: Empêcher les joueurs de casser leurs propres blocs replacePlaceholders: Remplacer {PLAYER} et les placeholders de PAPI + selectBlockLocation: '§eSélectionner la position du bloc' + selectBlockMaterial: '§eSélectionner le type de block' selectItems: '§eChoisir les items nécessaires' - selectItemsMessage: '§eModifier le message de demande' selectItemsComparisons: '§eSélectionnez les comparaisons d''items (AVANCÉ)' + selectItemsMessage: '§eModifier le message de demande' selectRegion: '§7Choisir la région' - toggleRegionExit: À la sortie - stageStartMsg: '§eModifier le message de départ' - selectBlockLocation: '§eSélectionner la position du bloc' - selectBlockMaterial: '§eSélectionner le type de block' - leftClick: Clic gauche nécessaire - editFishes: '§eModifier les poissons nécessaires' - editItemsToMelt: '§eModifier les items à cuire' - editItemsToEnchant: '§eModifier les items à enchanter' - editItem: '§eEditer l''objet à fabriquer' - editBucketType: '§eModifier le type de seau à remplir' - editBucketAmount: '§eModifier la quantité de seaux à remplir' - editLocation: '§eModifier l''endroit' - editRadius: '§eModifier la distance à partir de l''endroit' - currentRadius: '§eDistance actuelle : §6{0}' - changeTicksRequired: '§eChanger la quantité de ticks requis' - changeEntityType: '§eSélectionner un type d''entité' stage: - location: - worldPattern: '§aModifier le motif de nom de monde §d(AVANCÉ)' - worldPatternLore: 'Si vous voulez que l''étape soit terminée pour un monde correspondant à un motif spécifique, entrez ici une regex (expression régulière).' - death: - causes: '§aDéfinir les causes de la mort §d(AVANCED)' - anyCause: Toute cause de mort - setCauses: '{0} cause(s) de mort' dealDamage: damage: '§eDégâts à infliger' targetMobs: '§cMobs à heurter' + death: + anyCause: Toute cause de mort + causes: '§aDéfinir les causes de la mort §d(AVANCED)' + setCauses: '{causes_amount} cause(s) de mort' eatDrink: items: '§eModifier les objets à manger ou à boire' - stages: - name: Créer les étapes - nextPage: '§ePage suivante' - laterPage: '§ePage précédente' - endingItem: '§eRécompenses de fin' - descriptionTextItem: '§eModifier le texte de description' - regularPage: '§aÉtapes simples' - branchesPage: '§dÉtapes d''embranchement' - previousBranch: '§eRetourner à la branche précédente' - newBranch: '§eAller à la nouvelle branche' - validationRequirements: '§eConditions de validation' - validationRequirementsLore: Toutes les conditions doivent s'appliquer au joueur qui tente de terminer l'étape. Sinon, l'étape ne peut pas être terminée. + location: + worldPattern: '§aModifier le motif de nom de monde §d(AVANCÉ)' + worldPatternLore: Si vous voulez que l'étape soit terminée pour un monde correspondant à un motif spécifique, entrez ici une regex (expression régulière). + stageCreate: '§aCréer une nouvelle étape' + stageDown: Descendre + stageRemove: '§cSupprimer cette étape' + stageStartMsg: '§eModifier le message de départ' + stageType: '§7Type d''étape: §e{stage_type}' + stageUp: Monter + talkChat: '§aEcrire dans le chat' + tameAnimals: '§aApprivoiser des animaux' + toggleRegionExit: À la sortie + damageCause: + name: Cause de dégât + damageCausesList: + name: Liste des causes de dégât details: - hologramLaunch: '§eModifier l''item de l''hologramme "lancement"' - hologramLaunchLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur peut commencer la quête. - hologramLaunchNo: '§eModifier l''item de l''hologramme "lancement impossible"' - hologramLaunchNoLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur ne peut PAS démarrer la quête. + auto: Démarrer automatiquement à la première connexion + autoLore: Si activé, la quête sera lancée automatiquement lorsque le joueur rejoindra le serveur pour la première fois. + bypassLimit: Ne pas compter la limite de quêtes + bypassLimitLore: Si activé, la quête sera démarrée même si le joueur a atteint son nombre maximum de quêtes en cours. + cancelRewards: '§cActions d''annulation' + cancelRewardsLore: Actions effectuées lorsque les joueurs annulent cette quête. + cancellable: Annulable par le joueur + cancellableLore: Permet au joueur d'annuler la quête par l'intermédiaire de son menu de Quêtes. + createQuestLore: Vous devez définir le nom de la quête. + createQuestName: '§lCréer la quête' customConfirmMessage: '§eModifier le message de confirmation de quête' customConfirmMessageLore: Message affiché dans l'interface de confirmation lorsqu'un joueur est sur le point de commencer la quête. customDescription: '§eModifier la description de la quête' customDescriptionLore: Description affichée sous le nom de la quête dans les interfaces graphiques. - name: Derniers détails de la quête - multipleTime: - itemName: Activer/désactiver la répétition - itemLore: "La quête peut-elle être\nfaite plusieurs fois ?" - cancellable: Annulable par le joueur - cancellableLore: Permet au joueur d'annuler la quête par l'intermédiaire de son menu de Quêtes. - startableFromGUI: Démarrable depuis le GUI - startableFromGUILore: Permet au joueur de commencer la quête depuis son menu de Quêtes. - scoreboardItem: Activer le scoreboard - scoreboardItemLore: Si désactivée, la quête ne sera pas affichée dans le scoreboard. + customMaterial: '§eModifiez l''item de la quête' + customMaterialLore: Item représentant cette quête dans le menu de Quêtes. + defaultValue: '§8(valeur par défaut)' + editQuestName: '§lModifier la quête' + editRequirements: '§eModifier les nécessités' + editRequirementsLore: Toutes les conditions doivent s’appliquer au joueur avant de pouvoir commencer la quête. + endMessage: '§eModifier le message de fin' + endMessageLore: Message qui sera envoyé au joueur à la fin de la quête. + endSound: '§eModifier le son de fin' + endSoundLore: Son qui sera joué à la fin de la quête. + failOnDeath: Échec lors de la mort + failOnDeathLore: La quête sera-t-elle annulée à la mort du joueur ? + firework: '§dFeu d''artifice de fin' + fireworkLore: Feu d'artifice lancé lorsque le joueur termine la quête + fireworkLoreDrop: Déposez votre feu d'artifice personnalisé ici hideNoRequirementsItem: Masquer lorsque les conditions ne sont pas remplies hideNoRequirementsItemLore: Si activé, la quête ne sera pas affichée dans le menu des quêtes lorsque les conditions ne sont pas remplies. - bypassLimit: Ne pas compter la limite de quêtes - bypassLimitLore: Si activé, la quête sera démarrée même si le joueur a atteint son nombre maximum de quêtes en cours. - auto: Démarrer automatiquement à la première connexion - autoLore: Si activé, la quête sera lancée automatiquement lorsque le joueur rejoindra le serveur pour la première fois. + hologramLaunch: '§eModifier l''item de l''hologramme "lancement"' + hologramLaunchLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur peut commencer la quête. + hologramLaunchNo: '§eModifier l''item de l''hologramme "lancement impossible"' + hologramLaunchNoLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur ne peut PAS démarrer la quête. + hologramText: '§eTexte de l''hologramme' + hologramTextLore: Texte affiché sur l'hologramme au-dessus de la tête du NPC de démarrage. + keepDatas: Conserver les données des joueurs + keepDatasLore: 'Forcer le plugin à préserver les données des joueurs, même si les étapes ont été modifiées. §c§lAVERTISSEMENT §c- activer cette option peut endommager les données de vos joueurs.' + loreReset: '§e§lL''avancement de tous les joueurs sera réinitialisé' + multipleTime: + itemLore: La quête peut-elle être faite plusieurs fois ? + itemName: Activer/désactiver la répétition + name: Derniers détails de la quête + optionValue: '§8Valeur : §7{value}' questName: '§a§lModifier le nom de la quête' questNameLore: Un nom doit être défini pour terminer la création de quête. - setItemsRewards: '§eModifier les gains d''item' + questPool: '§eGroupe de quêtes' + questPoolLore: Attacher cette quête à un groupe de quêtes removeItemsReward: '§eRetirer des objets de l''inventaire' - setXPRewards: '§eModifier les gains d''expérience' + requiredParameter: '§7Paramètre requis' + requirements: '{amount} exigence(s)' + rewards: '{amount} récompense(s)' + rewardsLore: Actions effectuées à la fin de la quête. + scoreboardItem: Activer le scoreboard + scoreboardItemLore: Si désactivée, la quête ne sera pas affichée dans le scoreboard. + selectStarterNPC: '§e§lSélectionner le NPC de départ' + selectStarterNPCLore: Cliquer sur le PNJ sélectionné commencera la quête. + selectStarterNPCPool: '§c⚠ Un groupe de quêtes est sélectionné' setCheckpointReward: '§eModifier les récompenses du checkpoints' + setItemsRewards: '§eModifier les gains d''item' + setMoneyReward: '§eModifier le gain de monnaie' + setPermReward: '§eModifier les permissions' setRewardStopQuest: '§cArrêter la quête' - setRewardsWithRequirements: '§eRécompenses avec requirements' setRewardsRandom: '§dRécompenses aléatoires' - setPermReward: '§eModifier les permissions' - setMoneyReward: '§eModifier le gain de monnaie' - setWaitReward: '§eModifier l''attente' + setRewardsWithRequirements: '§eRécompenses avec requirements' setTitleReward: '§eModifier la récompense /title' - selectStarterNPC: '§e§lSélectionner le NPC de départ' - selectStarterNPCLore: Cliquer sur le PNJ sélectionné commencera la quête. - selectStarterNPCPool: '§c⚠ Un groupe de quêtes est sélectionné' - createQuestName: '§lCréer la quête' - createQuestLore: Vous devez définir le nom de la quête. - editQuestName: '§lModifier la quête' - endMessage: '§eModifier le message de fin' - endMessageLore: Message qui sera envoyé au joueur à la fin de la quête. - endSound: '§eModifier le son de fin' - endSoundLore: Son qui sera joué à la fin de la quête. - startMessage: '§eModifier le message de départ' - startMessageLore: Message qui sera envoyé au joueur au début de la quête. + setWaitReward: '§eModifier l''attente' + setXPRewards: '§eModifier les gains d''expérience' startDialog: '§eModifier le dialogue de début' startDialogLore: Dialogue qui sera joué avant le début de la quête lorsque les joueurs cliquent sur le NPC de démarrage. - editRequirements: '§eModifier les nécessités' - editRequirementsLore: Toutes les conditions doivent s’appliquer au joueur avant de pouvoir commencer la quête. + startMessage: '§eModifier le message de départ' + startMessageLore: Message qui sera envoyé au joueur au début de la quête. startRewards: '§6Récompenses de début' startRewardsLore: Actions effectuées au démarrage de la quête. - cancelRewards: '§cActions d''annulation' - cancelRewardsLore: Actions effectuées lorsque les joueurs annulent cette quête. - hologramText: '§eTexte de l''hologramme' - hologramTextLore: Texte affiché sur l'hologramme au-dessus de la tête du NPC de démarrage. + startableFromGUI: Démarrable depuis le GUI + startableFromGUILore: Permet au joueur de commencer la quête depuis son menu de Quêtes. timer: '§bTimer de redémarrage' timerLore: Temps avant que le joueur puisse recommencer la quête. - requirements: '{0} exigence(s)' - rewards: '{0} récompense(s)' - actions: '{0} action(s)' - rewardsLore: Actions effectuées à la fin de la quête. - customMaterial: '§eModifiez l''item de la quête' - customMaterialLore: Item représentant cette quête dans le menu de Quêtes. - failOnDeath: Échec lors de la mort - failOnDeathLore: La quête sera-t-elle annulée à la mort du joueur ? - questPool: '§eGroupe de quêtes' - questPoolLore: Attacher cette quête à un groupe de quêtes - firework: '§dFeu d''artifice de fin' - fireworkLore: Feu d'artifice lancé lorsque le joueur termine la quête - fireworkLoreDrop: Déposez votre feu d'artifice personnalisé ici visibility: '§bVisibilité de la quête' visibilityLore: Choisir dans quels onglets du menu seront affichés la quête et si la quête est visible sur les cartes dynamiques. - keepDatas: Conserver les données des joueurs - keepDatasLore: |- - Forcer le plugin à préserver les données des joueurs, même si les étapes ont été modifiées. - §c§lAVERTISSEMENT §c- activer cette option peut endommager les données de vos joueurs. - loreReset: '§e§lL''avancement de tous les joueurs sera réinitialisé' - optionValue: '§8Valeur : §7{0}' - defaultValue: '§8(valeur par défaut)' - requiredParameter: '§7Paramètre requis' - itemsSelect: - name: Modifier les items - none: |- - §aDéplacez un item ici ou - §acliquez pour ouvrir l'éditeur d'item - itemSelect: - name: Choisissez un objet - npcCreate: - name: Créer le NPC - setName: '§eModifier le nom du NPC' - setSkin: '§eModifier le skin du NPC' - setType: '§eModifier le type du NPC' - move: - itemName: '§eSe déplacer' - itemLore: '§aModifier la position du NPC.' - moveItem: '§a§lValider l''endroit' - npcSelect: - name: Sélectionner ou créer ? - selectStageNPC: '§eSélectionner un NPC existant' - createStageNPC: '§eCréer le NPC' + editTitle: + fadeIn: '§aDurée du fondu d''entrée' + fadeOut: '§aDurée du fondu de sortie' + name: Modifier le titre + stay: '§bDurée statique' + subtitle: '§eSous-titre' + title: '§6Titre' entityType: name: Choisir le type d'entité - chooseQuest: - name: Quelle quête ? - menu: '§aMenu des Quêtes' - menuLore: Vous ouvre votre menu de Quêtes. - mobs: - name: Choisir les mobs - none: '§aCliquer pour ajouter un mob.' - clickLore: |- - §a§lClic gauche§a pour modifier la quantité. - §a§l§nShift§a§l + clic gauche§a pour modifier le nom du mob. - §c§lclic-droit§c pour supprimer. - setLevel: Modifier le niveau minimum - mobSelect: - name: Choisir le type de monstre - bukkitEntityType: '§eSélectionner un type de mob' - mythicMob: '§6Sélectionner un Mythic Mob' - epicBoss: '§6Sélectionner un Epic Boss' - boss: '§6Choisir un Boss' - stageEnding: - locationTeleport: '§eModifier le point de téléportation' - command: '§eModifier la commande exécutée' - requirements: - name: Nécessités - rewards: - name: Récompenses - commands: 'Commandes : {0}' - teleportation: |- - §aSéléctionné : - X : {0} - Y : {1} - Z : {2} - World : {3} - random: - rewards: Modifier les récompenses - minMax: Modifier les quantités min/max - checkpointActions: - name: Actions du checkpoint - cancelActions: - name: Actions d'annulation - rewardsWithRequirements: - name: Récompenses avec requirements - listAllQuests: - name: Quêtes - listPlayerQuests: - name: 'Quêtes de {0}' - listQuests: - notStarted: Quêtes non commencées - finished: Quêtes terminées - inProgress: Quêtes en cours - loreDialogsHistoryClick: '§7Voir les dialogues' - loreCancelClick: '§cAnnuler la quête' - loreStart: '§a§oCliquez pour commencer la quête.' - loreStartUnavailable: '§c§oVous ne remplissez pas les conditions pour commencer la quête.' - timeToWaitRedo: '§3§oVous pouvez refaire cette quête dans {0}.' - canRedo: '§3§oVous pouvez refaire cette quête !' - timesFinished: '§3Quête accomplie {0} fois.' - itemCreator: - name: Créateur d'item - itemType: '§bType d''item' + equipmentSlots: + name: Emplacements d'équipement + factionsList.name: Liste des factions + factionsRequired.name: Factions requises + itemComparisons: + bukkit: Comparaison native de Bukkit + bukkitLore: Utilise le système de comparaison d'items par défaut de Bukkit. Compare le type d'item, la durabilité, les tags nbt... + customBukkit: Comparaison native de Bukkit - SANS NBT + customBukkitLore: Utilise le système de comparaison d'items par défaut de Bukkit, mais efface les balises NBT. Compare le type d'item, la durabilité... + enchants: Enchantements des items + enchantsLore: Compare les enchantements des items + itemLore: Description de l'item + itemLoreLore: Compare les descriptions des items + itemName: Nom de l’objet + itemNameLore: Compare les noms des items + itemsAdder: ItemsAdder + itemsAdderLore: Compare les IDs d'ItemsAdder + material: Type d'item + materialLore: Compare le type d'item (ex. pierre, épée de fer...) + name: Comparaisons d'item + repairCost: Coût de réparation + repairCostLore: Compare les coûts de réparation des armures et des épées + itemCreator: + isQuestItem: '§bItem de quête :' itemFlags: Flags d'item - itemName: '§bNom de l''item' itemLore: '§bDescription de l''item' - isQuestItem: '§bItem de quête :' - command: - name: Commande - value: '§eCommande' - console: Console - parse: Remplacer les placeholders - delay: '§bDélai' - chooseAccount: - name: Quel compte ? + itemName: '§bNom de l''item' + itemType: '§bType d''item' + name: Créateur d'item + itemSelect: + name: Choisissez un objet + itemsSelect: + name: Modifier les items + none: "§aDéplacez un item ici ou \n §acliquez pour ouvrir l'éditeur d'item" + listAllQuests: + name: Quêtes listBook: + noQuests: Aucune quête n'a été préalablement créée. + questMultiple: Plusieurs fois questName: Nom - questStarter: NPC questRewards: Récompenses - questMultiple: Plusieurs fois - requirements: Exigences questStages: Etapes - noQuests: Aucune quête n'a été préalablement créée. - commandsList: - name: Liste des commandes - value: '§eCommande : {0}' - console: '§eConsole : {0}' - block: - name: Choisir un bloc - material: '§eType de bloc : {0}' - materialNotItemLore: 'Le bloc choisi ne peut pas être affiché comme un item. Il est toujours correctement sauvegardé comme {0}.' - blockName: '§bNom de bloc personnalisé' - blockData: '§dBlockdata (avancé)' - blockTag: '§dTag (avancé)' - blockTagLore: 'Choisissez un tag qui décrit une liste de blocs possibles. Les tags peuvent être personnalisés en utilisant des datapacks. Vous pouvez trouver une liste des tags sur le Minecraft Wiki.' - blocksList: - name: Sélectionner des blocs - addBlock: '§aCliquez pour ajouter un block.' - blockAction: - name: Sélectionner l'action - location: '§eSélectionner un emplacement précis' - material: '§eSélectionner un type de bloc' - buckets: - name: Type de seau + questStarter: NPC + requirements: Exigences + listPlayerQuests: + name: 'Quêtes de {player_name}' + listQuests: + canRedo: '§3§oVous pouvez refaire cette quête !' + finished: Quêtes terminées + inProgress: Quêtes en cours + loreCancelClick: '§cAnnuler la quête' + loreDialogsHistoryClick: '§7Voir les dialogues' + loreStart: '§a§oCliquez pour commencer la quête.' + loreStartUnavailable: '§c§oVous ne remplissez pas les conditions pour commencer la quête.' + notStarted: Quêtes non commencées + timeToWaitRedo: '§3§oVous pouvez refaire cette quête dans {time_left}.' + timesFinished: '§3Quête accomplie {times_finished} fois.' + mobSelect: + boss: '§6Choisir un Boss' + bukkitEntityType: '§eSélectionner un type de mob' + epicBoss: '§6Sélectionner un Epic Boss' + mythicMob: '§6Sélectionner un Mythic Mob' + name: Choisir le type de monstre + mobs: + name: Choisir les mobs + none: '§aCliquer pour ajouter un mob.' + setLevel: Modifier le niveau minimum + npcCreate: + move: + itemLore: '§aModifier la position du NPC.' + itemName: '§eSe déplacer' + moveItem: '§a§lValider l''endroit' + name: Créer le NPC + setName: '§eModifier le nom du NPC' + setSkin: '§eModifier le skin du NPC' + setType: '§eModifier le type du NPC' + npcSelect: + createStageNPC: '§eCréer le NPC' + name: Sélectionner ou créer ? + selectStageNPC: '§eSélectionner un NPC existant' + particleEffect: + color: '§bCouleur des particules' + name: Créer un effet de particules + shape: '§dForme de l''effet' + type: '§eType de particules' + particleList: + colored: Particule colorée + name: Liste des particules permission: name: Choisir la permission perm: '§aPermission' - world: '§aMonde' - worldGlobal: '§b§lGlobal' remove: Supprimer la permission removeLore: '§7La permission sera retirée\n§7au lieu d''être donnée.' + world: '§aMonde' + worldGlobal: '§b§lGlobal' permissionList: name: Liste des permissions - removed: '§eRetiré : §6{0}' - world: '§eMonde : §6{0}' - classesRequired.name: Classes requises - classesList.name: Liste des classes - factionsRequired.name: Factions requises - factionsList.name: Liste des factions - poolsManage: - name: Groupe de quêtes - itemName: '§aGroupe #{0}' - poolNPC: '§8NPC : §7{0}' - poolMaxQuests: '§8Nombre maximum de quêtes : §7{0}' - poolQuestsPerLaunch: '§8Quêtes données par lancement : §7{0}' - poolRedo: '§8Peut refaire les quêtes : §7{0}' - poolTime: '§8Temps entre les quêtes : §7{0}' - poolHologram: '§8Hologramme : §7{0}' - poolAvoidDuplicates: '§8Éviter les doublons : §7{0}' - poolQuestsList: '§7{0} §8quête(s) : §7{1}' - create: '§aCréer un groupe de quêtes' - edit: '§e> §6§oModifier le groupe de quêtes... §e<' - choose: '§e> §6§oChoisir ce groupe §e<' + removed: '§eRetiré : §6{permission_removed}' + world: '§eMonde : §6{permission_world}' poolCreation: - name: Création du groupe de quêtes + avoidDuplicates: Éviter les doublons + avoidDuplicatesLore: '§8> §7Essaye d''éviter de faire\n la même quête encore et encore' hologramText: '§eHologramme personnalisé du groupe' maxQuests: '§aNombre maximum de quêtes' + name: Création du groupe de quêtes questsPerLaunch: '§aQuêtes commencées par lancement' - time: '§bDéfinir le temps entre les quêtes' redoAllowed: Est-il recommençable ? - avoidDuplicates: Éviter les doublons - avoidDuplicatesLore: '§8> §7Essaye d''éviter de faire\n la même quête encore et encore' requirements: '§bExigences pour démarrer une quête' + time: '§bDéfinir le temps entre les quêtes' poolsList.name: Groupe de quêtes - itemComparisons: - name: Comparaisons d'item - bukkit: Comparaison native de Bukkit - bukkitLore: "Utilise le système de comparaison d'items par défaut de Bukkit.\nCompare le type d'item, la durabilité, les tags nbt..." - customBukkit: Comparaison native de Bukkit - SANS NBT - customBukkitLore: "Utilise le système de comparaison d'items par défaut de Bukkit, mais efface les balises NBT.\nCompare le type d'item, la durabilité..." - material: Type d'item - materialLore: 'Compare le type d''item (ex. pierre, épée de fer...)' - itemName: Nom de l’objet - itemNameLore: Compare les noms des items - itemLore: Description de l'item - itemLoreLore: Compare les descriptions des items - enchants: Enchantements des items - enchantsLore: Compare les enchantements des items - repairCost: Coût de réparation - repairCostLore: Compare les coûts de réparation des armures et des épées - itemsAdder: ItemsAdder - itemsAdderLore: Compare les IDs d'ItemsAdder - editTitle: - name: Modifier le titre - title: '§6Titre' - subtitle: '§eSous-titre' - fadeIn: '§aDurée du fondu d''entrée' - stay: '§bDurée statique' - fadeOut: '§aDurée du fondu de sortie' - particleEffect: - name: Créer un effet de particules - shape: '§dForme de l''effet' - type: '§eType de particules' - color: '§bCouleur des particules' - particleList: - name: Liste des particules - colored: Particule colorée - damageCause: - name: Cause de dégât - damageCausesList: - name: Liste des causes de dégât + poolsManage: + choose: '§e> §6§oChoisir ce groupe §e<' + create: '§aCréer un groupe de quêtes' + edit: '§e> §6§oModifier le groupe de quêtes... §e<' + itemName: '§aGroupe #{pool}' + name: Groupe de quêtes + poolAvoidDuplicates: '§8Éviter les doublons : §7{pool_duplicates}' + poolHologram: '§8Hologramme : §7{pool_hologram}' + poolMaxQuests: '§8Nombre maximum de quêtes : §7{pool_max_quests}' + poolNPC: '§8NPC : §7{pool_npc_id}' + poolQuestsList: '§7{pool_quests_amount} §8quête(s) : §7{pool_quests}' + poolQuestsPerLaunch: '§8Quêtes données par lancement : §7{pool_quests_per_launch}' + poolRedo: '§8Peut refaire les quêtes : §7{pool_redo}' + poolTime: '§8Temps entre les quêtes : §7{pool_time}' + requirements: + name: Nécessités + rewards: + commands: 'Commandes : {amount}' + name: Récompenses + random: + minMax: Modifier les quantités min/max + rewards: Modifier les récompenses + rewardsWithRequirements: + name: Récompenses avec requirements + search: '§e§lRechercher' + stageEnding: + command: '§eModifier la commande exécutée' + locationTeleport: '§eModifier le point de téléportation' + stages: + branchesPage: '§dÉtapes d''embranchement' + descriptionTextItem: '§eModifier le texte de description' + endingItem: '§eRécompenses de fin' + laterPage: '§ePage précédente' + name: Créer les étapes + newBranch: '§eAller à la nouvelle branche' + nextPage: '§ePage suivante' + previousBranch: '§eRetourner à la branche précédente' + regularPage: '§aÉtapes simples' + validationRequirements: '§eConditions de validation' + validationRequirementsLore: Toutes les conditions doivent s'appliquer au joueur qui tente de terminer l'étape. Sinon, l'étape ne peut pas être terminée. + validate: '§b§lValider' visibility: + finished: 'Onglet du menu "Terminées"' + inProgress: 'Onglet du menu "En cours"' + maps: Cartes (dynmap, BlueMap...) name: Visibilité de la quête notStarted: 'Onglet du menu "Non commencées"' - inProgress: 'Onglet du menu "En cours"' - finished: 'Onglet du menu "Terminées"' - maps: 'Cartes (dynmap, BlueMap...)' - equipmentSlots: - name: Emplacements d'équipement -scoreboard: - name: '§6§lQuêtes' - noLaunched: '§cAucune quête en cours.' - noLaunchedName: '§c§lChargement' - noLaunchedDescription: '§c§oChargement' - textBetwteenBranch: '§e ou' - asyncEnd: '§ex' - stage: - region: '§eTrouve la région §6{0}' - npc: '§eParle au NPC §6{0}' - items: '§eRapporte des items à §6{0} §e:' - mobs: '§eTue {0}' - mine: '§eMine {0}' - placeBlocks: '§ePose {0}' - chat: '§eEcrivez §6{0}' - interact: '§eCliquez sur le bloc à §6{0}' - interactMaterial: '§eCliquez sur un bloc §6{0}§e' - fish: '§ePêchez §6{0}' - melt: '§eCuis §6{0}' - enchant: '§eEnchante §6{0}' - craft: '§eFabriquez §6{0}' - bucket: '§eRemplissez §6{0}' - location: '§eAllez à §6{0}§e, §6{1}§e, §6{2}§e dans §6{3}' - playTimeFormatted: '§eJoue §6{0}' - breed: '§eFaites se reproduire §6{0}' - tame: '§eApprivoisez §6{0}' - die: '§cMourez' - dealDamage: - any: '§cInflige {0} dégâts' - mobs: '§cInflige {0} dégâts à {1}' - eatDrink: '§eConsomme §6{0}' -indication: - startQuest: '§7Voulez-vous commencer la quête {0} ?' - closeInventory: '§7Êtes-vous sûr de vouloir fermer l''interface graphique ?' - cancelQuest: '§7Êtes-vous sûr de vouloir annuler la quête {0} ?' - removeQuest: '§7Êtes-vous sûr de vouloir supprimer la quête {0} ?' -description: - requirement: - title: '§8§lConditions :' - level: 'Niveau {0}' - jobLevel: 'Niveau {0} pour {1}' - combatLevel: 'Niveau de combat {0}' - skillLevel: 'Niveau {0} pour {1}' - class: 'Classe {0}' - faction: 'Faction {0}' - quest: 'Terminer la quête §e{0}' - reward: - title: '§8§lRécompenses :' misc: - format: - prefix: '§6<§e§lQuêtes§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0} :§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0} :§r§e {1}' - offText: '§r§e{0}' - time: - weeks: '{0} semaines' - days: '{0} jours' - hours: '{0} heures' - minutes: '{0} minutes' - lessThanAMinute: 'moins d''une minute' - stageType: - region: Trouver une region - npc: Trouver un NPC - items: Rapporter des items - mobs: Tuer des mobs - mine: Casser des blocs - placeBlocks: Poser des blocs - chat: Parler dans le chat - interact: Intéragir avec un bloc - Fish: Pêcher - Melt: Cuire des items - Enchant: Enchanter des items - Craft: Fabriquer un objet - Bucket: Remplir un seau - location: Trouver un endroit - playTime: Temps de jeu - breedAnimals: Faire reproduire des animaux - tameAnimals: Apprivoiser des animaux - die: Mourir - dealDamage: Infliger des dégâts - eatDrink: Manger ou boire - comparison: - equals: égal à {0} - different: différent de {0} - less: strictement inférieur à {0} - lessOrEquals: inférieur à {0} - greater: strictement supérieur à {0} - greaterOrEquals: supérieur à {0} - requirement: - logicalOr: '§dOU logique (requirements)' - skillAPILevel: '§bNiveau SkillAPI requis' - class: '§bClasse(s) requise(s)' - faction: '§bFaction(s) requise(s)' - jobLevel: '§bNiveau de job requis' - combatLevel: '§bNiveau de combat requis' - experienceLevel: '§bNiveau d''expérience requis' - permissions: '§3Permission(s) requise(s)' - scoreboard: '§dScore requis' - region: '§dRégion requise' - placeholder: '§bPlaceholder requis' - quest: '§aQuête requise' - mcMMOSkillLevel: '§dNiveau de compétence requis' - money: '§dMonnaie requise' - equipment: '§eÉquipement requis' + amount: '§eQuantité : {amount}' + amounts: + comparisons: '{comparisons_amount} comparaison(s)' + dialogLines: '{lines_amount} ligne(s)' + and: et bucket: - water: Seau d'eau lava: Seau de lave milk: Seau de lait snow: Seau de neige + water: Seau d'eau click: - right: Clic droit left: Clic gauche - shift-right: Maj + clic-droit - shift-left: Maj + clic-gauche middle: Clic central - amounts: - items: '{0} item(s)' - comparisons: '{0} comparaison(s)' - dialogLines: '{0} ligne(s)' - permissions: '{0} permission(s)' - mobs: '{0} mob(s)' - ticks: '{0} ticks' - questItemLore: '§e§oItem de Quête' - hologramText: '§8§lNPC de Quête' - poolHologramText: '§eNouvelle quête disponible !' - mobsProgression: '§6§l{0} : §r§e{1}/{2}' - entityType: '§eType d''entité : {0}' - entityTypeAny: '§eN''importe quelle entité' - enabled: Activé + right: Clic droit + shift-left: Maj + clic-gauche + shift-right: Maj + clic-droit + comparison: + different: différent de {number} + equals: égal à {number} + greater: strictement supérieur à {number} + greaterOrEquals: supérieur à {number} + less: strictement inférieur à {number} + lessOrEquals: inférieur à {number} disabled: Désactivé - unknown: inconnu + enabled: Activé + entityType: '§eType d''entité : {entity_type}' + entityTypeAny: '§eN''importe quelle entité' + format: + npcText: '§6[{message_id}/{message_count}] §e§l{npc_name_message} :§r§e {text}' + prefix: '§6<§e§lQuêtes§r§6> §r' + selfText: '§6[{message_id}/{message_count}] §e§l{player_name} :§r§e {text}' + hologramText: '§8§lNPC de Quête' + 'no': 'Non' notSet: '§cnon défini' - unused: '§2§lInutilisé' - used: '§a§lUtilisé' - remove: '§7Clic central pour supprimer' + or: ou + poolHologramText: '§eNouvelle quête disponible !' + questItemLore: '§e§oItem de Quête' removeRaw: Supprimer + requirement: + class: '§bClasse(s) requise(s)' + combatLevel: '§bNiveau de combat requis' + equipment: '§eÉquipement requis' + experienceLevel: '§bNiveau d''expérience requis' + faction: '§bFaction(s) requise(s)' + jobLevel: '§bNiveau de job requis' + logicalOr: '§dOU logique (requirements)' + mcMMOSkillLevel: '§dNiveau de compétence requis' + money: '§dMonnaie requise' + permissions: '§3Permission(s) requise(s)' + placeholder: '§bPlaceholder requis' + quest: '§aQuête requise' + region: '§dRégion requise' + scoreboard: '§dScore requis' + skillAPILevel: '§bNiveau SkillAPI requis' reset: Réinitialiser - or: ou - amount: '§eQuantité : {0}' - items: objets - expPoints: points d'expérience + stageType: + Bucket: Remplir un seau + Craft: Fabriquer un objet + Enchant: Enchanter des items + Fish: Pêcher + Melt: Cuire des items + breedAnimals: Faire reproduire des animaux + chat: Parler dans le chat + dealDamage: Infliger des dégâts + die: Mourir + eatDrink: Manger ou boire + interact: Intéragir avec un bloc + items: Rapporter des items + location: Trouver un endroit + mine: Casser des blocs + mobs: Tuer des mobs + npc: Trouver un NPC + placeBlocks: Poser des blocs + playTime: Temps de jeu + region: Trouver une region + tameAnimals: Apprivoiser des animaux + time: + days: '{days_amount} jours' + hours: '{hours_amount} heures' + lessThanAMinute: moins d'une minute + weeks: '{weeks_amount} semaines' + unknown: inconnu 'yes': 'Oui' - 'no': 'Non' - and: et +msg: + bringBackObjects: Rapporte-moi {items}. + command: + adminModeEntered: '§aVous entrez dans le mode Administrateur.' + adminModeLeft: '§aVous sortez du mode Administrateur.' + backupCreated: '§6Vous avez créé une sauvegarde des quêtes et des données joueurs avec succès.' + backupPlayersFailed: '§cLa création d''une sauvegarde des données joueur a échoué.' + backupQuestsFailed: '§cLa création d''une sauvegarde des quêtes a échoué.' + cancelQuest: '§6Vous avez annulé la quête {quest}.' + cancelQuestUnavailable: '§cLa quête {quest} ne peut être annulée.' + checkpoint: + noCheckpoint: '§cAucun checkpoint trouvé pour la quête {quest}.' + questNotStarted: '§cVous ne faites pas cette quête.' + downloadTranslations: + downloaded: '§aLa langue {lang} a été téléchargée ! §7Vous devez maintenant modifier le fichier "/plugins/BeautyQuests/config.yml" pour changer la valeur de §ominecraftTranslationsFile§7 avec {lang}, puis redémarrer le serveur.' + exists: '§cLe fichier {file_name} existe déjà. Ajoutez "-overwrite" à votre commande pour l''écraser. (/quests downloadTranslations <lang> -overwrite)' + notFound: '§cLangue {lang} introuvable pour la version {version}.' + syntax: '§cVous devez spécifier une langue à télécharger. Exemple: "/quests downloadTranslations fr_FR".' + help: + adminMode: '§6/{label} adminMode : §eMode administrateur (réception d''informations journal)' + create: '§6/{label} create : §eCréer une quête.' + downloadTranslations: '§6/{label} downloadTranslations <langage>: §eTélécharge un fichier de traductions vanilla' + edit: '§6/{label} edit : §eModifier une quête.' + finishAll: '§6/{label} finishAll <joueur> : §eFinir toutes les quêtes d''un joueur.' + header: '§6§lBeautyQuests — Aide' + list: '§6/{label} list : §eVoir la liste des quêtes (seulement pour les versions supportées).' + reload: '§6/{label} reload : §eSauvegarder et recharger les fichiers de configuration/sauvegarde. (§cdéconseillé§e)' + remove: '§6/{label} remove <id> : §eSupprimer une quête avec un ID spécifié ou en cliquant sur son NPC.' + resetPlayer: '§6/{label} resetPlayer <joueur> : §eSupprimer les données d''un joueur.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <joueur> [id] : §eSupprimer les données d''une seule quête pour un joueur.' + save: '§6/{label} save: §eFaire une sauvegarde manuelles des données.' + seePlayer: '§6/{label} seePlayer <joueur> : §eVoir les données d''un joueur.' + setFirework: '§6/{label} setFirework : §eModifie le feu d''artifice de fin par défaut.' + setItem: '§6/{label} setItem <talk|launch> : §eSauvegarder l''item de l''hologramme dans le fichier de données.' + setStage: '§6/{label} setStage <joueur> <id> [nouvelle branche] [nouvelle étape]: §ePasser l''étape en cours/lancer une branche/lancer une étape pour une branche.' + start: '§6/{label} start <joueur> [id] : §eForcer le lancement d''une quête.' + startDialog: '§6/{label} startDialog <joueur> <id de quête>: §eDémarre le dialogue en attente pour une étape "NPC" ou le dialogue de début d''une quête.' + version: '§6/{label} version : §eVoir la version du plugin.' + invalidCommand: + simple: '§cCette commande n''existe pas, tapez §ehelp§c.' + itemChanged: '§aL''item a été modifié. Le changement prendra effet après redémarrage.' + itemRemoved: '§aL''item de l''hologramme a été supprimé.' + leaveAll: '§aVous avez forcé la fin de {success} quête(s). §c{errors} erreur(s).' + removed: '§aLa quête {quest_name} a bien été supprimée.' + resetPlayer: + player: '§6Les données de vos {quest_amount} quêtes ont été supprimées par {deleter_name}.' + remover: '§6Les données de {quest_amount} quête(s) (et {quest_pool} pools) pour le joueur {player} ont bien été supprimées.' + resetPlayerPool: + full: '§aVous avez réinitialisé les données de {player} pour le groupe {pool}.' + timer: '§aVous avez réinitialisé le minuteur de {player} pour le groupe {pool}.' + resetPlayerQuest: + player: '§6Les données de la quête {quest} ont été supprimées par {deleter_name}.' + remover: '§6Les données de la quête {quest} du joueur {player} ont bien été supprimées.' + resetQuest: '§6Les données de la quête ont été supprimées pour {player_amount} joueurs.' + scoreboard: + hidden: '§6Le scoreboard du joueur {player_name} a été masqué.' + lineInexistant: '§cLa ligne {line_id} n''existe pas.' + lineRemoved: '§6Vous avez supprimé la ligne {line_id}.' + lineReset: '§6Vous avez réinitialisé la ligne {line_id}.' + lineSet: '§6Vous avez modifié la ligne {line_id}.' + own: + hidden: '§6Votre scoreboard est désormais caché.' + shown: '§6Votre scoreboard est de nouveau visible.' + resetAll: '§6Vous avez réinitialisé le scoreboard du joueur {player_name}.' + shown: '§6Le scoreboard du joueur {player_name} est maintenant affiché.' + setStage: + branchDoesntExist: '§cLa branche avec l''id {branch_id} n''existe pas.' + doesntExist: '§cL''étape avec l''id {stage_id} n''existe pas.' + next: '§aL''étape a été passée.' + nextUnavailable: '§cL''option "passer l''étape" n''est pas disponible quand le joueur est à la fin d''une branche.' + set: '§aL''étape {stage_id} a été lancée.' + startDialog: + alreadyIn: '§cLe joueur est déjà dans un dialogue.' + impossible: '§cImpossible de démarrer le dialogue maintenant.' + noDialog: '§cLe joueur n''a aucun dialogue en attente.' + success: '§aDébut du dialogue pour le joueur {player} dans la quête {quest}!' + startPlayerPool: + error: Impossible de démarrer le groupe {pool} pour {player}. + success: 'Groupe {pool} démarré pour {player}. Résultat: {result}' + startQuest: '§6Vous avez forcé le début de la quête {quest} (UUID du joueur : {player}).' + startQuestNoRequirements: '§cLe joueur ne remplit pas les conditions pour la quête {quest}... Ajoutez "-overrideRequirements" à la fin de votre commande pour ne pas effectuer la vérification des conditions.' + dialogs: + skipped: '§8§o Le dialogue a été passé.' + tooFar: '§7§oVous êtes trop loin de {npc_name}...' + editor: + advancedSpawnersMob: 'Écrivez le nom du mob de AdvancedSpawners à tuer :' + already: '§cVous êtes déjà dans un éditeur.' + availableElements: 'Éléments disponibles : §e{available_elements}' + blockAmount: '§aÉcrivez le nombre de blocs :' + blockData: '§aÉcrivez la blockdata (blockdatas disponibles : {available_datas}) :' + blockName: '§aÉcrivez le nom du bloc :' + blockTag: '§aÉcrivez le tag de bloc (tagsdisponibles: §7{available_tags}§a):' + chat: '§6Vous êtes actuellement dans le mode éditeur. Entrez "/quests exitEditor" pour forcer la sortie de ce mode (peu recommandé, préférez l''usage de mots-clés tels que "close" ou "cancel" pour revenir à l''inventaire précédent).' + color: 'Entrez une couleur au format hexadécimal (#XXXXX) ou RVB (ROUGE VERT BLEU).' + colorNamed: 'Saisissez le nom de la couleur :' + comparisonTypeDefault: '§aChoissez le type de comparaison que vous voulez parmi {available}. La comparaison par défaut est: §e§l{default}§r§a. Tapez §onull§r§a pour l''utiliser.' + dialog: + cleared: '§a{amount} messages supprimés.' + edited: '§aMessage "§7{msg}§a" modifié.' + help: + addSound: '§6addSound <id> <son> : §eAjouter un son sur un message.' + clear: '§6clear: §eSupprimer tous les messages.' + close: '§6close: §eValider les messages.' + edit: '§6edit <id> <message>: §eModifier un message.' + header: '§e§lBeautyQuests — §6Aide de l''éditeur de dialogues' + list: '§6list: §eVoir une liste des messages.' + nothing: '§6noSender <message> : §eAjouter un message exempt d''entité parlante.' + nothingInsert: '§6nothingInsert <id> <message> : §eInsérer un message sans préfixe.' + npc: '§6npc <message> : §aAjouter un message dit par le NPC.' + npcInsert: '§6npcInsert <id> <message> : §eInsérer un message dit par le NPC.' + npcName: '§6npcName [nom du NPC] : §eModifie (ou remet au nom par défaut) le nom personnalisé du NPC dans le dialogue' + player: '§6player <message> : §eAjouter un message dit par le joueur.' + playerInsert: '§6playerInsert <id> <message> : §eInsérer un message dit par le joueur.' + remove: '§6remove <id> : §eSupprimer un message.' + setTime: '§6setTime <id> <time>: §eModifie le temps (en ticks) avant que le message suivant ne se lance.' + skippable: '§6skippable [true|false] : §eDéfinir si le dialogue peut être ignoré ou non' + messageRemoved: '§aMessage "§7{msg}§a" supprimé.' + noSender: '§aMessage "§7{msg}§a" ajouté pour aucune entité parlante.' + npc: '§aMessage "§7{msg}§a" ajouté pour le NPC.' + npcName: + set: '§aNom du NPC personnalisé modifié pour §7{new_name}§a (avant: §7{old_name}§a)' + unset: '§aNom du NPC personnalisé réinitialisé à la valeur par défaut (était §7{old_name}§a)' + player: '§aMessage "§7{msg}§a" ajouté pour le joueur.' + skippable: + set: '§aStatut "ignorable" du dialogue modifié pour §7{new_state}§a (avant: §7{old_state}§a)' + unset: '§aStatut "ignorable" du dialogue remis à la valeur par défaut (était §7{old_state}§a)' + soundAdded: '§aSon "§7{sound}§a" ajouté pour le message "§7{msg}§a".' + syntaxRemove: '§cSyntaxe correcte : remove <id>' + timeRemoved: '§aLe temps a été supprimé du message {msg}.' + timeSet: '§aLe temps a été modifié pour le message {msg}: il est maintenant de {time} tick(s).' + enter: + list: '§c⚠ §7Vous êtes entré dans un éditeur "liste". Utilisez "add" pour ajouter des lignes. Tapez "help" (sans slash) pour obtenir de l''aide. §e§lTapez "close" pour quitter l''éditeur.' + subtitle: '§6Entrez "/quests exitEditor" pour forcer la sortie.' + title: '§6~ mode éditeur ~' + firework: + edited: Feu d'artifice de quête modifié ! + invalid: Cet objet n'est pas un feu d'artifice valide. + invalidHand: Vous devez tenir un feu d'artifice dans votre main principale. + removed: Feu d'artifice de quête supprimé ! + goToLocation: '§aAllez à l''emplacement souhaité pour l''étape.' + invalidColor: La couleur que vous avez saisie n'est pas valide. Elle doit être hexadécimale ou RVB. + invalidPattern: '§cRegex invalide: §4{input}§c.' + itemCreator: + invalidBlockType: '§cType de bloc invalide.' + invalidItemType: '§cType d''item invalide (il doit être un item et non un bloc).' + itemAmount: '§aÉcrivez le nombre d''item(s) :' + itemLore: '§aModifiez la description de l''item. (Tapez "help" pour obtenir de l''aide.)' + itemName: '§aEntrez le nom de l''item :' + itemType: '§aEntrez le nom du type d''item voulu :' + unknownBlockType: '§cType de bloc inconnu.' + unknownItemType: '§cType d''item inconnu.' + mythicmobs: + disabled: '§cMythicMob est désactivé.' + isntMythicMob: '§cCe Mythic Mob n''existe pas.' + list: '§aListe de tous les MythicMobs :' + noSuchElement: '§cIl n''y a pas d’élément correspondant. Les éléments permis sont : §e{available_elements}' + npc: + choseStarter: '§aSélectionnez le NPC qui commence la quête.' + enter: '§aCliquez sur un NPC, ou tapez "cancel" pour annuler.' + notStarter: '§cCe NPC n''est pas lanceur de quête.' + pool: + hologramText: Écrivez le texte personnalisé de l'hologramme pour ce groupe (ou "null" si vous voulez le texte par défaut). + maxQuests: Écrivez le nombre maximum de quêtes lancées dans ce groupe. + questsPerLaunch: Écrivez le nombre de quêtes données lorsque les joueurs cliquent sur le NPC. + timeMsg: 'Écrivez le temps avant que les joueurs puissent prendre une nouvelle quête. (Unité par défaut: jours)' + scoreboardObjectiveNotFound: '§cObjectif de scoreboard inconnu.' + selectWantedBlock: '§aCliquez avec le bâton sur le bloc voulu pour l''étape.' + stage: + location: + typeWorldPattern: '§aÉcrivez une expression régulière (regex) pour les noms de monde :' + text: + argNotSupported: '§cArgument {arg} non supporté.' + chooseJobRequired: '§aEntrez le nom du le métier voulu :' + chooseLvlRequired: '§aEntrez la quantité de niveaux requise :' + chooseMoneyRequired: '§aEntrez la quantité de monnaie nécessaire :' + chooseObjectiveRequired: '§aÉcrivez le nom de l''objectif.' + chooseObjectiveTargetScore: '§aIndiquez le score visé pour cet objectif.' + choosePermissionMessage: '§aVous pouvez choisir un message de refus si le joueur n''a pas la permission requise. (pour passer cette étape, entrez "null" et aucun message ne sera envoyé)' + choosePermissionRequired: '§aEntrez les permissions requises pour commencer la quête :' + choosePlaceholderRequired: + identifier: '§aEntrez le nom du placeholder requis, sans les pourcentages de début et de fin :' + value: '§aEntrez la valeur requise pour le placeholder §e%§e{placeholder}§e%§a :' + chooseRegionRequired: '§aÉcrivez le nom de la région requise (vous devez être dans le même monde).' + chooseSkillRequired: '§aEntrez le nom de la compétence requise :' + reward: + money: '§aEntrez la quantité de monnaie gagnée :' + permissionName: '§aIndiquez le nom de la permission.' + permissionWorld: '§aIndiquez le monde dans lequel la permission sera mise à jour, ou "null" si vous voulez que ça le soit partout.' + random: + max: '§aÉcrivez le nombre maximum de récompenses données au joueur (inclus).' + min: '§aÉcrivez le nombre minimum de récompenses données au joueur (inclus).' + wait: '§aÉcrivez le nombre de ticks à attendre : (1 seconde = 20 ticks)' + textList: + added: '§aTexte "§7{msg}§a" ajouté.' + help: + add: '§6add <message> : §eAjouter un texte.' + close: '§6close: §eValider les textes.' + header: '§6§lBeautyQuests — Aide de l''éditeur de liste' + list: '§6list: §eVoir tout les textes.' + remove: '§6remove <id> : §eSupprimer un texte.' + removed: '§aTexte "§7{msg}§a" supprimé.' + syntax: '§cSyntaxe correcte : ' + title: + fadeIn: Écrivez la durée du fondu d'entrée, en ticks (20 ticks = 1 seconde). + fadeOut: Écrivez la durée du fondu de sortie, en ticks (20 ticks = 1 seconde). + stay: Écrivez la durée où le titre reste affiché, en ticks (20 ticks = 1 seconde). + subtitle: Écrivez le sous-titre (ou "null" si vous n'en voulez pas). + title: Écrivez le titre (ou "null" si vous n'en voulez pas). + typeBucketAmount: '§aÉcrivez la quantité de seaux à remplir :' + typeDamageAmount: 'Écrivez le nombre de dégâts que le joueur doit infliger :' + typeGameTicks: '§aEcrivez la quantité de ticks requis :' + typeLocationRadius: '§aÉcrivez la distance requise à partir de cet endroit :' + errorOccurred: '§cUne erreur est survenue, prévenez un administrateur ! §4§lCode d''erreur : {error}' + experience: + edited: '§aVous avez changé le gain d''expérience de {old_xp_amount} à {xp_amount} points.' + indexOutOfBounds: '§cLe numéro {index} est hors des limites ! Il doit se trouver entre {min} et {max}.' + invalidBlockData: '§cLa blockdata {block_data} est invalide ou incompatible avec le bloc {block_material}.' + invalidBlockTag: '§cTag de bloc {block_tag} indisponible.' + inventoryFull: '§cVotre inventaire est plein, l''item a été jeté au sol.' + moveToTeleportPoint: '§aAllez au lieu de téléportation désiré.' + npcDoesntExist: '§cLa quête avec l''id {npc_id} n''existe pas.' + number: + invalid: '§c{input} n''est pas un nombre valide.' + negative: '§cTu dois entrer un nombre positif !' + notInBounds: '§cLa valeur doit être comprise entre {min} et {max}.' + zero: '§cTu dois entrer un nombre autre que 0 !' + pools: + allCompleted: '§7Vous avez terminé toutes les quêtes !' + maxQuests: '§cVous ne pouvez pas avoir plus de {pool_max_quests} quête(s) simultanément...' + noAvailable: '§7Il n''y a plus de quête disponible...' + noTime: '§cVous devez attendre {time_left} avant de faire une autre quête.' + quest: + alreadyStarted: '§cVous avez déjà commencé cette quête !' + cancelling: '§cAnnulation du processus de création de quête.' + createCancelled: '§cLa création (ou l''édition) de votre quête a été annulée par un plugin tiers.' + created: '§aFélicitations ! Vous avez créé la quête §e{quest}§a, qui comporte {quest_branches} branche(s) !' + editCancelling: '§cAnnulation du processus d''édition de la quête.' + edited: '§aFélicitations ! Vous avez modifié la quête §e{quest}§a, qui comporte désormais {quest_branches} branche(s) !' + finished: + base: '§aFélicitations ! Vous avez complété la quête §e{quest_name}§r§a !' + obtain: '§aVous remportez {rewards} !' + invalidID: '§cLa quête avec l''id {quest_id} n''existe pas.' + invalidPoolID: '§cLe groupe {pool_id} n''existe pas.' + notStarted: '§cVous ne faites pas cette quête en ce moment.' + started: '§aVous commencez la quête §r§e{quest_name}§o§6 !' + questItem: + craft: '§cVous ne pouvez pas utiliser un objet de quête pour crafter !' + drop: '§cVous ne pouvez pas jeter un objet de quête !' + eat: '§cVous ne pouvez pas manger un objet de quête !' + quests: + checkpoint: '§7Checkpoint de quête atteint !' + failed: '§cVous avez échoué à la quête {quest_name}...' + maxLaunched: '§cVous ne pouvez pas avoir plus de {quests_max_amount} quête(s) simultanément...' + updated: '§7Quête §e{quest_name}§7 actualisée.' + regionDoesntExists: '§cCette région n''existe pas. (Vous devez être dans le même monde.)' + requirements: + combatLevel: '§cVotre niveau de combat doit être {long_level}!' + job: '§cVotre niveau pour le métier §e{job_name}§c doit être {long_level}!' + level: '§cVotre niveau doit être {long_level}!' + money: '§cVous devez avoir {money} !' + quest: '§cVous devez avoir terminé la quête §e{quest_name}§c !' + skill: '§cVotre niveau pour la compétence §e{skill_name}§c doit être {long_level}!' + waitTime: '§cVous devez encore attendre {time_left} avant de pouvoir recommencer cette quête !' + restartServer: '§7Redémarrez votre serveur pour voir les modifications.' + selectNPCToKill: '§aSélectionnez le NPC à tuer.' + stageMobs: + listMobs: '§aIl faut que vous tuiez {mobs}.' + typeCancel: '§aTapez "cancel" pour revenir à l''ancien texte.' + versionRequired: 'Version requise : §l{version}' + writeChatMessage: '§aÉcrivez le message requis (rajoutez "{SLASH}" au début pour en faire une commande.)' + writeCommand: '§aÉcrivez la commande : (n''écrivez pas le "/" ; le placeholder "{PLAYER}" est pris en charge. Il sera remplacée par le nom du joueur exécuteur.)' + writeCommandDelay: '§aIndiquez le délai de commande désiré, en ticks.' + writeConfirmMessage: '§aÉcrivez le message de confirmation affiché lorsqu''un joueur est sur le point de démarrer la quête : (Tapez "null" si vous voulez le message par défaut).' + writeDescriptionText: '§aEcrivez le texte qui décrira le but de l''étape :' + writeEndMsg: '§aÉcrivez le message qui sera envoyé à la fin de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas. Vous pouvez utiliser "{rewards}" qui sera remplacé par les récompenses obtenues.' + writeEndSound: '§aÉcrivez le nom du son qui sera joué au joueur à la fin de la quête, "null" si vous voulez le son par défaut ou "none" si vous n''en voulez pas :' + writeHologramText: '§aEcrivez le texte de l''hologramme. (tapez "none" si vous ne voulez pas d''hologramme, et "null" si vous voulez le texte par défaut.)' + writeMessage: '§aÉcrivez le message qui sera envoyé au joueur' + writeMobAmount: '§aEcrivez le nombre de mobs à tuer :' + writeMobName: '§aÉcrivez le nom personnalisé du mob à tuer :' + writeNPCText: '§aÉcrivez le dialogue qui sera dit au joueur par le NPC : (Tapez "help" pour recevoir de l''aide.)' + writeNpcName: '§aEcrivez le nom du NPC :' + writeNpcSkinName: '§aEcrivez le nom du skin du NPC :' + writeQuestDescription: '§aÉcrivez la description de la quête, affichée dans l''interface des quêtes du joueur.' + writeQuestMaterial: '§aIndiquez le type d''item pour la quête.' + writeQuestName: '§aEcrivez le nom de votre quête :' + writeQuestTimer: '§aRenseignez le temps nécessaire (en minutes) avant de pouvoir refaire la quête. (Tapez "null" si vous voulez le temps par défaut)' + writeRegionName: '§aEcrivez le nom de la région voulue pour l''étape :' + writeStageText: '§aEcrivez le texte qui sera transmis au joueur au début de l''étape :' + writeStartMessage: '§aÉcrivez le message qui sera envoyé au début de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas :' + writeXPGain: '§aÉcrivez le nombre de points d’expérience que le joueur va remporter. (Ancien gain : {xp_amount})' +scoreboard: + asyncEnd: '§ex' + name: '§6§lQuêtes' + noLaunched: '§cAucune quête en cours.' + noLaunchedDescription: '§c§oChargement' + noLaunchedName: '§c§lChargement' + stage: + breed: '§eFaites se reproduire §6{mobs}' + bucket: '§eRemplissez §6{buckets}' + chat: '§eEcrivez §6{text}' + craft: '§eFabriquez §6{items}' + dealDamage: + any: '§cInflige {damage_remaining} dégâts' + mobs: '§cInflige {damage_remaining} dégâts à {target_mobs}' + die: '§cMourez' + eatDrink: '§eConsomme §6{items}' + enchant: '§eEnchante §6{items}' + fish: '§ePêchez §6{items}' + interact: '§eCliquez sur le bloc à §6{x}' + interactMaterial: '§eCliquez sur un bloc §6{block}§e' + items: '§eRapporte des items à §6{dialog_npc_name} §e:' + location: '§eAllez à §6{target_x}§e, §6{target_y}§e, §6{target_z}§e dans §6{target_world}' + melt: '§eCuis §6{items}' + mobs: '§eTue {mobs}' + npc: '§eParle au NPC §6{dialog_npc_name}' + placeBlocks: '§ePose {blocks}' + playTimeFormatted: '§eJoue §6{time_remaining_human}' + region: '§eTrouve la région §6{region_id}' + tame: '§eApprivoisez §6{mobs}' + textBetwteenBranch: '§e ou' diff --git a/core/src/main/resources/locales/hu_HU.yml b/core/src/main/resources/locales/hu_HU.yml index d88f43f1..e41dc448 100644 --- a/core/src/main/resources/locales/hu_HU.yml +++ b/core/src/main/resources/locales/hu_HU.yml @@ -1,339 +1,316 @@ --- -msg: - quest: - finished: - base: '&aSikeresen teljesítetted a következő küldetést §e{0}§a!' - obtain: '§aEzt kaptad: {0}!' - started: '&aElkezdted a következő küldetést §r§e{0}§o§6!' - created: '&aSiker! Létrehoztad a következő küldetést §e{0}§a ami tartalmaz {1} ágat!' - edited: '§aSiker! Szerkeszetted a következő küldetést §e{0}§a ami tartalmaz {1} ágat!' - createCancelled: '§cA szerkesztés vagy az elkészítés megszakítva egy másik plugin miatt!' - cancelling: '§cA küldetés elkészítése közben hiba történt.' - editCancelling: '§cA küldetés szerkesztése megszakítva.' - invalidID: '§cA következő küldetés {0} nem létezik.' - alreadyStarted: '§cMár elkezdted ezt a küldetést!' - quests: - nopStep: '§cEz a küldetés nem tartalmaz lépéseket.' - updated: '§7A következő küldetés §e{0}§7 frissítve.' - checkpoint: '§7Küldetés ellenőrző pont elérve!' - failed: '§cNem sikerült a küldetés{0}' - pools: - noTime: '§cVárnod kell még {0} mielőtt elkezdenél egy újabb küldetést.' - allCompleted: '§7Az összes küldetést teljesítetted!' - noAvailable: '§7Nincsen elérhető küldetések.' - questItem: - drop: '§cKüldetés itemet nem dobhatsz el!' - craft: '§cNem barkácsolhatsz küldetés itemmel!' - stageMobs: - noMobs: '§cEz a lépés nem igényel szörny ölést.' - listMobs: '§aEnnyit megkell ölnöd {0}.' - writeNPCText: '§aÍrd le a párbeszédet amelyet a játékos fog folytatni az NPC vel: (Használd a "help" a segítségért)' - writeRegionName: '§aÍrd a helyet amit kér a küldetés:' - writeXPGain: '§Írd ide az xp mennyiséget amit a játékos kapni fog:(Utolsó érték:{0})' - writeMobAmount: '§aÍrd ide a mennyiséget,hogy mennyi szörnyet kell megölni:' - writeChatMessage: '§aÍrd a következő üzenetet: (Add {SLASH}" az elkezdéshez.)' - writeDescriptionText: '§aÍrd ide a szöveget ami leírja a lépéseket:' - writeStageText: '§aÍrd ide a szöveget amit a játékos fog kapni mikor elkezdi a lépést:' - moveToTeleportPoint: '§aMenj a kért teleportálás helyszínére.' - writeNpcName: '§aÍrd ide az NPC nevét:' - writeNpcSkinName: '§aÍrd ide az NPC skin nevét:' - writeQuestName: '§aÍrd ide a küldetést nevét:' - writeCommand: '§aÍrd ide a parancsot: (A parancs "/" nélkül és a szó "{PLAYER}" engedélyezett. Átlesz helyezve.)' - writeHologramText: '§aÍrd a hologram nevét ide: (Írd "none ha nem akarsz semmit és "null" ha az alap szöveget akarod.)' - writeQuestTimer: '§aÍrd a szükséges időt (percben) amielött újratudod indítani a küldetést: (Írd "null" ha az alapot akarod.)' - writeConfirmMessage: '§aÍrd a megerősítő üzenetet ide:(Írd "null" az alap szöveghez.)' - writeQuestDescription: '§aÍrd ide a leírást amit a játékos látni fog.' - writeQuestMaterial: '§aÍrd ide,hogy milyen tárgy legyen a küldetés.' - requirements: - quest: '§cBekell fejezned a következő küldetést §e{0}§c!' - level: '§cA szintednek a következőnek kell lennie{0}!' - combatLevel: '§aA harc szinted a következőnek kell lennie{0}!' - money: '§cEnnyi kell lennied nállad {0}!' - experience: - edited: '§aMegkell változtatnod az xp-t {0} ről ennyire {1}.' - selectNPCToKill: '§aVálazd ki az NPC akit megkell ölni.' - npc: - remove: '§aNPC kitörölve.' - talk: '§aMenj és beszélj a következő NPC-vel §e{0}§a.' - regionDoesntExists: '§cNem létezik ilyen hely. (Ugyanabban a világban kell lenned.)' - npcDoesntExist: '§cEz az NPC nem létezik {0}.' - objectDoesntExist: '§cA következő tárgy nem létezik {0}.' - number: - negative: '§cMuszály pozitív számot írnod!' - zero: '§cNagyobb számot kell írnod 0-nál!' - invalid: '§c{0} nem érvényes szám.' - errorOccurred: '§cHiba történt, lépj kapcsolatba egy adminisztrátorral! §4§lHiba kód: {0}' - commandsDisabled: '§cJelenleg nem tudsz parancsokat végrehajtani!' - indexOutOfBounds: '§cA szám {0} nem jó! Muszály {1} és {2} között lennie.' - bringBackObjects: Hozz nekem {0}. - inventoryFull: '§cTele van a táskád, a tárgy el lett dobva a földre.' - playerNeverConnected: '§cNem lehet információkat találni a játékosról {0}.' - playerNotOnline: '§cA következő játékos nem elérhető {0}.' - versionRequired: 'Szükséges verzió: §l{0}' - restartServer: '§7Indítsd újra a szervert, hogy lásd a módosításokat.' - dialogs: - skipped: '§8§oPárbeszéd átugorva.' - tooFar: '§7§oTúl messze vagy ettől: {0}...' - command: - checkpoint: - noCheckpoint: '§cNem találtunk ellenörző pontot a küldetéshez {0}' - questNotStarted: '§cNem ezt a küldetést csinálod.' - setStage: - branchDoesntExist: '§cA következő ág nem létezik {0}.' - doesntExist: '§cA következő szint {0} nem létezik.' - next: '§aA szint kihagyva.' - nextUnavailable: '§c A "kihagyás" opció nem elérhető mikor a játékos az ág végén van.' - set: '§aSzint {0} elindítva.' - startDialog: - noDialog: '§cA megadott játékosnak nincsen folyamatban lévő párbeszéde.' - alreadyIn: '§cA játékos már párbeszédben van.' - playerNeeded: '§cJátékos kell lenned, hogy lefuttathasd ezt a parancsot!' - incorrectSyntax: '§cHelytelen szintax.' - noPermission: '§cNincs elég jogod, hogy futtathasd a parancsot! (Szükséges: {0})' - invalidCommand: - quests: '§cEz a parancs nem létezik, írd §e/quests help§c.' - simple: '§cEz a parancs nem létezik, használd §ehelp§c.' - needItem: '§cEgy tárgynak kell lenni a fő kezedben!' - itemChanged: '§aA tárgy szerkesztve. A változtatások az újraindítás után fognak működni.' - itemRemoved: '§aA tárgy hologram eltávolítva.' - removed: '§aA következő küldetés sikeresen eltávolítva {0}.' - leaveAll: '§aKényszerítve lettél, hogy befejezd a következő küldetést {0}. Hibák:{1}' - resetPlayer: - player: '§6Az összes információ a következő küldetésedből {0} törölve lett általa {1}.' - resetPlayerQuest: - player: '§6Az összes infó a küldetésről {0} törölve lett általa {1}.' - remover: '§6Küldetés infó törölve {0} ennyiből {1}.' - resetQuest: '§6Küldetés adat törölve neki {0}.' - startQuest: '§6Kényszerítve lettél, hogy elkezd a következő küldetést {0} (Játékos UUID: {1}).' - startQuestNoRequirements: '§cA megadott játékosnak nincsen meg a szükséges követelményei a(z) {0} küldetéshez... Mellékeld a a "-overrideRequirements" szót a parancsod végére, hogy átugord a követelményeket.' - cancelQuest: '§6Elutasítottad a következő küldetést {0}.' - cancelQuestUnavailable: '§cA küldetés nem elutasítható {0}.' - backupCreated: '§6Sikeresen csináltál mentést.' - backupPlayersFailed: '§cA mentés sikertelen.' - backupQuestsFailed: '§cA mentés sikertelen.' - adminModeEntered: '§aBeléptél az Admin Módba.' - adminModeLeft: '§aKiléptél az Admin Módból.' - scoreboard: - lineSet: '§6Sikeresen átírtad a sort {0}.' - lineReset: '§6Sikeresen újraraktad a sort {0}.' - lineRemoved: '§6Sikeresen eltávolítottad a sort {0}.' - lineInexistant: '§cA sor {0} nem létezik.' - resetAll: '§6Sikeres újrarakás a következő játékosnak {0}.' - hidden: '§6A lista a következő játékosnak {0} láthatatlan.' - shown: '§6A lista következő játékosnak látható {0}.' - own: - hidden: '§6A scoreboard mostantól elvan rejtve.' - shown: '§6A scoreboard mostantól látható.' - help: - header: '§6§lBeautyQuests - Segítség' - create: '§6/{0} létrehoz: §eLétrehoz egy küldetést.' - edit: '§6/{0} szerkesztés: §eSzerkesz egy küldetést.' - remove: '§6/{0} eltávolít <id>:§EKitöröl egy küldetést a meghatározott id-vel vagy kattints az NPC-re.' - finishAll: '§6/{0} befejezmindent <player>: §eBefejezi az összes küldetést.' - setStage: '§6/{0} setStage <player> <id> új ág új szint: §eTovábblépi a jelenlegi szintet.' - resetPlayer: '§6/{0} resetPlayer <player>: §eTöröl minden információt.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <player> [id]: §eDelete információk egy küldetést, hogy egy játékos.' - seePlayer: '§6/{0} seePlayer <player>: §eView információt a játékos.' - reload: '§6/{0} reload: §eSave, majd újra konfigurációk, valamint a fájlok. (§cdeprecated§e)' - start: '§6/{0} start <player> [id]: §eForce a kezdő a küldetést.' - editor: - itemCreator: - itemName: '§aÍrd le az item nevét:' - unknownItemType: '§cIsmeretlen item típus.' - dialog: - help: - player: '§6játékos <message>: §eHozzáad egy szöveget amit a játékos ír.' - nothing: '§6noSender <message>: §eHozzáad egy szöveget küldő nélkül.' - remove: '§6remove <id>: §eEltávolít egy szöveget.' - list: '§6list: §eÖsszes szöveg megnézése.' - npcInsert: '§6npcInsert <id> <message>: §eHozzáadja az összes üzenetet amit az NPC mond.' - playerInsert: '§6playerinsert <id> <message>: §eHozzáad minden üzenetet amit a játékos mond.' - nothingInsert: '§6nothingInsert <id> <message>: §eHozzáad egy üzenetet prefix nélkül.' - addSound: '§6addSound <id> <sound>: §eHangot ad hozzá az üzenethez.' - clear: '§6clear: §eKitörli az összes üzenetet.' - close: '§6close: §eMinden üzenetet ment és kilép.' - setTime: '§6setTime <id> <time>: §eIdőt ad hozzá a szövegek közt.' - timeSet: '§aAz idő szerkesztve az üzenetnek {0}: mostmár {1} tick.' - timeRemoved: '§aIdő eltávolítva ennek az üzenetnek {0}.' - mythicmobs: - list: '§aAz összes Mythic Mob lista:' - isntMythicMob: '§cEz a Mythic Mob nem létezik.' - disabled: '§cMythicMob kikapcsolva.' - textList: - syntax: '§cHelyes szintax: ' - help: - header: '§6§lBeautyQuests - Lista szerkesztő segítség' - add: '§6add <message>: §eHozzáad egy szöveget.' - remove: '§6remove <id>: §eEltávolít egy szöveget.' - list: '§6list: §eÖsszes szöveg megnézése.' - close: '§6close: §eHozzáadott szöveg megerősítése.' - noSuchElement: '§cNincs ilyen elem. Engedélyezett elemek: §e{0}' - scoreboardObjectiveNotFound: '§cIsmeretlen lista objektum.' - writeCommandDelay: '§aÍrd a kívánt parancs késleltetést, tickben.' advancement: finished: Teljesítve notStarted: Nem elkezdett +description: + requirement: + level: Szint {short_level} +indication: + cancelQuest: '§7Biztos vagy benne, hogy megakarod szakítani ezt a küldetést {quest_name}?' + removeQuest: '§7Biztos vagy benne, hogy elakarod távolítani ezt a küldetést {quest}?' inv: - validate: '§b§lMegerősítés' cancel: '§c§lElutasítás' - search: '§e§lKeresés' + chooseQuest: + name: Melyik küldetés? confirm: name: Biztos vagy benne? - 'yes': '§aElfogad' 'no': '§cElutasít' + 'yes': '§aElfogad' create: - stageCreate: '§aÚj szint hozzáadás' - stageRemove: '§cSzint eltávolítás' - findNPC: '§aTaláld meg az NPC-t' bringBack: '§aHozz vissza tárgyakat' + bucket: '§aTölts meg vödröket' + craft: '§aKészíts tárgyakat' + findNPC: '§aTaláld meg az NPC-t' findRegion: '§aTaláld meg a helyet' + fish: '§aFogj halakat' + interact: '§aKattints rá a blokkra' killMobs: '§aÖlj szörnyeket' + location: '§aMenj el a helyre' mineBlocks: '§aTörj blokkokat' + stageCreate: '§aÚj szint hozzáadás' + stageRemove: '§cSzint eltávolítás' talkChat: '§aÍrj a chatbe' - interact: '§aKattints rá a blokkra' - fish: '§aFogj halakat' - craft: '§aKészíts tárgyakat' - bucket: '§aTölts meg vödröket' - location: '§aMenj el a helyre' - stages: - laterPage: Előző oldal details: + customMaterial: '§eTárgy id megváltoztatása' + editRequirements: '§eKövetelmények szerkesztése' endMessage: '§eBefejező üzenet szerkesztése' + hologramText: '§eHologram szöveg' + requirements: '{amount} követelmények' + rewards: '{amount} jutalmak' startDialog: '§eKezdő üzenet szerkesztése' - editRequirements: '§eKövetelmények szerkesztése' startRewards: '§6Índítási jutalmak' - hologramText: '§eHologram szöveg' - requirements: '{0} követelmények' - rewards: '{0} jutalmak' - customMaterial: '§eTárgy id megváltoztatása' - itemsSelect: - name: Tárgyak szerkesztése - none: |- - §aHúzz egy tárgyat ide vagy katt az tárgy szerkszető megnyitásához. + entityType: + name: Entitás tipus kiválasztása + itemCreator: + itemFlags: Tárgy funkciók bekapcsolása + itemType: '§bTárgy tipus' + name: Tárgy készítő itemSelect: name: Tárgy választás + itemsSelect: + name: Tárgyak szerkesztése + none: '§aHúzz egy tárgyat ide vagy katt az tárgy szerkszető megnyitásához.' + listAllQuests: + name: Küldetések + listPlayerQuests: + name: '{player_name} küldetései' + listQuests: + canRedo: '§3§oÚjratudod kezdeni ezt a küldetést!' + finished: Befejezett küldetések + inProgress: Folyamatban lévő küldetések + notStarted: Nem elindított küldetések + mobSelect: + boss: '§6Boss Kiválasztása' + bukkitEntityType: '§eEntitás tipus kiválasztása' + epicBoss: '§6Epic Boss kiválasztása' + mythicMob: '§6Mythic Mob kiválasztása' + name: Szörny tipus kiválasztása + mobs: + name: Szörnyek kiválasztása + none: '§aKattints a szörny hozzáadásához.' npcCreate: + move: + itemLore: '§aNPC hely megváltoztatás.' + itemName: '§eElmozdít' + moveItem: '§a§lHely megerősítése' name: NPC készítés setName: '§eNPC név szerkesztés' setSkin: '§eNPC kinézet szerkesztés' setType: '§eNPC tipus szerkesztés' - move: - itemName: '§eElmozdít' - itemLore: '§aNPC hely megváltoztatás.' - moveItem: '§a§lHely megerősítése' npcSelect: + createStageNPC: '§eNPC létrehozás' name: Kiválaszt vagy készít? selectStageNPC: '§eVálassz ki egy meglévő NPC-t' - createStageNPC: '§eNPC létrehozás' - entityType: - name: Entitás tipus kiválasztása - chooseQuest: - name: Melyik küldetés? - mobs: - name: Szörnyek kiválasztása - none: '§aKattints a szörny hozzáadásához.' - mobSelect: - name: Szörny tipus kiválasztása - bukkitEntityType: '§eEntitás tipus kiválasztása' - mythicMob: '§6Mythic Mob kiválasztása' - epicBoss: '§6Epic Boss kiválasztása' - boss: '§6Boss Kiválasztása' - stageEnding: - locationTeleport: '§eTeleportálási hely szerkesztése' - command: '§eParancs megváltoztatása' requirements: name: Követelmények rewards: + commands: 'Parancsok: {amount}' name: Jutalmak - commands: 'Parancsok: {0}' - teleportation: |- - §aKiválasztott: - X: {0} - Y: {1} - Z: {2} - Világ: {3} - listAllQuests: - name: Küldetések - listPlayerQuests: - name: '{0} küldetései' - listQuests: - notStarted: Nem elindított küldetések - finished: Befejezett küldetések - inProgress: Folyamatban lévő küldetések - canRedo: '§3§oÚjratudod kezdeni ezt a küldetést!' - itemCreator: - name: Tárgy készítő - itemType: '§bTárgy tipus' - itemFlags: Tárgy funkciók bekapcsolása -scoreboard: - stage: - npc: Beszélj az {0} npc-vel -indication: - cancelQuest: '§7Biztos vagy benne, hogy megakarod szakítani ezt a küldetést {0}?' - removeQuest: '§7Biztos vagy benne, hogy elakarod távolítani ezt a küldetést {0}?' -description: - requirement: - level: 'Szint {0}' + search: '§e§lKeresés' + stageEnding: + command: '§eParancs megváltoztatása' + locationTeleport: '§eTeleportálási hely szerkesztése' + stages: + laterPage: Előző oldal + validate: '§b§lMegerősítés' misc: + amount: '§eMennyiség: {amount}' + and: és + bucket: + lava: Lávás vödör + milk: Tejes vödör + water: Vizes vödör + click: + left: Bal klikk + right: Jobb klikk + shift-left: Shift+Bal klikk + shift-right: Shift+Jobb klikk + disabled: Kikapcsolva + enabled: Engedélyezve + entityType: '§eEntitás tipus: {entity_type}' format: + npcText: '§6[{message_id}/{message_count}] §e§l{npc_name_message}: §r§e {text}' prefix: '§6<§e§lKüldetések§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}: §r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - time: - weeks: '{0} hét' - days: '{0} nap' - hours: '{0} óra' - minutes: '{0} perc' - lessThanAMinute: 'kisebb mint egy perc' - stageType: - region: Találd meg a helyet - npc: Találd meg őt - items: Hozz vissza tárgyakat - mobs: Ölj meg szörnyeket - mine: Törj blokkokat - placeBlocks: Tegyél le egy blokkot - chat: Írj chatbe - interact: Lépj interakcióba blokkokal - Fish: Fogj halakat - Craft: Készíts tárgyakat - Bucket: Tölts meg vödröket - location: Találd meg a helyet + hologramText: '§7§lKüldetés NPC' + 'no': 'Nem' + notSet: '§cnincs beállítva' + or: vagy + questItemLore: '§e§o Küldetés Tárgy' requirement: class: '§bKaszt szükséges' - faction: '§bFrakció szükséges' - jobLevel: '§bMunka szint szükséges' combatLevel: '§bHarc szint szükséges' experienceLevel: '§bXp szint szükséges' + faction: '§bFrakció szükséges' + jobLevel: '§bMunka szint szükséges' + mcMMOSkillLevel: '§dSkill szint szükséges' + money: '§dArany szükséges' permissions: '§3Jog szükséges' - scoreboard: '§dPont szükséges' placeholder: '§bPlaceholder szám szükséges' quest: '§aKüldetés szükséges' - mcMMOSkillLevel: '§dSkill szint szükséges' - money: '§dArany szükséges' - bucket: - water: Vizes vödör - lava: Lávás vödör - milk: Tejes vödör - click: - right: Jobb klikk - left: Bal klikk - shift-right: Shift+Jobb klikk - shift-left: Shift+Bal klikk - questItemLore: '§e§o Küldetés Tárgy' - hologramText: '§7§lKüldetés NPC' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eEntitás tipus: {0}' - enabled: Engedélyezve - disabled: Kikapcsolva + scoreboard: '§dPont szükséges' + stageType: + Bucket: Tölts meg vödröket + Craft: Készíts tárgyakat + Fish: Fogj halakat + chat: Írj chatbe + interact: Lépj interakcióba blokkokal + items: Hozz vissza tárgyakat + location: Találd meg a helyet + mine: Törj blokkokat + mobs: Ölj meg szörnyeket + npc: Találd meg őt + placeBlocks: Tegyél le egy blokkot + region: Találd meg a helyet + time: + days: '{days_amount} nap' + hours: '{hours_amount} óra' + lessThanAMinute: kisebb mint egy perc + minutes: '{minutes_amount} perc' + weeks: '{weeks_amount} hét' unknown: ismeretlen - notSet: '§cnincs beállítva' - unused: '§2§lKihasználatlan' - used: '§a§lHasznált' - remove: '§7Középső-Katt az eltávolításhoz' - or: vagy - amount: '§eMennyiség: {0}' - items: tárgyak - expPoints: xp pontok 'yes': 'Igen' - 'no': 'Nem' - and: és +msg: + bringBackObjects: Hozz nekem {items}. + command: + adminModeEntered: '§aBeléptél az Admin Módba.' + adminModeLeft: '§aKiléptél az Admin Módból.' + backupCreated: '§6Sikeresen csináltál mentést.' + backupPlayersFailed: '§cA mentés sikertelen.' + backupQuestsFailed: '§cA mentés sikertelen.' + cancelQuest: '§6Elutasítottad a következő küldetést {quest}.' + cancelQuestUnavailable: '§cA küldetés nem elutasítható {quest}.' + checkpoint: + noCheckpoint: '§cNem találtunk ellenörző pontot a küldetéshez {quest}' + questNotStarted: '§cNem ezt a küldetést csinálod.' + help: + create: '§6/{label} létrehoz: §eLétrehoz egy küldetést.' + edit: '§6/{label} szerkesztés: §eSzerkesz egy küldetést.' + finishAll: '§6/{label} befejezmindent <player>: §eBefejezi az összes küldetést.' + header: '§6§lBeautyQuests - Segítség' + reload: '§6/{label} reload: §eSave, majd újra konfigurációk, valamint a fájlok. (§cdeprecated§e)' + remove: '§6/{label} eltávolít <id>:§EKitöröl egy küldetést a meghatározott id-vel vagy kattints az NPC-re.' + resetPlayer: '§6/{label} resetPlayer <player>: §eTöröl minden információt.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete információk egy küldetést, hogy egy játékos.' + seePlayer: '§6/{label} seePlayer <player>: §eView információt a játékos.' + setStage: '§6/{label} setStage <player> <id> új ág új szint: §eTovábblépi a jelenlegi szintet.' + start: '§6/{label} start <player> [id]: §eForce a kezdő a küldetést.' + invalidCommand: + simple: '§cEz a parancs nem létezik, használd §ehelp§c.' + itemChanged: '§aA tárgy szerkesztve. A változtatások az újraindítás után fognak működni.' + itemRemoved: '§aA tárgy hologram eltávolítva.' + leaveAll: '§aKényszerítve lettél, hogy befejezd a következő küldetést {success}. Hibák:{errors}' + removed: '§aA következő küldetés sikeresen eltávolítva {quest_name}.' + resetPlayer: + player: '§6Az összes információ a következő küldetésedből {quest_amount} törölve lett általa {deleter_name}.' + resetPlayerQuest: + player: '§6Az összes infó a küldetésről {quest} törölve lett általa {deleter_name}.' + remover: '§6Küldetés infó törölve {player} ennyiből {quest}.' + resetQuest: '§6Küldetés adat törölve neki {player_amount}.' + scoreboard: + hidden: '§6A lista a következő játékosnak {player_name} láthatatlan.' + lineInexistant: '§cA sor {line_id} nem létezik.' + lineRemoved: '§6Sikeresen eltávolítottad a sort {line_id}.' + lineReset: '§6Sikeresen újraraktad a sort {line_id}.' + lineSet: '§6Sikeresen átírtad a sort {line_id}.' + own: + hidden: '§6A scoreboard mostantól elvan rejtve.' + shown: '§6A scoreboard mostantól látható.' + resetAll: '§6Sikeres újrarakás a következő játékosnak {player_name}.' + shown: '§6A lista következő játékosnak látható {player_name}.' + setStage: + branchDoesntExist: '§cA következő ág nem létezik {branch_id}.' + doesntExist: '§cA következő szint {stage_id} nem létezik.' + next: '§aA szint kihagyva.' + nextUnavailable: '§c A "kihagyás" opció nem elérhető mikor a játékos az ág végén van.' + set: '§aSzint {stage_id} elindítva.' + startDialog: + alreadyIn: '§cA játékos már párbeszédben van.' + noDialog: '§cA megadott játékosnak nincsen folyamatban lévő párbeszéde.' + startQuest: '§6Kényszerítve lettél, hogy elkezd a következő küldetést {quest} (Játékos UUID: {player}).' + startQuestNoRequirements: '§cA megadott játékosnak nincsen meg a szükséges követelményei a(z) {quest} küldetéshez... Mellékeld a a "-overrideRequirements" szót a parancsod végére, hogy átugord a követelményeket.' + dialogs: + skipped: '§8§oPárbeszéd átugorva.' + tooFar: '§7§oTúl messze vagy ettől: {npc_name}...' + editor: + dialog: + help: + addSound: '§6addSound <id> <sound>: §eHangot ad hozzá az üzenethez.' + clear: '§6clear: §eKitörli az összes üzenetet.' + close: '§6close: §eMinden üzenetet ment és kilép.' + list: '§6list: §eÖsszes szöveg megnézése.' + nothing: '§6noSender <message>: §eHozzáad egy szöveget küldő nélkül.' + nothingInsert: '§6nothingInsert <id> <message>: §eHozzáad egy üzenetet prefix nélkül.' + npcInsert: '§6npcInsert <id> <message>: §eHozzáadja az összes üzenetet amit az NPC mond.' + player: '§6játékos <message>: §eHozzáad egy szöveget amit a játékos ír.' + playerInsert: '§6playerinsert <id> <message>: §eHozzáad minden üzenetet amit a játékos mond.' + remove: '§6remove <id>: §eEltávolít egy szöveget.' + setTime: '§6setTime <id> <time>: §eIdőt ad hozzá a szövegek közt.' + timeRemoved: '§aIdő eltávolítva ennek az üzenetnek {msg}.' + timeSet: '§aAz idő szerkesztve az üzenetnek {msg}: mostmár {time} tick.' + itemCreator: + itemName: '§aÍrd le az item nevét:' + unknownItemType: '§cIsmeretlen item típus.' + mythicmobs: + disabled: '§cMythicMob kikapcsolva.' + isntMythicMob: '§cEz a Mythic Mob nem létezik.' + list: '§aAz összes Mythic Mob lista:' + noSuchElement: '§cNincs ilyen elem. Engedélyezett elemek: §e{available_elements}' + scoreboardObjectiveNotFound: '§cIsmeretlen lista objektum.' + textList: + help: + add: '§6add <message>: §eHozzáad egy szöveget.' + close: '§6close: §eHozzáadott szöveg megerősítése.' + header: '§6§lBeautyQuests - Lista szerkesztő segítség' + list: '§6list: §eÖsszes szöveg megnézése.' + remove: '§6remove <id>: §eEltávolít egy szöveget.' + syntax: '§cHelyes szintax: ' + errorOccurred: '§cHiba történt, lépj kapcsolatba egy adminisztrátorral! §4§lHiba kód: {error}' + experience: + edited: '§aMegkell változtatnod az xp-t {old_xp_amount} ről ennyire {xp_amount}.' + indexOutOfBounds: '§cA szám {index} nem jó! Muszály {min} és {max} között lennie.' + inventoryFull: '§cTele van a táskád, a tárgy el lett dobva a földre.' + moveToTeleportPoint: '§aMenj a kért teleportálás helyszínére.' + npcDoesntExist: '§cEz az NPC nem létezik {npc_id}.' + number: + invalid: '§c{input} nem érvényes szám.' + negative: '§cMuszály pozitív számot írnod!' + zero: '§cNagyobb számot kell írnod 0-nál!' + pools: + allCompleted: '§7Az összes küldetést teljesítetted!' + maxQuests: '§cNem lehet több mint {pool_max_quests} küldetésed egy időben!' + noAvailable: '§7Nincsen elérhető küldetések.' + noTime: '§cVárnod kell még {time_left} mielőtt elkezdenél egy újabb küldetést.' + quest: + alreadyStarted: '§cMár elkezdted ezt a küldetést!' + cancelling: '§cA küldetés elkészítése közben hiba történt.' + createCancelled: '§cA szerkesztés vagy az elkészítés megszakítva egy másik plugin miatt!' + created: '&aSiker! Létrehoztad a következő küldetést §e{quest}§a ami tartalmaz {quest_branches} ágat!' + editCancelling: '§cA küldetés szerkesztése megszakítva.' + edited: '§aSiker! Szerkeszetted a következő küldetést §e{quest}§a ami tartalmaz {quest_branches} ágat!' + finished: + base: '&aSikeresen teljesítetted a következő küldetést §e{quest_name}§a!' + obtain: '§aEzt kaptad: {rewards}!' + invalidID: '§cA következő küldetés {quest_id} nem létezik.' + invalidPoolID: A(z) {pool_id} nem létezik. + notStarted: '§cJelenleg nem csinálod ezt a küldetést.' + started: '&aElkezdted a következő küldetést §r§e{quest_name}§o§6!' + questItem: + craft: '§cNem barkácsolhatsz küldetés itemmel!' + drop: '§cKüldetés itemet nem dobhatsz el!' + eat: '§cNem ehetsz meg egy Küldetés tárgyat!' + quests: + checkpoint: '§7Küldetés ellenőrző pont elérve!' + failed: '§cNem sikerült a küldetés{quest_name}' + maxLaunched: '§cNem lehet több mint {quests_max_amount} küldetésed egy időben!' + updated: '§7A következő küldetés §e{quest_name}§7 frissítve.' + regionDoesntExists: '§cNem létezik ilyen hely. (Ugyanabban a világban kell lenned.)' + requirements: + combatLevel: '§aA harc szinted a következőnek kell lennie{long_level}!' + level: '§cA szintednek a következőnek kell lennie{long_level}!' + money: '§cEnnyi kell lennied nállad {money}!' + quest: '§cBekell fejezned a következő küldetést §e{quest_name}§c!' + restartServer: '§7Indítsd újra a szervert, hogy lásd a módosításokat.' + selectNPCToKill: '§aVálazd ki az NPC akit megkell ölni.' + stageMobs: + listMobs: '§aEnnyit megkell ölnöd {mobs}.' + versionRequired: 'Szükséges verzió: §l{version}' + writeChatMessage: '§aÍrd a következő üzenetet: (Add {SLASH}" az elkezdéshez.)' + writeCommand: '§aÍrd ide a parancsot: (A parancs "/" nélkül és a szó "{PLAYER}" engedélyezett. Átlesz helyezve.)' + writeCommandDelay: '§aÍrd a kívánt parancs késleltetést, tickben.' + writeConfirmMessage: '§aÍrd a megerősítő üzenetet ide:(Írd "null" az alap szöveghez.)' + writeDescriptionText: '§aÍrd ide a szöveget ami leírja a lépéseket:' + writeHologramText: '§aÍrd a hologram nevét ide: (Írd "none ha nem akarsz semmit és "null" ha az alap szöveget akarod.)' + writeMobAmount: '§aÍrd ide a mennyiséget,hogy mennyi szörnyet kell megölni:' + writeNPCText: '§aÍrd le a párbeszédet amelyet a játékos fog folytatni az NPC vel: (Használd a "help" a segítségért)' + writeNpcName: '§aÍrd ide az NPC nevét:' + writeNpcSkinName: '§aÍrd ide az NPC skin nevét:' + writeQuestDescription: '§aÍrd ide a leírást amit a játékos látni fog.' + writeQuestMaterial: '§aÍrd ide,hogy milyen tárgy legyen a küldetés.' + writeQuestName: '§aÍrd ide a küldetést nevét:' + writeQuestTimer: '§aÍrd a szükséges időt (percben) amielött újratudod indítani a küldetést: (Írd "null" ha az alapot akarod.)' + writeRegionName: '§aÍrd a helyet amit kér a küldetés:' + writeStageText: '§aÍrd ide a szöveget amit a játékos fog kapni mikor elkezdi a lépést:' + writeXPGain: '§Írd ide az xp mennyiséget amit a játékos kapni fog:(Utolsó érték:{xp_amount})' +scoreboard: + stage: + npc: Beszélj az {dialog_npc_name} npc-vel diff --git a/core/src/main/resources/locales/it_IT.yml b/core/src/main/resources/locales/it_IT.yml index 06a8d932..64c75d73 100644 --- a/core/src/main/resources/locales/it_IT.yml +++ b/core/src/main/resources/locales/it_IT.yml @@ -1,521 +1,521 @@ --- -msg: - quest: - finished: - base: '§aCongratulazioni! Hai completato la missione §e{0}§a!' - obtain: '§aHai ottenuto {0}!' - started: '§aHai iniziato la quest §r§e{0}§o§6!' - created: '§aCongratulazioni! Hai creato la quest §e{0}§a, che comprende {1} ramo(i)!' - edited: '§aCongratulazioni! Hai modificato la quest §e{0}§a che ora include {1} ramo(i)!' - createCancelled: '§cLa creazione o la modifica è stata annullata da un altro plugin!' - cancelling: '§cProcesso di creazione della quest annullato.' - editCancelling: Processo di modifica della quest annullato. - invalidID: '§ cLa quest con id {0} non esiste.' - invalidPoolID: '§cLa piscina {0} Non esiste' - alreadyStarted: '§cHai già iniziato la missione!' - notStarted: '§cNon stai facendo questa missione attualmente.' - quests: - maxLaunched: '§cTu non puoi averne più di {0} quest(s) allo stesso momento...' - nopStep: '§cQuesta missione non ha alcun obbiettivo.' - updated: '§7Quest §e{0}§7 aggiornata.' - checkpoint: '§7Checkpoint raggiunto!' - failed: '§cHai fallito la missione {0}...' - pools: - noTime: '§cDevi aspettare {0} prima di fare un''altra quest.' - allCompleted: '§7Hai completato tutte le missioni!' - noAvailable: '§7Non ci sono più missioni disponibili...' - maxQuests: '§cNon puoi avere più di {0} missioni contemporaneamente...' - questItem: - drop: Non puoi buttare un oggetto necessario per la missione! - craft: '§cNon puoi usare un oggetto della missione per caftare!' - eat: '§cNon puoi mangiare un oggetto della missione!' - stageMobs: - noMobs: '§questa fase non ha bisogno di alcun mob da uccidere.' - listMobs: '§aDevi uccidere {0}.' - writeNPCText: '§aScrivi il dialogo che verrà detto al giocatore dal NPC: (Scrivi "help" per ricevere aiuto.)' - writeRegionName: '§aScrivi il nome della regione richiesta per l''obbiettivo:' - writeXPGain: '§aScrivi la quantità di punti esperienza che il giocatore otterrà: (Ultimo valore: {0})' - writeMobAmount: '§aScrivi la quantità di mob da uccidere:' - writeMobName: '§aScrivi il nome personalizzato del mob da uccidere:' - writeChatMessage: '§aScrivi il messaggio richiesto: (Aggiungi "{SLASH}" all''inizio se vuoi usare un comando.)' - writeMessage: '§aScrivi il messaggio che verrà inviato al giocatore' - writeStartMessage: '§aScrivi il messaggio che verrà inviato all''inizio della missione, "null" se vuoi quello predefinito o "none" se non vuoi:' - writeEndMsg: '§aScrivi il messaggio che verrà inviato alla fine della missione, "null" se vuoi quello predefinito o "nessuno" se vuoi nessuno. È possibile utilizzare "{0}" che verrà sostituito con i premi ottenuti.' - writeEndSound: '§aScrivi il nome del suono che verrà riprodotto al giocatore alla fine della missione, "null" se vuoi quello predefinito o "none" se non vuoi:' - writeDescriptionText: '§aScrivi il testo che descrive l''obiettivo della fase:' - writeStageText: '§aScrivi il testo che verrà inviato al giocatore all''inizio della fase:' - moveToTeleportPoint: '§aVai alla posizione di teletrasporto desiderata.' - writeNpcName: '§aScrivi il nome del NPC:' - writeNpcSkinName: '§aScrivi il nome della skin dell''NPC:' - writeQuestName: '§aScrivi il nome della quest:' - writeCommand: '§aScrivi il comando desiderato: (Il comando va inserito senza "/" e il placeholder "{PLAYER}" è supportato. Verrà sostituito con il nome del giocatore.)' - writeHologramText: '§aScrivi il testo dell''hologram: (Scrivi "none" se non vuoi un ologramma e "null" se vuoi il testo predefinito.)' - writeQuestTimer: '§aScrivi il tempo richiesto (in minuti) prima di poter riavviare la quest: (Scrivi "null" se vuoi il timer predefinito.)' - writeConfirmMessage: '§aScrivi il messaggio di conferma mostrato quando un giocatore sta per iniziare la quest: (Scrivi "null" se vuoi il messaggio predefinito.)' - writeQuestDescription: '§aScrivi la descrizione della missione, verrà mostrata nell''interfaccia delle missioni del giocatore.' - writeQuestMaterial: '§aScrivi il materiale dell''oggetto della missione.' - requirements: - quest: '§cDevi aver completato la missione §e{0}§c!' - level: '§cIl tuo livello deve essere {0}!' - job: '§cIl tuo livello per il lavoro §e{1}§c deve essere {0}!' - skill: '§cIl tuo livello per l''abilità §e{1}§c deve essere {0}!' - combatLevel: '§cIl tuo livello di combattimento deve essere {0}!' - money: '§cDevi avere {0}!' - waitTime: '§cDevi aspettare {0} minuto(i) prima di poter riavviare questa missione!' - experience: - edited: '§aHai cambiato l''esperienza guadagnata da {0} a {1} punti.' - selectNPCToKill: '§aSeleziona il NPC da uccidere.' - npc: - remove: '§aNPC eliminato.' - talk: '§aVai e parlare con il NPC chiamato §e{0}§a.' - regionDoesntExists: '§cQuesta regione non esiste. (Devi essere nello stesso mondo.)' - npcDoesntExist: '§cIl NPC con l''id {0} non esiste.' - objectDoesntExist: '§cL''oggetto specificato con l''id {0} non esiste.' - number: - negative: '§cDevi inserire un numero positivo!' - zero: '§cDevi inserire un numero diverso da 0!' - invalid: '§c{0} non è un numero valido.' - notInBounds: Il valore di entrata deve essere compreso fra {0} e {1} - errorOccurred: '§cSi è verificato un errore, contatta un amministratore! §4§lCodice di errore: {0}' - commandsDisabled: '§cAttualmente non sei autorizzato a eseguire comandi!' - indexOutOfBounds: '§cIl numero {0} è fuori dai limiti! Deve essere compreso tra {1} e {2}.' - invalidBlockData: '§cIl blockdata {0} non è valido o incompatibile con il blocco {1}.' - invalidBlockTag: '§cTag blocco {0} non disponibile.' - bringBackObjects: Riportami {0}. - inventoryFull: '§cIl tuo inventario è pieno, l''oggetto è stato droppato sul pavimento.' - playerNeverConnected: '§cImpossibile trovare informazioni sul giocatore {0}.' - playerNotOnline: '§cIl giocatore {0} è offline.' - command: - checkpoint: - noCheckpoint: '§cNessun checkpoint trovato per la missione {0}.' - questNotStarted: '§cNon stai facendo questa missione.' - setStage: - branchDoesntExist: '§cIl ramo con l''id {0} non esiste.' - doesntExist: '§cLa fase con l''id {0} non esiste.' - next: '§aLa fase è stata saltata.' - nextUnavailable: '§cL''opzione "salta" non è disponibile quando il giocatore è alla fine di un ramo.' - set: '§aFase {0} avviata.' - playerNeeded: '§cDevi essere un giocatore per eseguire questo comando!' - incorrectSyntax: '§cSintassi errata.' - noPermission: '§cNon hai i permessi richiesti per eseguire questo comando! (Richiesto: {0})' - invalidCommand: - quests: '§cQuesto comando non esiste, scrivi §e/quests help§c.' - simple: '§cQuesto comando non esiste, scrivi §ehelp§c.' - needItem: '§cDevi tenere un oggetto nella tua mano principale!' - itemChanged: '§aL''oggetto è stato modificato. Le modifiche verranno applicate dopo il riavvio.' - itemRemoved: '§aL''oggetto nell''hologram è stato rimosso.' - removed: '§aLa missione {0} è stata rimossa con successo.' - leaveAll: '§aHai forzato la fine della(e) quest {0}. Errori: {1}' - resetPlayer: - player: '§6Tutte le informazioni della(e) tua(e) {0} quest sono state/sono state eliminate da {1}.' - resetPlayerQuest: - player: '§6Tutte le informazioni sulla missione {0} sono state eliminate da {1}.' - remover: '§6{0} informazioni delle quest di {1} sono state eliminate.' - resetQuest: '§6Dati della missione rimossi per {0} giocatori.' - startQuest: '§6Hai forzato l''avvio della missione {0} (UUID giocatore: {1}).' - cancelQuest: '§6Hai annullato la missione {0}.' - cancelQuestUnavailable: '§cLa missione {0} non può essere annullata.' - backupCreated: '§6Hai creato con successo i backup di tutte le missioni e le informazioni dei giocatori.' - backupPlayersFailed: '§cCreazione di un backup per tutte le informazioni dei giocatori non riuscita.' - backupQuestsFailed: '§cCreazione di un backup per tutte le missioni non riuscita.' - adminModeEntered: '§aSei entrato nella modalità Admin.' - adminModeLeft: '§aSei uscito dalla modalità Admin.' - scoreboard: - lineSet: '§6Hai modificato con successo la riga {0}.' - lineReset: '§6Hai resettato con successo la riga {0}.' - lineRemoved: '§6Hai rimosso con successo la riga {0}.' - lineInexistant: '§cLa linea {0} non esiste.' - resetAll: '§6Hai resettato con successo la scoreboard del giocatore {0}.' - hidden: '§6ILa scoreboard del giocatore {0} è stata nascosta.' - shown: '§6La scoreboard del giocatore {0} è visibile.' - help: - header: '§6§lBeautyQuests — Aiuto' - create: '§6/{0} create: §eCrea una missione.' - edit: '§6/{0} edit: §eModifica una missione.' - remove: '§6/{0} remove <id>: §eElimina una quest con un id definito o clicca sul NPC quando non è specificato.' - finishAll: '§6/{0} finishAll <giocatore>:: §eTermina tutte le missioni di un giocatore.' - setStage: '§6/{0} setStage <giocatore> <id> [nuovo ramo] [nuova fase]: §eSalta la fase corrente/avvia il ramo/imposta una fase per un ramo.' - resetPlayer: '§6/{0} resetPlayer <giocatore>: §eRimuovi tutte le informazioni su un giocatore.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <giocatore> [id]: §eElimina le informazioni di una quest per un giocatore.' - seePlayer: '§6/{0} seePlayer <giocatore>: §eVisualizza le informazioni su un giocatore.' - reload: '§6/{0} reload: §eSalva e ricarica tutte le configurazioni e i file. (§cobsoleto§e)' - start: '§6/{0} start <giocatore> [id]: §eForza l''inizio di una missione.' - setItem: '§6/{0} setItem <talk|launch>: §eSalva l''oggetto dell''hologram.' - adminMode: '§6/{0} adminMode: §eAbilita/disabilita la modalità Admin. (Utile per visualizzare i messaggi di log.)' - version: '§6/{0} version: §eVisualizza la versione del plugin.' - save: '§6/{0} save: §eAvvia un salvataggio manuale del plugin.' - list: '§6/{0} list: §eVisualizza la lista delle missioni. (Solo per versioni supportate.)' - typeCancel: '§aScrivi "Annulla" per tornare all''ultimo testo.' - editor: - blockAmount: '§aScrivi la quantità di blocchi:' - blockName: '§aScrivi il nome del blocco:' - blockData: '§aScrivi il blockdata (blockdata disponibili: {0}):' - typeBucketAmount: '§aScrivi la quantità di secchi da riempire:' - goToLocation: '§aVai alla posizione desiderata per la fase.' - typeLocationRadius: '§aScrivi la distanza richiesta dalla posizione:' - typeGameTicks: '§aScrivi i ticket di gioco richiesti:' - already: '§cSei già nell''editor.' - enter: - title: '§6~ Modalità Editor ~' - npc: - enter: '§aClicca su un NPC o scrivi "cancel".' - choseStarter: '§aScegli il NPC che avvia la missione.' - notStarter: '§cQuesto NPC non avvia nessuna quest.' - text: - argNotSupported: '§cL''argomento {0} non è supportato.' - chooseLvlRequired: '§aScrivi la quantità richiesta di livelli:' - chooseJobRequired: '§aScrivi il nome del lavoro desiderato:' - choosePermissionRequired: '§aScrivi il permesso necessario per iniziare la missione:' - choosePermissionMessage: '§aPuoi scegliere un messaggio di rifiuto se il giocatore non ha il permesso necessario. (Per saltare questo passo, scrivi "null".)' - choosePlaceholderRequired: - identifier: '§aScrivi il nome del placeholder richiesto senza il carattere della percentuale:' - value: '§aScrivi il valore richiesto per il placeholder §e%§e{0}§e%§a:' - chooseSkillRequired: '§aScrivi il nome dell''abilità richiesta:' - chooseMoneyRequired: '§aScrivi la quantità di denaro richiesto:' - reward: - permissionName: '§aScrivi il nome del permesso.' - permissionWorld: '§aScrivi il mondo in cui verrà modificato il permesso, o "null" se vuoi che sia globale.' - money: '§aScrivi l''importo dei soldi ricevuti:' - chooseObjectiveRequired: '§aScrivi il nome dell''obbiettivo.' - chooseObjectiveTargetScore: '§aScrivi il punteggio richiesto per l''obiettivo.' - chooseRegionRequired: '§aScrivi il nome della region richiesta (devi essere nello stesso mondo).' - selectWantedBlock: '§aClicca con il bastone sul blocco desiderato per la fase.' - itemCreator: - itemType: '§aScrivi il nome del tipo di oggetto desiderato:' - itemAmount: '§aScrivi la quantità di oggetti:' - itemName: '§aScrivi il nome dell''oggetto:' - itemLore: '§aModifica la lore dell''oggetto: (Scrivi "help" per aiuto.)' - unknownItemType: '§cTipo oggetto sconosciuto.' - invalidItemType: '§cTipo di oggetto non valido. (L''oggetto non può essere un blocco.)' - unknownBlockType: '§cTipo di blocco sconosciuto.' - invalidBlockType: '§cTipo di blocco non valido.' - dialog: - syntax: '§cSintassi corretta: {0}{1} <messaggio>' - syntaxRemove: '§cSintassi corretta: remove <id>' - cleared: '§a{0} ha rimosso il messaggio(i).' - help: - header: '§6§lBeautyQuests — Aiuto editor' - npc: '§6npc <messaggio>: §eAggiungi un messaggio detto dal NPC.' - player: '§6player <messaggio>: §eAggiungi un messaggio detto dal giocatore.' - nothing: '§6noSender <messaggio>: §eAggiungi un messaggio senza un mittente.' - remove: '§6remove <id>:§eRimuovi un messaggio.' - list: '§6list: §eVisualizza tutti i messaggi.' - npcInsert: '§6npcInsert <id> <messaggio>: §eInserisci un messaggio detto dall''NPC.' - playerInsert: '§6playerInsert <id> <messaggio> §eInserisci un messaggio detto dal giocatore.' - nothingInsert: '§6nothingInsert <id> <messaggio>: §eInserisci un messaggio senza alcun prefix.' - addSound: '§6addSound <id> <suono>: §eAggiungi un suono a un messaggio.' - clear: '§6clear: §eRimuovi tutti i messaggi.' - close: '§6close: §eConvalida tutti i messaggi.' - setTime: '§6setTime <id> <time>: §eImposta il tempo (in ticks) prima che il prossimo msg venga inviato automaticamente.' - timeSet: '§aIl tempo è stato modificato per il messaggio {0}: ora è {1} tick.' - timeRemoved: '§aIl tempo è stato rimosso per il messaggio {0}.' - mythicmobs: - list: '§aUn elenco di tutti i Mythic Mobs:' - isntMythicMob: '§cQuesto Mythic Mob non esiste.' - disabled: '§cMythicMob è disabilitato.' - textList: - syntax: '§cSintassi corretta: ' - help: - header: '§6§lBeautyQuests — Guida editor' - add: '§6add <messaggio>: §eAggiungi un testo.' - remove: '§6remove <id>: §eRimuovi un testo.' - list: '§6list: §eVisualizza tutti i testi aggiunti.' - close: '§6close: §eConvalida i testi aggiunti.' - noSuchElement: '§cNon ci sono elementi del genere. Gli elementi consentiti sono: §e{0}' - scoreboardObjectiveNotFound: '§cObiettivo scoreboard sconosciuto.' - pool: - hologramText: 'Scrivi il testo dell''hologram personalizzato per questo pool (o "null" se vuoi quello predefinito).' - maxQuests: 'Scrivi la quantità massima di missioni lanciabili da questa pool.' - writeCommandDelay: '§aScrivi il ritardo del comando desiderato, in tick.' advancement: finished: Terminato notStarted: Non iniziato +indication: + cancelQuest: '§7Sei sicuro di voler annullare la missione {quest_name}?' + closeInventory: '§7Sei sicuro di voler chiudere la GUI?' + removeQuest: '§7Sei sicuro di voler rimuovere la missione {quest}?' + startQuest: '§7Vuoi iniziare la missione {quest_name}?' inv: - validate: '§b§lConvalida' - cancel: '§c§lAnnulla' - search: '§e§lCerca' addObject: '§aAggiungi un oggetto' + block: + blockData: '§dBlockdata (avanzato)' + material: '§eMateriale: {block_type}' + name: Scegli blocco + blockAction: + location: '§eSeleziona una posizione precisa' + material: '§eSeleziona un materiale del blocco' + name: Seleziona azione blocco + blocksList: + addBlock: '§aClicca per aggiungere un blocco.' + name: Seleziona blocchi + buckets: + name: Tipo di secchio + cancel: '§c§lAnnulla' + chooseAccount: + name: Quale account? + chooseQuest: + name: Quale quest? + classesList.name: Lista classi + classesRequired.name: Classi richieste + command: + console: Console + delay: '§bRitardo' + name: Comando + value: '§eComando' + commandsList: + name: Lista comandi + value: '§eComando: {command_label}' confirm: name: Sei sicuro? - 'yes': '§aConferma' 'no': '§cAnnulla' + 'yes': '§aConferma' create: - stageCreate: '§aCrea nuova fase' - stageRemove: '§cElimina questa fase' - findNPC: '§aTrova NPC' + NPCSelect: '§eScegli o crea NPC' + NPCText: '§eModifica dialogo' bringBack: '§aRiporta oggetti' + bucket: '§aRiempi secchi' + cancelMessage: Annulla invio + craft: '§aCrafta oggetto' + currentRadius: '§eDistanza attuale: §6{radius}' + editBlocksMine: '§eModifica blocchi da rompere' + editBlocksPlace: '§eModifica blocchi da posizionare' + editBucketAmount: '§eModifica la quantità di secchi da riempire' + editBucketType: '§eModifica il tipo di secchi da riempire' + editFishes: '§eModifica i pesci da catturare' + editItem: '§eModifica oggetti da craftare' + editLocation: '§eModifica posizione' + editMessageType: '§eModifica messaggio da scrivere' + editMobsKill: '§eModifica mob da uccidere' + editRadius: '§eModifica distanza dalla posizione' + findNPC: '§aTrova NPC' findRegion: '§aTrova regione' + fish: '§aPesca pesci' + hideClues: Nascondi particelle e holograms + ignoreCase: Ignora le lettere maiuscole del messaggio + interact: '§aInteragisci con un blocco' killMobs: '§aUccidi mob' + leftClick: Devi cliccare con il tasto destro + location: '§aVai alla posizione' mineBlocks: '§aRompi blocchi' + mobsKillFromAFar: Deve essere ucciso con una freccia placeBlocks: '§aPiazza blocchi' - talkChat: '§aScrivi in chat' - interact: '§aInteragisci con un blocco' - fish: '§aPesca pesci' - craft: '§aCrafta oggetto' - bucket: '§aRiempi secchi' - location: '§aVai alla posizione' playTime: '§eTempo di gioco' - NPCText: '§eModifica dialogo' - NPCSelect: '§eScegli o crea NPC' - hideClues: Nascondi particelle e holograms - editMobsKill: '§eModifica mob da uccidere' - mobsKillFromAFar: Deve essere ucciso con una freccia - editBlocksMine: '§eModifica blocchi da rompere' preventBlockPlace: Impedisci ai giocatori di rompere i propri blocchi - editBlocksPlace: '§eModifica blocchi da posizionare' - editMessageType: '§eModifica messaggio da scrivere' - cancelMessage: Annulla invio - ignoreCase: Ignora le lettere maiuscole del messaggio + selectBlockLocation: '§eSeleziona posizione blocco' + selectBlockMaterial: '§eSeleziona materiale del blocco' selectItems: '§eModifica gli elementi richiesti' selectRegion: '§7Scegli regione' - toggleRegionExit: All'uscita + stageCreate: '§aCrea nuova fase' + stageRemove: '§cElimina questa fase' stageStartMsg: '§eModifica messaggio iniziale' - selectBlockLocation: '§eSeleziona posizione blocco' - selectBlockMaterial: '§eSeleziona materiale del blocco' - leftClick: Devi cliccare con il tasto destro - editFishes: '§eModifica i pesci da catturare' - editItem: '§eModifica oggetti da craftare' - editBucketType: '§eModifica il tipo di secchi da riempire' - editBucketAmount: '§eModifica la quantità di secchi da riempire' - editLocation: '§eModifica posizione' - editRadius: '§eModifica distanza dalla posizione' - currentRadius: '§eDistanza attuale: §6{0}' - stages: - name: Crea fasi - nextPage: '§ePagina successiva' - laterPage: '§ePagina precedente' - endingItem: '§eModifica ricompense finali' - descriptionTextItem: '§eModifica descrizione' - regularPage: '§aFasi regolari' - branchesPage: '§dRami fasi' - previousBranch: '§eTorna al ramo precedente' - newBranch: '§eVai al nuovo branch' + talkChat: '§aScrivi in chat' + toggleRegionExit: All'uscita details: + bypassLimit: Non contare il limite della quest + cancellable: Annullabile dal giocatore + customConfirmMessage: '§eModifica il messaggio di conferma della missione' + editRequirements: '§eModifica i requisiti' + endMessage: '§eModifica messaggio finale' hologramLaunch: '§eModifica l''oggetto dell''hologram "Avvia"' hologramLaunchNo: '§eModifica l''oggetto dell''hologram "avvio non disponibile"' - customConfirmMessage: '§eModifica il messaggio di conferma della missione' - name: Ultimi dettagli della missione + hologramText: '§eTesto dell''Hologram' multipleTime: itemLore: "La missione può essere \navviata più volte?" - cancellable: Annullabile dal giocatore - scoreboardItem: Abilita scoreboard - bypassLimit: Non contare il limite della quest + name: Ultimi dettagli della missione questName: '§a§lModifica il nome della quest' + requirements: '{amount} requisito(i)' + rewards: '{amount} ricompensa(e)' + scoreboardItem: Abilita scoreboard + selectStarterNPC: '§e§lSeleziona un NPC di avvio' setItemsRewards: '§eModifica ricompense' - setXPRewards: '§eModifica esperienza ricevuta' - setPermReward: '§eModifica i permessi' setMoneyReward: '§eModifica la ricompensa in denaro' - selectStarterNPC: '§e§lSeleziona un NPC di avvio' - endMessage: '§eModifica messaggio finale' + setPermReward: '§eModifica i permessi' + setXPRewards: '§eModifica esperienza ricevuta' startDialog: '§eModifica dialogo di avvio' - editRequirements: '§eModifica i requisiti' startRewards: '§6Premi di avvio' - hologramText: '§eTesto dell''Hologram' - requirements: '{0} requisito(i)' - rewards: '{0} ricompensa(e)' - itemsSelect: - name: Modifica oggetti - none: |- - §aSposta un oggetto qui o - clicca per aprire l'editor degli item. + entityType: + name: Scegli tipo entità + factionsList.name: Lista delle Fazioni + factionsRequired.name: Fazioni richieste + itemCreator: + isQuestItem: '§bOggetto missione:' + itemFlags: Seleziona flag oggetto + itemLore: '§bItem lore' + itemName: '§bNome oggetto' + itemType: '§bTipo di oggetto' + name: Crea oggetti itemSelect: name: Scegli item + itemsSelect: + name: Modifica oggetti + none: '§aSposta un oggetto qui o clicca per aprire l''editor degli item.' + listAllQuests: + name: Missioni + listBook: + noQuests: Nessuna missione è stata creata in precedenza. + questMultiple: Più volte + questName: Nome + questRewards: Ricompense + questStages: Fasi + questStarter: Starter + requirements: Requisiti + listPlayerQuests: + name: 'Missioni di {player_name}' + listQuests: + canRedo: '§3§oPuoi riavviare questa missione!' + finished: Missioni completate + inProgress: Missioni in corso + loreStartUnavailable: '§c§oNon hai i requisiti per iniziare la missione.' + notStarted: Missioni non iniziate + mobSelect: + bukkitEntityType: '§eSeleziona tipo entità' + epicBoss: '§6Seleziona Epic Boss' + mythicMob: '§6Seleziona Mythic Mob' + mobs: + name: Seleziona mob + none: '§aClicca per aggiungere un mob.' npcCreate: + move: + itemLore: '§aCambia la posizione NPC.' + itemName: '§eSposta' + moveItem: '§a§lConvalida il luogo' name: Crea NPC setName: '§eModifica nome NPC' setSkin: '§eModifica skin NPC' setType: '§eModifica tipo NPC' - move: - itemName: '§eSposta' - itemLore: '§aCambia la posizione NPC.' - moveItem: '§a§lConvalida il luogo' npcSelect: + createStageNPC: '§eCrea NPC' name: Seleziona o crea? selectStageNPC: '§eSeleziona NPC esistente' - createStageNPC: '§eCrea NPC' - entityType: - name: Scegli tipo entità - chooseQuest: - name: Quale quest? - mobs: - name: Seleziona mob - none: '§aClicca per aggiungere un mob.' - mobSelect: - bukkitEntityType: '§eSeleziona tipo entità' - mythicMob: '§6Seleziona Mythic Mob' - epicBoss: '§6Seleziona Epic Boss' - stageEnding: - locationTeleport: '§eModifica la posizione del teletrasporto' - command: '§eModifica comando eseguito' - requirements: - name: Requisiti - rewards: - name: Ricompense - commands: 'Comandi: {0}' - listAllQuests: - name: Missioni - listPlayerQuests: - name: 'Missioni di {0}' - listQuests: - notStarted: Missioni non iniziate - finished: Missioni completate - inProgress: Missioni in corso - loreStartUnavailable: '§c§oNon hai i requisiti per iniziare la missione.' - canRedo: '§3§oPuoi riavviare questa missione!' - itemCreator: - name: Crea oggetti - itemType: '§bTipo di oggetto' - itemFlags: Seleziona flag oggetto - itemName: '§bNome oggetto' - itemLore: '§bItem lore' - isQuestItem: '§bOggetto missione:' - command: - name: Comando - value: '§eComando' - console: Console - delay: '§bRitardo' - chooseAccount: - name: Quale account? - listBook: - questName: Nome - questStarter: Starter - questRewards: Ricompense - questMultiple: Più volte - requirements: Requisiti - questStages: Fasi - noQuests: Nessuna missione è stata creata in precedenza. - commandsList: - name: Lista comandi - value: '§eComando: {0}' - console: '§eConsole: {0}' - block: - name: Scegli blocco - material: '§eMateriale: {0}' - blockData: '§dBlockdata (avanzato)' - blocksList: - name: Seleziona blocchi - addBlock: '§aClicca per aggiungere un blocco.' - blockAction: - name: Seleziona azione blocco - location: '§eSeleziona una posizione precisa' - material: '§eSeleziona un materiale del blocco' - buckets: - name: Tipo di secchio permission: name: Scegli il permesso perm: '§aPermesso' - world: '§aMondo' - worldGlobal: '§b§lGlobale' remove: Rimuovi permesso removeLore: '§7Il permesso sarà eliminato\n§7invece che dato.' + world: '§aMondo' + worldGlobal: '§b§lGlobale' permissionList: name: Elenco permessi - removed: '§eEliminato: §6{0}' - world: '§eMondo: §6{0}' - classesRequired.name: Classi richieste - classesList.name: Lista classi - factionsRequired.name: Fazioni richieste - factionsList.name: Lista delle Fazioni - poolsManage: - name: Pools missione - itemName: '§aPool #{0}' - create: '§aCrea un pool di missioni' + removed: '§eEliminato: §6{permission_removed}' + world: '§eMondo: §6{permission_world}' poolCreation: - name: Creazione pool di missioni hologramText: '§eHologram pool personalizzato' maxQuests: '§aMissioni massime' - time: '§bImposta il tempo tra le missioni' + name: Creazione pool di missioni redoAllowed: È permesso rifare + time: '§bImposta il tempo tra le missioni' poolsList.name: Pools missione -scoreboard: - name: '§6§lMissioni' - noLaunched: '§cNessuna missione in corso.' - noLaunchedName: '§c§lCaricamento' - noLaunchedDescription: '§c§oCaricamento' - textBetwteenBranch: '§e o' - stage: - region: '§eTrova regione §6{0}' - npc: '§eParla con NPC §6{0}' - items: '§ePorta gli oggetti a §6{0}§e:' - mobs: '§eUccidi §6{0}' - mine: '§eMina {0}' - placeBlocks: '§ePosiziona {0}' - chat: '§eScrivi §6{0}' - interact: '§eClicca sul blocco a §6{0}' - interactMaterial: '§eClicca su un blocco §6{0}§e' - fish: '§ePesca §6{0}' - craft: '§eCrafta §6{0}' - bucket: '§eRiempi §6{0}' - location: '§eVai a §6{0}§e, §6{1}§e, §6{2}§e in §6{3}' -indication: - startQuest: '§7Vuoi iniziare la missione {0}?' - closeInventory: '§7Sei sicuro di voler chiudere la GUI?' - cancelQuest: '§7Sei sicuro di voler annullare la missione {0}?' - removeQuest: '§7Sei sicuro di voler rimuovere la missione {0}?' + poolsManage: + create: '§aCrea un pool di missioni' + itemName: '§aPool #{pool}' + name: Pools missione + requirements: + name: Requisiti + rewards: + commands: 'Comandi: {amount}' + name: Ricompense + search: '§e§lCerca' + stageEnding: + command: '§eModifica comando eseguito' + locationTeleport: '§eModifica la posizione del teletrasporto' + stages: + branchesPage: '§dRami fasi' + descriptionTextItem: '§eModifica descrizione' + endingItem: '§eModifica ricompense finali' + laterPage: '§ePagina precedente' + name: Crea fasi + newBranch: '§eVai al nuovo branch' + nextPage: '§ePagina successiva' + previousBranch: '§eTorna al ramo precedente' + regularPage: '§aFasi regolari' + validate: '§b§lConvalida' misc: + amount: '§eQuantità: {amount}' + and: e + bucket: + lava: Secchio di Lava + milk: Secchio di latte + water: Secchio d'acqua + comparison: + different: diverso da {number} + equals: uguale a {number} + greater: rigorosamente maggiore di {number} + greaterOrEquals: maggiore di {number} + less: rigorosamente inferiore a {number} + lessOrEquals: Meno di {number} + disabled: Disabilitato + enabled: Abilitato + entityType: '§eTipo di entità: {entity_type}' format: prefix: '§6<§e§lMissioni§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - offText: '§r§e{0}' - time: - days: '{0} giorni' - hours: '{0} ore' - minutes: '{0} minuti' - stageType: - region: Trova la regione - npc: Trova l'NPC - items: Riporta gli oggetti - mobs: Uccidi mob - mine: Rompi blocchi - placeBlocks: Piazza blocchi - chat: Scrivi in chat - interact: Interagisci con un blocco - Fish: Pesca pesci - Craft: Crafta oggetto - Bucket: Riempi un secchio - location: Trova una posizione - playTime: Tempo di gioco - comparison: - equals: uguale a {0} - different: diverso da {0} - less: rigorosamente inferiore a {0} - lessOrEquals: Meno di {0} - greater: rigorosamente maggiore di {0} - greaterOrEquals: maggiore di {0} + hologramText: '§8§lNPC della missione' + 'no': 'No' + notSet: '§cnon impostato' + or: o + poolHologramText: '§eNuova missione disponibile!' + questItemLore: '§e§oQuest item' requirement: class: '§bClass(e) richiesta' - faction: '§bFazione(i) richiesta' - jobLevel: '§bLivello di lavoro richiesto' combatLevel: '§bLivello di combattimento richiesto' experienceLevel: '§bLivelli di esperienza richiesti' + faction: '§bFazione(i) richiesta' + jobLevel: '§bLivello di lavoro richiesto' + mcMMOSkillLevel: '§dLivello di abilità richiesto' + money: '§dDenaro richiesto' permissions: '§3Permesso(i) richiesti' - scoreboard: '§dPunteggio richiesto' - region: '§dRegione richiesta' placeholder: '§bValore Placeholder richiesto' quest: '§aMissione richiesta' - mcMMOSkillLevel: '§dLivello di abilità richiesto' - money: '§dDenaro richiesto' - bucket: - water: Secchio d'acqua - lava: Secchio di Lava - milk: Secchio di latte - questItemLore: '§e§oQuest item' - hologramText: '§8§lNPC della missione' - poolHologramText: '§eNuova missione disponibile!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eTipo di entità: {0}' - enabled: Abilitato - disabled: Disabilitato + region: '§dRegione richiesta' + scoreboard: '§dPunteggio richiesto' + stageType: + Bucket: Riempi un secchio + Craft: Crafta oggetto + Fish: Pesca pesci + chat: Scrivi in chat + interact: Interagisci con un blocco + items: Riporta gli oggetti + location: Trova una posizione + mine: Rompi blocchi + mobs: Uccidi mob + npc: Trova l'NPC + placeBlocks: Piazza blocchi + playTime: Tempo di gioco + region: Trova la regione + time: + days: '{days_amount} giorni' + hours: '{hours_amount} ore' + minutes: '{minutes_amount} minuti' unknown: sconosciuto - notSet: '§cnon impostato' - unused: '§2§lNon utilizzato' - used: '§a§lUtilizzato' - remove: '§7Click centrale per rimuovere' - or: o - amount: '§eQuantità: {0}' - items: oggetti - expPoints: punti esperienza 'yes': 'Si' - 'no': 'No' - and: e +msg: + bringBackObjects: Riportami {items}. + command: + adminModeEntered: '§aSei entrato nella modalità Admin.' + adminModeLeft: '§aSei uscito dalla modalità Admin.' + backupCreated: '§6Hai creato con successo i backup di tutte le missioni e le informazioni dei giocatori.' + backupPlayersFailed: '§cCreazione di un backup per tutte le informazioni dei giocatori non riuscita.' + backupQuestsFailed: '§cCreazione di un backup per tutte le missioni non riuscita.' + cancelQuest: '§6Hai annullato la missione {quest}.' + cancelQuestUnavailable: '§cLa missione {quest} non può essere annullata.' + checkpoint: + noCheckpoint: '§cNessun checkpoint trovato per la missione {quest}.' + questNotStarted: '§cNon stai facendo questa missione.' + downloadTranslations: + downloaded: '§aLa lingua {lang} è stata scaricata! §7Ora devi modificare il file "/plugins/BeautyQuests/config.yml" per cambiare il valore di §ominecraftTranslationsFile§7 con {lang}, quindi riavviare il server.' + exists: '§cIl file {file_name} esiste già. Aggiungi "-overwrite" al tuo comando per sovrascriverlo. (/quests downloadTranslations <lang> -overwrite)' + notFound: '§cLingua{lang} non trovata per la versione {version}.' + syntax: '§cDevi specificare una lingua per il download. Esempio: "/quests downloadTranslations en_US".' + help: + adminMode: '§6/{label} adminMode: §eAbilita/disabilita la modalità Admin. (Utile per visualizzare i messaggi di log.)' + create: '§6/{label} create: §eCrea una missione.' + edit: '§6/{label} edit: §eModifica una missione.' + finishAll: '§6/{label} finishAll <giocatore>:: §eTermina tutte le missioni di un giocatore.' + header: '§6§lBeautyQuests — Aiuto' + list: '§6/{label} list: §eVisualizza la lista delle missioni. (Solo per versioni supportate.)' + reload: '§6/{label} reload: §eSalva e ricarica tutte le configurazioni e i file. (§cobsoleto§e)' + remove: '§6/{label} remove <id>: §eElimina una quest con un id definito o clicca sul NPC quando non è specificato.' + resetPlayer: '§6/{label} resetPlayer <giocatore>: §eRimuovi tutte le informazioni su un giocatore.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <giocatore> [id]: §eElimina le informazioni di una quest per un giocatore.' + save: '§6/{label} save: §eAvvia un salvataggio manuale del plugin.' + seePlayer: '§6/{label} seePlayer <giocatore>: §eVisualizza le informazioni su un giocatore.' + setItem: '§6/{label} setItem <talk|launch>: §eSalva l''oggetto dell''hologram.' + setStage: '§6/{label} setStage <giocatore> <id> [nuovo ramo] [nuova fase]: §eSalta la fase corrente/avvia il ramo/imposta una fase per un ramo.' + start: '§6/{label} start <giocatore> [id]: §eForza l''inizio di una missione.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eAvvia la finestra di dialogo in attesa per uno stadio NPC o la finestra di partenza per una missione.' + version: '§6/{label} version: §eVisualizza la versione del plugin.' + invalidCommand: + simple: '§cQuesto comando non esiste, scrivi §ehelp§c.' + itemChanged: '§aL''oggetto è stato modificato. Le modifiche verranno applicate dopo il riavvio.' + itemRemoved: '§aL''oggetto nell''hologram è stato rimosso.' + leaveAll: '§aHai forzato la fine della(e) quest {success}. Errori: {errors}' + removed: '§aLa missione {quest_name} è stata rimossa con successo.' + resetPlayer: + player: '§6Tutte le informazioni della(e) tua(e) {quest_amount} quest sono state/sono state eliminate da {deleter_name}.' + remover: '§6{quest_amount} le/l''informazioni(e) (e {quest_pool} pools) della quest {player} è/sono stata/e eliminata/e.' + resetPlayerPool: + full: '§aHai resettato i dati del pool {pool} di {player}.' + timer: '§aHai resettato il timer del pool {pool} di {player}.' + resetPlayerQuest: + player: '§6Tutte le informazioni sulla missione {quest} sono state eliminate da {deleter_name}.' + remover: '§6{player} informazioni delle quest di {quest} sono state eliminate.' + resetQuest: '§6Dati della missione rimossi per {player_amount} giocatori.' + scoreboard: + hidden: '§6ILa scoreboard del giocatore {player_name} è stata nascosta.' + lineInexistant: '§cLa linea {line_id} non esiste.' + lineRemoved: '§6Hai rimosso con successo la riga {line_id}.' + lineReset: '§6Hai resettato con successo la riga {line_id}.' + lineSet: '§6Hai modificato con successo la riga {line_id}.' + own: + hidden: '§6La tua scoreboard è ora nascosta.' + shown: '§6La tua scoreboard è ora visibile di nuovo.' + resetAll: '§6Hai resettato con successo la scoreboard del giocatore {player_name}.' + shown: '§6La scoreboard del giocatore {player_name} è visibile.' + setStage: + branchDoesntExist: '§cIl ramo con l''id {branch_id} non esiste.' + doesntExist: '§cLa fase con l''id {stage_id} non esiste.' + next: '§aLa fase è stata saltata.' + nextUnavailable: '§cL''opzione "salta" non è disponibile quando il giocatore è alla fine di un ramo.' + set: '§aFase {stage_id} avviata.' + startDialog: + alreadyIn: '§cIl giocatore sta già riproducendo un dialogo.' + impossible: '§cImpossibile avviare la finestra di dialogo.' + noDialog: '§cIl giocatore non ha una finestra in sospeso.' + success: '§aAvviata la finestra di dialogo per il giocatore {player} nella missione {quest}!' + startPlayerPool: + error: Avvio del pool {pool} per {player} non riuscito. + success: 'Iniziato il pool {pool} a {player}. Risultato: {result}' + startQuest: '§6Hai forzato l''avvio della missione {quest} (UUID giocatore: {player}).' + startQuestNoRequirements: '§cIl giocatore non soddisfa i requisiti per la missione {quest}... Aggiungi "-overrideRequirements" alla fine del tuo comando per aggirare il controllo dei requisiti.' + dialogs: + skipped: '§8§o Dialogo saltato.' + tooFar: '§7§oSei troppo lontano da {npc_name}...' + editor: + already: '§cSei già nell''editor.' + blockAmount: '§aScrivi la quantità di blocchi:' + blockData: '§aScrivi il blockdata (blockdata disponibili: {available_datas}):' + blockName: '§aScrivi il nome del blocco:' + dialog: + cleared: '§a{amount} ha rimosso il messaggio(i).' + help: + addSound: '§6addSound <id> <suono>: §eAggiungi un suono a un messaggio.' + clear: '§6clear: §eRimuovi tutti i messaggi.' + close: '§6close: §eConvalida tutti i messaggi.' + header: '§6§lBeautyQuests — Aiuto editor' + list: '§6list: §eVisualizza tutti i messaggi.' + nothing: '§6noSender <messaggio>: §eAggiungi un messaggio senza un mittente.' + nothingInsert: '§6nothingInsert <id> <messaggio>: §eInserisci un messaggio senza alcun prefix.' + npc: '§6npc <messaggio>: §eAggiungi un messaggio detto dal NPC.' + npcInsert: '§6npcInsert <id> <messaggio>: §eInserisci un messaggio detto dall''NPC.' + player: '§6player <messaggio>: §eAggiungi un messaggio detto dal giocatore.' + playerInsert: '§6playerInsert <id> <messaggio> §eInserisci un messaggio detto dal giocatore.' + remove: '§6remove <id>:§eRimuovi un messaggio.' + setTime: '§6setTime <id> <time>: §eImposta il tempo (in ticks) prima che il prossimo msg venga inviato automaticamente.' + syntaxRemove: '§cSintassi corretta: remove <id>' + timeRemoved: '§aIl tempo è stato rimosso per il messaggio {msg}.' + timeSet: '§aIl tempo è stato modificato per il messaggio {msg}: ora è {time} tick.' + enter: + title: '§6~ Modalità Editor ~' + goToLocation: '§aVai alla posizione desiderata per la fase.' + itemCreator: + invalidBlockType: '§cTipo di blocco non valido.' + invalidItemType: '§cTipo di oggetto non valido. (L''oggetto non può essere un blocco.)' + itemAmount: '§aScrivi la quantità di oggetti:' + itemLore: '§aModifica la lore dell''oggetto: (Scrivi "help" per aiuto.)' + itemName: '§aScrivi il nome dell''oggetto:' + itemType: '§aScrivi il nome del tipo di oggetto desiderato:' + unknownBlockType: '§cTipo di blocco sconosciuto.' + unknownItemType: '§cTipo oggetto sconosciuto.' + mythicmobs: + disabled: '§cMythicMob è disabilitato.' + isntMythicMob: '§cQuesto Mythic Mob non esiste.' + list: '§aUn elenco di tutti i Mythic Mobs:' + noSuchElement: '§cNon ci sono elementi del genere. Gli elementi consentiti sono: §e{available_elements}' + npc: + choseStarter: '§aScegli il NPC che avvia la missione.' + enter: '§aClicca su un NPC o scrivi "cancel".' + notStarter: '§cQuesto NPC non avvia nessuna quest.' + pool: + hologramText: Scrivi il testo dell'hologram personalizzato per questo pool (o "null" se vuoi quello predefinito). + maxQuests: Scrivi la quantità massima di missioni lanciabili da questa pool. + scoreboardObjectiveNotFound: '§cObiettivo scoreboard sconosciuto.' + selectWantedBlock: '§aClicca con il bastone sul blocco desiderato per la fase.' + text: + argNotSupported: '§cL''argomento {arg} non è supportato.' + chooseJobRequired: '§aScrivi il nome del lavoro desiderato:' + chooseLvlRequired: '§aScrivi la quantità richiesta di livelli:' + chooseMoneyRequired: '§aScrivi la quantità di denaro richiesto:' + chooseObjectiveRequired: '§aScrivi il nome dell''obbiettivo.' + chooseObjectiveTargetScore: '§aScrivi il punteggio richiesto per l''obiettivo.' + choosePermissionMessage: '§aPuoi scegliere un messaggio di rifiuto se il giocatore non ha il permesso necessario. (Per saltare questo passo, scrivi "null".)' + choosePermissionRequired: '§aScrivi il permesso necessario per iniziare la missione:' + choosePlaceholderRequired: + identifier: '§aScrivi il nome del placeholder richiesto senza il carattere della percentuale:' + value: '§aScrivi il valore richiesto per il placeholder §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aScrivi il nome della region richiesta (devi essere nello stesso mondo).' + chooseSkillRequired: '§aScrivi il nome dell''abilità richiesta:' + reward: + money: '§aScrivi l''importo dei soldi ricevuti:' + permissionName: '§aScrivi il nome del permesso.' + permissionWorld: '§aScrivi il mondo in cui verrà modificato il permesso, o "null" se vuoi che sia globale.' + textList: + help: + add: '§6add <messaggio>: §eAggiungi un testo.' + close: '§6close: §eConvalida i testi aggiunti.' + header: '§6§lBeautyQuests — Guida editor' + list: '§6list: §eVisualizza tutti i testi aggiunti.' + remove: '§6remove <id>: §eRimuovi un testo.' + syntax: '§cSintassi corretta: ' + typeBucketAmount: '§aScrivi la quantità di secchi da riempire:' + typeGameTicks: '§aScrivi i ticket di gioco richiesti:' + typeLocationRadius: '§aScrivi la distanza richiesta dalla posizione:' + errorOccurred: '§cSi è verificato un errore, contatta un amministratore! §4§lCodice di errore: {error}' + experience: + edited: '§aHai cambiato l''esperienza guadagnata da {old_xp_amount} a {xp_amount} punti.' + indexOutOfBounds: '§cIl numero {index} è fuori dai limiti! Deve essere compreso tra {min} e {max}.' + invalidBlockData: '§cIl blockdata {block_data} non è valido o incompatibile con il blocco {block_material}.' + invalidBlockTag: '§cTag blocco {block_tag} non disponibile.' + inventoryFull: '§cIl tuo inventario è pieno, l''oggetto è stato droppato sul pavimento.' + moveToTeleportPoint: '§aVai alla posizione di teletrasporto desiderata.' + npcDoesntExist: '§cIl NPC con l''id {npc_id} non esiste.' + number: + invalid: '§c{input} non è un numero valido.' + negative: '§cDevi inserire un numero positivo!' + notInBounds: Il valore di entrata deve essere compreso fra {min} e {max} + zero: '§cDevi inserire un numero diverso da 0!' + pools: + allCompleted: '§7Hai completato tutte le missioni!' + maxQuests: '§cNon puoi avere più di {pool_max_quests} missioni contemporaneamente...' + noAvailable: '§7Non ci sono più missioni disponibili...' + noTime: '§cDevi aspettare {time_left} prima di fare un''altra quest.' + quest: + alreadyStarted: '§cHai già iniziato la missione!' + cancelling: '§cProcesso di creazione della quest annullato.' + createCancelled: '§cLa creazione o la modifica è stata annullata da un altro plugin!' + created: '§aCongratulazioni! Hai creato la quest §e{quest}§a, che comprende {quest_branches} ramo(i)!' + editCancelling: Processo di modifica della quest annullato. + edited: '§aCongratulazioni! Hai modificato la quest §e{quest}§a che ora include {quest_branches} ramo(i)!' + finished: + base: '§aCongratulazioni! Hai completato la missione §e{quest_name}§a!' + obtain: '§aHai ottenuto {rewards}!' + invalidID: '§ cLa quest con id {quest_id} non esiste.' + invalidPoolID: '§cLa piscina {pool_id} Non esiste' + notStarted: '§cNon stai facendo questa missione attualmente.' + started: '§aHai iniziato la quest §r§e{quest_name}§o§6!' + questItem: + craft: '§cNon puoi usare un oggetto della missione per caftare!' + drop: Non puoi buttare un oggetto necessario per la missione! + eat: '§cNon puoi mangiare un oggetto della missione!' + quests: + checkpoint: '§7Checkpoint raggiunto!' + failed: '§cHai fallito la missione {quest_name}...' + maxLaunched: '§cTu non puoi averne più di {quests_max_amount} quest(s) allo stesso momento...' + updated: '§7Quest §e{quest_name}§7 aggiornata.' + regionDoesntExists: '§cQuesta regione non esiste. (Devi essere nello stesso mondo.)' + requirements: + combatLevel: '§cIl tuo livello di combattimento deve essere {long_level}!' + job: '§cIl tuo livello per il lavoro §e{job_name}§c deve essere {long_level}!' + level: '§cIl tuo livello deve essere {long_level}!' + money: '§cDevi avere {money}!' + quest: '§cDevi aver completato la missione §e{quest_name}§c!' + skill: '§cIl tuo livello per l''abilità §e{skill_name}§c deve essere {long_level}!' + waitTime: '§cDevi aspettare {time_left} minuto(i) prima di poter riavviare questa missione!' + restartServer: '§7Riavvia il tuo server per applicare le modifiche.' + selectNPCToKill: '§aSeleziona il NPC da uccidere.' + stageMobs: + listMobs: '§aDevi uccidere {mobs}.' + typeCancel: '§aScrivi "Annulla" per tornare all''ultimo testo.' + versionRequired: 'Versione richiesta: §l{version}' + writeChatMessage: '§aScrivi il messaggio richiesto: (Aggiungi "{SLASH}" all''inizio se vuoi usare un comando.)' + writeCommand: '§aScrivi il comando desiderato: (Il comando va inserito senza "/" e il placeholder "{PLAYER}" è supportato. Verrà sostituito con il nome del giocatore.)' + writeCommandDelay: '§aScrivi il ritardo del comando desiderato, in tick.' + writeConfirmMessage: '§aScrivi il messaggio di conferma mostrato quando un giocatore sta per iniziare la quest: (Scrivi "null" se vuoi il messaggio predefinito.)' + writeDescriptionText: '§aScrivi il testo che descrive l''obiettivo della fase:' + writeEndMsg: '§aScrivi il messaggio che verrà inviato alla fine della missione, "null" se vuoi quello predefinito o "nessuno" se vuoi nessuno. È possibile utilizzare "{rewards}" che verrà sostituito con i premi ottenuti.' + writeEndSound: '§aScrivi il nome del suono che verrà riprodotto al giocatore alla fine della missione, "null" se vuoi quello predefinito o "none" se non vuoi:' + writeHologramText: '§aScrivi il testo dell''hologram: (Scrivi "none" se non vuoi un ologramma e "null" se vuoi il testo predefinito.)' + writeMessage: '§aScrivi il messaggio che verrà inviato al giocatore' + writeMobAmount: '§aScrivi la quantità di mob da uccidere:' + writeMobName: '§aScrivi il nome personalizzato del mob da uccidere:' + writeNPCText: '§aScrivi il dialogo che verrà detto al giocatore dal NPC: (Scrivi "help" per ricevere aiuto.)' + writeNpcName: '§aScrivi il nome del NPC:' + writeNpcSkinName: '§aScrivi il nome della skin dell''NPC:' + writeQuestDescription: '§aScrivi la descrizione della missione, verrà mostrata nell''interfaccia delle missioni del giocatore.' + writeQuestMaterial: '§aScrivi il materiale dell''oggetto della missione.' + writeQuestName: '§aScrivi il nome della quest:' + writeQuestTimer: '§aScrivi il tempo richiesto (in minuti) prima di poter riavviare la quest: (Scrivi "null" se vuoi il timer predefinito.)' + writeRegionName: '§aScrivi il nome della regione richiesta per l''obbiettivo:' + writeStageText: '§aScrivi il testo che verrà inviato al giocatore all''inizio della fase:' + writeStartMessage: '§aScrivi il messaggio che verrà inviato all''inizio della missione, "null" se vuoi quello predefinito o "none" se non vuoi:' + writeXPGain: '§aScrivi la quantità di punti esperienza che il giocatore otterrà: (Ultimo valore: {xp_amount})' +scoreboard: + name: '§6§lMissioni' + noLaunched: '§cNessuna missione in corso.' + noLaunchedDescription: '§c§oCaricamento' + noLaunchedName: '§c§lCaricamento' + stage: + bucket: '§eRiempi §6{buckets}' + chat: '§eScrivi §6{text}' + craft: '§eCrafta §6{items}' + fish: '§ePesca §6{items}' + interact: '§eClicca sul blocco a §6{x}' + interactMaterial: '§eClicca su un blocco §6{block}§e' + items: '§ePorta gli oggetti a §6{dialog_npc_name}§e:' + location: '§eVai a §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world}' + mine: '§eMina {blocks}' + mobs: '§eUccidi §6{mobs}' + npc: '§eParla con NPC §6{dialog_npc_name}' + placeBlocks: '§ePosiziona {blocks}' + region: '§eTrova regione §6{region_id}' + textBetwteenBranch: '§e o' diff --git a/core/src/main/resources/locales/ko_KR.yml b/core/src/main/resources/locales/ko_KR.yml new file mode 100755 index 00000000..67a723b7 --- /dev/null +++ b/core/src/main/resources/locales/ko_KR.yml @@ -0,0 +1,222 @@ +--- +advancement: + finished: 완료됨 + notStarted: 시작되지 않음 +description: + requirement: + class: '직업: {class_name}' + level: 레벨 {short_level} + skillLevel: 레벨 {short_level}/{skill_name} +indication: + cancelQuest: '§7{quest_name} 퀘스트를 포기 하시겠습니까?' + removeQuest: '§7{quest} 퀘스트를 삭제 하시겠습니까?' +inv: + addObject: '§a오브젝트 추가' + blocksList: + name: 블록 선택 + cancel: '§c§l취소' + chooseQuest: + name: 어떤 퀘스트? + commandsList: + name: 명령어 목록 + confirm: + name: 계속하시겠습니까? + 'no': '§c아니오' + 'yes': '§a예' + create: + NPCText: '§e엔피시 대화 편집' + bringBack: '§a아이템 가져오기' + cancelMessage: 발송 취소 + craft: '§a아이템 만들기' + currentRadius: '§e현재 거리: §6{radius}' + editBlocksMine: '§e부술 블럭 설정' + editBucketAmount: '§e채울 양동이의 갯수 편집' + editBucketType: '§e채울 양동이 유형 편집' + editFishes: '§e잡을 물고기 편집' + editItem: '§e만들 아이템 편집' + editLocation: '§e좌표 편집' + editMessageType: '§e채팅 치기 편집' + editMobsKill: '§e죽일 몬스터 설정하기' + editRadius: '§e좌표로부터의 거리 편집' + findNPC: '§aNPC 찾아가기' + findRegion: '§a지역 찾아가기' + fish: '§a물고기 잡기' + hideClues: 파티클 및 홀로그램 숨기기 + ignoreCase: 채팅치기 대소문자 구분 여부 + interact: '§a블럭 상호작용' + killMobs: '§a사냥하기' + leftClick: 좌클릭만 감지 + location: '§a특정 좌표로 이동하기' + mineBlocks: '§a블럭 부수기' + mobsKillFromAFar: 발사체로 죽일지 여부 + preventBlockPlace: 자신이 설치한 블럭 가능 여부 + selectBlockLocation: '§e블럭 위치 선택' + selectItems: '§e필수 항목 편집' + selectRegion: '§7지역 선택' + stageCreate: '§a새로운 퀘스트 만들기' + stageDown: 아래로 이동하기 + stageRemove: '§c단계 삭제' + stageStartMsg: '§e퀘스트 시작 메시지 편집' + stageUp: 위로 이동하기 + talkChat: '§a채팅치기' + details: + auto: 접속시 자동으로 수령 + autoLore: 활성화시 서버에 처음 접속하는 사람에게 해당 퀘스트가 시작됩니다. + createQuestLore: 퀘스트 이름을 정해야합니다. + customDescriptionLore: 퀘스트 GUI 아래에 설명이 표시됩니다. + failOnDeath: 사망 시 실패하기 + keepDatas: 플레이어 데이터 유지하기 + questName: 퀘스트 이름 정하기 + questNameLore: 퀘스트 편집을 끝내기 위해선 퀘스트 이름을 설정해야 합니다. + removeItemsReward: 인벤토리에서 아이템 제거 + scoreboardItem: 스코어보드 활성화하기 + setItemsRewards: 보상 설정하기 + setRewardStopQuest: 퀘스트 종료 + setXPRewards: 보상으로 받을 경험치 양 설정하기 + itemComparisons: + itemLore: 아이템 설명 + itemName: 아이템 이름 + itemsSelect: + name: 아이템 수정 + listBook: + questStages: 단계 + listPlayerQuests: + name: '{player_name}의 퀘스트' + listQuests: + canRedo: '§3§o이 퀘스트를 다시 수행할 수 있습니다!' + finished: 완료한 퀘스트 + inProgress: 진행중인 퀘스트 + loreCancelClick: '§c퀘스트 포기하기' + loreDialogsHistoryClick: '§7퀘스트 내용 다시보기' + loreStart: '§a클릭해서 퀘스트 시작하기' + notStarted: 시작 가능한 퀘스트 + timeToWaitRedo: '§3§o이 퀘스트는 {time_left} 뒤에 다시 시작할 수 있습니다.' + timesFinished: '§3퀘스트를 {times_finished} 번 완료함.' + mobSelect: + mythicMob: '§6미스틱 몹 선택' + mobs: + name: 몹 선택하기 + npcCreate: + name: NPC 생성 + setName: '§eNPC 이름 설정' + setSkin: '§eNPC 스킨 설정' + setType: '§eNPC 타입 설정' + poolsManage: + poolQuestsList: '§7{pool_quests_amount} §8퀘스트: §7{pool_quests}' + search: '§e§l검색' + stages: + branchesPage: '§d분기 페이지' + descriptionTextItem: '§e퀘스트 설정 설명' + endingItem: '§e최종 보상 설정' + laterPage: '§e이전 페이지' + name: 스테이지 작성 + newBranch: '§e새 페이지로 이동' + nextPage: '§e다음 페이지' + previousBranch: '§e이전 지점' + regularPage: '§a정규 페이지' + validate: '§b§l저장하다.' +misc: + amount: '§e갯수: {amount}' + and: 그리고 + click: + left: 좌클릭 + right: 우클릭 + shift-left: Shift-좌클릭 + shift-right: Shift-우클릭 + comparison: + greaterOrEquals: '{number} 이상' + disabled: 비활성화 + enabled: 활성화 + format: + prefix: '§6<§e§l퀘스트§r§6> §r' + hologramText: 퀘스트 NPC + 'no': '아니오' + or: 또는 + stageType: + mobs: 사냥하기 + npc: NPC 찾기 + region: 지역 찾아가기 + time: + days: '{days_amount}일' + hours: '{hours_amount}시간' + minutes: '{minutes_amount}분' + weeks: '{weeks_amount}주' + unknown: 알 수 없음 + 'yes': '예' +msg: + command: + invalidCommand: + simple: '§c알수없는 커맨드입니다. §ehelp §c를 입력해주세요.' + itemChanged: '§a항목이 재편집 되었습니다. 변경사항은 재시작 후 적용될것입니다.' + itemRemoved: '§a홀로그램 항목이 제거 되었습니다.' + leaveAll: '§a{success}퀘스트를 건너뛰었습니다. §c에러 : {errors}' + removed: '§a{quest_name} 퀘스트가 성공적으로 제거되었습니다.' + resetPlayer: + player: '§6당신의 {quest_amount} 퀘스트(들)에 대한 모든 설명이 {deleter_name}에 의해 삭제되었습니다.' + setStage: + next: '§a단계를 건너뛰었습니다.' + set: '§a스테이지 {stage_id} 이 시작되었습니다.' + editor: + mythicmobs: + disabled: '§c미스틱몹이 비활성화됩니다..' + isntMythicMob: '§c이 미스틱 몹은 존재하지 않습니다.' + list: '§a모든 미스틱 몹 목록:' + textList: + help: + add: '§6add <message>: §e텍스트를 추가합니다.' + close: '§6close: §e추가된 텍스트의 유효성을 확인하십시오.' + header: '§6§lBeautyQuests — 리스트 편집 도움말' + list: '§6list: §e추가된 모든 텍스트를 확인합니다.' + remove: '§6remove <id>: §e텍스트를 삭제합니다.' + errorOccurred: '§c에러가 발생했습니다. 관리자에게 문의하세요! §4§lError code: {error}' + indexOutOfBounds: '§c {index}는 범위를 벗어난 값입니다! {min} 과 {max} 사이여야 합니다.' + number: + invalid: '§c{input}는 유효한 숫자가 아닙니다.' + pools: + allCompleted: '§7모든 퀘스트를 완료했습니다!' + maxQuests: '§c당신은 {pool_max_quests}개 이상의 퀘스트를 동시에 가질 수 없습니다...' + noAvailable: '§7완료 가능한 퀘스트가 존재하지 않습니다.' + noTime: '§c다른 퀘스트를 하기위해 {time_left}만큼 기다려야 합니다.' + quest: + alreadyStarted: '§c퀘스트를 이미 시작하셨습니다!' + cancelling: '§c퀘스트 생성 프로세스가 취소되었습니다.' + createCancelled: '§c다른 플러그인으로 인해 생성 또는 수정이 취소되었습니다.' + created: '§a축하합니다! {quest_branches} 를(을) 포함하는 퀘스트 §e{quest}§a를(을) 제작했습니다!' + editCancelling: '§c퀘스트 에디션의 프로세스가 취소되었습니다.' + edited: '§a축하합니다! §e{quest}§a 를(을) 포함한 퀘스트를 수정했습니다.' + finished: + base: '§a축하합니다! §e{quest_name}§a 퀘스트를 완료하셨습니다.' + obtain: '§a{rewards}를 얻었습니다!' + invalidID: '§cID가 {quest_id} 인 퀘스트가 존재하지 않습니다.' + invalidPoolID: '§c{pool_id}이(가) 존재하지 않습니다.' + started: '§r§e{quest_name}§o§6 §a퀘스트를 시작하셨습니다.' + questItem: + craft: '§c퀘스트용 아이템을 조합에 사용할 수 없습니다!' + drop: '§c퀘스트 아이템은 버릴 수 없습니다!' + eat: 퀘스트 아이템은 팔 수 없습니다. + quests: + checkpoint: '§7퀘스트 체크포인트에 도달 하였습니다!' + failed: '§c당신은 {quest_name} 퀘스트를 실패했습니다...' + maxLaunched: '§c당신은 {quests_max_amount}개 이상의 퀘스트를 동시에 가질 수 없습니다...' + updated: '§7퀘스트 §e{quest_name}§7가 업데이트 되었습니다.' + requirements: + level: '§c퀘스트를 받기 위한 레벨이 부족합니다! {long_level}!' + money: '§c{money}를 가져야합니다!' + quest: '§c먼저 §e{quest_name}§c 퀘스트를 완료 해야합니다.' + stageMobs: + listMobs: '§a당신은 {mobs}를 죽여야만 합니다.' + versionRequired: '버전 요구 사항: §l{version}' + writeCommand: '§a원하는 커맨드를 입력하세요: (커맨드는 "/"와 "{PLAYER}" 를 제외하고 써도 좋습니다. 자동으로 실행하는 사람을 대상으로 설정할 것입니다.)' + writeMobAmount: '§a죽일 몹의 수를 적어 주세요:' + writeNPCText: '§aNPC가 플레이어에게 말할 대사를 작성해주세요: (도움말을 보려면 "help"를 입력하세요.)' + writeNpcName: '§aNPC의 이름을 적어주세요:' + writeNpcSkinName: '§aNPC 스킨의 이름을 입력하세요:' + writeQuestName: '§a퀘스트의 이름을 입력하세요:' + writeRegionName: '§a해당 단계에 필요한 지역의 이름을 입력하세요:' + writeXPGain: '§a플레이어가 획득할 경험치량을 입력하세요: (최근 값: {xp_amount})' +scoreboard: + name: '§6§l퀘스트' + stage: + mine: '&e블록 캐기 {blocks}' + mobs: '&e사냥하기 §6{mobs}' + region: '§6{region_id} §e지역 찾아가기' diff --git a/core/src/main/resources/locales/lt_LT.yml b/core/src/main/resources/locales/lt_LT.yml index def1cf08..95b396db 100644 --- a/core/src/main/resources/locales/lt_LT.yml +++ b/core/src/main/resources/locales/lt_LT.yml @@ -1,520 +1,482 @@ --- -msg: - quest: - finished: - base: '§aSveikiname! Jūs baigėte Misija §e{0}§a!' - obtain: '§aJūs gaunate {0}!' - started: '§aJūs pradėjote Misija §r§e{0}§o§6!' - created: '§aSveikiname! Jūs sukūrėte užduotį §e{0}§a, kuri apima {1} atšaka(s)!' - edited: '§aSveikiname! Redagavote užduotį §e{0}§a, kuri apima ir dabar {1} atšaka(s)!' - createCancelled: '§cKūrinį ar leidimą atšaukė kitas papildinys!' - cancelling: '§cUžduoties kūrimo procesas atšauktas.' - invalidID: '§cUžduotis su ID {0} neegzistuoja.' - alreadyStarted: '§cJūs jau pradėjote Misija!' - quests: - nopStep: '§cŠis Misija neturi jokio žingsnio.' - updated: '§7Misija §e{0}§7 atnaujinta.' - checkpoint: '§7Pasiektas misijos kontrolinis punktas!' - failed: '§cJums nepavyko užduotis {0}...' - questItem: - drop: '§cJūs negalite mesti Misija daiktas!' - craft: '§cNegalite naudoti Misijos Daikto, kad sukurtumėte!' - stageMobs: - noMobs: '§cŠiam etapui nereikia jokios minios, kad būtų galima nužudyti.' - listMobs: '§aPrivalai nužudyti {0}.' - writeNPCText: '§aParašykite dialogą, kurį žaidėjas pasakys NPC: (Write "help" gauti pagalbos.)' - writeRegionName: '§aParašykite žingsniui reikalingo regiono pavadinimą:' - writeXPGain: '§aParašykite, kiek patirties taškų gaus žaidėjas: (Paskutinis value: {0})' - writeMobAmount: '§aParašykite, kiek Monstru reikia nužudyti:' - writeChatMessage: '§aParašykite reikalingą pranešimą: (Jei, pridėkite "{SLASH}" prie pradžios norite komandos.) ' - writeEndMessage: '§aParašykite pranešimą, kuris bus išsiųstas užduoties pabaigoje arba scena: " writeDescriptionText: "§aParašykite tekstą, apibūdinantį etapo tikslą:' - writeStageText: '§aParašykite tekstą, kuris bus išsiųstas Žaidejui pradžioje žingsnio: " moveToTeleportPoint: §aEikite į norimą teleportavimo vietą. writeNpcName: "&aParašykite NPC pavadinimą" writeNpcSkinName: "§aParašykite NPC odos pavadinimą:" writeQuestName: "§aParašykite savo užduoties pavadinimą:" writeCommand: "§aParašykite norimą komandą: (Komanda yra be / ir" vietos rezervavimo priemonė „{PLAYER}“ palaikoma. Jis bus pakeistas pavadinimu vykdomas.) “ writeHologramText: "§aParašykite hologramos tekstą: (Jei nenorite, parašykite „nėra“ hologramos ir „null“, jei norite numatytojo teksto.) ' - writeQuestTimer: '§aParašykite reikiamą laiką (in minutes), kad galėtumėte paleisti iš naujo the quest: (Parašykite „null“, jei norite default laikmačio.)' - writeConfirmMessage: '§aParašykite patvirtinimo pranešimą, rodomą, kai žaidėjas yra apie to start the quest: (Parašykite „null“, jei norite numatytojo pranešimo.)' - writeQuestDescription: '§aParašykite Misijos aprašymą, parodytą žaidėjo Misijos GUI.' - writeQuestMaterial: '§aParašykite misijos Daikta medžiagą.' - requirements: - quest: '§cJūs turite baigti Misija §e{0}§c!' - level: '§cJūsų lygis turi būti {0}!' - job: '§cTuri būti jūsų lygis §e{1}§c {0}!' - skill: '§cTuri būti jūsų įgūdis §e{1} §c{0}!' - combatLevel: '§cJūsų kovinis lygis turi būti {0}!' - money: '§cTu privalai turėti {0}!' - experience: - edited: '§aPakeitėte patirties įgijimą iš {0} į {1} taškų.' - selectNPCToKill: '§aPasirinkite nužudyti NPC.' - npc: - remove: '§aNPC ištrintas.' - talk: '§aEik ir pasikalbėk su pavadintu NPC §e{0}§a.' - regionDoesntExists: '§cŠio regiono nėra. (Jūs turite būti tame pačiame pasaulyje.)' - npcDoesntExist: '§cNPC su ID {0} neegzistuoja.' - objectDoesntExist: '§cNurodyto Daikto, kurio ID yra {0}, nėra.' - number: - negative: '§cTurite įvesti teigiamą skaičių!' - zero: '§cTurite įvesti kitą nei. Numerį 0!' - invalid: '§c{0} neteisingas numeris.' - errorOccurred: '§cĮvyko klaida. Susisiekite su administratoriumi! §4§lKlaidos kodas: {0}' - commandsDisabled: '§cŠiuo metu jums neleidžiama vykdyti komandų!' - indexOutOfBounds: '§cSkaičius {0} yra ribų! Tai turi būti nuo {1} iki {2}.' - invalidBlockData: '§cBlokavimo duomenys {0} yra neteisingi arba nesuderinami su bloku {1}.' - bringBackObjects: Atnešk {0}. - inventoryFull: '§cJūsų inventorius yra pilnas, daiktas numestas ant grindų.' - playerNeverConnected: '§cNepavyko rasti informacijos apie žaidėją {0}.' - playerNotOnline: '§cŽaidėjas {0} yra neprisijungęs.' - command: - checkpoint: - noCheckpoint: '§cNerasta užduoties kontrolinio punkto {0}.' - questNotStarted: '§cJūs neatliekate šios Misijos.' - setStage: - branchDoesntExist: '§cFilialas su ID {0} neegzistuoja.' - doesntExist: '§Žyngsnio, kurios ID yra {0}, nėra.' - next: '§a„Žyngsnis“ praleistas.' - nextUnavailable: '§cParinktis „praleisti“ negalima, kai žaidėjas yra šakos pabaiga.' - set: '§aPaleistas {0} etapas.' - playerNeeded: '§cNorėdami vykdyti šią komandą, turite būti žaidėjas!' - incorrectSyntax: '§cNeteisinga sintaksė.' - noPermission: '§cJums nepakanka leidimų vykdyti šią komandą! (Būtina: {0})' - invalidCommand: - quests: '§cŠios komandos nėra, parašykite §e/quests help§c.' - simple: '§cŠios komandos nėra, parašykite §ehelp§c.' - needItem: '§cTurite laikyti daiktą pagrindinėje rankoje!' - itemChanged: '§aDaiktas buvo redaguotas. Pakeitimai turės įtakos iš naujo paleidus.' - itemRemoved: '§aHologramos Daiktas pašalintas.' - removed: '§aUžduotis {0} sėkmingai pašalinta.' - leaveAll: '§aPriverstinai baigėte {0} Misija Klaidos: {1}' - resetPlayer: - player: '§6Visą jūsų {0} užduoties (-ių) informaciją ištrynė {1}.' - remover: '§6{0} {1} Misijos informacija (-os) buvo ištrinta (-os).' - resetPlayerQuest: - player: '§6Visą informaciją apie užduotį {0} ištrynė {1}.' - remover: '§6{0} {1} Misijos informacija (-os) buvo ištrinta (-os).' - resetQuest: '§6Pašalinti {0} žaidėjų Misiju duomenys.' - startQuest: '§6Priverstinai pradėjote užduotį {0} (Žaidejo UUID: {1}).' - cancelQuest: '§6Atšaukėte užduotį {0}.' - cancelQuestUnavailable: '§cUžduoties {0} negalima atšaukti.' - backupCreated: '§6Jūs sėkmingai sukūrėte visų užduočių ir Žaidejo atsargines kopijas informacijos.' - backupPlayersFailed: '§cNepavyko sukurti visos žaidėjo informacijos atsarginės kopijos.' - backupQuestsFailed: '§cNepavyko sukurti visų užduočių atsarginės kopijos.' - adminModeEntered: '§aĮėjote į administratoriaus režimą.' - adminModeLeft: '§aIšėjote iš administratoriaus režimo.' - scoreboard: - lineSet: '§6Sėkmingai redagavote eilutę {0}.' - lineReset: '§6Sėkmingai nustatėte eilutę iš naujo {0}.' - lineRemoved: '§6Jūs sėkmingai pašalinote eilutę {0}.' - lineInexistant: '§cEilutės {0} nėra.' - resetAll: '§6Jūs sėkmingai iš naujo nustatėte žaidėjo rezultatų suvestinę {0}.' - hidden: '§6Žaidėjo {0} rezultatų suvestinė buvo paslėpta.' - shown: '§6Parodytas žaidėjo {0} rezultatų suvestinė.' - help: - header: '§6§lPagalba' - create: '§6/{0} create: §eSukurti kvestą.' - edit: '§6/{0} edit: §eRedaguoti užduotį.' - remove: '§6/{0} remove <id>: §eIštrinkite užduotį su nurodytu ID arba spustelėkite NPC, kai neapibrėžta.' - finishAll: '§6/{0} finishAll <player>: §eBaigti visus žaidėjo uždavinius.' - setStage: '§6/{0} setStage <player> <id> [new branch] [new stage]: §ePraleisti dabartinis etapas / šakos paleidimas / šakos nustatymas. ' - resetPlayer: '§6/{0} resetPlayer <player>: §ePašalinkite visą informaciją apie Žaideja.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <player> [id]: §eIštrinti informaciją apie žaidėjo ieškojimą “. seePlayer: "§6/{0} seePlayer <player>: §ePeržiūrėkite informaciją apie žaidėją.' - reload: '§6/{0} reload: §eIšsaugokite ir iš naujo įkelkite visas konfigūracijas ir failus. (§cdeprecated§e)' - start: '§6/{0} start <player> [id]: §ePriverskite pradėti Misija.' - setItem: '§6/{0} setItem <talk|launch>: §eIšsaugokite hologramos Daikta.' - adminMode: '§6/{0} adminMode: §ePerjungti administratoriaus režimą. (Naudinga rodyti mažai žurnalo pranešimų.) ' - version: '§6/{0} version: §eŽr. Dabartinę papildinio versiją.' - save: '§6/{0} save: §eIšsaugokite rankinį papildinį.' - list: '§6/{0} list: §eŽureti. Užduočių sąrašą. (Tik palaikomoms versijoms.)' - typeCancel: '§aRašykite "cancel" grįžti prie paskutinio teksto.' - editor: - blockAmount: '§aParašykite blokų kiekį:' - blockName: '§aParašykite bloko pavadinimą:' - blockData: '§aParašykite blokaduomenis (galimi blokiniai duomenys: {0}):' - typeBucketAmount: '§aParašykite užpildomų kibirų kiekį:' - goToLocation: '§aEikite į norimą Punkta vietą.' - typeLocationRadius: '§aParašykite reikiamą atstumą nuo vietos:' - typeGameTicks: '§aParašykite reikalingas žaidimo erkes:' - already: '§cJūs jau esate redaktoriuje.' - enter: - title: '§6~ Redaktoriaus režimas ~' - subtitle: '§6Rašykite "/quests editor" priversti išeiti.' - chat: '§6You are currently in the Editor Mode. Write "/quests editor" to force leaving the editor. (Highly not recommended, consider using commands such as "close" or "cancel" to come back to the previous inventory.)' - npc: - enter: '§aSpustelėkite NPC arba parašykite "cancel".' - choseStarter: '§aPasirinkite NPC, kuris pradeda užduotį.' - notStarter: '§cŠis NPC nėra užduočių pradininkas.' - text: - argNotSupported: '§cArgumentas {0} nepalaikomas.' - chooseLvlRequired: '§aParašykite reikiamą kiekį lygių:' - chooseJobRequired: '§aParašykite norimo darbo pavadinimą:' - choosePermissionRequired: '§aParašykite reikiamą leidimą pradėti užduotį:' - choosePermissionMessage: '§aGalite pasirinkti atmetimo pranešimą, jei grotuvas neturi reikiamo leidimo. (Jei norite praleisti šį veiksmą, parašykite „null“.)' - choosePlaceholderRequired: - identifier: '§aParašykite reikiamos placeholder pavadinimą be procentų personažai:' - value: '§aParašykite reikiamą vietos rezervavimo ženklo vertę §e%§e{0}§e%§a:' - chooseSkillRequired: '§aParašykite reikiamo įgūdžio pavadinimą:' - chooseMoneyRequired: '§aParašykite reikalingų pinigų sumą:' - reward: - permissionName: '§aParašykite leidimo pavadinimą.' - permissionWorld: '§aParašykite pasaulį, kuriame bus redaguojamas leidimas, arba „null“, jei norite būti globalus.' - money: '§aParašykite gautų pinigų sumą:' - chooseObjectiveRequired: '§aParašykite objektyvų pavadinimą.' - chooseObjectiveTargetScore: '§aParašykite tikslo tikslinį rezultatą.' - chooseRegionRequired: '§aParašykite reikiamo regiono pavadinimą (turite būti tas pats pasaulis).' - selectWantedBlock: '§aSpustelėkite lazda ant norimo Etapo bloko.' - itemCreator: - itemType: '§aParašykite norimo daikto tipo pavadinimą:' - itemAmount: '§aParašykite Daiktu (-ių) kiekį:' - itemName: '§aParašykite daikto pavadinimą:' - itemLore: '§aPakeiskite prekės aprašymą: (Parašykite „help“, kad gautumėte pagalbos.)' - unknownItemType: '§cNežinomas daikto tipas.' - invalidItemType: '§cNeteisingas daikto tipas. (daiktas negali būti blokas.)' - unknownBlockType: '§cNežinomas bloko tipas.' - invalidBlockType: '§cNeteisingas bloko tipas.' - dialog: - syntax: '§cteisinga syntax: {0}{1} <message>' - syntaxRemove: '§cTeisingai sytax: pašalinti <id>' - player: '§aŽaidėjui pridėtas pranešimas „{0}“.' - npc: '§aNPC pridėtas pranešimas „{0}“.' - noSender: '§aPranešimas „{0}“ pridėtas be siuntėjo.' - messageRemoved: '§aPranešimas „{0}“ pašalintas.' - soundAdded: '§aGarsas „{0}“ pridėtas prie pranešimo "{1}".' - cleared: '§a{0} pašalintas pranešimas (-ai).' - help: - header: '§6§l„Misiju“ - „Dialog“ redaktoriaus pagalba' - npc: '§6npc <message>: §ePridėkite pranešimą, kurį pasakė NPC.' - player: '§6player <message>: §ePridėkite žaidėjo pasakytą pranešimą.' - nothing: '§6noSender <message>: §ePridėkite pranešimą be siuntėjo.' - remove: '§6remove <id>: §ePašalinti pranešimą.' - list: '§6list: §ePeržiūrėti visus pranešimus.' - npcInsert: '§6npcInsert <id> <message>: §eĮterpkite pranešimą, kurį pasakė NPC.' - playerInsert: '§6playerInsert <id> <message>: §eĮterpkite žaidėjo pasakytą pranešimą.' - nothingInsert: '§6nothingInsert <id> <message>: §eĮterpti pranešimą be bet koks priešdėlis.' - addSound: '§6addSound <id> <sound>: §ePridėkite garsą prie pranešimo.' - clear: '§6clear: §ePašalinti visus pranešimus.' - close: '§6close: §ePatvirtinkite visus pranešimus.' - setTime: '§6setTime <id> <time>: §eSet the time (in ticks) prieš kitą msg groja automatiškai.' - timeSet: '§aPranešimo laikas redaguotas {0}: dabar {1} tick.' - timeRemoved: '§aPranešimo laikas pašalintas {0}.' - mythicmobs: - list: '§aVisų mitinių mobų sąrašas:' - isntMythicMob: '§cŠis mitinis mobas neegzistuoja.' - disabled: '§c„MythicMob“ yra išjungtas.' - epicBossDoesntExist: '§cŠio epo viršininko nėra.' - textList: - syntax: '§cTeisingai syntax: ' - added: '§aPridėtas tekstas „{0}“.' - removed: '§aTekstas „{0}“ pašalintas.' - help: - header: '§6§lMisiju' - add: '§6add <message>: §ePridėti tekstą.' - remove: '§6remove <id>: §ePašalinti tekstą.' - list: '§6list: §ePeržiūrėti visus pridėtus tekstus.' - close: '§6close: §ePatvirtinkite pridėtus tekstus.' - noSuchElement: '§cTokio elemento nėra. Leidžiami elementai yra: §e{0}' - comparisonType: '§aPasirinkite norimą palyginimo tipą tarp {0}. Numatytasis palyginimas is: §e§ldidesnis arba lygus§r§a. Norėdami jį naudoti, įveskite §onull§r§a.' - scoreboardObjectiveNotFound: '§cNežinomas rezultatų suvestinės tikslas.' - writeCommandDelay: '§aParašykite norimą komandos uždelsimą, pažymėdami varnele.' advancement: finished: Baigta notStarted: Nepradėta +indication: + cancelQuest: '§7Ar tikrai norite atšaukti užduotį {quest_name}?' + closeInventory: '§7Ar tikrai norite uždaryti GUI?' + removeQuest: '§7Ar tikrai norite pašalinti užduotį {quest}?' + startQuest: '§7Ar norite pradėti ieškojimą {quest_name}?' inv: - validate: '§b§lPatvirtinti' + block: + blockData: '§dBlokiniai duomenys (advanced)' + material: '§eMedžiaga: {block_type}' + name: Pasirinkite bloką + blockAction: + location: '§ePasirinkite tikslią vietą' + material: '§ePasirinkite bloko medžiagą' + name: Pasirinkite blokavimo veiksmą + blocksList: + addBlock: '§aSpustelėkite, jei norite pridėti bloką.' + name: Pasirinkite blokus + buckets: + name: kibiro tipas cancel: '§c§lAtšaukti' - search: '§e§lPaieška' + checkpointActions: + name: Kontrolės punkto veiksmai + chooseAccount: + name: Kokia sąskaita? + chooseQuest: + name: Kuris Misija? + command: + console: Konsolė + delay: '§bDelsimas' + name: Komanda + value: '§eKomanda' + commandsList: + console: '§eKonsolė: {command_console}' + name: Komandų sąrašas + value: '§eKomanda: {command_label}' confirm: name: Ar tu tuo tikras? - 'yes': '§aPatvirtinti' 'no': '§cAtšaukti' + 'yes': '§aPatvirtinti' create: - stageCreate: '§aSukurkite naują žingsnį' - stageRemove: '§cIštrinkite šį veiksmą' - findNPC: '§aRaskite NPC' + NPCSelect: '§ePasirinkite arba sukurkite NPC' + NPCText: '§eRedaguoti dialogo langą' bringBack: '§aGrąžinkite daiktus' + bucket: '§aUžpildykite kibirus' + cancelMessage: Atšaukti siuntimą + changeTicksRequired: '§eBūtina pakeisti žaidžiamas erkes' + craft: '§aAmatų daiktas' + currentRadius: '§eDabartinis atstumas: §6{radius}' + editBlocksMine: '§eRedaguokite blokus, kad sulaužytumėte' + editBlocksPlace: '§eRedaguokite blokus, kuriuos norite įdėti' + editBucketAmount: '§eRedaguokite užpildomų grupių kiekį' + editBucketType: '§eRedaguokite užpildomo segmento tipą' + editFishes: '§eRedaguokite žuvis, kad pagautumėte' + editItem: '§eRedaguoti daikto, kad būtų galima sukurti' + editLocation: '§eRedaguoti vietą' + editMessageType: '§eRedaguokite pranešimą, kad galėtumėte parašyti' + editMobsKill: '§eRedaguoti mobu nužudyti' + editRadius: '§eRedaguoti atstumą nuo vietos' + findNPC: '§aRaskite NPC' findRegion: '§aRaskite regioną' + fish: '§aGaudyti žuvis' + hideClues: Slėpti daleles ir hologramas + ignoreCase: Nepaisykite pranešimo atvejo + interact: '§aBendraukite su bloku' killMobs: '§aNužudyk mobys' + leftClick: Spustelėkite kairįjį pelės klavišą + location: '§aEikite į vietą' mineBlocks: '§aLaužyti blokus' + mobsKillFromAFar: Reikia nužudyti sviediniu placeBlocks: '§aVieta blokus' - talkChat: '§aRašykite pokalbyje' - interact: '§aBendraukite su bloku' - fish: '§aGaudyti žuvis' - craft: '§aAmatų daiktas' - bucket: '§aUžpildykite kibirus' - location: '§aEikite į vietą' playTime: '§eŽaidimo laikas' - NPCText: '§eRedaguoti dialogo langą' - NPCSelect: '§ePasirinkite arba sukurkite NPC' - hideClues: Slėpti daleles ir hologramas - editMobsKill: '§eRedaguoti mobu nužudyti' - mobsKillFromAFar: Reikia nužudyti sviediniu - editBlocksMine: '§eRedaguokite blokus, kad sulaužytumėte' preventBlockPlace: Neleiskite žaidėjams sulaužyti savo blokų - editBlocksPlace: '§eRedaguokite blokus, kuriuos norite įdėti' - editMessageType: '§eRedaguokite pranešimą, kad galėtumėte parašyti' - cancelMessage: Atšaukti siuntimą - ignoreCase: Nepaisykite pranešimo atvejo + selectBlockLocation: '§ePasirinkite blokavimo vietą' + selectBlockMaterial: '§ePasirinkite bloko medžiagą' selectItems: '§eRedaguokite reikalingus Daiktu' selectRegion: '§7Pasirinkite regioną' - toggleRegionExit: Išvažiuodamas + stageCreate: '§aSukurkite naują žingsnį' + stageRemove: '§cIštrinkite šį veiksmą' stageStartMsg: '§eRedaguoti pradinį pranešimą' - selectBlockLocation: '§ePasirinkite blokavimo vietą' - selectBlockMaterial: '§ePasirinkite bloko medžiagą' - leftClick: Spustelėkite kairįjį pelės klavišą - editFishes: '§eRedaguokite žuvis, kad pagautumėte' - editItem: '§eRedaguoti daikto, kad būtų galima sukurti' - editBucketType: '§eRedaguokite užpildomo segmento tipą' - editBucketAmount: '§eRedaguokite užpildomų grupių kiekį' - editLocation: '§eRedaguoti vietą' - editRadius: '§eRedaguoti atstumą nuo vietos' - currentRadius: '§eDabartinis atstumas: §6{0}' - changeTicksRequired: '§eBūtina pakeisti žaidžiamas erkes' - stages: - name: Kurkite etapus - nextPage: '§eKitas puslapis' - laterPage: '§eAnkstesnis puslapis' - endingItem: '§eRedaguokite pabaigos apdovanojimus' - descriptionTextItem: '§eRedaguoti aprašą' - regularPage: '§aReguliarūs etapai' - branchesPage: '§dFilialų etapai' - previousBranch: '§eGrįžti į ankstesnį skyrių' - newBranch: '§eEiti į naują filialą' - validationRequirements: '§ePatvirtinimo reikalavimai' - validationRequirementsLore: Visi reikalavimai turi atitikti bandantį žaidėją etapui užbaigti. Jei ne, etapas negali būti baigtas. + talkChat: '§aRašykite pokalbyje' + toggleRegionExit: Išvažiuodamas details: - hologramLaunch: '§eRedaguoti „paleisti“ hologramos elementą' - hologramLaunchLore: Holograma rodoma virš „Starter NPC“ galvos, kai grotuvas gali pradėti ieškojimą. - hologramLaunchNo: '§eRedaguokite daikta „Paleisti nepasiekiamą“' - hologramLaunchNoLore: Holograma rodoma virš „Starter NPC“ galvos, kai Žaidejo Negaliu pradėti Misijos. + actions: '{amount} veiksmai' + bypassLimit: Neskaičiuokite užduočių limito + bypassLimitLore: Jei bus įjungta, užduotis bus pradėta, net jei žaidėjas turi pasiekė maksimalų pradėtų užduočių kiekį. + cancellable: Atšaukiamas žaidėjo + cancellableLore: Leidžia žaidėjui atšaukti užduotį per „Quest“ meniu. + createQuestLore: Turite apibrėžti užduoties pavadinimą. + createQuestName: '§lSukurti kvestą' customConfirmMessage: '§eRedaguoti Misijos patvirtinimo pranešimą' customConfirmMessageLore: Pranešimas, rodomas patvirtinimo GUI, kai žaidėjas ruošiasi pradėti Misija. customDescription: '§eRedaguoti Misijos aprašą' customDescriptionLore: Aprašymas pateiktas po GUI vartotojo užduoties pavadinimu. - name: Paskutinės užduoties informacija + customMaterial: '§eRedaguoti kvesto daikto medžiagą' + customMaterialLore: Šio kvesto elementas „Quest“ meniu. + editQuestName: '§lRedaguoti Misija' + editRequirements: '§eRedaguoti reikalavimus' + editRequirementsLore: Visi reikalavimai žaidėjui turi būti taikomi prieš tai galint pradėti Misija. + endMessage: '§eRedaguoti pabaigos pranešimą' + endMessageLore: Pranešimas, kuris bus išsiųstas žaidėjui kvesto pabaigoje. + failOnDeath: Nesėkmė mirus + failOnDeathLore: Ar užduotis bus atšaukta, kai žaidėjas mirs? + hologramLaunch: '§eRedaguoti „paleisti“ hologramos elementą' + hologramLaunchLore: Holograma rodoma virš „Starter NPC“ galvos, kai grotuvas gali pradėti ieškojimą. + hologramLaunchNo: '§eRedaguokite daikta „Paleisti nepasiekiamą“' + hologramLaunchNoLore: Holograma rodoma virš „Starter NPC“ galvos, kai Žaidejo Negaliu pradėti Misijos. + hologramText: '§eHologramos tekstas' + hologramTextLore: Hologramoje rodomas tekstas virš „Starter NPC“ galvos. + keepDatas: Išsaugoti žaidėjų duomenis + keepDatasLore: 'Priverskite papildinį išsaugoti žaidėjų duomenis, nors etapai buvo redaguoti. §c§lWARNING §c- įjungus šią parinktį, gali būti sugadinti jūsų žaidėjų duomenys.' + loreReset: '§e§lVisi žaidėjais'' pažanga bus nustatyta iš naujo' multipleTime: - itemName: Perjungti pakartotinai itemLore: Ar Misijos galima atlikti kelis kartus? - cancellable: Atšaukiamas žaidėjo - cancellableLore: Leidžia žaidėjui atšaukti užduotį per „Quest“ meniu. - startableFromGUI: Pradedama nuo GUI - startableFromGUILore: Leidžia žaidėjui pradėti užduotis iš „Quests“ meniu. - scoreboardItem: Įgalinti rezultatų suvestinę - scoreboardItemLore: Jei išjungta, užduotis nebus stebima per rezultatų suvestinę. - hideItem: Slėpti meniu ir dinaminį žemėlapį - hideItemLore: Jei ši parinktis įgalinta, užduotis nebus rodoma nei dinaminiame žemėlapyje, nei „Quest“ meniu. - bypassLimit: Neskaičiuokite užduočių limito - bypassLimitLore: Jei bus įjungta, užduotis bus pradėta, net jei žaidėjas turi pasiekė maksimalų pradėtų užduočių kiekį. + itemName: Perjungti pakartotinai + name: Paskutinės užduoties informacija + optionValue: '§8Vertė: §7{value}' questName: '§a§lRedaguoti užduoties pavadinimą' questNameLore: Norint užbaigti užduotį, reikia nustatyti pavadinimą. - setItemsRewards: '§eRedaguokite atlygio daiktus' - setXPRewards: '§eRedaguokite atlygio patirtį' - setCheckpointReward: '§eRedaguoti kontrolinio taško atlygius' - setPermReward: '§eRedaguoti leidimus' - setMoneyReward: '§eRedaguokite piniginį atlygį' + requirements: '{amount} reikalavimas (-ai)' + rewards: '{amount} atlygis (-ai)' + rewardsLore: Veiksmai, atlikti pasibaigus kvestui. + scoreboardItem: Įgalinti rezultatų suvestinę + scoreboardItemLore: Jei išjungta, užduotis nebus stebima per rezultatų suvestinę. selectStarterNPC: '§e§lPasirinkite „NPC starter“' selectStarterNPCLore: Spustelėjus pasirinktą NPC bus pradėta užduotis. - createQuestName: '§lSukurti kvestą' - createQuestLore: Turite apibrėžti užduoties pavadinimą. - editQuestName: '§lRedaguoti Misija' - endMessage: '§eRedaguoti pabaigos pranešimą' - endMessageLore: Pranešimas, kuris bus išsiųstas žaidėjui kvesto pabaigoje. + setCheckpointReward: '§eRedaguoti kontrolinio taško atlygius' + setItemsRewards: '§eRedaguokite atlygio daiktus' + setMoneyReward: '§eRedaguokite piniginį atlygį' + setPermReward: '§eRedaguoti leidimus' + setXPRewards: '§eRedaguokite atlygio patirtį' startDialog: '§eRedaguoti pradžios dialogo langą' startDialogLore: Dialogas, kuris bus žaidžiamas prieš pradedant užduotis žaidėjams spustelėkite „Starter NPC“. - editRequirements: '§eRedaguoti reikalavimus' - editRequirementsLore: Visi reikalavimai žaidėjui turi būti taikomi prieš tai galint pradėti Misija. startRewards: '§6Pradėk apdovanojimus' startRewardsLore: Veiksmai, atliekami pradėjus Misija. - hologramText: '§eHologramos tekstas' - hologramTextLore: Hologramoje rodomas tekstas virš „Starter NPC“ galvos. + startableFromGUI: Pradedama nuo GUI + startableFromGUILore: Leidžia žaidėjui pradėti užduotis iš „Quests“ meniu. timer: '§bPaleiskite laikmatį iš naujo' - requirements: '{0} reikalavimas (-ai)' - rewards: '{0} atlygis (-ai)' - actions: '{0} veiksmai' - rewardsLore: Veiksmai, atlikti pasibaigus kvestui. - customMaterial: '§eRedaguoti kvesto daikto medžiagą' - customMaterialLore: Šio kvesto elementas „Quest“ meniu. - failOnDeath: Nesėkmė mirus - failOnDeathLore: Ar užduotis bus atšaukta, kai žaidėjas mirs? - keepDatas: Išsaugoti žaidėjų duomenis - keepDatasLore: |- - Priverskite papildinį išsaugoti žaidėjų duomenis, nors etapai buvo redaguoti. - §c§lWARNING §c- įjungus šią parinktį, gali būti sugadinti jūsų žaidėjų duomenys. - loreReset: '§e§lVisi žaidėjais'' pažanga bus nustatyta iš naujo' - optionValue: '§8Vertė: §7{0}' - itemsSelect: - name: Redaguoti daiktus - none: |- - §aPerkelkite elementą į čia arba - spustelėkite, jei norite atidaryti elementų redaktorių. - itemSelect: - name: Pasirinkite daikta - npcCreate: - name: Sukurkite NPC - setName: '§eRedaguoti NPC pavadinimą' - setSkin: '§eRedaguoti NPC odą' - setType: '§eRedaguoti NPC tipą' - move: - itemName: '§ePerkelti' - itemLore: '§aPakeiskite NPC vietą.' - moveItem: '§a§lPatvirtinti vietą' - npcSelect: - name: Pasirinkite arba sukurkite? - selectStageNPC: '§ePasirinkite esamą NPC' - createStageNPC: '§eSukurkite NPC' entityType: name: Pasirinkite objekto tipą - chooseQuest: - name: Kuris Misija? - mobs: - name: Pasirinkite mobus - none: '§aSpustelėkite, jei norite pridėti mobu.' - mobSelect: - name: Pasirinkite minios tipą - bukkitEntityType: '§ePasirinkite objekto tipą' - mythicMob: '§6Pasirinkite „Mitinis mobas“' - epicBoss: '§6Pasirinkite „Epic Boss“' - boss: '§6Pasirinkite bosą' - stageEnding: - locationTeleport: '§eRedaguoti teleportavimo vietą' - command: '§eRedaguoti įvykdytą komandą' - requirements: - name: Reikalavimai - checkpointActions: - name: Kontrolės punkto veiksmai + itemCreator: + isQuestItem: '§bUžduočių daiktas:' + itemFlags: Perjungti daiktu vėliavas + itemLore: '§bDaiktų žinios' + itemName: '§bDaikto pavadinimas' + itemType: '§bPrekės tipas' + name: daikto kūrėjasr + itemSelect: + name: Pasirinkite daikta + itemsSelect: + name: Redaguoti daiktus + none: '§aPerkelkite elementą į čia arba spustelėkite, jei norite atidaryti elementų redaktorių.' listAllQuests: name: Misijos + listBook: + noQuests: Anksčiau nebuvo sukurta jokių užduočių. + questMultiple: Kelis kartus + questName: vardas + questRewards: Apdovanojimai + questStages: Etapai + questStarter: Starteris + requirements: Reikalavimai listPlayerQuests: - name: '{0}''s Misijos' + name: '{player_name}''s Misijos' listQuests: - notStarted: Nepradėti Misija + canRedo: '§3§oGalite iš naujo paleisti šį užduoti!' finished: Atlikti Misija inProgress: Vykdomi Misijos - loreCancel: '§c§oSpustelėkite norėdami atšaukti užduotį.' loreStart: '§a§oSpustelėkite, kad pradėtumėte užduotį.' loreStartUnavailable: '§c§oNeatitinkate reikalavimų pradėti užduotį.' - canRedo: '§3§oGalite iš naujo paleisti šį užduoti!' - itemCreator: - name: daikto kūrėjasr - itemType: '§bPrekės tipas' - itemFlags: Perjungti daiktu vėliavas - itemName: '§bDaikto pavadinimas' - itemLore: '§bDaiktų žinios' - isQuestItem: '§bUžduočių daiktas:' - command: - name: Komanda - value: '§eKomanda' - console: Konsolė - delay: '§bDelsimas' - chooseAccount: - name: Kokia sąskaita? - listBook: - questName: vardas - questStarter: Starteris - questRewards: Apdovanojimai - questMultiple: Kelis kartus - requirements: Reikalavimai - questStages: Etapai - noQuests: Anksčiau nebuvo sukurta jokių užduočių. - commandsList: - name: Komandų sąrašas - value: '§eKomanda: {0}' - console: '§eKonsolė: {0}' - block: - name: Pasirinkite bloką - material: '§eMedžiaga: {0}' - blockData: '§dBlokiniai duomenys (advanced)' - blocksList: - name: Pasirinkite blokus - addBlock: '§aSpustelėkite, jei norite pridėti bloką.' - blockAction: - name: Pasirinkite blokavimo veiksmą - location: '§ePasirinkite tikslią vietą' - material: '§ePasirinkite bloko medžiagą' - buckets: - name: kibiro tipas + notStarted: Nepradėti Misija + mobSelect: + boss: '§6Pasirinkite bosą' + bukkitEntityType: '§ePasirinkite objekto tipą' + epicBoss: '§6Pasirinkite „Epic Boss“' + mythicMob: '§6Pasirinkite „Mitinis mobas“' + name: Pasirinkite minios tipą + mobs: + name: Pasirinkite mobus + none: '§aSpustelėkite, jei norite pridėti mobu.' + npcCreate: + move: + itemLore: '§aPakeiskite NPC vietą.' + itemName: '§ePerkelti' + moveItem: '§a§lPatvirtinti vietą' + name: Sukurkite NPC + setName: '§eRedaguoti NPC pavadinimą' + setSkin: '§eRedaguoti NPC odą' + setType: '§eRedaguoti NPC tipą' + npcSelect: + createStageNPC: '§eSukurkite NPC' + name: Pasirinkite arba sukurkite? + selectStageNPC: '§ePasirinkite esamą NPC' permission: name: Pasirinkite leidimą perm: '§aLeidimas' - world: '§aPasaulis' - worldGlobal: '§b§lVisuotinis' remove: Pašalinti leidimą removeLore: '§7Leidimas bus atimtas n§7vietoj duoto.' + world: '§aPasaulis' + worldGlobal: '§b§lVisuotinis' permissionList: name: Leidimų sąrašas - removed: '§ePakilo: §6{0}' - world: '§ePasaulis: §6{0}' -scoreboard: - name: '§6§lMisijos' - noLaunched: '§cNėra vykdomų užduočių.' - noLaunchedName: '§c§lĮkeliama' - noLaunchedDescription: '§c§oĮkeliama' - textBetwteenBranch: '§e arba' - stage: - region: '§eRaskite regioną §6{0}' - npc: '§eKalbėkitės su NPC §6{0}' - items: '§eAtneškite daiktus į §6{0}§e:' - mine: '§eMano {0}' - placeBlocks: '§eVieta {0}' - chat: '§eRašykite §6{0}' - interact: '§eSpustelėkite bloką adresu §6{0}' - interactMaterial: '§eSpustelėkite bloką §6 {0} §e' - fish: '§eŽuvis §6{0}' - craft: '§eAmatas §6{0}' - bucket: '§eUžpildykite §6{0}' - location: '§eEiti į §6{0}§e, §6{1}§e, §6{2}§e į §6{3}' - playTime: '§eŽaiskite §6 {0} žaidimo ticks' -indication: - startQuest: '§7Ar norite pradėti ieškojimą {0}?' - closeInventory: '§7Ar tikrai norite uždaryti GUI?' - cancelQuest: '§7Ar tikrai norite atšaukti užduotį {0}?' - removeQuest: '§7Ar tikrai norite pašalinti užduotį {0}?' + removed: '§ePakilo: §6{permission_removed}' + world: '§ePasaulis: §6{permission_world}' + requirements: + name: Reikalavimai + search: '§e§lPaieška' + stageEnding: + command: '§eRedaguoti įvykdytą komandą' + locationTeleport: '§eRedaguoti teleportavimo vietą' + stages: + branchesPage: '§dFilialų etapai' + descriptionTextItem: '§eRedaguoti aprašą' + endingItem: '§eRedaguokite pabaigos apdovanojimus' + laterPage: '§eAnkstesnis puslapis' + name: Kurkite etapus + newBranch: '§eEiti į naują filialą' + nextPage: '§eKitas puslapis' + previousBranch: '§eGrįžti į ankstesnį skyrių' + regularPage: '§aReguliarūs etapai' + validationRequirements: '§ePatvirtinimo reikalavimai' + validationRequirementsLore: Visi reikalavimai turi atitikti bandantį žaidėją etapui užbaigti. Jei ne, etapas negali būti baigtas. + validate: '§b§lPatvirtinti' misc: - format: - offText: '§r§e {0}' - stageType: - region: Raskite regioną - npc: Raskite NPC - items: atnesk daiktus - mobs: Nužudyk mobus - mine: Laužyti blokus - placeBlocks: Vieta blokus - interact: Bendraukite su bloku - Fish: Gaudyti žuvis - Craft: Amatų daiktas - Bucket: Užpildykite kibirą - location: Raskite vietą - playTime: Žaidimo laikas + amount: '§eSuma: {amount}' + and: ir + bucket: + lava: Lavos kibiras + milk: Pieno kibiras + water: Vandens kibiras comparison: - equals: lygus {0} - different: skiriasi nuo {0} - less: griežtai mažiau nei {0} - lessOrEquals: mažiau nei {0} - greater: griežtai didesnis nei {0} - greaterOrEquals: geresnis negu {0} + different: skiriasi nuo {number} + equals: lygus {number} + greater: griežtai didesnis nei {number} + greaterOrEquals: geresnis negu {number} + less: griežtai mažiau nei {number} + lessOrEquals: mažiau nei {number} + disabled: Išjungta + enabled: Įjungtas + format: + offText: '§r§e {message}' + hologramText: '§8§lMisija' + 'no': 'Ne' + notSet: '§cnenustatyta' + questItemLore: '§e§oUžduočių daiktas' requirement: class: '§bKlasė (-ės) reikalinga' - faction: '§bReikalinga frakcija (-os)' - jobLevel: '§bReikalingas darbo lygis' combatLevel: '§bBūtinas kovos lygis' experienceLevel: '§bReikalingi patirties lygiai' + faction: '§bReikalinga frakcija (-os)' + jobLevel: '§bReikalingas darbo lygis' + mcMMOSkillLevel: '§dĮgūdžių lygis reikalaujad' + money: '§dReikalingi pinigai' permissions: '§3Reikalingas leidimas (-ai)' - scoreboard: '§dBūtinas rezultatas' - region: '§dReikalingas regionas' placeholder: '§bPlaceholder reikalinga vertė' quest: '§aBūtina užduotis' - mcMMOSkillLevel: '§dĮgūdžių lygis reikalaujad' - money: '§dReikalingi pinigai' - bucket: - water: Vandens kibiras - lava: Lavos kibiras - milk: Pieno kibiras - questItemLore: '§e§oUžduočių daiktas' - hologramText: '§8§lMisija' - enabled: Įjungtas - disabled: Išjungta + region: '§dReikalingas regionas' + scoreboard: '§dBūtinas rezultatas' + stageType: + Bucket: Užpildykite kibirą + Craft: Amatų daiktas + Fish: Gaudyti žuvis + interact: Bendraukite su bloku + items: atnesk daiktus + location: Raskite vietą + mine: Laužyti blokus + mobs: Nužudyk mobus + npc: Raskite NPC + placeBlocks: Vieta blokus + playTime: Žaidimo laikas + region: Raskite regioną unknown: nežinoma - notSet: '§cnenustatyta' - unused: '§2§lNenaudojamas' - used: '§a§lPanaudota' - remove: '§7Spustelėkite vidurį, kad pašalintumėte' - amount: '§eSuma: {0}' - items: daiktų - expPoints: patirties taškai 'yes': 'Taip' - 'no': 'Ne' - and: ir +msg: + bringBackObjects: Atnešk {items}. + command: + adminModeEntered: '§aĮėjote į administratoriaus režimą.' + adminModeLeft: '§aIšėjote iš administratoriaus režimo.' + backupCreated: '§6Jūs sėkmingai sukūrėte visų užduočių ir Žaidejo atsargines kopijas informacijos.' + backupPlayersFailed: '§cNepavyko sukurti visos žaidėjo informacijos atsarginės kopijos.' + backupQuestsFailed: '§cNepavyko sukurti visų užduočių atsarginės kopijos.' + cancelQuest: '§6Atšaukėte užduotį {quest}.' + cancelQuestUnavailable: '§cUžduoties {quest} negalima atšaukti.' + checkpoint: + noCheckpoint: '§cNerasta užduoties kontrolinio punkto {quest}.' + questNotStarted: '§cJūs neatliekate šios Misijos.' + help: + adminMode: '§6/{label} adminMode: §ePerjungti administratoriaus režimą. (Naudinga rodyti mažai žurnalo pranešimų.) ' + create: '§6/{label} create: §eSukurti kvestą.' + edit: '§6/{label} edit: §eRedaguoti užduotį.' + finishAll: '§6/{label} finishAll <player>: §eBaigti visus žaidėjo uždavinius.' + header: '§6§lPagalba' + list: '§6/{label} list: §eŽureti. Užduočių sąrašą. (Tik palaikomoms versijoms.)' + reload: '§6/{label} reload: §eIšsaugokite ir iš naujo įkelkite visas konfigūracijas ir failus. (§cdeprecated§e)' + remove: '§6/{label} remove <id>: §eIštrinkite užduotį su nurodytu ID arba spustelėkite NPC, kai neapibrėžta.' + resetPlayer: '§6/{label} resetPlayer <player>: §ePašalinkite visą informaciją apie Žaideja.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eIštrinti informaciją apie žaidėjo ieškojimą “. seePlayer: "§6/{label} seePlayer <player>: §ePeržiūrėkite informaciją apie žaidėją.' + save: '§6/{label} save: §eIšsaugokite rankinį papildinį.' + setItem: '§6/{label} setItem <talk|launch>: §eIšsaugokite hologramos Daikta.' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §ePraleisti dabartinis etapas / šakos paleidimas / šakos nustatymas. ' + start: '§6/{label} start <player> [id]: §ePriverskite pradėti Misija.' + version: '§6/{label} version: §eŽr. Dabartinę papildinio versiją.' + invalidCommand: + simple: '§cŠios komandos nėra, parašykite §ehelp§c.' + itemChanged: '§aDaiktas buvo redaguotas. Pakeitimai turės įtakos iš naujo paleidus.' + itemRemoved: '§aHologramos Daiktas pašalintas.' + leaveAll: '§aPriverstinai baigėte {success} Misija Klaidos: {errors}' + removed: '§aUžduotis {quest_name} sėkmingai pašalinta.' + resetPlayer: + player: '§6Visą jūsų {quest_amount} užduoties (-ių) informaciją ištrynė {deleter_name}.' + remover: '§6{quest_amount} {player} Misijos informacija (-os) buvo ištrinta (-os).' + resetPlayerQuest: + player: '§6Visą informaciją apie užduotį {quest} ištrynė {deleter_name}.' + remover: '§6{player} {quest} Misijos informacija (-os) buvo ištrinta (-os).' + resetQuest: '§6Pašalinti {player_amount} žaidėjų Misiju duomenys.' + scoreboard: + hidden: '§6Žaidėjo {player_name} rezultatų suvestinė buvo paslėpta.' + lineInexistant: '§cEilutės {line_id} nėra.' + lineRemoved: '§6Jūs sėkmingai pašalinote eilutę {line_id}.' + lineReset: '§6Sėkmingai nustatėte eilutę iš naujo {line_id}.' + lineSet: '§6Sėkmingai redagavote eilutę {line_id}.' + resetAll: '§6Jūs sėkmingai iš naujo nustatėte žaidėjo rezultatų suvestinę {player_name}.' + shown: '§6Parodytas žaidėjo {player_name} rezultatų suvestinė.' + setStage: + branchDoesntExist: '§cFilialas su ID {branch_id} neegzistuoja.' + doesntExist: '§Žyngsnio, kurios ID yra {stage_id}, nėra.' + next: '§a„Žyngsnis“ praleistas.' + nextUnavailable: '§cParinktis „praleisti“ negalima, kai žaidėjas yra šakos pabaiga.' + set: '§aPaleistas {stage_id} etapas.' + startQuest: '§6Priverstinai pradėjote užduotį {quest} (Žaidejo UUID: {player}).' + editor: + already: '§cJūs jau esate redaktoriuje.' + blockAmount: '§aParašykite blokų kiekį:' + blockData: '§aParašykite blokaduomenis (galimi blokiniai duomenys: {available_datas}):' + blockName: '§aParašykite bloko pavadinimą:' + chat: '§6You are currently in the Editor Mode. Write "/quests editor" to force leaving the editor. (Highly not recommended, consider using commands such as "close" or "cancel" to come back to the previous inventory.)' + dialog: + cleared: '§a{amount} pašalintas pranešimas (-ai).' + help: + addSound: '§6addSound <id> <sound>: §ePridėkite garsą prie pranešimo.' + clear: '§6clear: §ePašalinti visus pranešimus.' + close: '§6close: §ePatvirtinkite visus pranešimus.' + header: '§6§l„Misiju“ - „Dialog“ redaktoriaus pagalba' + list: '§6list: §ePeržiūrėti visus pranešimus.' + nothing: '§6noSender <message>: §ePridėkite pranešimą be siuntėjo.' + nothingInsert: '§6nothingInsert <id> <message>: §eĮterpti pranešimą be bet koks priešdėlis.' + npc: '§6npc <message>: §ePridėkite pranešimą, kurį pasakė NPC.' + npcInsert: '§6npcInsert <id> <message>: §eĮterpkite pranešimą, kurį pasakė NPC.' + player: '§6player <message>: §ePridėkite žaidėjo pasakytą pranešimą.' + playerInsert: '§6playerInsert <id> <message>: §eĮterpkite žaidėjo pasakytą pranešimą.' + remove: '§6remove <id>: §ePašalinti pranešimą.' + setTime: '§6setTime <id> <time>: §eSet the time (in ticks) prieš kitą msg groja automatiškai.' + syntaxRemove: '§cTeisingai sytax: pašalinti <id>' + timeRemoved: '§aPranešimo laikas pašalintas {msg}.' + timeSet: '§aPranešimo laikas redaguotas {msg}: dabar {time} tick.' + enter: + subtitle: '§6Rašykite "/quests editor" priversti išeiti.' + title: '§6~ Redaktoriaus režimas ~' + goToLocation: '§aEikite į norimą Punkta vietą.' + itemCreator: + invalidBlockType: '§cNeteisingas bloko tipas.' + invalidItemType: '§cNeteisingas daikto tipas. (daiktas negali būti blokas.)' + itemAmount: '§aParašykite Daiktu (-ių) kiekį:' + itemLore: '§aPakeiskite prekės aprašymą: (Parašykite „help“, kad gautumėte pagalbos.)' + itemName: '§aParašykite daikto pavadinimą:' + itemType: '§aParašykite norimo daikto tipo pavadinimą:' + unknownBlockType: '§cNežinomas bloko tipas.' + unknownItemType: '§cNežinomas daikto tipas.' + mythicmobs: + disabled: '§c„MythicMob“ yra išjungtas.' + isntMythicMob: '§cŠis mitinis mobas neegzistuoja.' + list: '§aVisų mitinių mobų sąrašas:' + noSuchElement: '§cTokio elemento nėra. Leidžiami elementai yra: §e{available_elements}' + npc: + choseStarter: '§aPasirinkite NPC, kuris pradeda užduotį.' + enter: '§aSpustelėkite NPC arba parašykite "cancel".' + notStarter: '§cŠis NPC nėra užduočių pradininkas.' + scoreboardObjectiveNotFound: '§cNežinomas rezultatų suvestinės tikslas.' + selectWantedBlock: '§aSpustelėkite lazda ant norimo Etapo bloko.' + text: + argNotSupported: '§cArgumentas {arg} nepalaikomas.' + chooseJobRequired: '§aParašykite norimo darbo pavadinimą:' + chooseLvlRequired: '§aParašykite reikiamą kiekį lygių:' + chooseMoneyRequired: '§aParašykite reikalingų pinigų sumą:' + chooseObjectiveRequired: '§aParašykite objektyvų pavadinimą.' + chooseObjectiveTargetScore: '§aParašykite tikslo tikslinį rezultatą.' + choosePermissionMessage: '§aGalite pasirinkti atmetimo pranešimą, jei grotuvas neturi reikiamo leidimo. (Jei norite praleisti šį veiksmą, parašykite „null“.)' + choosePermissionRequired: '§aParašykite reikiamą leidimą pradėti užduotį:' + choosePlaceholderRequired: + identifier: '§aParašykite reikiamos placeholder pavadinimą be procentų personažai:' + value: '§aParašykite reikiamą vietos rezervavimo ženklo vertę §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aParašykite reikiamo regiono pavadinimą (turite būti tas pats pasaulis).' + chooseSkillRequired: '§aParašykite reikiamo įgūdžio pavadinimą:' + reward: + money: '§aParašykite gautų pinigų sumą:' + permissionName: '§aParašykite leidimo pavadinimą.' + permissionWorld: '§aParašykite pasaulį, kuriame bus redaguojamas leidimas, arba „null“, jei norite būti globalus.' + textList: + help: + add: '§6add <message>: §ePridėti tekstą.' + close: '§6close: §ePatvirtinkite pridėtus tekstus.' + header: '§6§lMisiju' + list: '§6list: §ePeržiūrėti visus pridėtus tekstus.' + remove: '§6remove <id>: §ePašalinti tekstą.' + syntax: '§cTeisingai syntax: ' + typeBucketAmount: '§aParašykite užpildomų kibirų kiekį:' + typeGameTicks: '§aParašykite reikalingas žaidimo erkes:' + typeLocationRadius: '§aParašykite reikiamą atstumą nuo vietos:' + errorOccurred: '§cĮvyko klaida. Susisiekite su administratoriumi! §4§lKlaidos kodas: {error}' + experience: + edited: '§aPakeitėte patirties įgijimą iš {old_xp_amount} į {xp_amount} taškų.' + indexOutOfBounds: '§cSkaičius {index} yra ribų! Tai turi būti nuo {min} iki {max}.' + invalidBlockData: '§cBlokavimo duomenys {block_data} yra neteisingi arba nesuderinami su bloku {block_material}.' + inventoryFull: '§cJūsų inventorius yra pilnas, daiktas numestas ant grindų.' + npcDoesntExist: '§cNPC su ID {npc_id} neegzistuoja.' + number: + invalid: '§c{input} neteisingas numeris.' + negative: '§cTurite įvesti teigiamą skaičių!' + zero: '§cTurite įvesti kitą nei. Numerį 0!' + quest: + alreadyStarted: '§cJūs jau pradėjote Misija!' + cancelling: '§cUžduoties kūrimo procesas atšauktas.' + createCancelled: '§cKūrinį ar leidimą atšaukė kitas papildinys!' + created: '§aSveikiname! Jūs sukūrėte užduotį §e{quest}§a, kuri apima {quest_branches} atšaka(s)!' + edited: '§aSveikiname! Redagavote užduotį §e{quest}§a, kuri apima ir dabar {quest_branches} atšaka(s)!' + finished: + base: '§aSveikiname! Jūs baigėte Misija §e{quest_name}§a!' + obtain: '§aJūs gaunate {rewards}!' + invalidID: '§cUžduotis su ID {quest_id} neegzistuoja.' + started: '§aJūs pradėjote Misija §r§e{quest_name}§o§6!' + questItem: + craft: '§cNegalite naudoti Misijos Daikto, kad sukurtumėte!' + drop: '§cJūs negalite mesti Misija daiktas!' + quests: + checkpoint: '§7Pasiektas misijos kontrolinis punktas!' + failed: '§cJums nepavyko užduotis {quest_name}...' + updated: '§7Misija §e{quest_name}§7 atnaujinta.' + regionDoesntExists: '§cŠio regiono nėra. (Jūs turite būti tame pačiame pasaulyje.)' + requirements: + combatLevel: '§cJūsų kovinis lygis turi būti {long_level}!' + job: '§cTuri būti jūsų lygis §e{job_name}§c {long_level}!' + level: '§cJūsų lygis turi būti {long_level}!' + money: '§cTu privalai turėti {money}!' + quest: '§cJūs turite baigti Misija §e{quest_name}§c!' + skill: '§cTuri būti jūsų įgūdis §e{skill_name} §c{long_level}!' + selectNPCToKill: '§aPasirinkite nužudyti NPC.' + stageMobs: + listMobs: '§aPrivalai nužudyti {mobs}.' + typeCancel: '§aRašykite "cancel" grįžti prie paskutinio teksto.' + writeChatMessage: '§aParašykite reikalingą pranešimą: (Jei, pridėkite "{SLASH}" prie pradžios norite komandos.) ' + writeCommandDelay: '§aParašykite norimą komandos uždelsimą, pažymėdami varnele.' + writeConfirmMessage: '§aParašykite patvirtinimo pranešimą, rodomą, kai žaidėjas yra apie to start the quest: (Parašykite „null“, jei norite numatytojo pranešimo.)' + writeMobAmount: '§aParašykite, kiek Monstru reikia nužudyti:' + writeNPCText: '§aParašykite dialogą, kurį žaidėjas pasakys NPC: (Write "help" gauti pagalbos.)' + writeQuestDescription: '§aParašykite Misijos aprašymą, parodytą žaidėjo Misijos GUI.' + writeQuestMaterial: '§aParašykite misijos Daikta medžiagą.' + writeQuestTimer: '§aParašykite reikiamą laiką (in minutes), kad galėtumėte paleisti iš naujo the quest: (Parašykite „null“, jei norite default laikmačio.)' + writeRegionName: '§aParašykite žingsniui reikalingo regiono pavadinimą:' + writeStageText: '§aParašykite tekstą, kuris bus išsiųstas Žaidejui pradžioje žingsnio: " moveToTeleportPoint: §aEikite į norimą teleportavimo vietą. writeNpcName: "&aParašykite NPC pavadinimą" writeNpcSkinName: "§aParašykite NPC odos pavadinimą:" writeQuestName: "§aParašykite savo užduoties pavadinimą:" writeCommand: "§aParašykite norimą komandą: (Komanda yra be / ir" vietos rezervavimo priemonė „{PLAYER}“ palaikoma. Jis bus pakeistas pavadinimu vykdomas.) “ writeHologramText: "§aParašykite hologramos tekstą: (Jei nenorite, parašykite „nėra“ hologramos ir „null“, jei norite numatytojo teksto.) ' + writeXPGain: '§aParašykite, kiek patirties taškų gaus žaidėjas: (Paskutinis value: {xp_amount})' +scoreboard: + name: '§6§lMisijos' + noLaunched: '§cNėra vykdomų užduočių.' + noLaunchedDescription: '§c§oĮkeliama' + noLaunchedName: '§c§lĮkeliama' + stage: + bucket: '§eUžpildykite §6{buckets}' + chat: '§eRašykite §6{text}' + craft: '§eAmatas §6{items}' + fish: '§eŽuvis §6{items}' + interact: '§eSpustelėkite bloką adresu §6{x}' + interactMaterial: '§eSpustelėkite bloką §6 {block} §e' + items: '§eAtneškite daiktus į §6{dialog_npc_name}§e:' + location: '§eEiti į §6{target_x}§e, §6{target_y}§e, §6{target_z}§e į §6{target_world}' + mine: '§eMano {blocks}' + npc: '§eKalbėkitės su NPC §6{dialog_npc_name}' + placeBlocks: '§eVieta {blocks}' + region: '§eRaskite regioną §6{region_id}' + textBetwteenBranch: '§e arba' diff --git a/core/src/main/resources/locales/nl_NL.yml b/core/src/main/resources/locales/nl_NL.yml new file mode 100755 index 00000000..78f2c86d --- /dev/null +++ b/core/src/main/resources/locales/nl_NL.yml @@ -0,0 +1,43 @@ +--- +msg: + pools: + allCompleted: U hebt de Quest voltooid + maxQuests: '§cJe kunt niet meer dan {pool_max_quests} quest(s) tegelijk hebben...' + noAvailable: '§7Er is geen quest meer beschikbaar...' + noTime: '§cJe moet {time_left} wachten voordat je een andere quest kunt doen.' + quest: + alreadyStarted: '§cJe hebt de quest al begonnen!' + cancelling: '§cProces van de vorming van de quest is geannuleerd.' + createCancelled: '§cDe creatie of editie is geannuleerd door een andere plugin!' + created: '§aGefeliciteerd! Je hebt de quest §e{quest}§a gemaakt met {quest_branches} branches!' + editCancelling: '§cProces van quest editie geannuleerd.' + edited: '§aGefeliciteerd! Je hebt de quest §e{quest}§a bewerkt met nu {quest_branches} branches!' + finished: + base: '§aGefeliciteerd! Je hebt de quest §e{quest_name}§a voltooid!' + obtain: '§aU krijgt {rewards}!' + invalidID: '§cDe quest met de id {quest_id} bestaat niet.' + invalidPoolID: De {pool_id} bestaat niet. + notStarted: '§cJe doet momenteel niet deze quest.' + started: '§aJe hebt de quest §r§f{quest_name}§o§6begonnen!' + questItem: + craft: '§cJe kan geen Quest voorwerp gebruiken om te craften!' + drop: '§cJe kan geen Quest item laten vallen!' + eat: '§cJe kan geen Quest item eten!' + quests: + checkpoint: '§7Zoektocht controlepunt bereikt!' + failed: '§cJe hebt de quest {quest_name} gefaald...' + maxLaunched: '§cJe kunt niet meer dan {quests_max_amount} quest(s) tegelijk hebben...' + updated: '§7Quest §e{quest_name}§7 bijgewerkt.' + stageMobs: + listMobs: '§aJe moet {mobs} doden.' + writeChatMessage: '§aSchrijf vereiste bericht: (Voeg "{SLASH}" toe aan het begin als je een opdracht wilt.)' + writeDescriptionText: '§aSchrijf de tekst die het doel van het stadium beschrijft:' + writeEndMsg: '§aSchrijf het bericht dat aan het einde van de quest zal worden verstuurd, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben. U kunt "{rewards}" gebruiken die vervangen zal worden door de verkregen beloningen.' + writeEndSound: '§aSchrijf het bericht dat zal worden verzonden aan het begin van de quest, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben:' + writeMessage: '§aSchrijf het bericht dat naar de speler wordt gestuurd' + writeMobAmount: '§aSchrijf de hoeveelheid mobs om te doden:' + writeMobName: '§aSchrijf de aangepaste naam van de mob om te doden:' + writeNPCText: '§aSchrijf het dialoogvenster dat door de NPC''s tegen de speler wordt gezegd: (Schrijf "help" om hulp te ontvangen.)' + writeRegionName: '§aSchrijf de naam van de regio die nodig is voor de stap:' + writeStartMessage: '§aSchrijf het bericht dat zal worden verzonden aan het begin van de quest, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben:' + writeXPGain: '§aSchrijf de hoeveelheid experience punten die de speler zal krijgen: (Laatste waarde: {xp_amount})' diff --git a/core/src/main/resources/locales/pl_PL.yml b/core/src/main/resources/locales/pl_PL.yml index c2df0400..286bcfac 100644 --- a/core/src/main/resources/locales/pl_PL.yml +++ b/core/src/main/resources/locales/pl_PL.yml @@ -1,837 +1,799 @@ --- -msg: - quest: - finished: - base: '§aGratulacje! Ukończyłeś/aś zadanie §e{0}§a!' - obtain: '§aOtrzymujesz {0}!' - started: '§aRozpocząłeś zadanie §r§e{0}§o§6!' - created: '§aGraulacje! Stworzyłeś zadanie §e{0}§a które zawiera {1} wielokrotnych wyborów!' - edited: '§aGratulacje! Zmodyfikowałeś zadanie§e{0}§a które zawiera {1} wielokrotnych wyborów!' - createCancelled: '§cTworzenie lub modyfikowanie zostało anulowane przez inny plugin!' - cancelling: '§cAnulowano proces tworzenia misji.' - editCancelling: '§cAnulowano proces edytowania misji.' - invalidID: '§cZadanie o id {0} nie istnieje' - invalidPoolID: '§cPula {0} nie istnieje.' - alreadyStarted: '§cJuż rozpocząłeś te zadanie!' - notStarted: '§cObecnie nie wykonujesz tego zadania.' - quests: - maxLaunched: '§cNie możesz mieć aktywnych więcej niż {0} zadań jednocześnie...' - nopStep: '§cTe zadanie nie ma żadnych etapów.' - updated: '§7Zadanie §e{0}§7 zostało zaktualizowane.' - checkpoint: '§7Osiągnięto punkt kontrolny misji!' - failed: '§cNie udało Ci się wykonać zadania {0}...' - pools: - noTime: '§cMusisz poczekać {0} przed wykonaniem kolejnego zadania.' - allCompleted: '§7Wykonałeś/aś wszystkie zadania!' - noAvailable: '§7Nie ma więcej dostępnych zadań...' - maxQuests: '§cNie możesz mieć aktywnych więcej niż {0} zadań jednocześnie...' - questItem: - drop: '§cNie możesz wyrzucić przedmiotu misji!' - craft: '§cNie możesz użyć przedmiotu misji do stworzenia innych przedmiotów!' - eat: '§cNie możesz zjeść przedmiotu misji!' - stageMobs: - noMobs: '§cTen etap nie wymaga żadnych potworów do zabicia.' - listMobs: '§aMusisz zabić {0}' - writeNPCText: '§aNapisz wiadomość, która została powiedziana graczowi przez NPC: (Wpisz "help" żeby otrzymać pomoc.)' - writeRegionName: '§aNapisz nazwę regionu wymaganego dla tego etapu:' - writeXPGain: '§aNapisz liczbę punktów doświadczenia jaką otrzyma gracz: (Poprzednia wartość: {0})' - writeMobAmount: '§aNapisz liczbę potworów do zabicia:' - writeMobName: '§aNapisz niestandardową nazwę potwora do zabicia:' - writeChatMessage: '§aNapisz wymaganą wiadomość: (Dodaj "{SLASH}" na początku wiadomości jeśli chcesz wymagać komendy)' - writeMessage: '§aNapisz wiadomość, która zostanie wysłana graczowi' - writeStartMessage: '§aNapisz wiadomość która będzie się wyświetlać na początku zadania, wpisz "null" aby pozostawić domyślną, wpisz "none" aby zostawić puste:' - writeEndMsg: '§aNapisz wiadomość, która zostanie wysłana na koniec zadania, "null" jeśli chcesz domyślną lub "none" jeśli nie chcesz. Możesz użyć "{0}", które zostanie zastąpione otrzymanymi nagrodami.' - writeEndSound: '§aWpisz nazwę dźwięku, który usłyszy gracz na końcu zadania, wpisz "null" aby pozostawić domyślny dźwięk lub "none", aby pozostawić puste:' - writeDescriptionText: '§aNapisz tekst, który opisuje cel tego etapu:' - writeStageText: '§aNapisz tekst, który zostanie wysłany do gracza na początku tego etapu:' - moveToTeleportPoint: '§aUdaj się do poszukiwanej lokalizacji.' - writeNpcName: '§aNapisz nazwę NPC' - writeNpcSkinName: '§aNapisz nazwę skina NPC' - writeQuestName: '§aNapisz nazwę zadania' - writeCommand: '§aNapisz żądane polecenie (Napisz polecenie bez "/", a "{PLAYER}" zostanie zastąpione nazwą wykonawcy)' - writeHologramText: '§aNapisz tekst hologramu: (Napisz "none" jeśli nie chcesz hologramu, a "null" jeśli chcesz domyślną wiadomość)' - writeQuestTimer: '§aNapisz wymagany czas (w minutach) przed ponownym uruchomieniem zadania: (Napisz "null" jeśli chcesz ustawić domyślną wartość)' - writeConfirmMessage: '§aNapisz wiadomość potwierdzającą w momencie kiedy gracz rozpoczyna zadanie: (Napisz "null" jeśli chcesz użyć domyślnej wiadomości)' - writeQuestDescription: '§aNapisz opis zadania, który zostanie wyświetlony w GUI zadań gracza.' - writeQuestMaterial: '§aNapisz typ przedmiotu zadania.' - requirements: - quest: '§cMusisz ukończyć zadanie §e{0}§c!' - level: '§cMusisz mieć {0} poziom!' - job: '§cMusisz mieć {0} poziom Twojej pracy §e{1}!' - skill: '§cMusisz mieć {0} poziom umiejętności §e{1}!' - combatLevel: '§cMusisz mieć {0} poziom walki!' - money: '§cMusisz posiadać {0}!' - waitTime: '§cMusisz poczekać {0} zanim będziesz mógł ponownie uruchomić to zadanie!' - experience: - edited: '§aZmieniłeś zdobywane doświadczenie z {0} na {1} punktów.' - selectNPCToKill: '§aWybierz NPC do zabicia.' - npc: - remove: '§aUsunięto NPC.' - talk: '§aIdź i porozmawiaj z NPC o nazwie §e{0}§a.' - regionDoesntExists: '§cRegion o takie nazwie nie istnieje (musisz być w tym samym świecie).' - npcDoesntExist: '§cNPC z id {0} nie istnieje' - objectDoesntExist: '§cPrzedmiot z id {0} nie istnieje' - number: - negative: '§cMusisz wprowadzić liczbę dodatnią!' - zero: '§cMusisz podać liczbę inną od 0!' - invalid: '§c{0} nie jest prawidłową liczbą.' - notInBounds: '§cWartość, którą wpiszesz musi mieścić się w zakresie od {0} do {1}' - errorOccurred: '§cWystąpił błąd, skontaktuj się z administratorem! §4§lKod błędu: {0}' - commandsDisabled: '§cObecnie nie możesz wykonywać poleceń!' - indexOutOfBounds: '§cLiczba {0} jest poza granicami! Musi być pomiędzy {1} a {2}.' - invalidBlockData: '§cBlokada danych {0} jest nieprawidłowa lub niezgodna z blokiem {1}.' - invalidBlockTag: '§cNiedostępny tag bloku {0}.' - bringBackObjects: Przynieś mnie z powrotem {0}. - inventoryFull: '§cTwój ekwipunek jest pełny, przedmiot został wyrzucony na podłogę.' - playerNeverConnected: '§cNie można znaleźć informacji o graczu {0}.' - playerNotOnline: '§cGracz {0} jest offline.' - playerDataNotFound: '§cNie znaleziono danych gracza {0}.' - versionRequired: 'Wymagana wersja: §l{0}' - restartServer: '§7Uruchom ponownie serwer, aby zobaczyć zmiany.' - dialogs: - skipped: '§8Dialog pominięty.' - tooFar: '§7§oJesteś za daleko od {0}...' - command: - downloadTranslations: - syntax: '§cMusisz określić język do pobrania. Przykład: "/quests downloadTranslations en_US".' - notFound: '§cJęzyk {0} nie został znaleziony dla wersji {1}. .' - exists: '§cPlik {0} już istnieje. Dołącz "-overwrite" do swojej komendy aby ją nadpisać. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§aJęzyk {0} został pobrany! §7Musisz teraz edytować plik "/plugins/BeautyQuests/config.yml" aby zmienić wartość §ominecraftTranslationsFile§7 na {0}, a następnie zrestartować serwer.' - checkpoint: - noCheckpoint: '§cNie znaleziono punktu kontrolnego dla zadania {0}.' - questNotStarted: '§cNie wykonujesz tego zadania.' - setStage: - branchDoesntExist: '§cGałąź z id {0} nie istnieje' - doesntExist: '§cEtap z id {0} nie istnieje' - next: '§aEtap został pominięty.' - nextUnavailable: '§cOpcja pominięcia nie jest dostępna kiedy gracz jest na końcu gałęzi.' - set: '§aEtap {0} został uruchomiony.' - startDialog: - impossible: '§cNie można teraz uruchomić dialogu.' - noDialog: '§cGracz nie ma oczekującego dialogu.' - alreadyIn: '§cGracz jest już w trakcie dialogu.' - success: '§aRozpoczęto dialog dla gracza {0} w misji {1}!' - playerNeeded: '§cMusisz być graczem aby użyć tego polecenia.' - incorrectSyntax: '§cNiepoprawna składnia.' - noPermission: '§cNie masz wystarczających uprawnień do wykonania tej komendy! (Wymagane: {0})' - invalidCommand: - quests: '§cTa komenda nie istnieje, napisz §e/quests help§c.' - simple: '§cTa komenda nie istnieje, napisz §ehelp§c.' - needItem: '§cMusisz trzymać przedmiot w swojej głównej ręki!' - itemChanged: '§aElement został edytowany. Zmiany będą dostępne po ponownym uruchomieniu.' - itemRemoved: '§aHologram został usunięty.' - removed: '§aZadanie {0} zostało pomyślnie usunięte.' - leaveAll: '§aWymusiłeś/aś koniec {0} zadań. Błędy: {1}' - resetPlayer: - player: '§6Wszystkie informacje o twoich zadaniach {0} zostały usunięte przez {1}.' - remover: '§6{0} informacja(e) o zadaniu (oraz {2}puli) {1} zostało usunięte.' - resetPlayerQuest: - player: '§6Wszystkie informacje o zadaniu {0} zostały usunięte przez {1}.' - remover: '§6{0} informacja(e/i) o zadaniu {1} została(y) usunięta(e).' - resetQuest: '§6Usunięto dane zadania dla {0} graczy.' - startQuest: '§6Wymusiłeś/aś rozpoczęcie zadania {0} (UUID gracza: {1}).' - startQuestNoRequirements: '§cGracz nie spełnia wymagań dla zadania {0}... Dołącz "-overrideRequirements" na końcu twojej komendy aby ominąć sprawdzanie wymagań.' - cancelQuest: '§6Anulowałeś zadanie {0}.' - cancelQuestUnavailable: '§cZadanie {0} nie może zostać anulowane.' - backupCreated: '§6Pomyślnie utworzyłeś kopie zapasowe wszystkich zadań i informacji o graczach.' - backupPlayersFailed: '§cTworzenie kopii zapasowej dla wszystkich graczy nie powiodło się.' - backupQuestsFailed: '§cTworzenie kopii zapasowej dla wszystkich zadań nie powiodło się.' - adminModeEntered: '§aWłączyłeś/aś tryb administratora.' - adminModeLeft: '§aWyłączyłeś/aś tryb administratora.' - resetPlayerPool: - timer: '§aZresetowałeś {0} zegar puli {1}.' - full: '§aZresetowałeś dane puli {0} {1}.' - scoreboard: - lineSet: '§6Pomyślnie edytowałeś/aś linię {0}.' - lineReset: '§6Pomyślnie zresetowałeś/aś wiersz {0}.' - lineRemoved: '§6Pomyślnie usunąłeś/aś wiersz {0}.' - lineInexistant: '§cWiersz {0} nie istnieje.' - resetAll: '§6Pomyślnie zresetowałeś/aś tablicę wyników gracza {0}.' - hidden: '§6Tablica wyników gracza {0} została ukryta.' - shown: '§6Tablica wyników gracza {0} została pokazana.' - own: - hidden: '§6Twoja tablica wyników jest teraz ukryta.' - shown: '§6Twoja tablica wyników pojawiła się ponownie.' - help: - header: '§6§lBeautyQuests - Pomoc' - create: '§6/{0} create: §eUtwórz zadanie.' - edit: '§6/{0} edit: §eEdytuj zadanie.' - remove: '§6/{0} remove <id>: §eUsuń zadanie z podanym id lub kliknij na NPC jeśli nie zdefiniowano.' - finishAll: '§6/{0} finishAll <player>: §eZakończ wszystkie zadania gracza.' - setStage: '§6/{0} setStage <gracz> <id> [nowa gałąź] [nowy etap]: §ePomiń bieżący etap/uruchom gałąź/ustaw etap dla gałęzi.' - startDialog: '§7/{0} startDialog <player> <quest id>: §eUruchamia oczekujące okno dialogowe dla etapu NPC lub startowego okna dialogowego dla zadania.' - resetPlayer: '§6/{0} resetPlayer <gracz>: §eUsuń wszystkie informacje o graczu.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <gracz> [id]: §eUsuń informacje o zadaniu danego gracza.' - seePlayer: '§6/{0} SeePlayer <gracz>: §eWyświetl informacje o graczu.' - reload: '§6/{0} reload: §eZapisz i odśwież wszystkie konfiguracje i pliki. (§cprzestarzałe§e)' - start: '§6/{0} start <gracz> [id]: §eWymuś rozpoczęcie zadania.' - setItem: '§6/{0} setItem <talk|launch>: §eZapisz hologram.' - setFirework: '§6/{0} setFirework: §eEdytuj domyślny końcowy efekt fajerwerki.' - adminMode: '§6/{0} adminMode: §ePrzełącz tryb administratora. (Przydatne do wyświetlania małych wiadomości dziennika.)' - version: '§6/{0} version: §eZobacz aktualną wersję pluginu.' - downloadTranslations: '§6/{0} downloadTranslations <język>: §ePobiera plik z tłumaczeniem vanilla' - save: '§6/{0} save: §eZapisz ręcznie plugin (postęp/zmiany).' - list: '§6/{0} list: §eZobacz listę zadań. (Tylko dla obsługiwanych wersji.)' - typeCancel: '§aNapisz "cancel" aby wrócić do ostatniego tekstu.' - editor: - blockAmount: '§aNapisz liczbę bloków:' - blockName: '§aNapisz nazwę bloku:' - blockData: '§aNapisz dane bloków (dostępne dane bloków: {0}):' - blockTag: '§aWpisz tag bloku (dostępne tagi: §7{0}§a):' - typeBucketAmount: '§aNapisz liczbę wiader do napełnienia:' - typeDamageAmount: 'Zapisz ilość obrażeń gracza:' - goToLocation: '§aIdź do pożądanej lokalizacji dla tego etapu.' - typeLocationRadius: '§aNapisz wymaganą odległość od lokalizacji:' - typeGameTicks: '§aNapisz wymaganą ilość ticków gry:' - already: '§cJesteś już w edytorze.' - stage: - location: - typeWorldPattern: '§aNapisz regex dla nazw świata:' - enter: - title: '§6~ Tryb edytora ~' - subtitle: '§7Napisz "/quests exitEditor" aby wymusić opuszczenie edytora.' - list: '§c⚠ §7Otworzyłeś edytor "listy". Użyj "add", aby dodać linie. Aby uzyskać pomoc, wpisz "help" (bez znaku ukośnika). §e§lWpisz "close", aby opuścić edytor.' - chat: '§6Jesteś obecnie w trybie edytora. Napisz "/quests exitEditor", aby wymusić opuszczenie edytora. (Wysoko niezalecane, rozważ użycie poleceń, takich jak "close" lub "cancel", aby wrócić do poprzedniego ekwipunku)' - npc: - enter: '§aKliknij na NPC, lub napisz "cancel".' - choseStarter: '§aWybierz NPC który rozpoczyna zadanie.' - notStarter: '§cTen NPC nie rozpoczyna misji.' - text: - argNotSupported: '§cArgument {0} nie jest obsługiwany.' - chooseLvlRequired: '§aNapisz wymaganą ilość poziomów:' - chooseJobRequired: '§aNapisz nazwę wymaganej pracy:' - choosePermissionRequired: '§aNapisz wymagane uprawnienia, aby rozpocząć zadanie:' - choosePermissionMessage: '§aMożesz wybrać wiadomość o odrzuceniu jeśli gracz nie ma wymaganego uprawnienia (aby pominąć ten krok, napisz "null")' - choosePlaceholderRequired: - identifier: '§aWpisz nazwę wymaganego placeholdera bez procentu znaków:' - value: '§aNapisz wymaganą wartość dla tego placeholdera §e%§e{0}§e%§a:' - chooseSkillRequired: '§aNapisz nazwę wymaganej umiejętności:' - chooseMoneyRequired: '§aNapisz wymaganą ilość pieniędzy:' - reward: - permissionName: '§aNapisz nazwę uprawnień.' - permissionWorld: '§aNapisz świat, w którym uprawnienia będą edytowane, lub "null" jeśli chcesz żeby były globalnie.' - money: '§aNapisz ilość otrzymanych pieniędzy:' - wait: '§aNapisz ilość ticków do poczekania: (1 sekunda = 20 ticków w grze)' - random: - min: '§aZapisz minimalną ilość nagród przyznanych graczowi (włącznie).' - max: '§aZapisz maksymalną ilość nagród przyznanych graczowi (włącznie).' - chooseObjectiveRequired: '§aNapisz nazwę celu.' - chooseObjectiveTargetScore: '§aNapisz docelowy wynik dla celu.' - chooseRegionRequired: '§aNapisz nazwę wymaganego regionu (musisz być w tym samym świecie).' - selectWantedBlock: '§aKliknij patykiem na pożądany blok dla etapu.' - itemCreator: - itemType: '§aNapisz nazwę pożądanego typu przedmiotu:' - itemAmount: '§aNapisz liczbę przedmiotow:' - itemName: '§aNapisz nazwę przedmiotu:' - itemLore: '§aModyfikuj lore przedmiotu: (Napisz "help", aby wyświetlić pomoc.)' - unknownItemType: '§cNieznany typ przedmiotu.' - invalidItemType: '§cNieprawidłowy typ przedmiotu. (Przedmiot nie może być blokiem.)' - unknownBlockType: '§cNieznany typ bloku.' - invalidBlockType: '§cNieprawidłowy typ bloku.' - dialog: - syntax: '§cPoprawna składnia: {0}{1} <message>' - syntaxRemove: '§cPoprawna składnia: remove <id>' - player: '§aWiadomość "§7{0}§a" została dodana dla gracza.' - npc: '§aWiadomość "§7{0}§a" została dodana dla NPC.' - noSender: '§aWiadomość "§7{0}§a" została dodana bez nadawcy.' - messageRemoved: '§aWiadomość "§7{0}§a" usunięta.' - edited: '§aWiadomość "§7{0}§a" została edytowana.' - soundAdded: '§aDźwięk "§7{0}§a" dodał do wiadomości "§7{1}§a".' - cleared: '§aUsunięto {0} wiadomość(ci).' - help: - header: '§6§lBeautyQuests - Pomoc do edytora okna dialogowego' - npc: '§6npc <wiadomość>: §eDodaj wiadomość wysłaną przez NPC.' - player: '§6player <wiadomość>: §eDodaj wiadomość wysłaną przez gracza.' - nothing: '§6noSender <wiadomość>: §eDodaj wiadomość bez nadawcy.' - remove: '§6remove <id>: §eUsuń wiadomość.' - list: '§6list: §eWyświetl wszystkie wiadomości.' - npcInsert: '§6npcInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez NPC.' - playerInsert: '§6playerInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez gracza.' - nothingInsert: '§6nothingInsert <id> <wiadomość>: §eWstaw wiadomość bez żadnego prefiksu.' - edit: '§7edytuj <id> <message>: §eEdytuj wiadomość.' - addSound: '§6addSound <id> <dźwięk>: §eDodaj dźwięk do wiadomości.' - clear: '§6clear: §eUsuń wszystkie wiadomości.' - close: '§6close: §ePotwierdź wszystkie wiadomości.' - setTime: '§6setTime <id> <czas>: §eUstaw czas (w tickach) zanim następna automatyczna wiadomość zostanie wysłana.' - npcName: '§7npcName [niestandardowa nazwa NPC]: §eUstaw (lub zresetuj do domyślnej) niestandardową nazwę NPC w oknie dialogowym' - skippable: '§7pomijalne [true|false]: §eUstaw jeśli okno dialogowe może być pominięte lub nie' - timeSet: '§aCzas został edytowany dla wiadomości {0}: teraz {1} ticków.' - timeRemoved: '§aCzas został usunięty dla wiadomości {0}.' - npcName: - set: '§aWłasna nazwa NPC ustawiona na §7{1}§a (był §7{0}§a)' - unset: '§aWłasna nazwa NPC została przywrócona do domyślnej (była §7{0}§a)' - skippable: - set: '§aPominięty status okna dialogowego jest ustawiony na §7{1}§a (był §7{0}§a)' - unset: '§aPominięty status okna dialogowego jest przywrócony do domyślnego (był §7{0}§a)' - mythicmobs: - list: '§aLista wszystkich Mitycznych mobów:' - isntMythicMob: '§cTen Mityczny Mob nie istnieje.' - disabled: '§cMythicMob jest wyłączony.' - advancedSpawnersMob: 'Napisz nazwę niestandardowego moba spawnera, aby zabić:' - textList: - syntax: '§cPoprawna składnia: ' - added: '§aTekst "§7{0}§a" dodany.' - removed: '§aTekst "§7{0}§a" usunięty.' - help: - header: '§6§lBeautyQuests — Pomoc edytora list' - add: '§6add <wiadomość>: §eDodaj tekst.' - remove: '§6remove <id>: §eUsuń tekst.' - list: '§6list: §eZobacz wszystkie dodane teksty.' - close: '§6close: §ePotwierdź dodane teksty.' - availableElements: 'Dostępne elementy: §e{0}' - noSuchElement: '§cNie ma takiego elementu. Dozwolone elementy to: §e{0}' - invalidPattern: '§cNieprawidłowy wzór regex §4{0}§c.' - comparisonTypeDefault: '§aWybierz typ porównania, który chcesz wśród {0}. Domyślne porównanie to: §e§l{1}§r§a. Wpisz §onull§r§a aby go użyć.' - scoreboardObjectiveNotFound: '§cNieznany cel tablicy wyników.' - pool: - hologramText: 'Napisz niestandardowy tekst hologramu dla tej puli (lub "null" jeśli chcesz domyślnie).' - maxQuests: 'Wpisz maksymalną ilość zadań uruchamianych z tej puli.' - questsPerLaunch: 'Napisz liczbę zadań, gdy gracze klikną na NPC.' - timeMsg: 'Napisz czas, zanim gracze mogą zająć nowe zadanie. (domyślna jednostka: dni)' - title: - title: 'Napisz tytuł teksu (lub wpisz "null" aby pozostawić puste).' - subtitle: 'Napisz podtytuł teksu (lub wpisz "null" aby pozostawić puste).' - fadeIn: 'Wpisz czas "fade-in" w tickach (20 ticków = 1 sekunda).' - stay: 'Wpisz czas "stay" w tickach (20 ticków = 1 sekunda).' - fadeOut: 'Napisz czas "fade-out" w tickach (20 ticków = 1 sekunda).' - colorNamed: 'Wprowadź nazwę koloru.' - color: 'Wprowadź kolor w formacie szesnastkowym (#XXXXX) lub formatu RGB (RED GRE BLU).' - invalidColor: 'Wprowadzony kolor jest nieprawidłowy. Musi być szesnastkowy lub RGB.' - firework: - invalid: 'Ten przedmiot nie jest poprawnym fajerwerkiem.' - invalidHand: 'Musisz trzymać fajerwerk w swojej głównej ręce.' - edited: 'Edytowałeś fajerwerk misji!' - removed: 'Usunięto fajerwerk misji!' - writeCommandDelay: '§aNapisz żądane opóźnienie komendy, w tickach.' advancement: finished: Zakończono notStarted: Nie rozpoczęto +description: + requirement: + class: Klasa {class_name} + combatLevel: Poziom bojowy {short_level} + faction: Frakcja {faction_name} + jobLevel: Poziom {short_level} dla {job_name} + level: Poziom {short_level} + quest: Zakończ zadanie §e{quest_name} + skillLevel: Poziom {short_level} dla {skill_name} + title: '§8§lWymagania:' + reward: + title: '§8§lNagrody:' +indication: + cancelQuest: '§7Czy na pewno chcesz anulować zadanie {quest_name}?' + closeInventory: '§7Czy na pewno chcesz zamknąć GUI?' + removeQuest: '§7Czy na pewno chcesz usunąć zadanie {quest}?' + startQuest: '§7Czy chcesz rozpocząć zadanie {quest_name}?' inv: - validate: '§b§lPotwierdź' - cancel: '§c§lAnuluj' - search: '§e§lSzukaj' addObject: '§aDodaj obiekt' + block: + blockData: '§dBlockdata (zaawansowane)' + blockName: '§bWłasna nazwa bloku' + blockTag: '§dTag (zaawansowane)' + blockTagLore: Wybierz tag, który opisuje listę możliwych bloków. Tagi można dostosować za pomocą apacków. Listę tagów można znaleźć na wiki Minecraft. + material: '§eMateriał: {block_type}' + materialNotItemLore: Wybrany blok nie może być wyświetlany jako element. Nadal jest poprawnie przechowywany jako {block_material}. + name: Wybierz blok + blockAction: + location: '§eWybierz dokładną lokalizację' + material: '§eWybierz materiał bloku' + name: Wybierz akcję bloku + blocksList: + addBlock: '§aKliknij, aby dodać blok.' + name: Wybierz bloki + buckets: + name: Typ wiadra + cancel: '§c§lAnuluj' + cancelActions: + name: Anuluj akcje + checkpointActions: + name: Akcje punktu kontrolnego + chooseAccount: + name: Jakie konto? + chooseQuest: + menu: '§aQuests Menu' + menuLore: Pobiera cię do menu Zadań. + name: Wybór zadania + classesList.name: Lista klas + classesRequired.name: Wymagane klasy + command: + console: Konsola + delay: '§bOpóźnienie' + name: Komenda + parse: Parsetowe symbole zastępcze + value: '§eKomenda' + commandsList: + console: '§eKonsola: {command_console}' + name: Lista komend + value: '§Komenda: {command_label}' confirm: name: Jesteś pewien? - 'yes': '§aPotwierdź' 'no': '§cAnuluj' + 'yes': '§aPotwierdź' create: - stageCreate: '§aUtwórz nowy krok' - stageRemove: '§cUsuń ten krok' - stageUp: Przesuń w górę - stageDown: Przesuń w dół - stageType: '§7Rodzaj sceny: §e{0}' - cantFinish: '§7Musisz utworzyć co najmniej jeden etap przed zakończeniem tworzenia misji!' - findNPC: '§aZnajdź NPC' + NPCSelect: '§eWybierz lub utwórz NPC' + NPCText: '§eEdytuj okno dialogowe' + breedAnimals: '§aRozmnóż zwierzęta' bringBack: '§aPrzynieś przedmioty' - findRegion: '§aZnajdź region' - killMobs: '§aZabij potwora' - mineBlocks: '§aZniszcz bloki' - placeBlocks: '§aPołóż bloki' - talkChat: '§aNapisz na czacie' - interact: '§aInterakcja z blokiem' - fish: '§aZłap ryby' - melt: '§7Wytopione przedmioty' - enchant: '§dZaklnij przedmioty' - craft: '§aStwórz przedmiot' bucket: '§aWypełnij wiadra' - location: '§aIdź do lokalizacji' - playTime: '§eCzas gry' - breedAnimals: '§aRozmnóż zwierzęta' - tameAnimals: '§aOswój zwierzęta' - death: '§cZgiń' + cancelMessage: Anuluj wysyłanie + cantFinish: '§7Musisz utworzyć co najmniej jeden etap przed zakończeniem tworzenia misji!' + changeEntityType: '§eZmień typ obiektu/jednostki' + changeTicksRequired: '§eZmiana ticków jest wymagana' + craft: '§aStwórz przedmiot' + currentRadius: '§eObecna odległość: §6{radius}' dealDamage: '§cZadaj obrażenia mobom' + death: '§cZgiń' eatDrink: '§aZjedz lub pij jedzenie lub mikstury' - NPCText: '§eEdytuj okno dialogowe' - dialogLines: '{0} linii' - NPCSelect: '§eWybierz lub utwórz NPC' - hideClues: Ukryj cząsteczki i hologramy - gps: Wyświetla kompas pokazujący kierunek celu - editMobsKill: '§eEdytuj moby do zabicia' - mobsKillFromAFar: Należy zabić pociskiem editBlocksMine: '§eEdytuj bloki do zniszczenia' - preventBlockPlace: Zablokuj graczom możliwość niszczenia własnych bloków editBlocksPlace: '§eEdytuj bloki do postawienia' - editMessageType: '§eEdytuj wiadomość do napisania' - cancelMessage: Anuluj wysyłanie + editBucketAmount: '§eEdytuj ilość wiader do wypełnienia' + editBucketType: '§eEdytuj typ wiadra do wypełnienia' + editFishes: '§eEdytuj ryby do złowienia' + editItem: '§eEdytuj przedmioty do stworzenia' + editItemsToEnchant: '§eEdytuj przedmioty do zaczarowania' + editItemsToMelt: '§eEdytuj przedmioty do stopienia' + editLocation: '§eEdytuj lokalizację' + editMessageType: '§eEdytuj wiadomość do napisania' + editMobsKill: '§eEdytuj moby do zabicia' + editRadius: '§eEdytuj odległość od lokalizacji' + enchant: '§dZaklnij przedmioty' + findNPC: '§aZnajdź NPC' + findRegion: '§aZnajdź region' + fish: '§aZłap ryby' + hideClues: Ukryj cząsteczki i hologramy ignoreCase: Ignoruj wielkość liter w wiadomości + interact: '§aInterakcja z blokiem' + killMobs: '§aZabij potwora' + leftClick: Musisz kliknąć lewym przyciskiem myszy + location: '§aIdź do lokalizacji' + melt: '§7Wytopione przedmioty' + mineBlocks: '§aZniszcz bloki' + mobsKillFromAFar: Należy zabić pociskiem + placeBlocks: '§aPołóż bloki' + playTime: '§eCzas gry' + preventBlockPlace: Zablokuj graczom możliwość niszczenia własnych bloków replacePlaceholders: Zastąp {PLAYER} i placeholdery z PAPI + selectBlockLocation: '§eWybierz lokalizację bloku' + selectBlockMaterial: '§eWybierz materiał bloku' selectItems: '§eEdytuj wymagane przedmioty' - selectItemsMessage: '§eEdytuj wiadomość z pytaniem' selectItemsComparisons: '§eWybierz porównania przedmiotów (ZAAWANSOWANE)' + selectItemsMessage: '§eEdytuj wiadomość z pytaniem' selectRegion: '§7Wybierz region' - toggleRegionExit: Przy wyjściu - stageStartMsg: '§eEdytuj wiadomość początkową' - selectBlockLocation: '§eWybierz lokalizację bloku' - selectBlockMaterial: '§eWybierz materiał bloku' - leftClick: Musisz kliknąć lewym przyciskiem myszy - editFishes: '§eEdytuj ryby do złowienia' - editItemsToMelt: '§eEdytuj przedmioty do stopienia' - editItemsToEnchant: '§eEdytuj przedmioty do zaczarowania' - editItem: '§eEdytuj przedmioty do stworzenia' - editBucketType: '§eEdytuj typ wiadra do wypełnienia' - editBucketAmount: '§eEdytuj ilość wiader do wypełnienia' - editLocation: '§eEdytuj lokalizację' - editRadius: '§eEdytuj odległość od lokalizacji' - currentRadius: '§eObecna odległość: §6{0}' - changeTicksRequired: '§eZmiana ticków jest wymagana' - changeEntityType: '§eZmień typ obiektu/jednostki' stage: - location: - worldPattern: '§aUstaw wzór nazwy świata §d(ADVANCED)' - worldPatternLore: 'Jeśli chcesz, aby etap został ukończony dla dowolnego świata pasującego do określonego wzoru, wprowadź wyrażenie regularne tutaj tutaj.' - death: - causes: '§aUstaw śmierć powoduje §d(ADVANCED)' - anyCause: Każda przyczyna zgonu - setCauses: '{0} przyczyna zgonu' dealDamage: damage: '§eObrażenia' targetMobs: '§cMoby do obrażeń' + death: + anyCause: Każda przyczyna zgonu + causes: '§aUstaw śmierć powoduje §d(ADVANCED)' + setCauses: '{causes_amount} przyczyna zgonu' eatDrink: items: '§eEdytuj przedmioty do jedzenia lub picia' - stages: - name: Stwórz etapy - nextPage: '§eNastępna strona' - laterPage: '§ePoprzednia strona' - endingItem: '§eEdytuj końcowe nagrody' - descriptionTextItem: '§eEdytuj opis' - regularPage: '§aZwykłe etapy' - branchesPage: '§dEtapy gałęzi' - previousBranch: '§eWróć do poprzedniej gałęzi' - newBranch: '§ePrzejdź do nowej gałęzi' - validationRequirements: '§eWymagania sprawdzające' - validationRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, który chce ukończyć poziom. Bez tego poziom nie może zostać ukończony. + location: + worldPattern: '§aUstaw wzór nazwy świata §d(ADVANCED)' + worldPatternLore: Jeśli chcesz, aby etap został ukończony dla dowolnego świata pasującego do określonego wzoru, wprowadź wyrażenie regularne tutaj tutaj. + stageCreate: '§aUtwórz nowy krok' + stageDown: Przesuń w dół + stageRemove: '§cUsuń ten krok' + stageStartMsg: '§eEdytuj wiadomość początkową' + stageType: '§7Rodzaj sceny: §e{stage_type}' + stageUp: Przesuń w górę + talkChat: '§aNapisz na czacie' + tameAnimals: '§aOswój zwierzęta' + toggleRegionExit: Przy wyjściu + damageCause: + name: Powód obrażeń + damageCausesList: + name: Lista przyczyn obrażeń details: - hologramLaunch: '§eEdytuj hologram - "launch"' - hologramLaunchLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz może rozpocząć zadanie. - hologramLaunchNo: '§eEdytuj hologram - "launch unavailable"' - hologramLaunchNoLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz nie może rozpocząć zadania. + actions: '{amount} akcja(j)' + auto: Uruchom automatycznie po zalogowaniu + autoLore: Jeśli włączone, zadanie zostanie uruchomione automatycznie, gdy gracz dołączy do serwera po raz pierwszy. + bypassLimit: Nie licz limitu zadań + bypassLimitLore: Jeśli włączone, zadanie będzie uruchamialne, nawet jeśli gracz osiągnie maksymalną liczbę rozpoczętych zadań. + cancelRewards: '§cAnuluj akcje' + cancelRewardsLore: Akcje wykonywane, gdy gracze anulują to zadanie. + cancellable: Możliwość anulowania przez gracza + cancellableLore: Pozwala graczowi anulować zadanie przez menu zadań. + createQuestLore: Musisz zdefiniować nazwę zadania. + createQuestName: '§lUtwórz zadanie' customConfirmMessage: '§eEdytuj wiadomość potwierdzającą zadanie' customConfirmMessageLore: Wiadomość wyświetlana w interfejsie potwierdzania, gdy gracz ma wkrótce rozpocząć zadanie. customDescription: '§eEdytuj opis zadania' customDescriptionLore: Opis pokazany pod nazwą zadania w GUI. - name: Szczegóły ostatniego zadania - multipleTime: - itemName: Włącz/wyłącz możliwość powtarzania - itemLore: Czy zadanie można wykonać kilkakrotnie? - cancellable: Możliwość anulowania przez gracza - cancellableLore: Pozwala graczowi anulować zadanie przez menu zadań. - startableFromGUI: Możliwość uruchomienia z GUI - startableFromGUILore: Pozwala graczowi rozpocząć zadanie z menu zadań. - scoreboardItem: Włącz tabelę wyników - scoreboardItemLore: Jeśli wyłączone, zadanie nie będzie śledzone przez tablicę wyników. + customMaterial: '§eEdytuj przedmiot zadania' + customMaterialLore: Przedmiot reprezentujący to zadanie znajduje się w menu zadań. + defaultValue: '§8(domyślna wartość)' + editQuestName: '§lEdytuj zadanie' + editRequirements: '§eEdytuj wymagania' + editRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, zanim będzie mógł on rozpocząć zadanie. + endMessage: '§eEdytuj wiadomość końcową' + endMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. + endSound: '§eEdytuj dźwięk końca' + endSoundLore: Dźwięk, który będzie odtwarzany na końcu zadania. + failOnDeath: Niepowodzenie podczas śmierci + failOnDeathLore: Czy zadanie zostanie anulowane po śmierci gracza? + firework: '§dKończenie fajerwerków' + fireworkLore: Fajerwerk wystrzelony po zakończeniu misji + fireworkLoreDrop: Upuść niestandardowe fajerwerki tutaj hideNoRequirementsItem: Ukryj gdy wymagania nie są spełnione hideNoRequirementsItemLore: Jeśli włączone, zadanie nie będzie wyświetlane w Menu Zadań, gdy wymagania nie zostaną spełnione. - bypassLimit: Nie licz limitu zadań - bypassLimitLore: Jeśli włączone, zadanie będzie uruchamialne, nawet jeśli gracz osiągnie maksymalną liczbę rozpoczętych zadań. - auto: Uruchom automatycznie po zalogowaniu - autoLore: Jeśli włączone, zadanie zostanie uruchomione automatycznie, gdy gracz dołączy do serwera po raz pierwszy. + hologramLaunch: '§eEdytuj hologram - "launch"' + hologramLaunchLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz może rozpocząć zadanie. + hologramLaunchNo: '§eEdytuj hologram - "launch unavailable"' + hologramLaunchNoLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz nie może rozpocząć zadania. + hologramText: '§eTekst Hologramu' + hologramTextLore: Tekst wyświetlany na hologramie nad głową startowego NPC. + keepDatas: Zachowaj dane graczy + keepDatasLore: 'Wymuś, aby plugin zachował dane graczy, nawet jeśli etapy zostały edytowane. §c§lOSTRZEŻENIE §c- włączenie tej opcji może zepsuć dane Twoich gracza.' + loreReset: '§e§lPostęp wszystkich graczy zostanie zresetowany' + multipleTime: + itemLore: Czy zadanie można wykonać kilkakrotnie? + itemName: Włącz/wyłącz możliwość powtarzania + name: Szczegóły ostatniego zadania + optionValue: '§8Wartość: §7{value}' questName: '§a§lEdytuj nazwę zadania' questNameLore: Nazwa musi być ustawiona, aby ukończyć tworzenie zadania. - setItemsRewards: '§eEdytuj nagrody przedmiotowe' + questPool: '§ePula Zadań' + questPoolLore: Dołącz to zadanie do puli zadań removeItemsReward: '§eUsuń przedmioty z ekwipunku' - setXPRewards: '§eEdytuj nagrody doświadczenia' + requiredParameter: '§7Wymagany parametr' + requirements: '{amount} wymaganie(a)' + rewards: '{amount} nagroda(ód)' + rewardsLore: Akcje wykonywane po zakończeniu misji. + scoreboardItem: Włącz tabelę wyników + scoreboardItemLore: Jeśli wyłączone, zadanie nie będzie śledzone przez tablicę wyników. + selectStarterNPC: '§e§lWybierz NPC startowego' + selectStarterNPCLore: Kliknięcie na wybranego NPC rozpocznie zadanie. + selectStarterNPCPool: '§c⚠ Wybrana pula zadań' setCheckpointReward: '§eEdytuj nagrody punktu kontrolnego' + setItemsRewards: '§eEdytuj nagrody przedmiotowe' + setMoneyReward: '§eEdytuj nagrodę pieniężną' + setPermReward: '§eEdytuj uprawnienia' setRewardStopQuest: '§cZatrzymaj zadanie' - setRewardsWithRequirements: '§eNagrody z wymaganiami' setRewardsRandom: '§dLosowe nagrody' - setPermReward: '§eEdytuj uprawnienia' - setMoneyReward: '§eEdytuj nagrodę pieniężną' - setWaitReward: '§eEdytuj nagrodę "czekania"' + setRewardsWithRequirements: '§eNagrody z wymaganiami' setTitleReward: '§eEdytuj tytuł nagrody' - selectStarterNPC: '§e§lWybierz NPC startowego' - selectStarterNPCLore: Kliknięcie na wybranego NPC rozpocznie zadanie. - selectStarterNPCPool: '§c⚠ Wybrana pula zadań' - createQuestName: '§lUtwórz zadanie' - createQuestLore: Musisz zdefiniować nazwę zadania. - editQuestName: '§lEdytuj zadanie' - endMessage: '§eEdytuj wiadomość końcową' - endMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. - endSound: '§eEdytuj dźwięk końca' - endSoundLore: Dźwięk, który będzie odtwarzany na końcu zadania. - startMessage: '§eEdytuj wiadomość początkową' - startMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. + setWaitReward: '§eEdytuj nagrodę "czekania"' + setXPRewards: '§eEdytuj nagrody doświadczenia' startDialog: '§eEdytuj okno startowe' startDialogLore: Okno dialogowe, które będzie wyświetlane przed rozpoczęciem zadań, kiedy gracze klikną na NPC Startowego. - editRequirements: '§eEdytuj wymagania' - editRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, zanim będzie mógł on rozpocząć zadanie. + startMessage: '§eEdytuj wiadomość początkową' + startMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. startRewards: '§6Nagrody startowe' startRewardsLore: Akcje wykonywane w momencie rozpoczęcia misji. - cancelRewards: '§cAnuluj akcje' - cancelRewardsLore: Akcje wykonywane, gdy gracze anulują to zadanie. - hologramText: '§eTekst Hologramu' - hologramTextLore: Tekst wyświetlany na hologramie nad głową startowego NPC. + startableFromGUI: Możliwość uruchomienia z GUI + startableFromGUILore: Pozwala graczowi rozpocząć zadanie z menu zadań. timer: '§bZrestartuj zegar' timerLore: Czas zanim gracz może ponownie rozpocząć zadanie. - requirements: '{0} wymaganie(a)' - rewards: '{0} nagroda(ód)' - actions: '{0} akcja(j)' - rewardsLore: Akcje wykonywane po zakończeniu misji. - customMaterial: '§eEdytuj przedmiot zadania' - customMaterialLore: Przedmiot reprezentujący to zadanie znajduje się w menu zadań. - failOnDeath: Niepowodzenie podczas śmierci - failOnDeathLore: Czy zadanie zostanie anulowane po śmierci gracza? - questPool: '§ePula Zadań' - questPoolLore: Dołącz to zadanie do puli zadań - firework: '§dKończenie fajerwerków' - fireworkLore: Fajerwerk wystrzelony po zakończeniu misji - fireworkLoreDrop: Upuść niestandardowe fajerwerki tutaj visibility: '§bWidoczność Zadań' visibilityLore: Wybierz, w których zakładkach menu będą wyświetlane zadania, a jeśli zadanie będzie widoczne na mapach dynamicznych. - keepDatas: Zachowaj dane graczy - keepDatasLore: |- - Wymuś, aby plugin zachował dane graczy, nawet jeśli etapy zostały edytowane. - §c§lOSTRZEŻENIE §c- włączenie tej opcji może zepsuć dane Twoich gracza. - loreReset: '§e§lPostęp wszystkich graczy zostanie zresetowany' - optionValue: '§8Wartość: §7{0}' - defaultValue: '§8(domyślna wartość)' - requiredParameter: '§7Wymagany parametr' - itemsSelect: - name: Edytuj przedmioty - none: |- - §aPrzenieś tutaj przedmiot lub - kliknij, aby otworzyć edytor przedmiotu. - itemSelect: - name: Wybierz przedmiot - npcCreate: - name: Utwórz NPC - setName: '§eEdytuj nazwę NPC' - setSkin: '§eEdytuj skórkę NPC' - setType: '§eEdytuj typ NPC' - move: - itemName: '§ePrzenieś' - itemLore: '§aZmień lokalizację NPC.' - moveItem: '§a§lPotwierdź miejsce' - npcSelect: - name: Wybrać czy stworzyć? - selectStageNPC: '§eWybierz istniejącego NPC' - createStageNPC: '§eUtwórz NPC' + editTitle: + fadeIn: '§aCzas pojawiania' + fadeOut: '§aCzas zanikania' + name: Edytuj tytuł + stay: '§bCzas trwania' + subtitle: '§ePodtytuł' + title: '§6Tytuł' entityType: name: Wybierz typ jednostki - chooseQuest: - name: Wybór zadania - menu: '§aQuests Menu' - menuLore: Pobiera cię do menu Zadań. - mobs: - name: Wybierz moby - none: '§aKliknij, aby dodać moba.' - clickLore: |- - §a§lKliknij lewym przyciskiem myszy§a aby edytować kwotę. - §a§l§nShift§a§l + lewym kliknięciem§a aby edytować nazwę potwora. - §c§lKliknij prawym przyciskiem myszy§c aby usunąć. - setLevel: Ustaw minimalny poziom - mobSelect: - name: Wybierz typ moba - bukkitEntityType: '§eWybierz typ jednostki' - mythicMob: '§6Wybierz Mitycznego moba' - epicBoss: '§6Wybierz Epickiego Bossa' - boss: '§6Wybierz Bossa' - stageEnding: - locationTeleport: '§eEdytuj lokalizację teleportu' - command: '§eEdytuj wykonywaną komendę' - requirements: - name: Wymagania - rewards: - name: Nagrody - commands: 'Komendy: {0}' - teleportation: |- - §aWybrane: - X: {0} - Y: {1} - Z: {2} - Świat: {3} - random: - rewards: Edytuj nagrody - minMax: Edytuj min. i maks. - checkpointActions: - name: Akcje punktu kontrolnego - cancelActions: - name: Anuluj akcje - rewardsWithRequirements: - name: Nagrody z wymaganiami - listAllQuests: - name: Zadania - listPlayerQuests: - name: 'Zadania {0}' - listQuests: - notStarted: Nierozpoczęte zadania - finished: Ukończone zadania - inProgress: Aktywne zadania - loreDialogsHistoryClick: '§7Zobacz okna dialogowe' - loreCancelClick: '§cAnuluj zadanie' - loreStart: '§a§oKliknij aby rozpocząć zadanie' - loreStartUnavailable: '§c§oNie spełniasz wymagań do rozpoczęcia zadania' - timeToWaitRedo: '§3§oMożesz ponownie uruchomić to zadanie za {0}.' - canRedo: '§3§oMożesz ponownie uruchomić to zadanie!' - timesFinished: '§3Zadanie wykonano {0} razy.' + equipmentSlots: + name: Miejsca na wyposażenie + factionsList.name: Lista frakcji + factionsRequired.name: Wymagane frakcje + itemComparisons: + bukkit: Porównanie natywne Bukkit + bukkitLore: Używa domyślnego systemu porównywania przedmiotów Bukkit. Porównuje materiał, trwałość, tagi nbt... + customBukkit: Porównanie natywne Bukkit - NO NBT + customBukkitLore: Używa domyślnego systemu porównywania przedmiotów Bukkit, ale usuwa znaczniki NBT. Porównuje materiał, trwałość... + enchants: Zaklęcia przedmiotów + enchantsLore: Porównuje zaklęcia przedmiotów + itemLore: Opis przedmiotu + itemLoreLore: Porównuje opisy przedmiotów + itemName: Nazwa przedmiotu + itemNameLore: Porównuje nazwy przedmiotów + itemsAdder: ItemsAdder + itemsAdderLore: Porównuje ID ItemsAdder'a + material: Materiał przedmiotu + materialLore: Porównuje materiał przedmiotu (tj. kamień, żelazny miecz...) + name: Porównania pozycji + repairCost: Koszt naprawy + repairCostLore: Porównuje koszty naprawy pancerza i mieczy itemCreator: - name: Kreator przedmiotów - itemType: '§bTyp przedmiotu' + isQuestItem: '§bPrzedmiot misji:' itemFlags: Przełącz flagi przedmiotu - itemName: '§bNazwa przedmiotu' itemLore: '§bLore przedmiotu' - isQuestItem: '§bPrzedmiot misji:' - command: - name: Komenda - value: '§eKomenda' - console: Konsola - parse: Parsetowe symbole zastępcze - delay: '§bOpóźnienie' - chooseAccount: - name: Jakie konto? + itemName: '§bNazwa przedmiotu' + itemType: '§bTyp przedmiotu' + name: Kreator przedmiotów + itemSelect: + name: Wybierz przedmiot + itemsSelect: + name: Edytuj przedmioty + none: '§aPrzenieś tutaj przedmiot lub kliknij, aby otworzyć edytor przedmiotu.' + listAllQuests: + name: Zadania listBook: + noQuests: Nie utworzono wcześniej żadnych zadań. + questMultiple: Kilka razy questName: Nazwa - questStarter: Starter questRewards: Nagrody - questMultiple: Kilka razy - requirements: Wymagania questStages: Etapy - noQuests: Nie utworzono wcześniej żadnych zadań. - commandsList: - name: Lista komend - value: '§Komenda: {0}' - console: '§eKonsola: {0}' - block: - name: Wybierz blok - material: '§eMateriał: {0}' - materialNotItemLore: 'Wybrany blok nie może być wyświetlany jako element. Nadal jest poprawnie przechowywany jako {0}.' - blockName: '§bWłasna nazwa bloku' - blockData: '§dBlockdata (zaawansowane)' - blockTag: '§dTag (zaawansowane)' - blockTagLore: 'Wybierz tag, który opisuje listę możliwych bloków. Tagi można dostosować za pomocą apacków. Listę tagów można znaleźć na wiki Minecraft.' - blocksList: - name: Wybierz bloki - addBlock: '§aKliknij, aby dodać blok.' - blockAction: - name: Wybierz akcję bloku - location: '§eWybierz dokładną lokalizację' - material: '§eWybierz materiał bloku' - buckets: - name: Typ wiadra + questStarter: Starter + requirements: Wymagania + listPlayerQuests: + name: 'Zadania {player_name}' + listQuests: + canRedo: '§3§oMożesz ponownie uruchomić to zadanie!' + finished: Ukończone zadania + inProgress: Aktywne zadania + loreCancelClick: '§cAnuluj zadanie' + loreDialogsHistoryClick: '§7Zobacz okna dialogowe' + loreStart: '§a§oKliknij aby rozpocząć zadanie' + loreStartUnavailable: '§c§oNie spełniasz wymagań do rozpoczęcia zadania' + notStarted: Nierozpoczęte zadania + timeToWaitRedo: '§3§oMożesz ponownie uruchomić to zadanie za {time_left}.' + timesFinished: '§3Zadanie wykonano {times_finished} razy.' + mobSelect: + boss: '§6Wybierz Bossa' + bukkitEntityType: '§eWybierz typ jednostki' + epicBoss: '§6Wybierz Epickiego Bossa' + mythicMob: '§6Wybierz Mitycznego moba' + name: Wybierz typ moba + mobs: + name: Wybierz moby + none: '§aKliknij, aby dodać moba.' + setLevel: Ustaw minimalny poziom + npcCreate: + move: + itemLore: '§aZmień lokalizację NPC.' + itemName: '§ePrzenieś' + moveItem: '§a§lPotwierdź miejsce' + name: Utwórz NPC + setName: '§eEdytuj nazwę NPC' + setSkin: '§eEdytuj skórkę NPC' + setType: '§eEdytuj typ NPC' + npcSelect: + createStageNPC: '§eUtwórz NPC' + name: Wybrać czy stworzyć? + selectStageNPC: '§eWybierz istniejącego NPC' + particleEffect: + color: '§bKolor cząsteczek' + name: Utwórz efekt cząsteczek + shape: '§dKształt cząsteczek' + type: '§eTyp cząsteczek' + particleList: + colored: Kolorowe cząstki + name: Lista cząsteczek permission: name: Wybierz uprawnienie perm: '§aUprawnienia' - world: '§aŚwiat' - worldGlobal: '§b§lGlobalny' remove: Usuń uprawnienie removeLore: '§7Uprawnienie zostanie odebrane\n§7zamiast dodane.' + world: '§aŚwiat' + worldGlobal: '§b§lGlobalny' permissionList: name: Lista uprawnień - removed: '§eOdebrane: §6{0}' - world: '§eŚwiat: §6{0}' - classesRequired.name: Wymagane klasy - classesList.name: Lista klas - factionsRequired.name: Wymagane frakcje - factionsList.name: Lista frakcji - poolsManage: - name: Pula Zadań - itemName: '§aPula #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Maks. zadań: §7{0}' - poolQuestsPerLaunch: '§8Zadania podane podczas startu: §7{0}' - poolRedo: '§8Można wykonywać ponownie ukończone zadania: §7{0}' - poolTime: '§8Czas pomiędzy zadaniami: §7{0}' - poolHologram: '§8Tekst hologramu: §7{0}' - poolAvoidDuplicates: '§8Unikaj duplikatów: §7{0}' - poolQuestsList: '§7{0} §8zadań(ia): §7{1}' - create: '§aUtwórz pulę zadań' - edit: '§e> §6§oEdytuj pulę... §e<' - choose: '§e> §6§oWybierz tę pulę §e<' + removed: '§eOdebrane: §6{permission_removed}' + world: '§eŚwiat: §6{permission_world}' poolCreation: - name: Tworzenie puli zadań + avoidDuplicates: Unikaj duplikatów + avoidDuplicatesLore: '§8> §7Spróbuj unikać wykonywania\n tego samego zadania' hologramText: '§ePool niestandardowy hologram' maxQuests: '§aMaks. zadań' + name: Tworzenie puli zadań questsPerLaunch: '§8Zadania podane podczas startu' - time: '§bUstaw czas pomiędzy zadaniami' redoAllowed: Jest dozwolone ponawianie - avoidDuplicates: Unikaj duplikatów - avoidDuplicatesLore: '§8> §7Spróbuj unikać wykonywania\n tego samego zadania' requirements: '§bWymagania do rozpoczęcia zadania' + time: '§bUstaw czas pomiędzy zadaniami' poolsList.name: Pule zadań - itemComparisons: - name: Porównania pozycji - bukkit: Porównanie natywne Bukkit - bukkitLore: "Używa domyślnego systemu porównywania przedmiotów Bukkit.\nPorównuje materiał, trwałość, tagi nbt..." - customBukkit: Porównanie natywne Bukkit - NO NBT - customBukkitLore: "Używa domyślnego systemu porównywania przedmiotów Bukkit, ale usuwa znaczniki NBT.\nPorównuje materiał, trwałość..." - material: Materiał przedmiotu - materialLore: 'Porównuje materiał przedmiotu (tj. kamień, żelazny miecz...)' - itemName: Nazwa przedmiotu - itemNameLore: Porównuje nazwy przedmiotów - itemLore: Opis przedmiotu - itemLoreLore: Porównuje opisy przedmiotów - enchants: Zaklęcia przedmiotów - enchantsLore: Porównuje zaklęcia przedmiotów - repairCost: Koszt naprawy - repairCostLore: Porównuje koszty naprawy pancerza i mieczy - editTitle: - name: Edytuj tytuł - title: '§6Tytuł' - subtitle: '§ePodtytuł' - fadeIn: '§aCzas pojawiania' - stay: '§bCzas trwania' - fadeOut: '§aCzas zanikania' - particleEffect: - name: Utwórz efekt cząsteczek - shape: '§dKształt cząsteczek' - type: '§eTyp cząsteczek' - color: '§bKolor cząsteczek' - particleList: - name: Lista cząsteczek - colored: Kolorowe cząstki - damageCause: - name: Powód obrażeń - damageCausesList: - name: Lista przyczyn obrażeń + poolsManage: + choose: '§e> §6§oWybierz tę pulę §e<' + create: '§aUtwórz pulę zadań' + edit: '§e> §6§oEdytuj pulę... §e<' + itemName: '§aPula #{pool}' + name: Pula Zadań + poolAvoidDuplicates: '§8Unikaj duplikatów: §7{pool_duplicates}' + poolHologram: '§8Tekst hologramu: §7{pool_hologram}' + poolMaxQuests: '§8Maks. zadań: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8zadań(ia): §7{pool_quests}' + poolQuestsPerLaunch: '§8Zadania podane podczas startu: §7{pool_quests_per_launch}' + poolRedo: '§8Można wykonywać ponownie ukończone zadania: §7{pool_redo}' + poolTime: '§8Czas pomiędzy zadaniami: §7{pool_time}' + requirements: + name: Wymagania + rewards: + commands: 'Komendy: {amount}' + name: Nagrody + random: + minMax: Edytuj min. i maks. + rewards: Edytuj nagrody + rewardsWithRequirements: + name: Nagrody z wymaganiami + search: '§e§lSzukaj' + stageEnding: + command: '§eEdytuj wykonywaną komendę' + locationTeleport: '§eEdytuj lokalizację teleportu' + stages: + branchesPage: '§dEtapy gałęzi' + descriptionTextItem: '§eEdytuj opis' + endingItem: '§eEdytuj końcowe nagrody' + laterPage: '§ePoprzednia strona' + name: Stwórz etapy + newBranch: '§ePrzejdź do nowej gałęzi' + nextPage: '§eNastępna strona' + previousBranch: '§eWróć do poprzedniej gałęzi' + regularPage: '§aZwykłe etapy' + validationRequirements: '§eWymagania sprawdzające' + validationRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, który chce ukończyć poziom. Bez tego poziom nie może zostać ukończony. + validate: '§b§lPotwierdź' visibility: + finished: 'Zakładka menu "Zakończone"' + inProgress: 'Zakładka menu "W toku"' + maps: Mapy (takie jak dynmapa lub BlueMap) name: Widoczność zadań notStarted: 'Zakładka menu "Nie rozpoczęte"' - inProgress: 'Zakładka menu "W toku"' - finished: 'Zakładka menu "Zakończone"' - maps: 'Mapy (takie jak dynmapa lub BlueMap)' - equipmentSlots: - name: Miejsca na wyposażenie -scoreboard: - name: '§7§lZadania' - noLaunched: '§cBrak zadań w toku.' - noLaunchedName: '§c§lŁadowanie' - noLaunchedDescription: '§c§lŁadowanie' - textBetwteenBranch: '§e lub' - asyncEnd: '§ex' - stage: - region: '§eZnajdź region §6{0}' - npc: '§ePorozmawiaj z NPC §6{0}' - items: '§ePrzynieś przedmioty do §6{0}§e:' - mobs: '§eZabij §6{0}' - mine: '§eWykop {0}' - placeBlocks: '§ePostaw {0}' - chat: '§eNapisz §6{0}' - interact: '§eKliknij na blok na §6{0}' - interactMaterial: '§eKliknij na blok §6{0}' - fish: '§eZłów §6{0}' - melt: '§eMelt §6{0}' - enchant: '§eZaklinaj §6{0}' - craft: '§eStwórz §6{0}' - bucket: '§eUzupełnij §6{0}' - location: '§eIdź do §7{0}§e, §7{1}§e, §7{2}§e w §6{3}' - playTimeFormatted: '§eGraj §7{0}' - breed: '§eRozmnóż §6{0}' - tame: '§eOswój §6{0}' - die: '§cDie' - dealDamage: - any: '§cZadaj {0} obrażeń' - mobs: '§cZadaj {0} obrażeń {1}' - eatDrink: '§eZużyj §7{0}' -indication: - startQuest: '§7Czy chcesz rozpocząć zadanie {0}?' - closeInventory: '§7Czy na pewno chcesz zamknąć GUI?' - cancelQuest: '§7Czy na pewno chcesz anulować zadanie {0}?' - removeQuest: '§7Czy na pewno chcesz usunąć zadanie {0}?' -description: - requirement: - title: '§8§lWymagania:' - level: 'Poziom {0}' - jobLevel: 'Poziom {0} dla {1}' - combatLevel: 'Poziom bojowy {0}' - skillLevel: 'Poziom {0} dla {1}' - class: 'Klasa {0}' - faction: 'Frakcja {0}' - quest: 'Zakończ zadanie §e{0}' - reward: - title: '§8§lNagrody:' misc: - format: - prefix: '§6<§e§lZadania§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - offText: '§r§e{0}' - time: - weeks: '{0} tygodni' - days: '{0} dni' - hours: '{0} godzin' - minutes: '{0} minut' - lessThanAMinute: 'mniej niż minutę' - stageType: - region: Znajdź region - npc: Znajdź NPC - items: Przynieś przedmioty z powrotem - mobs: Zabij potwory - mine: Zniszcz bloki - placeBlocks: Postaw bloki - chat: Napisz na czacie - interact: Interakcja z blokiem - Fish: Złap ryby - Melt: Elementy stopu - Enchant: Zaklinaj przedmioty - Craft: Wytwórz przedmiot - Bucket: Wypełnij wiadro - location: Znajdź lokalizację - playTime: Czas w grze - breedAnimals: Rozmnóż zwierzęta - tameAnimals: Oswój zwierzęta - die: Giń - dealDamage: Zadaj obrażenia - eatDrink: Jedz lub napój - comparison: - equals: równe {0} - different: inne niż {0} - less: ściśle mniej niż {0} - lessOrEquals: mniej niż {0} - greater: ściśle więcej niż {0} - greaterOrEquals: więcej niż {0} - requirement: - logicalOr: '§dLogiczne LUB (wymagania)' - skillAPILevel: '§bWymagany poziom SkillAPI' - class: '§bKlasa(y) wymagane' - faction: '§bFrakcja(e) wymagana(e)' - jobLevel: '§bWymagany poziom pracy' - combatLevel: '§bWymagany poziom walki' - experienceLevel: '§bWymagane poziomy doświadczenia' - permissions: '§3Uprawnienie(a) jest/są wymagane' - scoreboard: '§dWymagany wynik' - region: '§dRegion jest wymagany' - placeholder: '§bWymagana jest wartość Placeholdera' - quest: '§aZadanie jest wymagane' - mcMMOSkillLevel: '§dWymagany poziom umiejętności' - money: '§dWymagane pieniądze' - equipment: '§eWymagane Wyposażenie' + amount: '§eIlość: {amount}' + amounts: + comparisons: '{comparisons_amount} comparaison(s)' + dialogLines: '{lines_amount} wiersze' + items: '{items_amount} element(ów)' + mobs: '{mobs_amount} mobów' + permissions: '{permissions_amount} uprawnień' + and: i bucket: - water: Wiadro wody lava: Wiadro lawy milk: Wiadro mleka snow: Śnieżne wiadro + water: Wiadro wody click: - right: Prawy przycisk myszy left: Kliknij lewym przyciskiem myszy - shift-right: Shift i kliknięcie prawym przyciskiem myszki - shift-left: Shift i kliknięcie lewym przyciskiem myszki middle: Kliknij środkowo - amounts: - items: '{0} element(ów)' - comparisons: '{0} comparaison(s)' - dialogLines: '{0} wiersze' - permissions: '{0} uprawnień' - mobs: '{0} mobów' - ticks: '{0} ticków' - questItemLore: '§e§oPrzedmiot zadań' - hologramText: '§8§lNPC zadań' - poolHologramText: '§eNowe zadanie jest dostępne!' - mobsProgression: '§7§l{0}: §r§e{1}/{2}' - entityType: '§eTyp jednostki: {0}' - entityTypeAny: '§eDowolny obiekt/jednostka' - enabled: Włączone + right: Prawy przycisk myszy + shift-left: Shift i kliknięcie lewym przyciskiem myszki + shift-right: Shift i kliknięcie prawym przyciskiem myszki + comparison: + different: inne niż {number} + equals: równe {number} + greater: ściśle więcej niż {number} + greaterOrEquals: więcej niż {number} + less: ściśle mniej niż {number} + lessOrEquals: mniej niż {number} disabled: Wyłączone - unknown: nieznany + enabled: Włączone + entityType: '§eTyp jednostki: {entity_type}' + entityTypeAny: '§eDowolny obiekt/jednostka' + format: + prefix: '§6<§e§lZadania§r§6> §r' + hologramText: '§8§lNPC zadań' + 'no': 'Nie' notSet: '§cnie ustawione' - unused: '§2§lNieużywane' - used: '§a§lUżywane' - remove: '§7Kliknij środkowy przycisk myszy aby usunąć' + or: lub + poolHologramText: '§eNowe zadanie jest dostępne!' + questItemLore: '§e§oPrzedmiot zadań' removeRaw: Usuń + requirement: + class: '§bKlasa(y) wymagane' + combatLevel: '§bWymagany poziom walki' + equipment: '§eWymagane Wyposażenie' + experienceLevel: '§bWymagane poziomy doświadczenia' + faction: '§bFrakcja(e) wymagana(e)' + jobLevel: '§bWymagany poziom pracy' + logicalOr: '§dLogiczne LUB (wymagania)' + mcMMOSkillLevel: '§dWymagany poziom umiejętności' + money: '§dWymagane pieniądze' + permissions: '§3Uprawnienie(a) jest/są wymagane' + placeholder: '§bWymagana jest wartość Placeholdera' + quest: '§aZadanie jest wymagane' + region: '§dRegion jest wymagany' + scoreboard: '§dWymagany wynik' + skillAPILevel: '§bWymagany poziom SkillAPI' reset: Reset - or: lub - amount: '§eIlość: {0}' - items: przedmioty - expPoints: punkty doświadczenia + stageType: + Bucket: Wypełnij wiadro + Craft: Wytwórz przedmiot + Enchant: Zaklinaj przedmioty + Fish: Złap ryby + Melt: Elementy stopu + breedAnimals: Rozmnóż zwierzęta + chat: Napisz na czacie + dealDamage: Zadaj obrażenia + die: Giń + eatDrink: Jedz lub napój + interact: Interakcja z blokiem + items: Przynieś przedmioty z powrotem + location: Znajdź lokalizację + mine: Zniszcz bloki + mobs: Zabij potwory + npc: Znajdź NPC + placeBlocks: Postaw bloki + playTime: Czas w grze + region: Znajdź region + tameAnimals: Oswój zwierzęta + ticks: '{ticks} ticków' + time: + days: '{days_amount} dni' + hours: '{hours_amount} godzin' + lessThanAMinute: mniej niż minutę + minutes: '{minutes_amount} minut' + weeks: '{weeks_amount} tygodni' + unknown: nieznany 'yes': 'Tak' - 'no': 'Nie' - and: i +msg: + bringBackObjects: Przynieś mnie z powrotem {items}. + command: + adminModeEntered: '§aWłączyłeś/aś tryb administratora.' + adminModeLeft: '§aWyłączyłeś/aś tryb administratora.' + backupCreated: '§6Pomyślnie utworzyłeś kopie zapasowe wszystkich zadań i informacji o graczach.' + backupPlayersFailed: '§cTworzenie kopii zapasowej dla wszystkich graczy nie powiodło się.' + backupQuestsFailed: '§cTworzenie kopii zapasowej dla wszystkich zadań nie powiodło się.' + cancelQuest: '§6Anulowałeś zadanie {quest}.' + cancelQuestUnavailable: '§cZadanie {quest} nie może zostać anulowane.' + checkpoint: + noCheckpoint: '§cNie znaleziono punktu kontrolnego dla zadania {quest}.' + questNotStarted: '§cNie wykonujesz tego zadania.' + downloadTranslations: + downloaded: '§aJęzyk {lang} został pobrany! §7Musisz teraz edytować plik "/plugins/BeautyQuests/config.yml" aby zmienić wartość §ominecraftTranslationsFile§7 na {lang}, a następnie zrestartować serwer.' + exists: '§cPlik {file_name} już istnieje. Dołącz "-overwrite" do swojej komendy aby ją nadpisać. (/quests downloadTranslations <lang> -overwrite)' + notFound: '§cJęzyk {lang} nie został znaleziony dla wersji {version}. .' + syntax: '§cMusisz określić język do pobrania. Przykład: "/quests downloadTranslations en_US".' + help: + adminMode: '§6/{label} adminMode: §ePrzełącz tryb administratora. (Przydatne do wyświetlania małych wiadomości dziennika.)' + create: '§6/{label} create: §eUtwórz zadanie.' + downloadTranslations: '§6/{label} downloadTranslations <język>: §ePobiera plik z tłumaczeniem vanilla' + edit: '§6/{label} edit: §eEdytuj zadanie.' + finishAll: '§6/{label} finishAll <player>: §eZakończ wszystkie zadania gracza.' + header: '§6§lBeautyQuests - Pomoc' + list: '§6/{label} list: §eZobacz listę zadań. (Tylko dla obsługiwanych wersji.)' + reload: '§6/{label} reload: §eZapisz i odśwież wszystkie konfiguracje i pliki. (§cprzestarzałe§e)' + remove: '§6/{label} remove <id>: §eUsuń zadanie z podanym id lub kliknij na NPC jeśli nie zdefiniowano.' + resetPlayer: '§6/{label} resetPlayer <gracz>: §eUsuń wszystkie informacje o graczu.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <gracz> [id]: §eUsuń informacje o zadaniu danego gracza.' + save: '§6/{label} save: §eZapisz ręcznie plugin (postęp/zmiany).' + seePlayer: '§6/{label} SeePlayer <gracz>: §eWyświetl informacje o graczu.' + setFirework: '§6/{label} setFirework: §eEdytuj domyślny końcowy efekt fajerwerki.' + setItem: '§6/{label} setItem <talk|launch>: §eZapisz hologram.' + setStage: '§6/{label} setStage <gracz> <id> [nowa gałąź] [nowy etap]: §ePomiń bieżący etap/uruchom gałąź/ustaw etap dla gałęzi.' + start: '§6/{label} start <gracz> [id]: §eWymuś rozpoczęcie zadania.' + startDialog: '§7/{label} startDialog <player> <quest id>: §eUruchamia oczekujące okno dialogowe dla etapu NPC lub startowego okna dialogowego dla zadania.' + version: '§6/{label} version: §eZobacz aktualną wersję pluginu.' + invalidCommand: + simple: '§cTa komenda nie istnieje, napisz §ehelp§c.' + itemChanged: '§aElement został edytowany. Zmiany będą dostępne po ponownym uruchomieniu.' + itemRemoved: '§aHologram został usunięty.' + leaveAll: '§aWymusiłeś/aś koniec {success} zadań. Błędy: {errors}' + removed: '§aZadanie {quest_name} zostało pomyślnie usunięte.' + resetPlayer: + player: '§6Wszystkie informacje o twoich zadaniach {quest_amount} zostały usunięte przez {deleter_name}.' + remover: '§6{quest_amount} informacja(e) o zadaniu (oraz {quest_pool}puli) {player} zostało usunięte.' + resetPlayerPool: + full: '§aZresetowałeś dane puli {pool} {player}.' + timer: '§aZresetowałeś {pool} zegar puli {player}.' + resetPlayerQuest: + player: '§6Wszystkie informacje o zadaniu {quest} zostały usunięte przez {deleter_name}.' + remover: '§6{player} informacja(e/i) o zadaniu {quest} została(y) usunięta(e).' + resetQuest: '§6Usunięto dane zadania dla {player_amount} graczy.' + scoreboard: + hidden: '§6Tablica wyników gracza {player_name} została ukryta.' + lineInexistant: '§cWiersz {line_id} nie istnieje.' + lineRemoved: '§6Pomyślnie usunąłeś/aś wiersz {line_id}.' + lineReset: '§6Pomyślnie zresetowałeś/aś wiersz {line_id}.' + lineSet: '§6Pomyślnie edytowałeś/aś linię {line_id}.' + own: + hidden: '§6Twoja tablica wyników jest teraz ukryta.' + shown: '§6Twoja tablica wyników pojawiła się ponownie.' + resetAll: '§6Pomyślnie zresetowałeś/aś tablicę wyników gracza {player_name}.' + shown: '§6Tablica wyników gracza {player_name} została pokazana.' + setStage: + branchDoesntExist: '§cGałąź z id {branch_id} nie istnieje' + doesntExist: '§cEtap z id {stage_id} nie istnieje' + next: '§aEtap został pominięty.' + nextUnavailable: '§cOpcja pominięcia nie jest dostępna kiedy gracz jest na końcu gałęzi.' + set: '§aEtap {stage_id} został uruchomiony.' + startDialog: + alreadyIn: '§cGracz jest już w trakcie dialogu.' + impossible: '§cNie można teraz uruchomić dialogu.' + noDialog: '§cGracz nie ma oczekującego dialogu.' + success: '§aRozpoczęto dialog dla gracza {player} w misji {quest}!' + startPlayerPool: + error: Nie udało się uruchomić puli {pool} dla {player}. + success: 'Rozpoczęto pulę od {pool} do {player}. Wynik: {result}' + startQuest: '§6Wymusiłeś/aś rozpoczęcie zadania {quest} (UUID gracza: {player}).' + startQuestNoRequirements: '§cGracz nie spełnia wymagań dla zadania {quest}... Dołącz "-overrideRequirements" na końcu twojej komendy aby ominąć sprawdzanie wymagań.' + dialogs: + skipped: '§8Dialog pominięty.' + tooFar: '§7§oJesteś za daleko od {npc_name}...' + editor: + advancedSpawnersMob: 'Napisz nazwę niestandardowego moba spawnera, aby zabić:' + already: '§cJesteś już w edytorze.' + availableElements: 'Dostępne elementy: §e{available_elements}' + blockAmount: '§aNapisz liczbę bloków:' + blockData: '§aNapisz dane bloków (dostępne dane bloków: {available_datas}):' + blockName: '§aNapisz nazwę bloku:' + blockTag: '§aWpisz tag bloku (dostępne tagi: §7{available_tags}§a):' + chat: '§6Jesteś obecnie w trybie edytora. Napisz "/quests exitEditor", aby wymusić opuszczenie edytora. (Wysoko niezalecane, rozważ użycie poleceń, takich jak "close" lub "cancel", aby wrócić do poprzedniego ekwipunku)' + color: 'Wprowadź kolor w formacie szesnastkowym (#XXXXX) lub formatu RGB (RED GRE BLU).' + colorNamed: Wprowadź nazwę koloru. + comparisonTypeDefault: '§aWybierz typ porównania, który chcesz wśród {available}. Domyślne porównanie to: §e§l{default}§r§a. Wpisz §onull§r§a aby go użyć.' + dialog: + cleared: '§aUsunięto {amount} wiadomość(ci).' + edited: '§aWiadomość "§7{msg}§a" została edytowana.' + help: + addSound: '§6addSound <id> <dźwięk>: §eDodaj dźwięk do wiadomości.' + clear: '§6clear: §eUsuń wszystkie wiadomości.' + close: '§6close: §ePotwierdź wszystkie wiadomości.' + edit: '§7edytuj <id> <message>: §eEdytuj wiadomość.' + header: '§6§lBeautyQuests - Pomoc do edytora okna dialogowego' + list: '§6list: §eWyświetl wszystkie wiadomości.' + nothing: '§6noSender <wiadomość>: §eDodaj wiadomość bez nadawcy.' + nothingInsert: '§6nothingInsert <id> <wiadomość>: §eWstaw wiadomość bez żadnego prefiksu.' + npc: '§6npc <wiadomość>: §eDodaj wiadomość wysłaną przez NPC.' + npcInsert: '§6npcInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez NPC.' + npcName: '§7npcName [niestandardowa nazwa NPC]: §eUstaw (lub zresetuj do domyślnej) niestandardową nazwę NPC w oknie dialogowym' + player: '§6player <wiadomość>: §eDodaj wiadomość wysłaną przez gracza.' + playerInsert: '§6playerInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez gracza.' + remove: '§6remove <id>: §eUsuń wiadomość.' + setTime: '§6setTime <id> <czas>: §eUstaw czas (w tickach) zanim następna automatyczna wiadomość zostanie wysłana.' + skippable: '§7pomijalne [true|false]: §eUstaw jeśli okno dialogowe może być pominięte lub nie' + messageRemoved: '§aWiadomość "§7{msg}§a" usunięta.' + noSender: '§aWiadomość "§7{msg}§a" została dodana bez nadawcy.' + npc: '§aWiadomość "§7{msg}§a" została dodana dla NPC.' + npcName: + set: '§aWłasna nazwa NPC ustawiona na §7{new_name}§a (był §7{old_name}§a)' + unset: '§aWłasna nazwa NPC została przywrócona do domyślnej (była §7{old_name}§a)' + player: '§aWiadomość "§7{msg}§a" została dodana dla gracza.' + skippable: + set: '§aPominięty status okna dialogowego jest ustawiony na §7{new_state}§a (był §7{old_state}§a)' + unset: '§aPominięty status okna dialogowego jest przywrócony do domyślnego (był §7{old_state}§a)' + soundAdded: '§aDźwięk "§7{sound}§a" dodał do wiadomości "§7{msg}§a".' + syntaxRemove: '§cPoprawna składnia: remove <id>' + timeRemoved: '§aCzas został usunięty dla wiadomości {msg}.' + timeSet: '§aCzas został edytowany dla wiadomości {msg}: teraz {time} ticków.' + enter: + list: '§c⚠ §7Otworzyłeś edytor "listy". Użyj "add", aby dodać linie. Aby uzyskać pomoc, wpisz "help" (bez znaku ukośnika). §e§lWpisz "close", aby opuścić edytor.' + subtitle: '§7Napisz "/quests exitEditor" aby wymusić opuszczenie edytora.' + title: '§6~ Tryb edytora ~' + firework: + edited: Edytowałeś fajerwerk misji! + invalid: Ten przedmiot nie jest poprawnym fajerwerkiem. + invalidHand: Musisz trzymać fajerwerk w swojej głównej ręce. + removed: Usunięto fajerwerk misji! + goToLocation: '§aIdź do pożądanej lokalizacji dla tego etapu.' + invalidColor: Wprowadzony kolor jest nieprawidłowy. Musi być szesnastkowy lub RGB. + invalidPattern: '§cNieprawidłowy wzór regex §4{input}§c.' + itemCreator: + invalidBlockType: '§cNieprawidłowy typ bloku.' + invalidItemType: '§cNieprawidłowy typ przedmiotu. (Przedmiot nie może być blokiem.)' + itemAmount: '§aNapisz liczbę przedmiotow:' + itemLore: '§aModyfikuj lore przedmiotu: (Napisz "help", aby wyświetlić pomoc.)' + itemName: '§aNapisz nazwę przedmiotu:' + itemType: '§aNapisz nazwę pożądanego typu przedmiotu:' + unknownBlockType: '§cNieznany typ bloku.' + unknownItemType: '§cNieznany typ przedmiotu.' + mythicmobs: + disabled: '§cMythicMob jest wyłączony.' + isntMythicMob: '§cTen Mityczny Mob nie istnieje.' + list: '§aLista wszystkich Mitycznych mobów:' + noSuchElement: '§cNie ma takiego elementu. Dozwolone elementy to: §e{available_elements}' + npc: + choseStarter: '§aWybierz NPC który rozpoczyna zadanie.' + enter: '§aKliknij na NPC, lub napisz "cancel".' + notStarter: '§cTen NPC nie rozpoczyna misji.' + pool: + hologramText: Napisz niestandardowy tekst hologramu dla tej puli (lub "null" jeśli chcesz domyślnie). + maxQuests: Wpisz maksymalną ilość zadań uruchamianych z tej puli. + questsPerLaunch: Napisz liczbę zadań, gdy gracze klikną na NPC. + timeMsg: 'Napisz czas, zanim gracze mogą zająć nowe zadanie. (domyślna jednostka: dni)' + scoreboardObjectiveNotFound: '§cNieznany cel tablicy wyników.' + selectWantedBlock: '§aKliknij patykiem na pożądany blok dla etapu.' + stage: + location: + typeWorldPattern: '§aNapisz regex dla nazw świata:' + text: + argNotSupported: '§cArgument {arg} nie jest obsługiwany.' + chooseJobRequired: '§aNapisz nazwę wymaganej pracy:' + chooseLvlRequired: '§aNapisz wymaganą ilość poziomów:' + chooseMoneyRequired: '§aNapisz wymaganą ilość pieniędzy:' + chooseObjectiveRequired: '§aNapisz nazwę celu.' + chooseObjectiveTargetScore: '§aNapisz docelowy wynik dla celu.' + choosePermissionMessage: '§aMożesz wybrać wiadomość o odrzuceniu jeśli gracz nie ma wymaganego uprawnienia (aby pominąć ten krok, napisz "null")' + choosePermissionRequired: '§aNapisz wymagane uprawnienia, aby rozpocząć zadanie:' + choosePlaceholderRequired: + identifier: '§aWpisz nazwę wymaganego placeholdera bez procentu znaków:' + value: '§aNapisz wymaganą wartość dla tego placeholdera §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aNapisz nazwę wymaganego regionu (musisz być w tym samym świecie).' + chooseSkillRequired: '§aNapisz nazwę wymaganej umiejętności:' + reward: + money: '§aNapisz ilość otrzymanych pieniędzy:' + permissionName: '§aNapisz nazwę uprawnień.' + permissionWorld: '§aNapisz świat, w którym uprawnienia będą edytowane, lub "null" jeśli chcesz żeby były globalnie.' + random: + max: '§aZapisz maksymalną ilość nagród przyznanych graczowi (włącznie).' + min: '§aZapisz minimalną ilość nagród przyznanych graczowi (włącznie).' + wait: '§aNapisz ilość ticków do poczekania: (1 sekunda = 20 ticków w grze)' + textList: + added: '§aTekst "§7{msg}§a" dodany.' + help: + add: '§6add <wiadomość>: §eDodaj tekst.' + close: '§6close: §ePotwierdź dodane teksty.' + header: '§6§lBeautyQuests — Pomoc edytora list' + list: '§6list: §eZobacz wszystkie dodane teksty.' + remove: '§6remove <id>: §eUsuń tekst.' + removed: '§aTekst "§7{msg}§a" usunięty.' + syntax: '§cPoprawna składnia: ' + title: + fadeIn: Wpisz czas "fade-in" w tickach (20 ticków = 1 sekunda). + fadeOut: Napisz czas "fade-out" w tickach (20 ticków = 1 sekunda). + stay: Wpisz czas "stay" w tickach (20 ticków = 1 sekunda). + subtitle: Napisz podtytuł teksu (lub wpisz "null" aby pozostawić puste). + title: Napisz tytuł teksu (lub wpisz "null" aby pozostawić puste). + typeBucketAmount: '§aNapisz liczbę wiader do napełnienia:' + typeDamageAmount: 'Zapisz ilość obrażeń gracza:' + typeGameTicks: '§aNapisz wymaganą ilość ticków gry:' + typeLocationRadius: '§aNapisz wymaganą odległość od lokalizacji:' + errorOccurred: '§cWystąpił błąd, skontaktuj się z administratorem! §4§lKod błędu: {error}' + experience: + edited: '§aZmieniłeś zdobywane doświadczenie z {old_xp_amount} na {xp_amount} punktów.' + indexOutOfBounds: '§cLiczba {index} jest poza granicami! Musi być pomiędzy {min} a {max}.' + invalidBlockData: '§cBlokada danych {block_data} jest nieprawidłowa lub niezgodna z blokiem {block_material}.' + invalidBlockTag: '§cNiedostępny tag bloku {block_tag}.' + inventoryFull: '§cTwój ekwipunek jest pełny, przedmiot został wyrzucony na podłogę.' + moveToTeleportPoint: '§aUdaj się do poszukiwanej lokalizacji.' + npcDoesntExist: '§cNPC z id {npc_id} nie istnieje' + number: + invalid: '§c{input} nie jest prawidłową liczbą.' + negative: '§cMusisz wprowadzić liczbę dodatnią!' + notInBounds: '§cWartość, którą wpiszesz musi mieścić się w zakresie od {min} do {max}' + zero: '§cMusisz podać liczbę inną od 0!' + pools: + allCompleted: '§7Wykonałeś/aś wszystkie zadania!' + maxQuests: '§cNie możesz mieć aktywnych więcej niż {pool_max_quests} zadań jednocześnie...' + noAvailable: '§7Nie ma więcej dostępnych zadań...' + noTime: '§cMusisz poczekać {time_left} przed wykonaniem kolejnego zadania.' + quest: + alreadyStarted: '§cJuż rozpocząłeś te zadanie!' + cancelling: '§cAnulowano proces tworzenia misji.' + createCancelled: '§cTworzenie lub modyfikowanie zostało anulowane przez inny plugin!' + created: '§aGraulacje! Stworzyłeś zadanie §e{quest}§a które zawiera {quest_branches} wielokrotnych wyborów!' + editCancelling: '§cAnulowano proces edytowania misji.' + edited: '§aGratulacje! Zmodyfikowałeś zadanie§e{quest}§a które zawiera {quest_branches} wielokrotnych wyborów!' + finished: + base: '§aGratulacje! Ukończyłeś/aś zadanie §e{quest_name}§a!' + obtain: '§aOtrzymujesz {rewards}!' + invalidID: '§cZadanie o id {quest_id} nie istnieje' + invalidPoolID: '§cPula {pool_id} nie istnieje.' + notStarted: '§cObecnie nie wykonujesz tego zadania.' + started: '§aRozpocząłeś zadanie §r§e{quest_name}§o§6!' + questItem: + craft: '§cNie możesz użyć przedmiotu misji do stworzenia innych przedmiotów!' + drop: '§cNie możesz wyrzucić przedmiotu misji!' + eat: '§cNie możesz zjeść przedmiotu misji!' + quests: + checkpoint: '§7Osiągnięto punkt kontrolny misji!' + failed: '§cNie udało Ci się wykonać zadania {quest_name}...' + maxLaunched: '§cNie możesz mieć aktywnych więcej niż {quests_max_amount} zadań jednocześnie...' + updated: '§7Zadanie §e{quest_name}§7 zostało zaktualizowane.' + regionDoesntExists: '§cRegion o takie nazwie nie istnieje (musisz być w tym samym świecie).' + requirements: + combatLevel: '§cMusisz mieć {long_level} poziom walki!' + job: '§cMusisz mieć {long_level} poziom Twojej pracy §e{job_name}!' + level: '§cMusisz mieć {long_level} poziom!' + money: '§cMusisz posiadać {money}!' + quest: '§cMusisz ukończyć zadanie §e{quest_name}§c!' + skill: '§cMusisz mieć {long_level} poziom umiejętności §e{skill_name}!' + waitTime: '§cMusisz poczekać {time_left} zanim będziesz mógł ponownie uruchomić to zadanie!' + restartServer: '§7Uruchom ponownie serwer, aby zobaczyć zmiany.' + selectNPCToKill: '§aWybierz NPC do zabicia.' + stageMobs: + listMobs: '§aMusisz zabić {mobs}' + typeCancel: '§aNapisz "cancel" aby wrócić do ostatniego tekstu.' + versionRequired: 'Wymagana wersja: §l{version}' + writeChatMessage: '§aNapisz wymaganą wiadomość: (Dodaj "{SLASH}" na początku wiadomości jeśli chcesz wymagać komendy)' + writeCommand: '§aNapisz żądane polecenie (Napisz polecenie bez "/", a "{PLAYER}" zostanie zastąpione nazwą wykonawcy)' + writeCommandDelay: '§aNapisz żądane opóźnienie komendy, w tickach.' + writeConfirmMessage: '§aNapisz wiadomość potwierdzającą w momencie kiedy gracz rozpoczyna zadanie: (Napisz "null" jeśli chcesz użyć domyślnej wiadomości)' + writeDescriptionText: '§aNapisz tekst, który opisuje cel tego etapu:' + writeEndMsg: '§aNapisz wiadomość, która zostanie wysłana na koniec zadania, "null" jeśli chcesz domyślną lub "none" jeśli nie chcesz. Możesz użyć "{rewards}", które zostanie zastąpione otrzymanymi nagrodami.' + writeEndSound: '§aWpisz nazwę dźwięku, który usłyszy gracz na końcu zadania, wpisz "null" aby pozostawić domyślny dźwięk lub "none", aby pozostawić puste:' + writeHologramText: '§aNapisz tekst hologramu: (Napisz "none" jeśli nie chcesz hologramu, a "null" jeśli chcesz domyślną wiadomość)' + writeMessage: '§aNapisz wiadomość, która zostanie wysłana graczowi' + writeMobAmount: '§aNapisz liczbę potworów do zabicia:' + writeMobName: '§aNapisz niestandardową nazwę potwora do zabicia:' + writeNPCText: '§aNapisz wiadomość, która została powiedziana graczowi przez NPC: (Wpisz "help" żeby otrzymać pomoc.)' + writeNpcName: '§aNapisz nazwę NPC' + writeNpcSkinName: '§aNapisz nazwę skina NPC' + writeQuestDescription: '§aNapisz opis zadania, który zostanie wyświetlony w GUI zadań gracza.' + writeQuestMaterial: '§aNapisz typ przedmiotu zadania.' + writeQuestName: '§aNapisz nazwę zadania' + writeQuestTimer: '§aNapisz wymagany czas (w minutach) przed ponownym uruchomieniem zadania: (Napisz "null" jeśli chcesz ustawić domyślną wartość)' + writeRegionName: '§aNapisz nazwę regionu wymaganego dla tego etapu:' + writeStageText: '§aNapisz tekst, który zostanie wysłany do gracza na początku tego etapu:' + writeStartMessage: '§aNapisz wiadomość która będzie się wyświetlać na początku zadania, wpisz "null" aby pozostawić domyślną, wpisz "none" aby zostawić puste:' + writeXPGain: '§aNapisz liczbę punktów doświadczenia jaką otrzyma gracz: (Poprzednia wartość: {xp_amount})' +scoreboard: + asyncEnd: '§ex' + name: '§7§lZadania' + noLaunched: '§cBrak zadań w toku.' + noLaunchedDescription: '§c§lŁadowanie' + noLaunchedName: '§c§lŁadowanie' + stage: + breed: '§eRozmnóż §6{mobs}' + bucket: '§eUzupełnij §6{buckets}' + chat: '§eNapisz §6{text}' + craft: '§eStwórz §6{items}' + dealDamage: + any: '§cZadaj {damage_remaining} obrażeń' + mobs: '§cZadaj {damage_remaining} obrażeń {target_mobs}' + die: '§cDie' + eatDrink: '§eZużyj §7{items}' + enchant: '§eZaklinaj §6{items}' + fish: '§eZłów §6{items}' + interact: '§eKliknij na blok na §6{x}' + interactMaterial: '§eKliknij na blok §6{block}' + items: '§ePrzynieś przedmioty do §6{dialog_npc_name}§e:' + location: '§eIdź do §7{target_x}§e, §7{target_y}§e, §7{target_z}§e w §6{target_world}' + mine: '§eWykop {blocks}' + mobs: '§eZabij §6{mobs}' + npc: '§ePorozmawiaj z NPC §6{dialog_npc_name}' + placeBlocks: '§ePostaw {blocks}' + playTimeFormatted: '§eGraj §7{time_remaining_human}' + region: '§eZnajdź region §6{region_id}' + tame: '§eOswój §6{mobs}' + textBetwteenBranch: '§e lub' diff --git a/core/src/main/resources/locales/pt_BR.yml b/core/src/main/resources/locales/pt_BR.yml index 3ed7dca0..c9b246f3 100644 --- a/core/src/main/resources/locales/pt_BR.yml +++ b/core/src/main/resources/locales/pt_BR.yml @@ -1,834 +1,796 @@ --- -msg: - quest: - finished: - base: '§aParabéns! Você terminou a missão §e{0}§a!' - obtain: '§aVocê recebeu {0}!' - started: '§aVocê iniciou a missão §r§e{0}§o§6!' - created: '§aParabéns! Você criou a missão §e{0}§a que inclui {1} ramo(s)!' - edited: '§aParabéns! Você editou a missão §e{0}§a que agora inclui {1} ramo(s)!' - createCancelled: '§cA criação ou edição foi cancelada por outro plugin!' - cancelling: '§cProcesso de criação da missão cancelado.' - editCancelling: '§cProcesso de edição da missão cancelado.' - invalidID: '§cA missão com o ID {0} não existe.' - invalidPoolID: '§cO grupo {0} não existe.' - alreadyStarted: '§cVocê já iniciou a missão!' - notStarted: '§cVocê não está fazendo esta missão no momento.' - quests: - maxLaunched: '§cVocê não pode ter mais que {0} missão(ões) ao mesmo tempo...' - nopStep: '§cEsta missão não tem nenhuma etapa.' - updated: '§7Missão §e{0}§7 atualizada.' - checkpoint: '§7Checkpoint da missão alcançado!' - failed: '§cVocê falhou na missão {0}...' - pools: - noTime: '§cVocê deve esperar {0} antes de fazer outra missão.' - allCompleted: '§7Você completou todas as missões!' - noAvailable: '§7Não há mais missões disponíveis...' - maxQuests: '§cVocê não pode ter mais que {0} missão(ões) ao mesmo tempo...' - questItem: - drop: '§cVocê não pode dropar um item da missão!' - craft: '§cVocê não pode usar um item da missão para craftar!' - eat: '§cVocê não pode comer um item de missão!' - stageMobs: - noMobs: '§cEste estágio não exige matar nenhum mob.' - listMobs: '§aVocê deve matar {0}.' - writeNPCText: '§aEscreva o diálogo que será dito ao jogador pelo NPC: (Escreva "help" para receber ajuda).' - writeRegionName: '§aEscreva o nome da região necessária para a etapa:' - writeXPGain: '§aEscreva a quantidade de pontos de experiência que o jogador irá receber: (Último valor: {0})' - writeMobAmount: '§aEscreva a quantidade de mobs para matar:' - writeMobName: '§aEscreva o nome personalizado do mob para matar:' - writeChatMessage: '§aEscreva a mensagem obrigatória: (Adicionar "{SLASH}" no início se quiser um comando).' - writeMessage: '§aEscreva a mensagem que será enviada ao jogador' - writeStartMessage: '§aEscreva a mensagem que será enviada no início da missão, "null" se você quiser o padrão ou "none" se você não quiser nenhum:' - writeEndMsg: '§aEscreva a mensagem que será enviada no final da missão, "null" se você quiser o padrão ou "none" se você não quiser nenhum. Você pode usar "{0}", que será substituído pelas recompensas recebidas.' - writeEndSound: '§aEscreva o nome do som que será tocado ao jogador no final da missão, "null" se você quiser o padrão ou "none" se você não quiser nenhum:' - writeDescriptionText: '§aEscreva o texto que descreva o objetivo do estágio:' - writeStageText: '§aEscreva o texto que será enviado ao jogador no início da etapa:' - moveToTeleportPoint: '§aVá para o local de teletransporte desejado.' - writeNpcName: '§aEscreva o nome do NPC:' - writeNpcSkinName: '§aEscreva o nome da skin do NPC:' - writeQuestName: '§aEscreva o nome da sua missão:' - writeCommand: '§aEscreva o comando desejado: (O comando não inclui a barra "/" e suporta o espaço reservado "{PLAYER}". Ele será substituído pelo nome de quem executou o comando.)' - writeHologramText: '§aEscreva o texto do holograma: (Escreva "none" se você não quiser um holograma e "null" se você quiser o texto padrão.)' - writeQuestTimer: '§aEscreva o tempo necessário (em minutos) antes de poder reiniciar a missão: (Escreva "null" se você quiser o temporizador padrão).' - writeConfirmMessage: '§aEscreva a mensagem de confirmação que mostra quando um jogador está prestes a iniciar a missão: (Escreva "null" se você quiser a mensagem padrão).' - writeQuestDescription: '§aEscreva a descrição da missão, mostrada no menu da missão do jogador.' - writeQuestMaterial: '§aEscreva o material do item da missão.' - requirements: - quest: '§cVocê precisa ter concluído a missão §e{0}§c!' - level: '§cSeu nível deve ser {0}!' - job: '§cSeu nível de trabalho §e{1}§c deve ser {0}!' - skill: '§cSeu nível para a habilidade §e{1}§c deve ser {0}!' - combatLevel: '§cSeu nível de combate deve ser {0}!' - money: '§cVocê deve ter {0}!' - waitTime: '§cVocê deve esperar {0} antes de reiniciar esta missão!' - experience: - edited: '§aVocê mudou a experiência ganha de {0} para {1} pontos.' - selectNPCToKill: '§aSelecione o NPC para matar.' - npc: - remove: '§aNPC excluído.' - talk: '§aVá e fale com o NPC chamado §e{0}§a.' - regionDoesntExists: '§cEsta região não existe. (Você precisa estar no mesmo mundo).' - npcDoesntExist: '§cO NPC com o id {0} não existe.' - objectDoesntExist: '§cO item especificado com o id {0} não existe.' - number: - negative: '§cVocê deve digitar um número positivo!' - zero: '§cVocê deve inserir um número diferente de 0!' - invalid: '§c{0} não é um número válido.' - notInBounds: '§cSeu número deve estar entre {0} e {1}.' - errorOccurred: '§cOcorreu um erro, entre em contato com um administrador! §4§lCódigo de erro: {0}' - commandsDisabled: '§cAtualmente, você não tem permissão para executar comandos!' - indexOutOfBounds: '§cO número {0} está fora dos limites! Ele deve estar entre {1} e {2}.' - invalidBlockData: '§cO blockdata {0} é inválido ou incompatível com o bloco {1}.' - invalidBlockTag: '§cTag de bloqueio {0} indisponível.' - bringBackObjects: Traga-me de volta {0}. - inventoryFull: '§cSeu inventário está cheio, o item foi dropado no chão.' - playerNeverConnected: '§cNão foi possível encontrar informações sobre o jogador {0}.' - playerNotOnline: '§cO jogador {0} está offline.' - playerDataNotFound: '§cDados de jogador {0} não encontrado.' - versionRequired: 'Versão necessária: §l{0}' - restartServer: '§7Reinicie seu servidor para ver as modificações.' - dialogs: - skipped: '§8§oDiálogo ignorado.' - tooFar: '§5§oVocê está muito longe de {0}...' - command: - downloadTranslations: - syntax: '§cVocê deve especificar um idioma para baixar. Exemplo: "/quests downloadTranslations pt_BR".' - notFound: '§cIdioma {0} não foi encontrado para a versão {1}.' - exists: '§cO arquivo {0} já existe. Acrescente "-overwrite" ao seu comando para substituí-lo. (/quests downloadTranslations <idioma> -overwrite)' - downloaded: '§aIdioma {0} foi baixado! §7Você precisa editar o arquivo "/plugins/BeautyQuests/config.yml" para alterar o valor de §ominecraftTranslationsFile§7 para {0}, então reinicie o servidor.' - checkpoint: - noCheckpoint: '§cNenhum checkpoint encontrado para a missão {0}.' - questNotStarted: '§cVocê não está fazendo esta missão.' - setStage: - branchDoesntExist: '§cO ramo com o id {0} não existe.' - doesntExist: '§cO estágio com o id {0} não existe.' - next: '§aO estágio foi ignorado.' - nextUnavailable: '§cA opção "Pular" não está disponível quando o jogador está no final de um ramo.' - set: '§aEstágio {0} iniciado.' - startDialog: - impossible: '§cNão é possível iniciar o diálogo agora.' - noDialog: '§cO jogador não tem nenhum diálogo pendente.' - alreadyIn: '§cO jogador já está participando de um diálogo.' - success: '§aDiálogo iniciado para o jogador {0} na missão {1}!' - playerNeeded: '§cVocê deve ser um jogador para executar este comando!' - incorrectSyntax: '§cSintaxe incorreta.' - noPermission: '§cVocê não tem permissão suficiente para executar este comando! (Requerido: {0})' - invalidCommand: - quests: '§cEste comando não existe, escreva §e/quests help§c.' - simple: '§cEste comando não existe, escreva §ehelp§c.' - needItem: '§cVocê deve segurar um item em sua mão principal!' - itemChanged: '§aO item foi editado. As mudanças terão efeito após a reinicialização.' - itemRemoved: '§aO item do holograma foi removido.' - removed: '§aA missão {0} foi removida com sucesso.' - leaveAll: '§aVocê forçou o fim de {0} missão(ões). Erros: {1}' - resetPlayer: - player: '§6Todas as informações de sua(s) {0} missão(ões) foi/foram excluídas por {1}.' - remover: '§6Informação(ões) da missão {0} (e grupos de {2}) de {1} foi/foram excluídos.' - resetPlayerQuest: - player: '§6Todas as informações sobre a missão {0} foram excluídas por {1}.' - remover: '§6{0} informações da(s) missão(ões) de {1} foi/foram apagada(s).' - resetQuest: '§6Dados removidos da missão para {0} jogadores.' - startQuest: '§6Você forçou o início da missão {0} (Player UUID: {1}).' - startQuestNoRequirements: '§cO jogador não atende aos requisitos para a missão {0}... Acrescente "-overrideRequirements" no final do seu comando para ignorar a verificação de requisitos.' - cancelQuest: '§6Você cancelou a missão {0}.' - cancelQuestUnavailable: '§cA missão {0} não pode ser cancelada.' - backupCreated: '§6Você criou backups de todas as missões e informações de jogadores com sucesso.' - backupPlayersFailed: '§cFalha ao criar um backup de todas as informações dos jogadores.' - backupQuestsFailed: '§cFalha ao criar um backup de todas as missões.' - adminModeEntered: '§aVocê entrou no Modo Admin.' - adminModeLeft: '§aVocê saiu do Modo Admin.' - resetPlayerPool: - timer: '§aVocê resetou o temporizador do grupo {0} de {1}.' - full: '§aVocê resetou os dados do grupo {0} de {1}.' - scoreboard: - lineSet: '§6Você editou a linha {0} com sucesso.' - lineReset: '§6Você resetou a linha {0} com sucesso.' - lineRemoved: '§6Você removeu a linha {0} com sucesso.' - lineInexistant: '§cA linha {0} não existe.' - resetAll: '§6Você redefiniu o scoreboard do jogador {0} com sucesso.' - hidden: '§6O scoreboard do jogador {0} foi ocultado.' - shown: '§6O scoreboard do jogador {0} foi exibido.' - own: - hidden: '§6Seu scoreboard agora está oculto.' - shown: '§6Seu soreboard está visível novamente.' - help: - header: '§6§lBeautyQuests — Ajuda' - create: '§6/{0} create: §eCriar uma missão.' - edit: '§6/{0} edit: §eEdita uma missão.' - remove: '§6/{0} remove <id>: §eExclua uma missão com um id específico ou clique no NPC quando não for definido.' - finishAll: '§6/{0} finishAll <player>: §eTermina todas as missões de um jogador.' - setStage: '§6/{0} setStage <jogador> <id> [novo ramo] [novo estágio]: §ePula o estágio atual/inicia o ramo/define um estágio para um ramo.' - startDialog: '§6/{0} startDialog <jogador> <id da missão>: §eInicia a caixa de diálogo pendente para um estágio de NPC ou a caixa de diálogo inicial para uma missão.' - resetPlayer: '§6/{0} resetPlayer <jogador>: §eRemove todas as informações sobre um jogador.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <jogador> [id]: §eExclui informações de uma missão de um jogador.' - seePlayer: '§6/{0} seePlayer <jogador>: §eVer informações sobre um jogador.' - reload: '§6/{0} reload: §eSalvar e recarregar todas as configurações e arquivos. (§cobsoleto§e)' - start: '§6/{0} start <jogador> [id]: §eForce o início de uma missão.' - setItem: '§6/{0} setItem <conversar|lançamento>: §eSalve o item de holograma.' - setFirework: '§6/{0} setFirework: §eEditar os fogos de artifício padrão.' - adminMode: '§6/ adminMode:{0} §eAlterne o Modo Admin. (Útil para exibir pequenas mensagens de registro).' - version: '§6/{0} version: §eVeja a versão atual do plugin.' - downloadTranslations: '§6/{0} downloadTranslations <idioma>: §eBaixa um arquivo de tradução padrão' - save: '§6/{0} save: §eFaz um salvamento manual do plugin.' - list: '§6/{0} list: §eVeja a lista de quests. (Somente para versões suportadas).' - typeCancel: '§aEscreva "cancel" para voltar ao último texto.' - editor: - blockAmount: '§aEscreva a quantidade de blocos:' - blockName: '§aEscreva o nome do bloco:' - blockData: '§aEscreva o blockdata (blockdatas disponíveis: §7{0}§a):' - blockTag: '§aEscreva a tag de bloco (tags disponíveis: §7{0}§a):' - typeBucketAmount: '§aEscreva a quantidade de baldes para encher:' - typeDamageAmount: 'Escreva a quantidade de dano que o jogador tem de causar:' - goToLocation: '§aVá ao local desejado para o estágio.' - typeLocationRadius: '§aEscreva a distância necessária até o local:' - typeGameTicks: '§aEscrever os ticks necessários do jogo:' - already: '§cVocê já está no editor.' - stage: - location: - typeWorldPattern: '§aEscreva o regex para nomes de mundo:' - enter: - title: '§6~ Modo Editor ~' - subtitle: '§6Escreva "/quests exitEditor" para forçar a saída do editor.' - list: '§c⚠ §7Você entrou no editor de "lista". Use "add" para adicionar linhas. Digite "help" (sem barra) para obter ajuda. §e§lEscreva "close" para sair do editor.' - chat: '§6Você está atualmente no Modo Editor. Escreva "/quests exitEditor" para forçar a saída do editor. (Altamente não recomendado, considere o uso de comandos como "close" ou "cancel" para voltar ao inventário anterior).' - npc: - enter: '§aClique em um NPC, ou escreva "cancelar".' - choseStarter: '§aEscolha o NPC que inicia a missão.' - notStarter: '§cEsse NPC não é um iniciador de missões.' - text: - argNotSupported: '§cO argumento {0} não é suportado.' - chooseLvlRequired: '§aEscreva a quantidade de níveis necessários:' - chooseJobRequired: '§aEscreva o nome da profissão desejada:' - choosePermissionRequired: '§aEscreva a permissão necessária para iniciar a missão:' - choosePermissionMessage: '§aVocê pode escolher uma mensagem de rejeição se o jogador não tiver a permissão necessária. (Para pular esta etapa, escreva "null").' - choosePlaceholderRequired: - identifier: '§aEscreva o nome do placeholder necessário sem o caractere de porcentagem:' - value: '§aEscreva o valor necessário para o placeholder §e%§e{0}§e%§a:' - chooseSkillRequired: '§aEscreva o nome da habilidade necessária:' - chooseMoneyRequired: '§aEscreva a quantidade de dinheiro necessário:' - reward: - permissionName: '§aEscreva o nome da permissão.' - permissionWorld: '§aEscreva o mundo em que a permissão será editada, ou "null" se você quiser que seja global.' - money: '§aEscreva a quantia do dinheiro recebido:' - wait: '§aEscreva a quantidade de ticks do jogo para esperar: (1 segundo = 20 ticks)' - random: - min: '§aEscreva a quantidade mínima de recompensas dadas ao jogador (inclusive).' - max: '§aEscreva a quantidade máxima de recompensas dadas ao jogador (inclusive).' - chooseObjectiveRequired: '§aEscreva o nome do objetivo.' - chooseObjectiveTargetScore: '§aEscreva a pontuação alvo para o objetivo.' - chooseRegionRequired: '§aEscreva o nome da região necessária (você deve estar no mesmo mundo).' - selectWantedBlock: '§aClique com a vareta (stick) no bloco desejado para o estágio.' - itemCreator: - itemType: '§aEscreva o nome do tipo de item desejado:' - itemAmount: '§aEscreva a quantidade de item(ns):' - itemName: '§aEscreva o nome do item:' - itemLore: '§aModifique a lore do item: (Escreva "help" para obter ajuda).' - unknownItemType: '§cTipo de item desconhecido.' - invalidItemType: '§cTipo de item inválido (O item não pode ser um bloco).' - unknownBlockType: '§cTipo de bloco desconhecido.' - invalidBlockType: '§cTipo de bloco inválido.' - dialog: - syntax: '§cSintaxe correta: {0}{1} <mensagem>' - syntaxRemove: '§cSintaxe correta: remove <id>' - player: '§aMensagem "§7{0}§a" adicionada ao jogador.' - npc: '§aMensagem "§7{0}§a" adicionada ao NPC.' - noSender: '§aMensagem "§7{0}§a" adicionada sem um remetente.' - messageRemoved: '§aMensagem "§7{0}§a" removida.' - edited: '§aMensagem "§7{0}§a" editada.' - soundAdded: '§aSom "§7{0}§a" adicionado para a mensagem "§7{1}§a".' - cleared: '§aRemovida §2§l{0}§a mensagem(ns).' - help: - header: '§6§lBeautyQuests — Ajuda do editor de diálogo' - npc: '§6npc <mensagem>: §eAdicione uma mensagem dita pelo NPC.' - player: '§6player <mensagem>: §eAdiciona uma mensagem dita pelo jogador.' - nothing: '§6noSender <mensagem>: §eAdicione uma mensagem sem um remetente.' - remove: '§6remove <id>: §eRemove uma mensagem.' - list: '§6list: §eVeja todas as mensagens.' - npcInsert: '§6npcInsert <id> <mensagem>: §eInsira uma mensagem falada pelo NPC.' - playerInsert: '§6playerInsert <id> <mensagem>: §eInsira uma mensagem dita pelo jogador.' - nothingInsert: '§6nothingInsert <id> <mensagem>: §eInsira uma mensagem sem qualquer prefixo.' - edit: '§6edit <id> <mensagem>: §eEdite uma mensagem.' - addSound: '§6addSound <id> <som>: §eAdicione um som para uma mensagem.' - clear: '§6clear: §eRemove todas as mensagens.' - close: '§6close: §eValide todas as mensagens.' - setTime: '§6setTime <id> <tempo>: §eDefine o tempo (em ticks) antes da próxima mensagem ser reproduzida automaticamente.' - npcName: '§6npcName [nome personalizado do NPC]: §eDefine (ou redefine para o padrão) nome personalizado do NPC no diálogo' - skippable: '§6skippable [true|false]: §eDefine se o diálogo pode ser ignorado ou não' - timeSet: '§aTempo foi editado para a mensagem {0}: agora {1} ticks.' - timeRemoved: '§aO tempo foi removido da mensagem {0}.' - npcName: - set: '§aNome de NPC personalizado definido para §7{1}§a (era §7{0}§a)' - unset: '§aNome de NPC personalizado redefinido para o padrão (era §7{0}§a)' - skippable: - set: '§aO status de diálogo ignorável foi definido para §7{1}§a (era §7{0}§a)' - unset: '§aO status do diálogo ignorável foi redefinido para o padrão (era §7{0}§a)' - mythicmobs: - list: '§aLista de todos os Monstros Míticos (Mythic Mobs):' - isntMythicMob: '§cEste Mob Mítico (Mythic Mob) não existe.' - disabled: '§cMythicMob está desativado.' - advancedSpawnersMob: 'Escreva o nome do spawner de mob personalizado para matar:' - textList: - syntax: '§cSintaxe correta: ' - added: '§aTexto "§7{0}§a" adicionado.' - removed: '§aTexto "§7{0}§a" removido.' - help: - header: '§6§lBeautyQuests — Ajuda do editor de lista' - add: '§6add <mensagem>: §eAdiciona um texto.' - remove: '§6remove <id>: §eRemove um texto.' - list: '§6list: §eVeja todos os textos adicionados.' - close: '§6close §eValide os textos adicionados.' - availableElements: 'Elementos disponíveis: §e{0}' - noSuchElement: '§cNão existe tal elemento. Os elementos permitidos são: §e{0}' - invalidPattern: '§cPadrão de regex inválido §4{0}§c.' - comparisonTypeDefault: '§aEscolha o tipo de comparação que deseja entre {0}. A comparação padrão é: §e§l{1}§r§a. Digite §onull§r§a para usar.' - scoreboardObjectiveNotFound: '§cObjetivo de scoreboard desconhecido.' - pool: - hologramText: '§aEscreva o texto personalizado do holograma para este grupo (ou "null" se você quiser o padrão).' - maxQuests: 'Escreva a quantidade máxima de missões que podem ser iniciadas neste grupo.' - questsPerLaunch: 'Escreva a quantidade de missões que serão dadas quando jogadores clicarem no NPC.' - timeMsg: 'Escreva o tempo necessário para que os jogadores possam pegar uma nova missão. (unidade padrão: dias)' - title: - title: 'Escreva o texto do título (ou "null" se você não quiser nenhum).' - subtitle: 'Escreva o texto da legenda (ou "null" se você não quiser nenhum).' - fadeIn: 'Escreva a duração do "fade-in", em ticks (20 ticks = 1 segundo).' - stay: 'Escreva a duração da "permanência", em ticks (20 ticks = 1 segundo).' - fadeOut: 'Escreva a duração do "fade-out", em ticks (20 ticks = 1 segundo).' - colorNamed: 'Insira o nome de uma cor.' - color: 'Informe uma cor no formato hexadecimal (#XXXXX) ou RGB (RED GRE BLU).' - invalidColor: 'A cor inserida é inválida. Ela deve ser hexadecimal ou RGB.' - firework: - invalid: 'Este item não é um fogo de artifício válido.' - invalidHand: 'Você deve manter um fogo de artifício em sua mão principal.' - edited: 'Fogos de artifício da missão editado!' - removed: 'Fogos de artifício da missão removido!' - writeCommandDelay: '§aEscreva o atraso do comando desejado, em ticks.' advancement: finished: Finalizado notStarted: Não iniciado +description: + requirement: + class: Classe {class_name} + combatLevel: Nível de Combate {short_level} + faction: Facção {faction_name} + jobLevel: Nível {short_level} para {job_name} + level: Nível {short_level} + quest: Terminar a missão §e{quest_name} + skillLevel: Nível {short_level} para {skill_name} + title: '§8§lRequisitos:' + reward: + title: '§8§lRecompensas:' +indication: + cancelQuest: '§7Tem certeza que deseja cancelar a missão {quest_name}?' + closeInventory: '§7Você tem certeza de que deseja fechar o menu?' + removeQuest: '§7Tem certeza que deseja remover a missão {quest}?' + startQuest: '§7Deseja iniciar a missão {quest_name}?' inv: - validate: '§b§lValidar' - cancel: '§c§lCancelar' - search: '§a§lPesquisar' addObject: '§aAdicionar um objeto' + block: + blockData: '§dBlockdata (avançado)' + blockName: '§bNome do bloco personalizado' + blockTag: '§dTag (avançado)' + blockTagLore: Escolha uma tag que descreva uma lista de blocos possíveis. Tags podem ser personalizadas usando datapacks. Você pode encontrar lista de tags na wiki do Minecraft. + materialNotItemLore: O bloco escolhido não pode ser exibido como um item. Ele ainda é armazenado corretamente como {block_material}. + name: Escolher bloco + blockAction: + location: '§eSelecione um local preciso' + material: '§eSelecionar um material de bloco' + name: Selecionar ação de bloqueio + blocksList: + addBlock: '§aClique para adicionar um bloco.' + name: Selecionar blocos + buckets: + name: Tipo de balde + cancel: '§c§lCancelar' + cancelActions: + name: Cancelar ações + checkpointActions: + name: Ações de checkpoint + chooseAccount: + name: Qual conta? + chooseQuest: + menu: '§aMenu de Missões' + menuLore: Te leva para o seu Menu de Missões. + name: Qual missão? + classesList.name: Lista de classes + classesRequired.name: Classes necessárias + command: + console: Console + delay: '§bAtraso' + name: Comando + parse: Analisar placeholders + value: '§eComando' + commandsList: + name: Lista de comandos + value: '§eComando: {command_label}' confirm: name: Você tem certeza? - 'yes': '§aConfirmar' 'no': '&cCancelar' + 'yes': '§aConfirmar' create: - stageCreate: '§aCriar nova etapa' - stageRemove: '§cExcluir esta etapa' - stageUp: Mover para cima - stageDown: Mover para baixo - stageType: '§7Tipo de estágio: §e{0}' - cantFinish: '§7Você deve criar pelo menos um estágio antes de terminar a criação da missão!' - findNPC: '§aEncontrar NPC' + NPCSelect: '§eEscolha ou crie NPC' + NPCText: '§eEditar diálogo' + breedAnimals: '§aProcrie animais' bringBack: '§aTraga itens de volta' - findRegion: '§aEncontrar região' - killMobs: '§aMatar mobs' - mineBlocks: '§aQuebrar blocos' - placeBlocks: '§aColocar blocos' - talkChat: '§aEscrever no chat' - interact: '§aInteragir com bloco' - fish: '§aPegar peixes' - melt: '§6Derreter itens' - enchant: '§dEncantar itens' - craft: '§aCraftar item' bucket: '§aEncher baldes' - location: '§aIr para localização' - playTime: '§eTempo de jogo' - breedAnimals: '§aProcrie animais' - tameAnimals: '§aDome animais' - death: '§cMorrer' + cancelMessage: Cancelar envio + cantFinish: '§7Você deve criar pelo menos um estágio antes de terminar a criação da missão!' + changeEntityType: '§eMudar tipo de entidade' + changeTicksRequired: '§eAlterar os ticks jogados necessários' + craft: '§aCraftar item' + currentRadius: '§eDistância atual: §6{radius}' dealDamage: '§cCause dano a mobs' + death: '§cMorrer' eatDrink: '§aComa ou beba poções' - NPCText: '§eEditar diálogo' - dialogLines: '{0} linhas' - NPCSelect: '§eEscolha ou crie NPC' - hideClues: Ocultar partículas e hologramas - gps: Aparece uma bússola mostrando a direção do objetivo. - editMobsKill: '§eEdite os mobs para matar' - mobsKillFromAFar: Precisa ser morto com projéteis editBlocksMine: '§eEditar blocos para quebrar' - preventBlockPlace: Impedir que jogadores quebrem seus próprios blocos editBlocksPlace: '§eEditar blocos para colocar' + editBucketAmount: '§eEditar a quantidade de baldes para encher' + editBucketType: '§eEditar o tipo de balde para encher' + editFishes: '§eEditar os peixes a pegar' + editItem: '§eEditar o item para craftar' + editItemsToEnchant: '§eEditar os itens a encantar' + editItemsToMelt: '§eEditar os itens a derreter' + editLocation: '§eEditar local' editMessageType: '§eEditar mensagem para escrever' - cancelMessage: Cancelar envio + editMobsKill: '§eEdite os mobs para matar' + editRadius: '§eEditar a distância a partir do local' + enchant: '§dEncantar itens' + findNPC: '§aEncontrar NPC' + findRegion: '§aEncontrar região' + fish: '§aPegar peixes' + hideClues: Ocultar partículas e hologramas ignoreCase: Desconsidere a diferença entre letras maiúsculas e minúsculas na mensagem + interact: '§aInteragir com bloco' + killMobs: '§aMatar mobs' + leftClick: O clique deve ser com o botão esquerdo + location: '§aIr para localização' + melt: '§6Derreter itens' + mineBlocks: '§aQuebrar blocos' + mobsKillFromAFar: Precisa ser morto com projéteis + placeBlocks: '§aColocar blocos' + playTime: '§eTempo de jogo' + preventBlockPlace: Impedir que jogadores quebrem seus próprios blocos replacePlaceholders: Substituir {PLAYER} e placeholders do PAPI + selectBlockLocation: '§eSelecione o local do bloco' + selectBlockMaterial: '§eSelecione o material do bloco' selectItems: '§eEditar itens necessários' - selectItemsMessage: '§eEditar a mensagem de pergunta' selectItemsComparisons: '§eSelecionar comparações de itens (AVANÇADO)' + selectItemsMessage: '§eEditar a mensagem de pergunta' selectRegion: '§7Escolher região' - toggleRegionExit: Ao sair - stageStartMsg: '§eEditar mensagem inicial' - selectBlockLocation: '§eSelecione o local do bloco' - selectBlockMaterial: '§eSelecione o material do bloco' - leftClick: O clique deve ser com o botão esquerdo - editFishes: '§eEditar os peixes a pegar' - editItemsToMelt: '§eEditar os itens a derreter' - editItemsToEnchant: '§eEditar os itens a encantar' - editItem: '§eEditar o item para craftar' - editBucketType: '§eEditar o tipo de balde para encher' - editBucketAmount: '§eEditar a quantidade de baldes para encher' - editLocation: '§eEditar local' - editRadius: '§eEditar a distância a partir do local' - currentRadius: '§eDistância atual: §6{0}' - changeTicksRequired: '§eAlterar os ticks jogados necessários' - changeEntityType: '§eMudar tipo de entidade' stage: - location: - worldPattern: '§aDefinir padrão de nome do mundo §d(AVANÇADO)' - worldPatternLore: 'Se você deseja que o estágio seja completado para qualquer mundo que corresponda a um padrão específico, insira uma regex (expressão regular) aqui.' - death: - causes: '§aDefinir causas de morte §d(AVANÇADO)' - anyCause: Qualquer causa de morte - setCauses: '{0} causa(s) da morte' dealDamage: damage: '§eDano para causar' targetMobs: '§cMobs a dar dano' + death: + anyCause: Qualquer causa de morte + causes: '§aDefinir causas de morte §d(AVANÇADO)' + setCauses: '{causes_amount} causa(s) da morte' eatDrink: items: '§eEditar itens para comer ou beber' - stages: - name: Criar estágios - nextPage: '§ePróxima página' - laterPage: '§ePágina Anterior' - endingItem: '§eEditar recompensas finais' - descriptionTextItem: '§eEditar descrição' - regularPage: '§aEstágios regulares' - branchesPage: '§dEtapas do Ramo' - previousBranch: '§eVoltar para o ramo anterior' - newBranch: '§eIr para o novo ramo' - validationRequirements: '§eRequisitos de validação' - validationRequirementsLore: Todas as exigências devem coincidir com o jogador que tentar completar o estágio. Caso contrário, a etapa não pode ser concluída. + location: + worldPattern: '§aDefinir padrão de nome do mundo §d(AVANÇADO)' + worldPatternLore: Se você deseja que o estágio seja completado para qualquer mundo que corresponda a um padrão específico, insira uma regex (expressão regular) aqui. + stageCreate: '§aCriar nova etapa' + stageDown: Mover para baixo + stageRemove: '§cExcluir esta etapa' + stageStartMsg: '§eEditar mensagem inicial' + stageType: '§7Tipo de estágio: §e{stage_type}' + stageUp: Mover para cima + talkChat: '§aEscrever no chat' + tameAnimals: '§aDome animais' + toggleRegionExit: Ao sair + damageCause: + name: Causa do dano + damageCausesList: + name: Lista de causas do dano details: - hologramLaunch: '§eEditar item do holograma "iniciar"' - hologramLaunchLore: Holograma exibido acima da cabeça do NPC iniciador quando o jogador pode iniciar a missão. - hologramLaunchNo: '§eEditar item do holograma "iniciar indisponível"' - hologramLaunchNoLore: Holograma exibido acima da cabeça do NPC iniciador quando o jogador NÃO pode iniciar a missão. + actions: '{amount} ação(ões)' + auto: Iniciar automaticamente na primeira entrada + autoLore: Se ativado, a missão será iniciada automaticamente quando o jogador entrar no servidor pela primeira vez. + bypassLimit: Não contar limite de missão + bypassLimitLore: Se ativado, a missão será iniciável mesmo que o jogador tenha atingido a quantidade máxima de missões iniciadas. + cancelRewards: '§cCancelar ações' + cancelRewardsLore: Ações executadas quando os jogadores cancelam esta missão. + cancellable: Cancelável pelo jogador + cancellableLore: Permite que o jogador cancele a missão através do seu Menu de Missões. + createQuestLore: Você precisa definir o nome da missão. + createQuestName: '§lCriar missão' customConfirmMessage: '§eEditar mensagem de confirmação da missão' customConfirmMessageLore: Mensagem exibida na interface de confirmação do menu quando um jogador estiver prestes a iniciar a missão. customDescription: '§eEditar descrição da missão' customDescriptionLore: Descrição mostrada abaixo do nome da missão no menu. - name: Detalhes da última missão - multipleTime: - itemName: Alternar repetição - itemLore: A missão pode ser feita várias vezes? - cancellable: Cancelável pelo jogador - cancellableLore: Permite que o jogador cancele a missão através do seu Menu de Missões. - startableFromGUI: Iniciável pelo menu - startableFromGUILore: Permite que o jogador inicie a missão pelo Menu de Missões. - scoreboardItem: Habilitar scoreboard - scoreboardItemLore: Se desativada, a missão não será rastreada através do scoreboard. + customMaterial: '§eEditar material do item da missão' + customMaterialLore: Item representativo desta missão no Menu de Missões. + defaultValue: '§8(valor padrão)' + editQuestName: '§lEditar quest' + editRequirements: '§eEditar requisitos' + editRequirementsLore: Todos os requisitos devem se aplicar ao jogador antes de iniciar a missão. + endMessage: '§eEditar mensagem final' + endMessageLore: Mensagem que será enviada para o jogador no final da missão. + endSound: '§eEditar som final' + endSoundLore: Som que será tocado no final da missão. + failOnDeath: Falhar ao morrer + failOnDeathLore: A missão será cancelada quando o jogador morrer? + firework: '§dFogos de Artifício de encerramento' + fireworkLore: Fogos de artifício lançado quando o jogador terminar a missão + fireworkLoreDrop: Solte seu fogo de artifício personalizado aqui hideNoRequirementsItem: Esconder quando requisitos não forem cumpridos hideNoRequirementsItemLore: Se ativado, a missão não será exibida no Menu de Missões quando os requisitos não forem atendidos. - bypassLimit: Não contar limite de missão - bypassLimitLore: Se ativado, a missão será iniciável mesmo que o jogador tenha atingido a quantidade máxima de missões iniciadas. - auto: Iniciar automaticamente na primeira entrada - autoLore: Se ativado, a missão será iniciada automaticamente quando o jogador entrar no servidor pela primeira vez. + hologramLaunch: '§eEditar item do holograma "iniciar"' + hologramLaunchLore: Holograma exibido acima da cabeça do NPC iniciador quando o jogador pode iniciar a missão. + hologramLaunchNo: '§eEditar item do holograma "iniciar indisponível"' + hologramLaunchNoLore: Holograma exibido acima da cabeça do NPC iniciador quando o jogador NÃO pode iniciar a missão. + hologramText: '§eTexto do holograma' + hologramTextLore: Texto exibido no holograma acima da cabeça do NPC iniciador. + keepDatas: Preservar dados dos jogadores + keepDatasLore: 'Forçar o plugin a preservar os dados dos jogadores, mesmo que os estágios tenham sido editados. §c§lCUIDADO §c- habilitar essa opção pode corromper os dados dos jogadores.' + loreReset: '§e§lO avanço de todos os jogadores será redefinido' + multipleTime: + itemLore: A missão pode ser feita várias vezes? + itemName: Alternar repetição + name: Detalhes da última missão + optionValue: '§8Valor: §7{value}' questName: '§a§lEditar o nome da missão' questNameLore: Um nome deve ser definido para completar a criação da missão. - setItemsRewards: '§eEditar itens de recompensa' + questPool: '§eGrupo de missões' + questPoolLore: Adicione esta missão a um grupo de missão removeItemsReward: '§eRemover itens do inventário' - setXPRewards: '§eEditar experiência de recompensa' + requiredParameter: '§7Parâmetro obrigatório' + requirements: '{amount} requerimento(s)' + rewards: '{amount} recompensa(s)' + rewardsLore: Ações executadas quando a missão termina. + scoreboardItem: Habilitar scoreboard + scoreboardItemLore: Se desativada, a missão não será rastreada através do scoreboard. + selectStarterNPC: '§e§lSelecionar NPC iniciador' + selectStarterNPCLore: Clique no NPC selecionado para iniciar a missão. + selectStarterNPCPool: '§c⚠ Um grupo de missões foi selecionado' setCheckpointReward: '§eEditar recompensas de checkpoint' + setItemsRewards: '§eEditar itens de recompensa' + setMoneyReward: '§eEditar prêmio em dinheiro' + setPermReward: '§eEditar permissões' setRewardStopQuest: '§cParar a missão' - setRewardsWithRequirements: '§eRecompensas com requisitos' setRewardsRandom: '§dRecompensas aleatórias' - setPermReward: '§eEditar permissões' - setMoneyReward: '§eEditar prêmio em dinheiro' - setWaitReward: '§eEditar recompensa de "espera"' + setRewardsWithRequirements: '§eRecompensas com requisitos' setTitleReward: '§eEditar recompensa por título' - selectStarterNPC: '§e§lSelecionar NPC iniciador' - selectStarterNPCLore: Clique no NPC selecionado para iniciar a missão. - selectStarterNPCPool: '§c⚠ Um grupo de missões foi selecionado' - createQuestName: '§lCriar missão' - createQuestLore: Você precisa definir o nome da missão. - editQuestName: '§lEditar quest' - endMessage: '§eEditar mensagem final' - endMessageLore: Mensagem que será enviada para o jogador no final da missão. - endSound: '§eEditar som final' - endSoundLore: Som que será tocado no final da missão. - startMessage: '§eEditar mensagem inicial' - startMessageLore: Mensagem que será enviada ao jogador no início da missão. + setWaitReward: '§eEditar recompensa de "espera"' + setXPRewards: '§eEditar experiência de recompensa' startDialog: '§eEditar diálogo inicial' startDialogLore: Diálogo que será reproduzido antes do início das missões quando os jogadores clicarem no NPC iniciador. - editRequirements: '§eEditar requisitos' - editRequirementsLore: Todos os requisitos devem se aplicar ao jogador antes de iniciar a missão. + startMessage: '§eEditar mensagem inicial' + startMessageLore: Mensagem que será enviada ao jogador no início da missão. startRewards: '§6Recompensas iniciais' startRewardsLore: Ações executadas quando a missão começa. - cancelRewards: '§cCancelar ações' - cancelRewardsLore: Ações executadas quando os jogadores cancelam esta missão. - hologramText: '§eTexto do holograma' - hologramTextLore: Texto exibido no holograma acima da cabeça do NPC iniciador. + startableFromGUI: Iniciável pelo menu + startableFromGUILore: Permite que o jogador inicie a missão pelo Menu de Missões. timer: '§bReiniciar temporizador' timerLore: Tempo até que o jogador possa começar a missão novamente. - requirements: '{0} requerimento(s)' - rewards: '{0} recompensa(s)' - actions: '{0} ação(ões)' - rewardsLore: Ações executadas quando a missão termina. - customMaterial: '§eEditar material do item da missão' - customMaterialLore: Item representativo desta missão no Menu de Missões. - failOnDeath: Falhar ao morrer - failOnDeathLore: A missão será cancelada quando o jogador morrer? - questPool: '§eGrupo de missões' - questPoolLore: Adicione esta missão a um grupo de missão - firework: '§dFogos de Artifício de encerramento' - fireworkLore: Fogos de artifício lançado quando o jogador terminar a missão - fireworkLoreDrop: Solte seu fogo de artifício personalizado aqui visibility: '§bVisibilidade da Missão' visibilityLore: Escolha em que abas do menu a missão será mostrada, e se a missão é visível em mapas dinâmicos. - keepDatas: Preservar dados dos jogadores - keepDatasLore: |- - Forçar o plugin a preservar os dados dos jogadores, mesmo que os estágios tenham sido editados. - §c§lCUIDADO §c- habilitar essa opção pode corromper os dados dos jogadores. - loreReset: '§e§lO avanço de todos os jogadores será redefinido' - optionValue: '§8Valor: §7{0}' - defaultValue: '§8(valor padrão)' - requiredParameter: '§7Parâmetro obrigatório' - itemsSelect: - name: Editar itens - none: |- - §aMova um item para aqui ou - clique para abrir o editor do item. - itemSelect: - name: Escolher item - npcCreate: - name: Criar NPC - setName: '§eEditar nome do NPC' - setSkin: '§eEditar skin do NPC' - setType: '§eEditar tipo do NPC' - move: - itemName: '§eMover' - itemLore: '§aMudar o local do NPC.' - moveItem: '§a§lValidar local' - npcSelect: - name: Selecionar ou criar? - selectStageNPC: '§eSelecionar um NPC existente' - createStageNPC: '§eCriar NPC' + editTitle: + fadeIn: '§aDuração do fade-in' + fadeOut: '§aDuração do fade-out' + name: Editar título + stay: '§bDuração da permanência' + subtitle: '§eSubtítulo' + title: '§6Título' entityType: name: Escolher tipo de entidade - chooseQuest: - name: Qual missão? - menu: '§aMenu de Missões' - menuLore: Te leva para o seu Menu de Missões. - mobs: - name: Selecionar mobs - none: '§aClique para adicionar um mob.' - clickLore: |- - §a§lClique esquerdo para editar o valor. - §a§l§nShift§a§l + clique esquerdo§a para editar o nome do mob. - §c§lBotão direito§c para excluir. - setLevel: Definir nível mínimo - mobSelect: - name: Selecionar tipo de mob - bukkitEntityType: '§eSelecione o tipo de entidade' - mythicMob: '§6Selecionar Mob Místico (Mythic Mob)' - epicBoss: '§6Selecione o Chefe Épico (Epic Boss)' - boss: '§6Selecione um Boss' - stageEnding: - locationTeleport: '§eEditar localização de teleporte' - command: '§eEditar comando executado' - requirements: - name: Requisitos - rewards: - name: Recompensas - commands: 'Comandos: {0}' - teleportation: |- - §aSelecionado: - X: {0} - Y: {1} - Z: {2} - Mundo: {3} - random: - rewards: Editar recompensas - minMax: Editar mínimo e máximo - checkpointActions: - name: Ações de checkpoint - cancelActions: - name: Cancelar ações - rewardsWithRequirements: - name: Recompensas com requisitos - listAllQuests: - name: Missões - listPlayerQuests: - name: 'Missões de {0}' - listQuests: - notStarted: Missões não iniciadas - finished: Missões concluídas - inProgress: Missões em andamento - loreDialogsHistoryClick: '§7Ver os diálogos' - loreCancelClick: '§cCancelar a missão' - loreStart: '§a§oClique para iniciar a missão.' - loreStartUnavailable: '§c§oVocê não cumpre os requisitos para iniciar a missão.' - timeToWaitRedo: '§3§oVocê pode reiniciar essa missão em {0}.' - canRedo: '§3§oVocê pode reiniciar esta missão!' - timesFinished: '§3Missão feita {0} vezes.' + equipmentSlots: + name: Espaços do equipamento + factionsList.name: Lista de facções + factionsRequired.name: Facções necessárias + itemComparisons: + bukkit: Comparação nativa do Bukkit + bukkitLore: Usa sistema de comparação de itens padrão do Bukkit. Compara material, durabilidade, tags de nbt... + customBukkit: Comparação nativa de Bukkit - SEM NBT + customBukkitLore: Usa o sistema de comparação de itens padrão do Bukkit, mas limpa as tags NBT. Compara material, durabilidade... + enchants: Encantamentos de itens + enchantsLore: Compara encantamentos de itens + itemLore: Lore do item + itemLoreLore: Compara lores dos itens + itemName: Nome do item + itemNameLore: Compara nomes de itens + itemsAdder: ItemsAdder + itemsAdderLore: Compara IDs do ItemsAdder + material: Material do Item + materialLore: Compara material do item (i. e. pedra, espada de ferro...) + name: Comparações de Itens + repairCost: Custo do reparo + repairCostLore: Compara o custo de reparo para armaduras e espadas itemCreator: - name: Criador de item - itemType: '§bTipo do Item' + isQuestItem: '§bItem de missão:' itemFlags: Alternar flags de item - itemName: '§bNome do Item' itemLore: '§bLore do item' - isQuestItem: '§bItem de missão:' - command: - name: Comando - value: '§eComando' - console: Console - parse: Analisar placeholders - delay: '§bAtraso' - chooseAccount: - name: Qual conta? + itemName: '§bNome do Item' + itemType: '§bTipo do Item' + name: Criador de item + itemSelect: + name: Escolher item + itemsSelect: + name: Editar itens + none: '§aMova um item para aqui ou clique para abrir o editor do item.' + listAllQuests: + name: Missões listBook: + noQuests: Nenhuma missão foi criada anteriormente. + questMultiple: Várias vezes questName: Nome - questStarter: Iniciador questRewards: Recompensas - questMultiple: Várias vezes - requirements: Requisitos questStages: Estágios - noQuests: Nenhuma missão foi criada anteriormente. - commandsList: - name: Lista de comandos - value: '§eComando: {0}' - console: '§eConsole: {0}' - block: - name: Escolher bloco - material: '§eMaterial: {0}' - materialNotItemLore: 'O bloco escolhido não pode ser exibido como um item. Ele ainda é armazenado corretamente como {0}.' - blockName: '§bNome do bloco personalizado' - blockData: '§dBlockdata (avançado)' - blockTag: '§dTag (avançado)' - blockTagLore: 'Escolha uma tag que descreva uma lista de blocos possíveis. Tags podem ser personalizadas usando datapacks. Você pode encontrar lista de tags na wiki do Minecraft.' - blocksList: - name: Selecionar blocos - addBlock: '§aClique para adicionar um bloco.' - blockAction: - name: Selecionar ação de bloqueio - location: '§eSelecione um local preciso' - material: '§eSelecionar um material de bloco' - buckets: - name: Tipo de balde + questStarter: Iniciador + requirements: Requisitos + listPlayerQuests: + name: 'Missões de {player_name}' + listQuests: + canRedo: '§3§oVocê pode reiniciar esta missão!' + finished: Missões concluídas + inProgress: Missões em andamento + loreCancelClick: '§cCancelar a missão' + loreDialogsHistoryClick: '§7Ver os diálogos' + loreStart: '§a§oClique para iniciar a missão.' + loreStartUnavailable: '§c§oVocê não cumpre os requisitos para iniciar a missão.' + notStarted: Missões não iniciadas + timeToWaitRedo: '§3§oVocê pode reiniciar essa missão em {time_left}.' + timesFinished: '§3Missão feita {times_finished} vezes.' + mobSelect: + boss: '§6Selecione um Boss' + bukkitEntityType: '§eSelecione o tipo de entidade' + epicBoss: '§6Selecione o Chefe Épico (Epic Boss)' + mythicMob: '§6Selecionar Mob Místico (Mythic Mob)' + name: Selecionar tipo de mob + mobs: + name: Selecionar mobs + none: '§aClique para adicionar um mob.' + setLevel: Definir nível mínimo + npcCreate: + move: + itemLore: '§aMudar o local do NPC.' + itemName: '§eMover' + moveItem: '§a§lValidar local' + name: Criar NPC + setName: '§eEditar nome do NPC' + setSkin: '§eEditar skin do NPC' + setType: '§eEditar tipo do NPC' + npcSelect: + createStageNPC: '§eCriar NPC' + name: Selecionar ou criar? + selectStageNPC: '§eSelecionar um NPC existente' + particleEffect: + color: '§bCor de partícula' + name: Criar efeito de partícula + shape: '§dForma da partícula' + type: '§eTipo da partícula' + particleList: + colored: Partícula colorida + name: Lista de partículas permission: name: Escolher permissão perm: '§aPermissão' - world: '§aMundo' - worldGlobal: '§b§Global' remove: Remover permissão removeLore: '§7A permissão será retirada \n§7ao invés de dada.' + world: '§aMundo' + worldGlobal: '§b§Global' permissionList: name: Lista de permissões - removed: '§eRemovido: §6{0}' - world: '§eMundo: §6{0}' - classesRequired.name: Classes necessárias - classesList.name: Lista de classes - factionsRequired.name: Facções necessárias - factionsList.name: Lista de facções - poolsManage: - name: Grupo de missões - itemName: '§aGrupo #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Missões máximas: §7{0}' - poolQuestsPerLaunch: '§8Missões feitas por lançamento: §7{0}' - poolRedo: '§8Pode refazer missões concluídas: §7{0}' - poolTime: '§8Tempo entre as missões: §7{0}' - poolHologram: '§8Texto do holograma: §7{0}' - poolAvoidDuplicates: '§8Evitar duplicatas: §7{0}' - poolQuestsList: '§7{0} §8Missão(ões): §7{1}' - create: '§aCrie um grupo de missões' - edit: '§e> §6§oEditar o grupo... §e<' - choose: '§e> §6§oEscolha este grupo §e<' + removed: '§eRemovido: §6{permission_removed}' + world: '§eMundo: §6{permission_world}' poolCreation: - name: Criação de grupo de missões + avoidDuplicates: Evitar duplicatas + avoidDuplicatesLore: '§8> §7Tente evitar fazer\n a mesma missão várias vezes' hologramText: '§eHolograma personalizado do grupo' maxQuests: '§aMáximo de missões' + name: Criação de grupo de missões questsPerLaunch: '§aMissões iniciadas por lançamento' - time: '§bDefinir tempo entre as missões' redoAllowed: Refazer é permitido? - avoidDuplicates: Evitar duplicatas - avoidDuplicatesLore: '§8> §7Tente evitar fazer\n a mesma missão várias vezes' requirements: '§bRequisitos para iniciar uma missão' + time: '§bDefinir tempo entre as missões' poolsList.name: Grupo de missões - itemComparisons: - name: Comparações de Itens - bukkit: Comparação nativa do Bukkit - bukkitLore: "Usa sistema de comparação de itens padrão do Bukkit.\nCompara material, durabilidade, tags de nbt..." - customBukkit: Comparação nativa de Bukkit - SEM NBT - customBukkitLore: "Usa o sistema de comparação de itens padrão do Bukkit, mas limpa as tags NBT.\nCompara material, durabilidade..." - material: Material do Item - materialLore: 'Compara material do item (i. e. pedra, espada de ferro...)' - itemName: Nome do item - itemNameLore: Compara nomes de itens - itemLore: Lore do item - itemLoreLore: Compara lores dos itens - enchants: Encantamentos de itens - enchantsLore: Compara encantamentos de itens - repairCost: Custo do reparo - repairCostLore: Compara o custo de reparo para armaduras e espadas - editTitle: - name: Editar título - title: '§6Título' - subtitle: '§eSubtítulo' - fadeIn: '§aDuração do fade-in' - stay: '§bDuração da permanência' - fadeOut: '§aDuração do fade-out' - particleEffect: - name: Criar efeito de partícula - shape: '§dForma da partícula' - type: '§eTipo da partícula' - color: '§bCor de partícula' - particleList: - name: Lista de partículas - colored: Partícula colorida - damageCause: - name: Causa do dano - damageCausesList: - name: Lista de causas do dano + poolsManage: + choose: '§e> §6§oEscolha este grupo §e<' + create: '§aCrie um grupo de missões' + edit: '§e> §6§oEditar o grupo... §e<' + itemName: '§aGrupo #{pool}' + name: Grupo de missões + poolAvoidDuplicates: '§8Evitar duplicatas: §7{pool_duplicates}' + poolHologram: '§8Texto do holograma: §7{pool_hologram}' + poolMaxQuests: '§8Missões máximas: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8Missão(ões): §7{pool_quests}' + poolQuestsPerLaunch: '§8Missões dadas por início: §7{pool_quests_per_launch}' + poolRedo: '§8Pode refazer missões concluídas: §7{pool_redo}' + poolTime: '§8Tempo entre as missões: §7{pool_time}' + requirements: + name: Requisitos + rewards: + commands: 'Comandos: {amount}' + name: Recompensas + random: + minMax: Editar mínimo e máximo + rewards: Editar recompensas + rewardsWithRequirements: + name: Recompensas com requisitos + search: '§a§lPesquisar' + stageEnding: + command: '§eEditar comando executado' + locationTeleport: '§eEditar localização de teleporte' + stages: + branchesPage: '§dEtapas do Ramo' + descriptionTextItem: '§eEditar descrição' + endingItem: '§eEditar recompensas finais' + laterPage: '§ePágina Anterior' + name: Criar estágios + newBranch: '§eIr para o novo ramo' + nextPage: '§ePróxima página' + previousBranch: '§eVoltar para o ramo anterior' + regularPage: '§aEstágios regulares' + validationRequirements: '§eRequisitos de validação' + validationRequirementsLore: Todas as exigências devem coincidir com o jogador que tentar completar o estágio. Caso contrário, a etapa não pode ser concluída. + validate: '§b§lValidar' visibility: + finished: 'Aba de menu "Finalizada"' + inProgress: 'Aba de menu "Em andamento"' + maps: Mapas (como dynmap ou BlueMap) name: Visibilidade da missão notStarted: 'Aba de menu "Não Iniciado"' - inProgress: 'Aba de menu "Em andamento"' - finished: 'Aba de menu "Finalizada"' - maps: 'Mapas (como dynmap ou BlueMap)' - equipmentSlots: - name: Espaços do equipamento -scoreboard: - name: '§6§lMissões' - noLaunched: '§cNenhuma missão em andamento.' - noLaunchedName: '§c§lCarregando' - noLaunchedDescription: '§c§oCarregando' - textBetwteenBranch: '§e ou' - asyncEnd: '§ex' - stage: - region: '§eEncontre a região §6{0}' - npc: '§eFale com o NPC §6{0}' - items: '§eTraga itens para §6{0}§e:' - mobs: '§eMate §6{0}' - mine: '§eMinere {0}' - placeBlocks: '§eColoque {0}' - chat: '§eEscreva §6{0}' - interact: '§eClique no bloco em §6{0}' - interactMaterial: '§eClique em um bloco de §6{0}§e' - fish: '§ePeixe §6{0}' - melt: '§eDerreta §6{0}' - enchant: '§eEncante §6{0}' - craft: '§eCrafte §6{0}' - bucket: '§eEncha §6{0}' - location: '§eVá para §6{0}§e, §6{1}§e, §6{2}§e em §6{3}' - playTimeFormatted: '§eJogue §6{0}' - breed: '§eProcrie §6{0}' - tame: '§eDome §6{0}' - die: '§cMorra' - dealDamage: - any: '§cCause {0} de dano' - mobs: '§cCause {0} de dano para {1}' - eatDrink: '§eConsuma §6{0}' -indication: - startQuest: '§7Deseja iniciar a missão {0}?' - closeInventory: '§7Você tem certeza de que deseja fechar o menu?' - cancelQuest: '§7Tem certeza que deseja cancelar a missão {0}?' - removeQuest: '§7Tem certeza que deseja remover a missão {0}?' -description: - requirement: - title: '§8§lRequisitos:' - level: 'Nível {0}' - jobLevel: 'Nível {0} para {1}' - combatLevel: 'Nível de Combate {0}' - skillLevel: 'Nível {0} para {1}' - class: 'Classe {0}' - faction: 'Facção {0}' - quest: 'Terminar a missão §e{0}' - reward: - title: '§8§lRecompensas:' misc: - format: - prefix: '§6<§e§lQuests§r§6> §r' - time: - weeks: '{0} semanas' - days: '{0} dias' - hours: '{0} horas' - minutes: '{0} minutos' - lessThanAMinute: 'menos de um minuto' - stageType: - region: Encontrar região - npc: Encontrar NPC - items: Traga itens de volta - mobs: Matar mobs - mine: Quebrar blocos - placeBlocks: Colocar blocos - chat: Escreva no chat - interact: Interagir com bloco - Fish: Pegar peixes - Melt: Derreter itens - Enchant: Encantar itens - Craft: Craftar item - Bucket: Encher balde - location: Encontrar localização - playTime: Tempo de jogo - breedAnimals: Procriar animais - tameAnimals: Domar animais - die: Morrer - dealDamage: Causar dano - eatDrink: Comer ou beber - comparison: - equals: igual a {0} - different: diferente de {0} - less: estritamente menor que {0} - lessOrEquals: menor do que {0} - greater: estritamente maior que {0} - greaterOrEquals: maior que {0} - requirement: - logicalOr: '§dOperador OU (requisitos)' - skillAPILevel: '§bSkillAPI nível necessário' - class: '§bClasse(s) necessária(s)' - faction: '§bFacção(ões) obrigatória(s)' - jobLevel: '§bNível de trabalho necessário' - combatLevel: '§bNível de combate necessário' - experienceLevel: '§bNível de experiência necessário' - permissions: '§3Permissão(ões) obrigatória(s)' - scoreboard: '§dPontuação necessária' - region: '§dRegião necessária' - placeholder: '§bValor de placeholder obrigatório' - quest: '§aMissão necessária' - mcMMOSkillLevel: '§dNível de habilidade necessário' - money: '§dDinheiro necessário' - equipment: '§eEquipamento necessário' + amount: '§eQuantidade: {amount}' + amounts: + comparisons: '{comparisons_amount} comparação(ões)' + dialogLines: '{lines_amount} linha(s)' + items: '{items_amount} item(ns)' + permissions: '{permissions_amount} permissão(ões)' + and: e bucket: - water: Balde de água lava: Balde de lava milk: Balde de leite snow: Balde de neve + water: Balde de água click: - right: Clique direito left: Clique esquerdo - shift-right: Shift-clique direito - shift-left: Shift-clique esquerdo middle: Clique do meio - amounts: - items: '{0} item(ns)' - comparisons: '{0} comparação(ões)' - dialogLines: '{0} linha(s)' - permissions: '{0} permissão(ões)' - mobs: '{0} mob(s)' - ticks: '{0} ticks' - questItemLore: '§oItem da Missão' - hologramText: '§8§lQuest NPC' - poolHologramText: '§eNova missão disponível!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eTipo de entidade: {0}' - entityTypeAny: '§eQualquer entidade' - enabled: Ativado + right: Clique direito + shift-left: Shift-clique esquerdo + shift-right: Shift-clique direito + comparison: + different: diferente de {number} + equals: igual a {number} + greater: estritamente maior que {number} + greaterOrEquals: maior que {number} + less: estritamente menor que {number} + lessOrEquals: menor do que {number} disabled: Desabilitado - unknown: desconhecido + enabled: Ativado + entityType: '§eTipo de entidade: {entity_type}' + entityTypeAny: '§eQualquer entidade' + format: + prefix: '§6<§e§lQuests§r§6> §r' + hologramText: '§8§lQuest NPC' + 'no': 'Não' notSet: '§cnão definido' - unused: '§2§lNão usado' - used: '§a§lUsado' - remove: '§7Clique com o botão do meio para remover.' + or: ou + poolHologramText: '§eNova missão disponível!' + questItemLore: '§oItem da Missão' removeRaw: Excluir + requirement: + class: '§bClasse(s) necessária(s)' + combatLevel: '§bNível de combate necessário' + equipment: '§eEquipamento necessário' + experienceLevel: '§bNível de experiência necessário' + faction: '§bFacção(ões) obrigatória(s)' + jobLevel: '§bNível de trabalho necessário' + logicalOr: '§dOperador OU (requisitos)' + mcMMOSkillLevel: '§dNível de habilidade necessário' + money: '§dDinheiro necessário' + permissions: '§3Permissão(ões) obrigatória(s)' + placeholder: '§bValor de placeholder obrigatório' + quest: '§aMissão necessária' + region: '§dRegião necessária' + scoreboard: '§dPontuação necessária' + skillAPILevel: '§bSkillAPI nível necessário' reset: Redefinir - or: ou - amount: '§eQuantidade: {0}' - items: Itens - expPoints: pontos de experiência + stageType: + Bucket: Encher balde + Craft: Craftar item + Enchant: Encantar itens + Fish: Pegar peixes + Melt: Derreter itens + breedAnimals: Procriar animais + chat: Escreva no chat + dealDamage: Causar dano + die: Morrer + eatDrink: Comer ou beber + interact: Interagir com bloco + items: Traga itens de volta + location: Encontrar localização + mine: Quebrar blocos + mobs: Matar mobs + npc: Encontrar NPC + placeBlocks: Colocar blocos + playTime: Tempo de jogo + region: Encontrar região + tameAnimals: Domar animais + time: + days: '{days_amount} dias' + hours: '{hours_amount} horas' + lessThanAMinute: menos de um minuto + minutes: '{minutes_amount} minutos' + weeks: '{weeks_amount} semanas' + unknown: desconhecido 'yes': 'Sim' - 'no': 'Não' - and: e +msg: + bringBackObjects: Traga-me de volta {items}. + command: + adminModeEntered: '§aVocê entrou no Modo Admin.' + adminModeLeft: '§aVocê saiu do Modo Admin.' + backupCreated: '§6Você criou backups de todas as missões e informações de jogadores com sucesso.' + backupPlayersFailed: '§cFalha ao criar um backup de todas as informações dos jogadores.' + backupQuestsFailed: '§cFalha ao criar um backup de todas as missões.' + cancelQuest: '§6Você cancelou a missão {quest}.' + cancelQuestUnavailable: '§cA missão {quest} não pode ser cancelada.' + checkpoint: + noCheckpoint: '§cNenhum checkpoint encontrado para a missão {quest}.' + questNotStarted: '§cVocê não está fazendo esta missão.' + downloadTranslations: + downloaded: '§aIdioma {lang} foi baixado! §7Você precisa editar o arquivo "/plugins/BeautyQuests/config.yml" para alterar o valor de §ominecraftTranslationsFile§7 para {lang}, então reinicie o servidor.' + exists: '§cO arquivo {file_name} já existe. Acrescente "-overwrite" ao seu comando para substituí-lo. (/quests downloadTranslations <idioma> -overwrite)' + notFound: '§cIdioma {lang} não foi encontrado para a versão {version}.' + syntax: '§cVocê deve especificar um idioma para baixar. Exemplo: "/quests downloadTranslations pt_BR".' + help: + adminMode: '§6/ adminMode:{label} §eAlterne o Modo Admin. (Útil para exibir pequenas mensagens de registro).' + create: '§6/{label} create: §eCriar uma missão.' + downloadTranslations: '§6/{label} downloadTranslations <idioma>: §eBaixa um arquivo de tradução padrão' + edit: '§6/{label} edit: §eEdita uma missão.' + finishAll: '§6/{label} finishAll <player>: §eTermina todas as missões de um jogador.' + header: '§6§lBeautyQuests — Ajuda' + list: '§6/{label} list: §eVeja a lista de quests. (Somente para versões suportadas).' + reload: '§6/{label} reload: §eSalvar e recarregar todas as configurações e arquivos. (§cobsoleto§e)' + remove: '§6/{label} remove <id>: §eExclua uma missão com um id específico ou clique no NPC quando não for definido.' + resetPlayer: '§6/{label} resetPlayer <jogador>: §eRemove todas as informações sobre um jogador.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <jogador> [id]: §eExclui informações de uma missão de um jogador.' + save: '§6/{label} save: §eFaz um salvamento manual do plugin.' + seePlayer: '§6/{label} seePlayer <jogador>: §eVer informações sobre um jogador.' + setFirework: '§6/{label} setFirework: §eEditar os fogos de artifício padrão.' + setItem: '§6/{label} setItem <conversar|lançamento>: §eSalve o item de holograma.' + setStage: '§6/{label} setStage <jogador> <id> [novo ramo] [novo estágio]: §ePula o estágio atual/inicia o ramo/define um estágio para um ramo.' + start: '§6/{label} start <jogador> [id]: §eForce o início de uma missão.' + startDialog: '§6/{label} startDialog <jogador> <id da missão>: §eInicia a caixa de diálogo pendente para um estágio de NPC ou a caixa de diálogo inicial para uma missão.' + version: '§6/{label} version: §eVeja a versão atual do plugin.' + invalidCommand: + simple: '§cEste comando não existe, escreva §ehelp§c.' + itemChanged: '§aO item foi editado. As mudanças terão efeito após a reinicialização.' + itemRemoved: '§aO item do holograma foi removido.' + leaveAll: '§aVocê forçou o fim de {success} missão(ões). Erros: {errors}' + removed: '§aA missão {quest_name} foi removida com sucesso.' + resetPlayer: + player: '§6Todas as informações de sua(s) {quest_amount} missão(ões) foi/foram excluídas por {deleter_name}.' + remover: '§6Informação(ões) da missão {quest_amount} (e grupos de {quest_pool}) de {player} foi/foram excluídos.' + resetPlayerPool: + full: '§aVocê resetou os dados do grupo {pool} de {player}.' + timer: '§aVocê resetou o temporizador do grupo {pool} de {player}.' + resetPlayerQuest: + player: '§6Todas as informações sobre a missão {quest} foram excluídas por {deleter_name}.' + remover: '§6{player} informações da(s) missão(ões) de {quest} foi/foram apagada(s).' + resetQuest: '§6Dados removidos da missão para {player_amount} jogadores.' + scoreboard: + hidden: '§6O scoreboard do jogador {player_name} foi ocultado.' + lineInexistant: '§cA linha {line_id} não existe.' + lineRemoved: '§6Você removeu a linha {line_id} com sucesso.' + lineReset: '§6Você resetou a linha {line_id} com sucesso.' + lineSet: '§6Você editou a linha {line_id} com sucesso.' + own: + hidden: '§6Seu scoreboard agora está oculto.' + shown: '§6Seu soreboard está visível novamente.' + resetAll: '§6Você redefiniu o scoreboard do jogador {player_name} com sucesso.' + shown: '§6O scoreboard do jogador {player_name} foi exibido.' + setStage: + branchDoesntExist: '§cO ramo com o id {branch_id} não existe.' + doesntExist: '§cO estágio com o id {stage_id} não existe.' + next: '§aO estágio foi ignorado.' + nextUnavailable: '§cA opção "Pular" não está disponível quando o jogador está no final de um ramo.' + set: '§aEstágio {stage_id} iniciado.' + startDialog: + alreadyIn: '§cO jogador já está participando de um diálogo.' + impossible: '§cNão é possível iniciar o diálogo agora.' + noDialog: '§cO jogador não tem nenhum diálogo pendente.' + success: '§aDiálogo iniciado para o jogador {player} na missão {quest}!' + startPlayerPool: + error: Falha ao iniciar o grupo {pool} para {player}. + success: 'Grupo {pool} iniciado para {player}. Resultado: {result}' + startQuest: '§6Você forçou o início da missão {quest} (Player UUID: {player}).' + startQuestNoRequirements: '§cO jogador não atende aos requisitos para a missão {quest}... Acrescente "-overrideRequirements" no final do seu comando para ignorar a verificação de requisitos.' + dialogs: + skipped: '§8§oDiálogo ignorado.' + tooFar: '§5§oVocê está muito longe de {npc_name}...' + editor: + advancedSpawnersMob: 'Escreva o nome do spawner de mob personalizado para matar:' + already: '§cVocê já está no editor.' + availableElements: 'Elementos disponíveis: §e{available_elements}' + blockAmount: '§aEscreva a quantidade de blocos:' + blockData: '§aEscreva o blockdata (blockdatas disponíveis: §7{available_datas}§a):' + blockName: '§aEscreva o nome do bloco:' + blockTag: '§aEscreva a tag de bloco (tags disponíveis: §7{available_tags}§a):' + chat: '§6Você está atualmente no Modo Editor. Escreva "/quests exitEditor" para forçar a saída do editor. (Altamente não recomendado, considere o uso de comandos como "close" ou "cancel" para voltar ao inventário anterior).' + color: 'Informe uma cor no formato hexadecimal (#XXXXX) ou RGB (RED GRE BLU).' + colorNamed: Insira o nome de uma cor. + comparisonTypeDefault: '§aEscolha o tipo de comparação que deseja entre {available}. A comparação padrão é: §e§l{default}§r§a. Digite §onull§r§a para usar.' + dialog: + cleared: '§aRemovida §2§l{amount}§a mensagem(ns).' + edited: '§aMensagem "§7{msg}§a" editada.' + help: + addSound: '§6addSound <id> <som>: §eAdicione um som para uma mensagem.' + clear: '§6clear: §eRemove todas as mensagens.' + close: '§6close: §eValide todas as mensagens.' + edit: '§6edit <id> <mensagem>: §eEdite uma mensagem.' + header: '§6§lBeautyQuests — Ajuda do editor de diálogo' + list: '§6list: §eVeja todas as mensagens.' + nothing: '§6noSender <mensagem>: §eAdicione uma mensagem sem um remetente.' + nothingInsert: '§6nothingInsert <id> <mensagem>: §eInsira uma mensagem sem qualquer prefixo.' + npc: '§6npc <mensagem>: §eAdicione uma mensagem dita pelo NPC.' + npcInsert: '§6npcInsert <id> <mensagem>: §eInsira uma mensagem falada pelo NPC.' + npcName: '§6npcName [nome personalizado do NPC]: §eDefine (ou redefine para o padrão) nome personalizado do NPC no diálogo' + player: '§6player <mensagem>: §eAdiciona uma mensagem dita pelo jogador.' + playerInsert: '§6playerInsert <id> <mensagem>: §eInsira uma mensagem dita pelo jogador.' + remove: '§6remove <id>: §eRemove uma mensagem.' + setTime: '§6setTime <id> <tempo>: §eDefine o tempo (em ticks) antes da próxima mensagem ser reproduzida automaticamente.' + skippable: '§6skippable [true|false]: §eDefine se o diálogo pode ser ignorado ou não' + messageRemoved: '§aMensagem "§7{msg}§a" removida.' + noSender: '§aMensagem "§7{msg}§a" adicionada sem um remetente.' + npc: '§aMensagem "§7{msg}§a" adicionada ao NPC.' + npcName: + set: '§aNome de NPC personalizado definido para §7{new_name}§a (era §7{old_name}§a)' + unset: '§aNome de NPC personalizado redefinido para o padrão (era §7{old_name}§a)' + player: '§aMensagem "§7{msg}§a" adicionada ao jogador.' + skippable: + set: '§aO status de diálogo ignorável foi definido para §7{new_state}§a (era §7{old_state}§a)' + unset: '§aO status do diálogo ignorável foi redefinido para o padrão (era §7{old_state}§a)' + soundAdded: '§aSom "§7{sound}§a" adicionado para a mensagem "§7{msg}§a".' + syntaxRemove: '§cSintaxe correta: remove <id>' + timeRemoved: '§aO tempo foi removido da mensagem {msg}.' + timeSet: '§aTempo foi editado para a mensagem {msg}: agora {time} ticks.' + enter: + list: '§c⚠ §7Você entrou no editor de "lista". Use "add" para adicionar linhas. Digite "help" (sem barra) para obter ajuda. §e§lEscreva "close" para sair do editor.' + subtitle: '§6Escreva "/quests exitEditor" para forçar a saída do editor.' + title: '§6~ Modo Editor ~' + firework: + edited: Fogos de artifício da missão editado! + invalid: Este item não é um fogo de artifício válido. + invalidHand: Você deve manter um fogo de artifício em sua mão principal. + removed: Fogos de artifício da missão removido! + goToLocation: '§aVá ao local desejado para o estágio.' + invalidColor: A cor inserida é inválida. Ela deve ser hexadecimal ou RGB. + invalidPattern: '§cPadrão de regex inválido §4{input}§c.' + itemCreator: + invalidBlockType: '§cTipo de bloco inválido.' + invalidItemType: '§cTipo de item inválido (O item não pode ser um bloco).' + itemAmount: '§aEscreva a quantidade de item(ns):' + itemLore: '§aModifique a lore do item: (Escreva "help" para obter ajuda).' + itemName: '§aEscreva o nome do item:' + itemType: '§aEscreva o nome do tipo de item desejado:' + unknownBlockType: '§cTipo de bloco desconhecido.' + unknownItemType: '§cTipo de item desconhecido.' + mythicmobs: + disabled: '§cMythicMob está desativado.' + isntMythicMob: '§cEste Mob Mítico (Mythic Mob) não existe.' + list: '§aLista de todos os Monstros Míticos (Mythic Mobs):' + noSuchElement: '§cNão existe tal elemento. Os elementos permitidos são: §e{available_elements}' + npc: + choseStarter: '§aEscolha o NPC que inicia a missão.' + enter: '§aClique em um NPC, ou escreva "cancelar".' + notStarter: '§cEsse NPC não é um iniciador de missões.' + pool: + hologramText: '§aEscreva o texto personalizado do holograma para este grupo (ou "null" se você quiser o padrão).' + maxQuests: Escreva a quantidade máxima de missões que podem ser iniciadas neste grupo. + questsPerLaunch: Escreva a quantidade de missões que serão dadas quando jogadores clicarem no NPC. + timeMsg: 'Escreva o tempo necessário para que os jogadores possam pegar uma nova missão. (unidade padrão: dias)' + scoreboardObjectiveNotFound: '§cObjetivo de scoreboard desconhecido.' + selectWantedBlock: '§aClique com a vareta (stick) no bloco desejado para o estágio.' + stage: + location: + typeWorldPattern: '§aEscreva o regex para nomes de mundo:' + text: + argNotSupported: '§cO argumento {arg} não é suportado.' + chooseJobRequired: '§aEscreva o nome da profissão desejada:' + chooseLvlRequired: '§aEscreva a quantidade de níveis necessários:' + chooseMoneyRequired: '§aEscreva a quantidade de dinheiro necessário:' + chooseObjectiveRequired: '§aEscreva o nome do objetivo.' + chooseObjectiveTargetScore: '§aEscreva a pontuação alvo para o objetivo.' + choosePermissionMessage: '§aVocê pode escolher uma mensagem de rejeição se o jogador não tiver a permissão necessária. (Para pular esta etapa, escreva "null").' + choosePermissionRequired: '§aEscreva a permissão necessária para iniciar a missão:' + choosePlaceholderRequired: + identifier: '§aEscreva o nome do placeholder necessário sem o caractere de porcentagem:' + value: '§aEscreva o valor necessário para o placeholder §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aEscreva o nome da região necessária (você deve estar no mesmo mundo).' + chooseSkillRequired: '§aEscreva o nome da habilidade necessária:' + reward: + money: '§aEscreva a quantia do dinheiro recebido:' + permissionName: '§aEscreva o nome da permissão.' + permissionWorld: '§aEscreva o mundo em que a permissão será editada, ou "null" se você quiser que seja global.' + random: + max: '§aEscreva a quantidade máxima de recompensas dadas ao jogador (inclusive).' + min: '§aEscreva a quantidade mínima de recompensas dadas ao jogador (inclusive).' + wait: '§aEscreva a quantidade de ticks do jogo para esperar: (1 segundo = 20 ticks)' + textList: + added: '§aTexto "§7{msg}§a" adicionado.' + help: + add: '§6add <mensagem>: §eAdiciona um texto.' + close: '§6close §eValide os textos adicionados.' + header: '§6§lBeautyQuests — Ajuda do editor de lista' + list: '§6list: §eVeja todos os textos adicionados.' + remove: '§6remove <id>: §eRemove um texto.' + removed: '§aTexto "§7{msg}§a" removido.' + syntax: '§cSintaxe correta: ' + title: + fadeIn: Escreva a duração do "fade-in", em ticks (20 ticks = 1 segundo). + fadeOut: Escreva a duração do "fade-out", em ticks (20 ticks = 1 segundo). + stay: Escreva a duração da "permanência", em ticks (20 ticks = 1 segundo). + subtitle: Escreva o texto da legenda (ou "null" se você não quiser nenhum). + title: Escreva o texto do título (ou "null" se você não quiser nenhum). + typeBucketAmount: '§aEscreva a quantidade de baldes para encher:' + typeDamageAmount: 'Escreva a quantidade de dano que o jogador tem de causar:' + typeGameTicks: '§aEscrever os ticks necessários do jogo:' + typeLocationRadius: '§aEscreva a distância necessária até o local:' + errorOccurred: '§cOcorreu um erro, entre em contato com um administrador! §4§lCódigo de erro: {error}' + experience: + edited: '§aVocê mudou a experiência ganha de {old_xp_amount} para {xp_amount} pontos.' + indexOutOfBounds: '§cO número {index} está fora dos limites! Ele deve estar entre {min} e {max}.' + invalidBlockData: '§cO blockdata {block_data} é inválido ou incompatível com o bloco {block_material}.' + invalidBlockTag: '§cTag de bloqueio {block_tag} indisponível.' + inventoryFull: '§cSeu inventário está cheio, o item foi dropado no chão.' + moveToTeleportPoint: '§aVá para o local de teletransporte desejado.' + npcDoesntExist: '§cO NPC com o id {npc_id} não existe.' + number: + invalid: '§c{input} não é um número válido.' + negative: '§cVocê deve digitar um número positivo!' + notInBounds: '§cSeu número deve estar entre {min} e {max}.' + zero: '§cVocê deve inserir um número diferente de 0!' + pools: + allCompleted: '§7Você completou todas as missões!' + maxQuests: '§cVocê não pode ter mais que {pool_max_quests} missão(ões) ao mesmo tempo...' + noAvailable: '§7Não há mais missões disponíveis...' + noTime: '§cVocê deve esperar {time_left} antes de fazer outra missão.' + quest: + alreadyStarted: '§cVocê já iniciou a missão!' + cancelling: '§cProcesso de criação da missão cancelado.' + createCancelled: '§cA criação ou edição foi cancelada por outro plugin!' + created: '§aParabéns! Você criou a missão §e{quest}§a que inclui {quest_branches} ramo(s)!' + editCancelling: '§cProcesso de edição da missão cancelado.' + edited: '§aParabéns! Você editou a missão §e{quest}§a que agora inclui {quest_branches} ramo(s)!' + finished: + base: '§aParabéns! Você terminou a missão §e{quest_name}§a!' + obtain: '§aVocê recebeu {rewards}!' + invalidID: '§cA missão com o ID {quest_id} não existe.' + invalidPoolID: '§cO grupo {pool_id} não existe.' + notStarted: '§cVocê não está fazendo esta missão no momento.' + started: '§aVocê iniciou a missão §r§e{quest_name}§o§6!' + questItem: + craft: '§cVocê não pode usar um item da missão para craftar!' + drop: '§cVocê não pode dropar um item da missão!' + eat: '§cVocê não pode comer um item de missão!' + quests: + checkpoint: '§7Checkpoint da missão alcançado!' + failed: '§cVocê falhou na missão {quest_name}...' + maxLaunched: '§cVocê não pode ter mais que {quests_max_amount} missão(ões) ao mesmo tempo...' + updated: '§7Missão §e{quest_name}§7 atualizada.' + regionDoesntExists: '§cEsta região não existe. (Você precisa estar no mesmo mundo).' + requirements: + combatLevel: '§cSeu nível de combate deve ser {long_level}!' + job: '§cSeu nível de trabalho §e{job_name}§c deve ser {long_level}!' + level: '§cSeu nível deve ser {long_level}!' + money: '§cVocê deve ter {money}!' + quest: '§cVocê precisa ter concluído a missão §e{quest_name}§c!' + skill: '§cSeu nível para a habilidade §e{skill_name}§c deve ser {long_level}!' + waitTime: '§cVocê deve esperar {time_left} antes de reiniciar esta missão!' + restartServer: '§7Reinicie seu servidor para ver as modificações.' + selectNPCToKill: '§aSelecione o NPC para matar.' + stageMobs: + listMobs: '§aVocê deve matar {mobs}.' + typeCancel: '§aEscreva "cancel" para voltar ao último texto.' + versionRequired: 'Versão necessária: §l{version}' + writeChatMessage: '§aEscreva a mensagem obrigatória: (Adicionar "{SLASH}" no início se quiser um comando).' + writeCommand: '§aEscreva o comando desejado: (O comando não inclui a barra "/" e suporta o espaço reservado "{PLAYER}". Ele será substituído pelo nome de quem executou o comando.)' + writeCommandDelay: '§aEscreva o atraso do comando desejado, em ticks.' + writeConfirmMessage: '§aEscreva a mensagem de confirmação que mostra quando um jogador está prestes a iniciar a missão: (Escreva "null" se você quiser a mensagem padrão).' + writeDescriptionText: '§aEscreva o texto que descreva o objetivo do estágio:' + writeEndMsg: '§aEscreva a mensagem que será enviada no final da missão, "null" se você quiser o padrão ou "none" se você não quiser nenhum. Você pode usar "{rewards}", que será substituído pelas recompensas recebidas.' + writeEndSound: '§aEscreva o nome do som que será tocado ao jogador no final da missão, "null" se você quiser o padrão ou "none" se você não quiser nenhum:' + writeHologramText: '§aEscreva o texto do holograma: (Escreva "none" se você não quiser um holograma e "null" se você quiser o texto padrão.)' + writeMessage: '§aEscreva a mensagem que será enviada ao jogador' + writeMobAmount: '§aEscreva a quantidade de mobs para matar:' + writeMobName: '§aEscreva o nome personalizado do mob para matar:' + writeNPCText: '§aEscreva o diálogo que será dito ao jogador pelo NPC: (Escreva "help" para receber ajuda).' + writeNpcName: '§aEscreva o nome do NPC:' + writeNpcSkinName: '§aEscreva o nome da skin do NPC:' + writeQuestDescription: '§aEscreva a descrição da missão, mostrada no menu da missão do jogador.' + writeQuestMaterial: '§aEscreva o material do item da missão.' + writeQuestName: '§aEscreva o nome da sua missão:' + writeQuestTimer: '§aEscreva o tempo necessário (em minutos) antes de poder reiniciar a missão: (Escreva "null" se você quiser o temporizador padrão).' + writeRegionName: '§aEscreva o nome da região necessária para a etapa:' + writeStageText: '§aEscreva o texto que será enviado ao jogador no início da etapa:' + writeStartMessage: '§aEscreva a mensagem que será enviada no início da missão, "null" se você quiser o padrão ou "none" se você não quiser nenhum:' + writeXPGain: '§aEscreva a quantidade de pontos de experiência que o jogador irá receber: (Último valor: {xp_amount})' +scoreboard: + asyncEnd: '§ex' + name: '§6§lMissões' + noLaunched: '§cNenhuma missão em andamento.' + noLaunchedDescription: '§c§oCarregando' + noLaunchedName: '§c§lCarregando' + stage: + breed: '§eProcrie §6{mobs}' + bucket: '§eEncha §6{buckets}' + chat: '§eEscreva §6{text}' + craft: '§eCrafte §6{items}' + dealDamage: + any: '§cCause {damage_remaining} de dano' + mobs: '§cCause {damage_remaining} de dano para {target_mobs}' + die: '§cMorra' + eatDrink: '§eConsuma §6{items}' + enchant: '§eEncante §6{items}' + fish: '§ePeixe §6{items}' + interact: '§eClique no bloco em §6{x}' + interactMaterial: '§eClique em um bloco de §6{block}§e' + items: '§eTraga itens para §6{dialog_npc_name}§e:' + location: '§eVá para §6{target_x}§e, §6{target_y}§e, §6{target_z}§e em §6{target_world}' + melt: '§eDerreta §6{items}' + mine: '§eMinere {blocks}' + mobs: '§eMate §6{mobs}' + npc: '§eFale com o NPC §6{dialog_npc_name}' + placeBlocks: '§eColoque {blocks}' + playTimeFormatted: '§eJogue §6{time_remaining_human}' + region: '§eEncontre a região §6{region_id}' + tame: '§eDome §6{mobs}' + textBetwteenBranch: '§e ou' diff --git a/core/src/main/resources/locales/pt_PT.yml b/core/src/main/resources/locales/pt_PT.yml index 776b246f..b06749be 100644 --- a/core/src/main/resources/locales/pt_PT.yml +++ b/core/src/main/resources/locales/pt_PT.yml @@ -1,527 +1,481 @@ --- -msg: - quest: - finished: - base: '§aParabéns! Terminaste a missão §e{0}§a!' - obtain: '§aObtiveste {0}!' - started: '§aComeçaste a missão §r§e{0}§o§6!' - created: '§aParabéns! Criaste a missão §e{0}§a que tem {1} ramo(s)!' - edited: '§aParabéns! Editaste a missão §e{0}§a que tem agora {1} ramo(s)!' - createCancelled: '§cA criação ou edição foi cancelada por outro plugin!' - cancelling: '§cO processo de criação de missão foi cancelado.' - editCancelling: '§cO processo de edição de missão foi cancelado.' - invalidID: '§cA missão com o id {0} não existe.' - alreadyStarted: '§cJá iniciaste a missão!' - quests: - maxLaunched: '§cVocê não pode ter mais de {0} missões ao mesmo tempo...' - nopStep: '§cEsta missão não tem nenhum passo.' - updated: '§7Missão §e{0}§7 atualizada.' - failed: '§cVocê falhou na missão {0}...' - pools: - noAvailable: '§7TNão existe missões disponíveis...' - stageMobs: - noMobs: '§cNesta etapa não é preciso matar nenhum mob.' - listMobs: '§aDeves matar {0}.' - writeNPCText: '§aEscreve o diálogo que será dito ao jogador pelo NPC: (Escreve "help" para receber ajuda.)' - writeRegionName: '§aEscreve o nome da região necessária para a etapa:' - writeXPGain: '§aEscreve a quantidade de pontos de experiência que o jogador obterá: (Último valor: {0})' - writeMobAmount: '§aEscreve a quantidade de mobs para matar:' - writeChatMessage: '§aEscreve a mensagem necessária: (Adiciona "{SLASH}" no início, caso quiseres um comando.)' - writeEndMessage: '§aEscreve a mensagem que será enviada no final da missão ou na etapa:' - writeDescriptionText: '§aEscreve o texto que descreve o objetivo da etapa:' - writeStageText: '§aEscreve o texto que será enviado para o jogador no início da etapa:' - moveToTeleportPoint: '§aVai ao local de teleporte desejado.' - writeNpcName: '§aEscreve o nome do NPC:' - writeNpcSkinName: '§aEscreve o nome da skin do NPC:' - writeQuestName: '§aEscreve o nome da missão:' - writeCommand: '§aEscreve o comando desejado: (O comando está sem o "/" e o espaço reservado "{PLAYER}" é suportado. Ele será substituído pelo nome do executor.)' - writeHologramText: '§aEscreve o texto do holograma: (Escreve "none" se não queres um holograma e "null" se queres o texto padrão.)' - writeQuestTimer: '§aEscreve o tempo necessário (em minutos) antes de reiniciar a missão: (Escreve "null" se desejas o temporizador padrão.)' - writeConfirmMessage: '§aEscreve a mensagem de confirmação mostrada quando um jogador está prestes a iniciar a missão: (Escreve "null" se queres a mensagem padrão.)' - writeQuestDescription: '§aEscreva a descrição da missão, exibida no meno de missões do jogador.' - requirements: - quest: '§cTens que ter terminado a missão §e{0}§c!' - money: '§cVocê tem que ter {0}!' - waitTime: '§cVocê deve esperar {0} antes de reiniciar esta missão!' - experience: - edited: '§aAlteraste a experiência adquirida de {0} para {1} pontos.' - selectNPCToKill: '§aSeleciona o NPC para matar.' - npc: - remove: '§aNPC apagado.' - talk: '§aVai e fala com o NPC chamado §e{0}§a.' - regionDoesntExists: '§cEsta região não existe. (Precisas de estar no mesmo mundo.)' - npcDoesntExist: '§cO NPC com o id {0} não existe.' - objectDoesntExist: '§cO item com o id especificado {0} não existe.' - number: - negative: '§cDeves inserir um número positivo!' - zero: '§cDeves inserir um número diferente de 0!' - invalid: '§c{0} não é um número válido.' - errorOccurred: '§cOcorreu um erro, entra em contacto com um administrador! §4§lCódigo de erro: {0}' - commandsDisabled: '§cNo momento, não tens permissão para executar comandos!' - indexOutOfBounds: '§cO número {0} está fora dos limites! Deve estar entre {1} e {2}.' - invalidBlockData: '§cAs configurações desse bloco {0} é inválida ou incompatível com o bloco {1}.' - bringBackObjects: Traz-me {0} de volta. - inventoryFull: '§cO teu inventário está cheio, o item foi largado no chão.' - playerNeverConnected: '§cNão foi possível encontrar informações sobre o jogador {0}.' - playerNotOnline: '§cO jogador {0} está offline.' - command: - setStage: - branchDoesntExist: '§cO ramo com o id {0} não existe.' - doesntExist: '§cA etapa com o id {0} não existe.' - next: '§aA etapa foi ignorada.' - nextUnavailable: '§cThe "skip" option is not available when the player is at the end of a branch.' - set: '§aA etapa {0} foi lançada.' - playerNeeded: '§cDeves ser um jogador para executar este comando!' - incorrectSyntax: '§cSintaxe incorreto.' - noPermission: '§cVocê não tem permissões suficientes para executar este comando! (Requer: {0})' - invalidCommand: - quests: '§cEste comando não existe, escreve §e/quests help§c.' - simple: '§cEste comando não existe, escreve §ehelp§c.' - needItem: '§cDeves segurar um item na tua mão principal!' - itemChanged: '§aO item foi editado. As alterações afetarão após uma reinicialização.' - itemRemoved: '§aO item do holograma foi removido.' - removed: '§aA missão {0} foi removida com sucesso.' - leaveAll: '§aFoste forçado a terminar {0} missão(ões). Erros: {1}' - resetPlayer: - player: '§6Todas as informações da(s) tua(s) {0} missão(ões) foram apagadas por {1}.' - remover: '§6A/s {0} informação/ões de {1} foi/foram excluída/s.' - resetPlayerQuest: - player: '§6Todas as informações da missão {0} foram apagadas por {1}.' - remover: '§6Informações da missão(ões) de {0} de {1} foi/foram apagada(s).' - startQuest: '§6Foste forçado a iniciar a missão {0} (UUID de Jogador: {1}).' - cancelQuest: '§6Cancelaste a missão {0}.' - cancelQuestUnavailable: '§cA missão {0} não pode ser cancelada.' - backupCreated: '§6Criaste com sucesso, cópias de segurança de todas as informações e de missões e jogadores.' - backupPlayersFailed: '§cA criação de cópias de segurança de todas as informações de jogadores falhou.' - backupQuestsFailed: '§cA criação de cópias de segurança para todas as missões, falhou.' - adminModeEntered: '§aEntraste no Modo Admin.' - adminModeLeft: '§aSaíste do Modo Admin.' - scoreboard: - lineSet: '§6Editaste a linha {0} com sucesso.' - lineReset: '§6Redefiniste a linha {0} com sucesso.' - lineRemoved: '§6Removeste a linha {0} com sucesso.' - lineInexistant: '§cA linha {0} não existe.' - resetAll: '§6Redefiniste com sucesso o placar de classificação do jogador {0}.' - hidden: '§6O placar do jogador {0} foi ocultado.' - shown: '§6O placar do jogador {0} foi exibido.' - help: - header: '§6§lBeautyQuests — Ajuda' - create: '§6/{0} create: §eCriar uma missão.' - edit: '§6/{0} edit: §eEditar uma missão.' - remove: '§6/{0} remove [id]: §eApagar uma missão com um id especificado ou clicar no NPC quando não definido.' - finishAll: '§6/{0} finishAll <player>: §eFinish all quests of a player.' - setStage: '§6/{0} setStage <player> <id> [new branch] [new stage]: §eSkip the current stage/start the branch/set a stage for a branch.' - resetPlayer: '§6/{0} resetPlayer <player>: §eRemove todas as informações sobre um jogador.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <player> [id]: §eApagar as informações duma missão para um jogador.' - seePlayer: '§6/{0} seePlayer <player>: §eVer todas as informações sobre um jogador.' - reload: '§6/{0} reload: §eGuarda e recarrega todas as configurações e ficheiros. (§cdeprecated§e)' - start: '§6/{0} start <player> [id]: §eForçar o início de uma missão.' - setItem: '§6/{0} setItem <talk|launch>: §eGuarda o item de holograma.' - adminMode: '§6/{0} adminMode: §eAlterna o Modo Admin. (Útil para exibir pequenas mensagens de registo.)' - version: '§6/{0} version: §eVer a versão atual do plugin.' - save: '§6/{0} save: §eFazer um salvamento manual de plugin.' - list: '§6/{0} list: §eVer a lista de missões. (Somente para versões suportadas.)' - typeCancel: '§aEscreve "cancel" para voltar ao último texto.' - editor: - blockAmount: '§aEspecifique a quantidade de blocos:' - blockData: '§aEspecifique as configurações do bloco (Configurações disponíveis: {0}):' - typeBucketAmount: '§aEspecifique a quantidade de baldes para encher:' - goToLocation: '§aVá ao local desejado para o estágio.' - typeLocationRadius: '§aEspecifique a distância necessária até o local:' - typeGameTicks: '§aEspecifique os TICKS necessários:' - already: '§cJá estás no editor.' - enter: - title: '§6~ Modo Editor ~' - subtitle: '§6Escreva "/quests exitEditor" para sair do editor.' - chat: '§6Você está atualmente no modo Editor. Escreva "/quests exitEditor" para sair do editor. (Altamente não recomendado, considere usar comandos como "fechar" ou "cancelar" para voltar á aba anterior.)' - npc: - enter: '§aClica num NPC, ou escreve "cancel".' - choseStarter: '§aEscolhe o NPC que inicia a missão.' - notStarter: '§cEste NPC não é um iniciador de missões.' - text: - argNotSupported: '§cO argumento {0} não é suportado.' - chooseLvlRequired: '§aEscreve a quantidade necessária de níveis:' - chooseJobRequired: '§aEscreve o nome do trabalho desejado:' - choosePermissionRequired: '§aEscreve a permissão necessária para iniciar a missão:' - choosePermissionMessage: '§aPodes escolher uma mensagem de rejeição caso o jogador não tiver a permissão necessária. (Para ignorar esta etapa, escreve "null".)' - choosePlaceholderRequired: - identifier: '§aEscreve o nome do espaço reservado obrigatório sem os caracteres percentuais:' - value: '§aEscreva o valor necessário para o placeholder §e%§e{0}§e%§a:' - chooseSkillRequired: '§aEscreve o nome da habilidade necessária:' - chooseMoneyRequired: '§aEscreva a quantidade de dinheiro necessário:' - reward: - permissionName: '§aEscreva o nome da permissão.' - permissionWorld: '§aEscreva o mundo em que a permissão será editada, ou "null" se você quiser ser global.' - money: '§aEscreve a quantidade do dinheiro recebido:' - wait: '§aEscreva a quantidade de TICKS para esperar: (1 segundo = 20 ticks)' - chooseObjectiveRequired: '§aEscreva o nome do objetivo.' - chooseObjectiveTargetScore: '§aEspecifique a pontuação necessária para o objetivo.' - chooseRegionRequired: '§aEscreva o nome da região necessária (você deve estar no mesmo mundo).' - selectWantedBlock: '§aClica com o pau no bloco desejado para a etapa.' - itemCreator: - itemType: '§aEscreve o nome do tipo de item desejado:' - itemAmount: '§aEscreva a quantidade de item(ns):' - itemName: '§aEscreve o nome do item:' - itemLore: '§aModifica o conhecimento do item: (Escreve "help" para obter ajuda.)' - unknownItemType: '§cTipo de item desconhecido.' - invalidItemType: '§cTipo de item inválido. (O item não pode ser um bloco.)' - unknownBlockType: '§cTipo de bloco não reconhecido ou não existe.' - invalidBlockType: '§cTipo de bloco inválido' - dialog: - syntax: '§cSintaxe correta: {0}{1} <message>' - syntaxRemove: '§cSintaxe correta: remove <id>' - player: '§aMensagem "{0}" adicionada para o jogador.' - npc: '§aMensagem "{0}" adicionada para o NPC.' - noSender: '§aMensagem "{0}" adicionada sem um remetente.' - messageRemoved: '§aMensagem "{0}" removida.' - edited: '§aMensagem "{0}" editada.' - soundAdded: '§aSom "{0}" adicionado para a mensagem "{1}".' - cleared: '§a{0} removeu a(s) mensagem(s).' - help: - header: '§6§lBeautyQuests — Ajuda do editor de diálogo' - npc: '§6npc [message]: §eAdiciona uma mensagem dita pelo NPC.' - player: '§6player [message]: §eAdiciona uma mensagem dito pelo jogador.' - nothing: '§6noSender [message]: §eAdiciona uma mensagem sem um remetente.' - remove: '§6remove [id]: §eRemove uma mensagem.' - list: '§6list: §eVer todas as mensagens.' - npcInsert: '§6npcInsert [id] [message]: §eAdiciona uma mensagem dita pelo NPC.' - playerInsert: '§6playerInsert [id] [message]: §eAdiciona uma mensagem dita pelo jogador.' - nothingInsert: '§6nothingInsert [id] [message]: §eAdiciona uma mensagem sem prefixo.' - edit: '§6edit <id> <message>: §eEdita uma mensagem.' - addSound: '§6addSound [id] [sound]: §eAdiciona um som para uma mensagem.' - clear: '§6clear: §eRemove todas as mensagens.' - close: '§6close: §eValida todas as mensagens.' - setTime: '§6setTime <id> <time>: §eDefiniu o tempo (em ticks) antes da próxima mensagem ser reproduzida automaticamente.' - timeSet: '§aTempo foi editado para a mensagem {0}: agora é {1} ticks.' - timeRemoved: '§aO tempo da mensagem foi removido{0}.' - mythicmobs: - list: '§aUma lista de todos os Mobs Míticos:' - isntMythicMob: '§cEste Mob Mítico não existe.' - disabled: '§cMythicMob está desativado.' - epicBossDoesntExist: '§cEste Boss Épico não existe.' - textList: - syntax: '§cSintaxe correta: ' - added: '§aTexto "{0}" adicionado.' - removed: '§aTexto "{0}" removido.' - help: - header: '§6§lBeautyQuests — Ajuda do editor de lista' - add: '§6add [message]: §eAdiciona um texto.' - remove: '§6remove [id]: §eRemove um texto.' - list: '§6list: §eVer todos os textos.' - close: '§6close: §eValidar os textos adicionados.' - noSuchElement: '§cEsse elemento não existe. Os elementos permitidos são: §e{0}' - comparisonType: '§aEscolha o tipo de comparação que deseja entre {0}. A comparação padrão é: §e§lmaior ou igual§r§a. Digite §onull§r§a para utilizá-lo.' - scoreboardObjectiveNotFound: '§cObjetivo de placar desconhecido' - pool: - maxQuests: 'Escreva a quantidade máxima de missões possíveis neste pool.' - time: 'Escreva o número de dias antes que os jogadores possam fazer uma nova missão.' advancement: finished: Concluído notStarted: Não iniciado +indication: + cancelQuest: '§7Tens a certeza de que desejas cancelar a missão {quest_name}?' + closeInventory: '§7Tens a certeza que desejas fechar o GUI?' + removeQuest: '§7Tens a certeza de que desejas remover a missão {quest}?' + startQuest: '§7Desejas iniciar a missão {quest_name}?' inv: - validate: '§b§lValidar' - cancel: '§c§lCancelar' - search: '§e§lProcurar' addObject: '§aAdicionar um objeto' + block: + name: Escolher bloco + blocksList: + addBlock: '§aClica para adicionar um bloco.' + name: Selecionar blocos + buckets: + name: Tipo de balde + cancel: '§c§lCancelar' + chooseAccount: + name: Qual conta? + chooseQuest: + name: Qual missão? + classesList.name: Lista de Classes + classesRequired.name: '§bClasses necessárias' + command: + console: Consola + delay: '§bAtraso' + name: Comando + value: '§eComando' + commandsList: + console: '§eConsola: {command_console}' + name: Lista de comandos + value: '§eComandos: {command_label}' confirm: name: Tens a certeza? - 'yes': '§aConfirmar' 'no': '§cCancelar' + 'yes': '§aConfirmar' create: - stageCreate: '§aCriar nova etapa' - stageRemove: '§cApagar esta etapa' - findNPC: '§aEncontrar NPC' + NPCText: '§eEditar diálogo' bringBack: '§aTrazer itens de volta' + bucket: '§aEncher baldes' + cancelMessage: Cancelar envio + changeTicksRequired: '§eAlterar a quantidade de tiques jogados necessários' + craft: '§aCriar item' + currentRadius: '§eDistância atual: §6{radius}' + editBlocksMine: '§eEditar blocos para quebrar' + editBlocksPlace: '§eEditar blocos a colocar' + editBucketAmount: '§eEdite a quantidade de baldes para preencher' + editBucketType: '§eEdite o tipo de balde para preencher' + editFishes: '§eEditar peixes para pescar' + editItem: '§eEditar item para criar' + editLocation: '§eEditar a localização' + editMessageType: '§eEditar mensagem para escrever' + editMobsKill: '§eEditar mobs para matar' + editRadius: '§eEditar a distância a partir da localização' + findNPC: '§aEncontrar NPC' findRegion: '§aEncontrar região' + fish: '§aApanhar peixe' + hideClues: Ocultar partículas e hologramas + ignoreCase: Ignorar uso de maiúsculas na mensagem + interact: '§aInteragir com bloco' killMobs: '§aMatar mobs' + leftClick: O clique deve ser com o botão esquerdo + location: Ir para Localização mineBlocks: '§aQuebrar blocos' + mobsKillFromAFar: Precisa de ser morto com projétil placeBlocks: '§aColocar blocos' - talkChat: '§aEscrever no chat' - interact: '§aInteragir com bloco' - fish: '§aApanhar peixe' - craft: '§aCriar item' - bucket: '§aEncher baldes' - location: Ir para Localização playTime: '§eTempo de jogo' - NPCText: '§eEditar diálogo' - hideClues: Ocultar partículas e hologramas - editMobsKill: '§eEditar mobs para matar' - mobsKillFromAFar: Precisa de ser morto com projétil - editBlocksMine: '§eEditar blocos para quebrar' preventBlockPlace: Impede que os jogadores quebrem os seus próprios blocos - editBlocksPlace: '§eEditar blocos a colocar' - editMessageType: '§eEditar mensagem para escrever' - cancelMessage: Cancelar envio - ignoreCase: Ignorar uso de maiúsculas na mensagem + selectBlockLocation: '§eSelecionar localização do bloco' + selectBlockMaterial: '§eSelecionar o material do bloco' selectItems: '§eEditar itens requeridos' selectRegion: '§7Escolher região' - toggleRegionExit: Na saída + stageCreate: '§aCriar nova etapa' + stageRemove: '§cApagar esta etapa' stageStartMsg: '§eEditar mensagem inicial' - selectBlockLocation: '§eSelecionar localização do bloco' - selectBlockMaterial: '§eSelecionar o material do bloco' - leftClick: O clique deve ser com o botão esquerdo - editFishes: '§eEditar peixes para pescar' - editItem: '§eEditar item para criar' - editBucketType: '§eEdite o tipo de balde para preencher' - editBucketAmount: '§eEdite a quantidade de baldes para preencher' - editLocation: '§eEditar a localização' - editRadius: '§eEditar a distância a partir da localização' - currentRadius: '§eDistância atual: §6{0}' - changeTicksRequired: '§eAlterar a quantidade de tiques jogados necessários' - stages: - name: Criar etapas - nextPage: '§ePróxima página' - laterPage: '§ePágina anterior' - endingItem: '§eEditar recompensas finais' - descriptionTextItem: '§eEditar descrição' - regularPage: '§aEtapas regulares' - branchesPage: '§dRamo de etapas' - previousBranch: '§eVoltar ao ramo anterior' - newBranch: '§eIr para o novo ramo' - validationRequirements: '§eRequisitos de Validação' - validationRequirementsLore: Todos os requisitos devem corresponder ao jogador que tente terminar a etapa. Se não, a etapa não pode ser completada. + talkChat: '§aEscrever no chat' + toggleRegionExit: Na saída details: - hologramLaunch: '§eEditar item holograma de "lançamento"' - hologramLaunchLore: Holograma mostrada acima da cabeça do NPC Inicial quando o jogador puder começar a missão. - hologramLaunchNo: '§eEditar item holograma de "launch unavailable"' - hologramLaunchNoLore: Holograma mostrada acima da cabeça do NPC Inicial quando o jogador NÃO puder começar a missão. + bypassLimit: Não contar limite de missão + cancellable: Pode ser cancelado pelo jogador + cancellableLore: Permite que o jogador cancele a missão através do seu Menu de Missões. + createQuestLore: Você deve definir um nome para a missão. + createQuestName: '§lCriar missão' customConfirmMessage: '§eEditar mensagem de confirmação da missão' customConfirmMessageLore: Mensagem mostrada na Interface de Confirmação quando um jogador está prestes a começar a missão. customDescription: '§eEditar descrição da missão' customDescriptionLore: Descrição mostrada abaixo do nome da missão nas interfaces. - name: Detalhes da última missão + editQuestName: '§lEditar missão' + editRequirements: '§eEditar requisitos' + endMessage: '§eEditar mensagem final' + endMessageLore: A mensagem será enviada para o jogador ao final da missão. + hologramLaunch: '§eEditar item holograma de "lançamento"' + hologramLaunchLore: Holograma mostrada acima da cabeça do NPC Inicial quando o jogador puder começar a missão. + hologramLaunchNo: '§eEditar item holograma de "launch unavailable"' + hologramLaunchNoLore: Holograma mostrada acima da cabeça do NPC Inicial quando o jogador NÃO puder começar a missão. + hologramText: '§eTexto do holograma' multipleTime: + itemLore: A missão pode ser feita várias vezes? itemName: Ligar/desligar repetição - itemLore: "A missão pode ser feita\nvárias vezes?" - cancellable: Pode ser cancelado pelo jogador - cancellableLore: Permite que o jogador cancele a missão através do seu Menu de Missões. - startableFromGUI: Iniciável a partir da Interface - startableFromGUILore: Permite que o jogador comece a missão através do Menu de Missões + name: Detalhes da última missão + questName: '§a§lEditar nome da missão' + requirements: '{amount} requisito(s)' + rewards: '{amount} recompensa(s)' scoreboardItem: Ativar painel de classificação scoreboardItemLore: Se desativado, a missão não será rastreada através do scoreboard. - hideItem: Ocultar menu e mapa dinâmico - bypassLimit: Não contar limite de missão - questName: '§a§lEditar nome da missão' + selectStarterNPC: '§e§lSelecionar iniciador de NPC' setItemsRewards: '§eEditar itens de recompensa' - setXPRewards: '§eEditar experiência de recompensa' - setPermReward: '§eEditar permissões' setMoneyReward: '§eEditar recompensa monetária' - selectStarterNPC: '§e§lSelecionar iniciador de NPC' - createQuestName: '§lCriar missão' - createQuestLore: Você deve definir um nome para a missão. - editQuestName: '§lEditar missão' - endMessage: '§eEditar mensagem final' - endMessageLore: A mensagem será enviada para o jogador ao final da missão. + setPermReward: '§eEditar permissões' + setXPRewards: '§eEditar experiência de recompensa' startDialog: '§eEditar diálogo inicial' - editRequirements: '§eEditar requisitos' startRewards: '§6Recompensas de início' - hologramText: '§eTexto do holograma' - requirements: '{0} requisito(s)' - rewards: '{0} recompensa(s)' - itemsSelect: - name: Editar itens - none: |- - §aMover um item para aqui ou - clicar para abrir o editor de itens. + startableFromGUI: Iniciável a partir da Interface + startableFromGUILore: Permite que o jogador comece a missão através do Menu de Missões + entityType: + name: Escolher tipo de entidade + factionsList.name: Lista de Fações + factionsRequired.name: Fações necessárias + itemComparisons: + name: Comparações de Itens + itemCreator: + isQuestItem: '§bItem de missão:' + itemFlags: Alternar flags de item + itemLore: '§bConhecimento do item' + itemName: '§bNome do item' + itemType: '§bTipo de item' + name: Criador de itens itemSelect: name: Escolher item + itemsSelect: + name: Editar itens + none: '§aMover um item para aqui ou clicar para abrir o editor de itens.' + listAllQuests: + name: Missões + listBook: + noQuests: Nenhuma missão foi criada anteriormente. + questMultiple: Várias vezes + questName: Nome + questRewards: Recompensas + questStages: Etapas + questStarter: Iniciador + requirements: Requisitos + listPlayerQuests: + name: 'Missões de {player_name}' + listQuests: + canRedo: '§3§oPodes reiniciar esta missão!' + finished: Missões concluídas + inProgress: Missões em andamento + notStarted: Missões não iniciadas + mobSelect: + bukkitEntityType: '§eSelecionar tipo de entidade' + epicBoss: '§6Seleciona Boss Épico' + mythicMob: '§6Seleciona Mob Mítico' + name: Escolha o tipo de mob + mobs: + name: Selecionar mobs + none: '§aClica para adicionar um mob.' npcCreate: + move: + itemLore: '§aAlterar a localização do NPC.' + itemName: '§eMover' + moveItem: '§a§lValidar local' name: Criar NPC setName: '§eEditar nome do NPC' setSkin: '§eEditar skin do NPC' setType: '§eEditar tipo de NPC' - move: - itemName: '§eMover' - itemLore: '§aAlterar a localização do NPC.' - moveItem: '§a§lValidar local' npcSelect: + createStageNPC: '§eCriar NPC' name: Selecionar ou criar? selectStageNPC: '§eSelecionar NPC existente' - createStageNPC: '§eCriar NPC' - entityType: - name: Escolher tipo de entidade - chooseQuest: - name: Qual missão? - mobs: - name: Selecionar mobs - none: '§aClica para adicionar um mob.' - mobSelect: - name: Escolha o tipo de mob - bukkitEntityType: '§eSelecionar tipo de entidade' - mythicMob: '§6Seleciona Mob Mítico' - epicBoss: '§6Seleciona Boss Épico' - stageEnding: - locationTeleport: '§eEditar localização do teleporte' - command: '§eEditar comando executado' - requirements: - name: Requisitos - rewards: - name: Recompensas - commands: 'Comandos: {0}' - rewardsWithRequirements: - name: Recompensas com requisitos - listAllQuests: - name: Missões - listPlayerQuests: - name: 'Missões de {0}' - listQuests: - notStarted: Missões não iniciadas - finished: Missões concluídas - inProgress: Missões em andamento - loreCancel: '§c§oClica para cancelar a missão.' - canRedo: '§3§oPodes reiniciar esta missão!' - format: - normal: '§6§l§o{0}' - withId: '§6§l§o{0}§r §e#{1}' - itemCreator: - name: Criador de itens - itemType: '§bTipo de item' - itemFlags: Alternar flags de item - itemName: '§bNome do item' - itemLore: '§bConhecimento do item' - isQuestItem: '§bItem de missão:' - command: - name: Comando - value: '§eComando' - console: Consola - delay: '§bAtraso' - chooseAccount: - name: Qual conta? - listBook: - questName: Nome - questStarter: Iniciador - questRewards: Recompensas - questMultiple: Várias vezes - requirements: Requisitos - questStages: Etapas - noQuests: Nenhuma missão foi criada anteriormente. - commandsList: - name: Lista de comandos - value: '§eComandos: {0}' - console: '§eConsola: {0}' - block: - name: Escolher bloco - material: '§eMaterial: {0}' - blocksList: - name: Selecionar blocos - addBlock: '§aClica para adicionar um bloco.' - buckets: - name: Tipo de balde permission: name: Escolher permissão perm: '§aPermissão' + remove: Remover permissão world: '§aMundo' worldGlobal: '§b§lGlobal' - remove: Remover permissão permissionList: name: Lista de permissões - world: '§eMundo: §6{0}' - classesRequired.name: '§bClasses necessárias' - classesList.name: Lista de Classes - factionsRequired.name: Fações necessárias - factionsList.name: Lista de Fações - poolsManage: - name: Grupo de Missões - itemName: '§aGrupo #{0}' - create: '§aCriar um grupo de missões' + world: '§eMundo: §6{permission_world}' poolCreation: - name: Criação de um grupo de missões hologramText: '§eHolograma personalizado do grupo' maxQuests: '§aMáximo de missões' - time: '§bDefinir tempo entre missões' + name: Criação de um grupo de missões redoAllowed: É permitido refazer? + time: '§bDefinir tempo entre missões' poolsList.name: Grupo de Missões - itemComparisons: - name: Comparações de Itens -scoreboard: - name: '§6§lMissões' - noLaunched: '§cNenhuma missão em andamento.' - noLaunchedName: '§c§lA carregar' - noLaunchedDescription: '§c§oA carregar' - textBetwteenBranch: '§e ou' - stage: - region: '§eLocalizar região §6{0}' - npc: '§eFalar com NPC §6{0}' - items: '§eLevar itens para §6{0}§e:' - mobs: '§eMatar §6{0}' - mine: '§eMinerar {0}' - placeBlocks: '§eColocar {0}' - chat: '§eEscrever §6{0}' - interact: '§eClica no bloco em §6{0}' - interactMaterial: '§eClica em um bloco §6{0}§e' - fish: '§ePescar §6{0}' - craft: '§eCriar §6{0}' - bucket: '§ePreencher §6{0}' - location: '§eVai a §6{0}§e, §6{1}§e, §6{2}§e em §6{3}' - playTime: '§eJoga §6{0} tiques do jogo' -indication: - startQuest: '§7Desejas iniciar a missão {0}?' - closeInventory: '§7Tens a certeza que desejas fechar o GUI?' - cancelQuest: '§7Tens a certeza de que desejas cancelar a missão {0}?' - removeQuest: '§7Tens a certeza de que desejas remover a missão {0}?' + poolsManage: + create: '§aCriar um grupo de missões' + itemName: '§aGrupo #{pool}' + name: Grupo de Missões + requirements: + name: Requisitos + rewards: + commands: 'Comandos: {amount}' + name: Recompensas + rewardsWithRequirements: + name: Recompensas com requisitos + search: '§e§lProcurar' + stageEnding: + command: '§eEditar comando executado' + locationTeleport: '§eEditar localização do teleporte' + stages: + branchesPage: '§dRamo de etapas' + descriptionTextItem: '§eEditar descrição' + endingItem: '§eEditar recompensas finais' + laterPage: '§ePágina anterior' + name: Criar etapas + newBranch: '§eIr para o novo ramo' + nextPage: '§ePróxima página' + previousBranch: '§eVoltar ao ramo anterior' + regularPage: '§aEtapas regulares' + validationRequirements: '§eRequisitos de Validação' + validationRequirementsLore: Todos os requisitos devem corresponder ao jogador que tente terminar a etapa. Se não, a etapa não pode ser completada. + validate: '§b§lValidar' misc: + amount: '§eQuantidade: {amount}' + and: e + bucket: + lava: Balde de lava + milk: Balde de leite + water: Balde de Água + comparison: + different: diferente de {number} + equals: igual a {number} + greater: estritamente maior que {number} + greaterOrEquals: maior que {number} + less: estritamente menor que {number} + lessOrEquals: menos do que {number} + disabled: Desativado + enabled: Ativado + entityType: '§eTipo de entidade: {entity_type}' format: prefix: '§6<§e§lMissões§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - time: - days: '{0} dias' - hours: '{0} horas' - minutes: '{0} minutos' - stageType: - region: Encontrar região - npc: Encontrar NPC - items: Trazer itens de volta - mobs: Matar mobs - mine: Quebrar blocos - placeBlocks: Colocar blocos - chat: Escrever no chat - interact: Interagir com bloco - Fish: Apanhar peixe - Craft: Criar item - Bucket: Preencher balde - location: Encontrar localização - playTime: Tempo de Jogo - comparison: - equals: igual a {0} - different: diferente de {0} - less: estritamente menor que {0} - lessOrEquals: menos do que {0} - greater: estritamente maior que {0} - greaterOrEquals: maior que {0} + hologramText: '§8§Missão de NPC' + 'no': 'Não' + notSet: '§cnão configurado' + or: ou + poolHologramText: '§eNova missão disponível!' + questItemLore: '§e§oItem de Missão' requirement: class: '§bClasse(es) necessária(s)' - faction: '§bFação(ões) necessária(s)' - jobLevel: '§bNível de trabalho necessário' combatLevel: '§bNível de combate necessário' experienceLevel: '§bNíveis de experiência necessários' + faction: '§bFação(ões) necessária(s)' + jobLevel: '§bNível de trabalho necessário' + mcMMOSkillLevel: '§dNível de habilidade necessário' + money: '§dDinheiro necessário' permissions: '§3Permissão(ões) necessária(s)' - scoreboard: '§dPontuação necessária' - region: '§dRegião necessária' placeholder: '§bValor de espaço reservado necessário' quest: '§aMissão necessária' - mcMMOSkillLevel: '§dNível de habilidade necessário' - money: '§dDinheiro necessário' - bucket: - water: Balde de Água - lava: Balde de lava - milk: Balde de leite - questItemLore: '§e§oItem de Missão' - hologramText: '§8§Missão de NPC' - poolHologramText: '§eNova missão disponível!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eTipo de entidade: {0}' - enabled: Ativado - disabled: Desativado + region: '§dRegião necessária' + scoreboard: '§dPontuação necessária' + stageType: + Bucket: Preencher balde + Craft: Criar item + Fish: Apanhar peixe + chat: Escrever no chat + interact: Interagir com bloco + items: Trazer itens de volta + location: Encontrar localização + mine: Quebrar blocos + mobs: Matar mobs + npc: Encontrar NPC + placeBlocks: Colocar blocos + playTime: Tempo de Jogo + region: Encontrar região + time: + days: '{days_amount} dias' + hours: '{hours_amount} horas' + minutes: '{minutes_amount} minutos' unknown: desconhecido - notSet: '§cnão configurado' - unused: '§2§lInutilizado' - used: '§a§lUtilizado' - remove: '§7Botão do meio para remover' - or: ou - amount: '§eQuantidade: {0}' - items: itens - expPoints: pontos de experiência 'yes': 'Sim' - 'no': 'Não' - and: e +msg: + bringBackObjects: Traz-me {items} de volta. + command: + adminModeEntered: '§aEntraste no Modo Admin.' + adminModeLeft: '§aSaíste do Modo Admin.' + backupCreated: '§6Criaste com sucesso, cópias de segurança de todas as informações e de missões e jogadores.' + backupPlayersFailed: '§cA criação de cópias de segurança de todas as informações de jogadores falhou.' + backupQuestsFailed: '§cA criação de cópias de segurança para todas as missões, falhou.' + cancelQuest: '§6Cancelaste a missão {quest}.' + cancelQuestUnavailable: '§cA missão {quest} não pode ser cancelada.' + help: + adminMode: '§6/{label} adminMode: §eAlterna o Modo Admin. (Útil para exibir pequenas mensagens de registo.)' + create: '§6/{label} create: §eCriar uma missão.' + edit: '§6/{label} edit: §eEditar uma missão.' + header: '§6§lBeautyQuests — Ajuda' + list: '§6/{label} list: §eVer a lista de missões. (Somente para versões suportadas.)' + reload: '§6/{label} reload: §eGuarda e recarrega todas as configurações e ficheiros. (§cdeprecated§e)' + remove: '§6/{label} remove [id]: §eApagar uma missão com um id especificado ou clicar no NPC quando não definido.' + resetPlayer: '§6/{label} resetPlayer <player>: §eRemove todas as informações sobre um jogador.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eApagar as informações duma missão para um jogador.' + save: '§6/{label} save: §eFazer um salvamento manual de plugin.' + seePlayer: '§6/{label} seePlayer <player>: §eVer todas as informações sobre um jogador.' + setItem: '§6/{label} setItem <talk|launch>: §eGuarda o item de holograma.' + start: '§6/{label} start <player> [id]: §eForçar o início de uma missão.' + version: '§6/{label} version: §eVer a versão atual do plugin.' + invalidCommand: + simple: '§cEste comando não existe, escreve §ehelp§c.' + itemChanged: '§aO item foi editado. As alterações afetarão após uma reinicialização.' + itemRemoved: '§aO item do holograma foi removido.' + leaveAll: '§aFoste forçado a terminar {success} missão(ões). Erros: {errors}' + removed: '§aA missão {quest_name} foi removida com sucesso.' + resetPlayer: + player: '§6Todas as informações da(s) tua(s) {quest_amount} missão(ões) foram apagadas por {deleter_name}.' + remover: '§6A/s {quest_amount} informação/ões de {player} foi/foram excluída/s.' + resetPlayerQuest: + player: '§6Todas as informações da missão {quest} foram apagadas por {deleter_name}.' + remover: '§6Informações da missão(ões) de {player} de {quest} foi/foram apagada(s).' + scoreboard: + hidden: '§6O placar do jogador {player_name} foi ocultado.' + lineInexistant: '§cA linha {line_id} não existe.' + lineRemoved: '§6Removeste a linha {line_id} com sucesso.' + lineReset: '§6Redefiniste a linha {line_id} com sucesso.' + lineSet: '§6Editaste a linha {line_id} com sucesso.' + resetAll: '§6Redefiniste com sucesso o placar de classificação do jogador {player_name}.' + shown: '§6O placar do jogador {player_name} foi exibido.' + setStage: + branchDoesntExist: '§cO ramo com o id {branch_id} não existe.' + doesntExist: '§cA etapa com o id {stage_id} não existe.' + next: '§aA etapa foi ignorada.' + nextUnavailable: '§cThe "skip" option is not available when the player is at the end of a branch.' + set: '§aA etapa {stage_id} foi lançada.' + startQuest: '§6Foste forçado a iniciar a missão {quest} (UUID de Jogador: {player}).' + editor: + already: '§cJá estás no editor.' + blockAmount: '§aEspecifique a quantidade de blocos:' + blockData: '§aEspecifique as configurações do bloco (Configurações disponíveis: {available_datas}):' + chat: '§6Você está atualmente no modo Editor. Escreva "/quests exitEditor" para sair do editor. (Altamente não recomendado, considere usar comandos como "fechar" ou "cancelar" para voltar á aba anterior.)' + dialog: + cleared: '§a{amount} removeu a(s) mensagem(s).' + help: + addSound: '§6addSound [id] [sound]: §eAdiciona um som para uma mensagem.' + clear: '§6clear: §eRemove todas as mensagens.' + close: '§6close: §eValida todas as mensagens.' + edit: '§6edit <id> <message>: §eEdita uma mensagem.' + header: '§6§lBeautyQuests — Ajuda do editor de diálogo' + list: '§6list: §eVer todas as mensagens.' + nothing: '§6noSender [message]: §eAdiciona uma mensagem sem um remetente.' + nothingInsert: '§6nothingInsert [id] [message]: §eAdiciona uma mensagem sem prefixo.' + npc: '§6npc [message]: §eAdiciona uma mensagem dita pelo NPC.' + npcInsert: '§6npcInsert [id] [message]: §eAdiciona uma mensagem dita pelo NPC.' + player: '§6player [message]: §eAdiciona uma mensagem dito pelo jogador.' + playerInsert: '§6playerInsert [id] [message]: §eAdiciona uma mensagem dita pelo jogador.' + remove: '§6remove [id]: §eRemove uma mensagem.' + setTime: '§6setTime <id> <time>: §eDefiniu o tempo (em ticks) antes da próxima mensagem ser reproduzida automaticamente.' + syntaxRemove: '§cSintaxe correta: remove <id>' + timeRemoved: '§aO tempo da mensagem foi removido{msg}.' + timeSet: '§aTempo foi editado para a mensagem {msg}: agora é {time} ticks.' + enter: + subtitle: '§6Escreva "/quests exitEditor" para sair do editor.' + title: '§6~ Modo Editor ~' + goToLocation: '§aVá ao local desejado para o estágio.' + itemCreator: + invalidBlockType: '§cTipo de bloco inválido' + invalidItemType: '§cTipo de item inválido. (O item não pode ser um bloco.)' + itemAmount: '§aEscreva a quantidade de item(ns):' + itemLore: '§aModifica o conhecimento do item: (Escreve "help" para obter ajuda.)' + itemName: '§aEscreve o nome do item:' + itemType: '§aEscreve o nome do tipo de item desejado:' + unknownBlockType: '§cTipo de bloco não reconhecido ou não existe.' + unknownItemType: '§cTipo de item desconhecido.' + mythicmobs: + disabled: '§cMythicMob está desativado.' + isntMythicMob: '§cEste Mob Mítico não existe.' + list: '§aUma lista de todos os Mobs Míticos:' + noSuchElement: '§cEsse elemento não existe. Os elementos permitidos são: §e{available_elements}' + npc: + choseStarter: '§aEscolhe o NPC que inicia a missão.' + enter: '§aClica num NPC, ou escreve "cancel".' + notStarter: '§cEste NPC não é um iniciador de missões.' + pool: + maxQuests: Escreva a quantidade máxima de missões possíveis neste pool. + scoreboardObjectiveNotFound: '§cObjetivo de placar desconhecido' + selectWantedBlock: '§aClica com o pau no bloco desejado para a etapa.' + text: + argNotSupported: '§cO argumento {arg} não é suportado.' + chooseJobRequired: '§aEscreve o nome do trabalho desejado:' + chooseLvlRequired: '§aEscreve a quantidade necessária de níveis:' + chooseMoneyRequired: '§aEscreva a quantidade de dinheiro necessário:' + chooseObjectiveRequired: '§aEscreva o nome do objetivo.' + chooseObjectiveTargetScore: '§aEspecifique a pontuação necessária para o objetivo.' + choosePermissionMessage: '§aPodes escolher uma mensagem de rejeição caso o jogador não tiver a permissão necessária. (Para ignorar esta etapa, escreve "null".)' + choosePermissionRequired: '§aEscreve a permissão necessária para iniciar a missão:' + choosePlaceholderRequired: + identifier: '§aEscreve o nome do espaço reservado obrigatório sem os caracteres percentuais:' + value: '§aEscreva o valor necessário para o placeholder §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aEscreva o nome da região necessária (você deve estar no mesmo mundo).' + chooseSkillRequired: '§aEscreve o nome da habilidade necessária:' + reward: + money: '§aEscreve a quantidade do dinheiro recebido:' + permissionName: '§aEscreva o nome da permissão.' + permissionWorld: '§aEscreva o mundo em que a permissão será editada, ou "null" se você quiser ser global.' + wait: '§aEscreva a quantidade de TICKS para esperar: (1 segundo = 20 ticks)' + textList: + help: + add: '§6add [message]: §eAdiciona um texto.' + close: '§6close: §eValidar os textos adicionados.' + header: '§6§lBeautyQuests — Ajuda do editor de lista' + list: '§6list: §eVer todos os textos.' + remove: '§6remove [id]: §eRemove um texto.' + syntax: '§cSintaxe correta: ' + typeBucketAmount: '§aEspecifique a quantidade de baldes para encher:' + typeGameTicks: '§aEspecifique os TICKS necessários:' + typeLocationRadius: '§aEspecifique a distância necessária até o local:' + errorOccurred: '§cOcorreu um erro, entra em contacto com um administrador! §4§lCódigo de erro: {error}' + experience: + edited: '§aAlteraste a experiência adquirida de {old_xp_amount} para {xp_amount} pontos.' + indexOutOfBounds: '§cO número {index} está fora dos limites! Deve estar entre {min} e {max}.' + invalidBlockData: '§cAs configurações desse bloco {block_data} é inválida ou incompatível com o bloco {block_material}.' + inventoryFull: '§cO teu inventário está cheio, o item foi largado no chão.' + moveToTeleportPoint: '§aVai ao local de teleporte desejado.' + npcDoesntExist: '§cO NPC com o id {npc_id} não existe.' + number: + invalid: '§c{input} não é um número válido.' + negative: '§cDeves inserir um número positivo!' + zero: '§cDeves inserir um número diferente de 0!' + pools: + noAvailable: '§7TNão existe missões disponíveis...' + quest: + alreadyStarted: '§cJá iniciaste a missão!' + cancelling: '§cO processo de criação de missão foi cancelado.' + createCancelled: '§cA criação ou edição foi cancelada por outro plugin!' + created: '§aParabéns! Criaste a missão §e{quest}§a que tem {quest_branches} ramo(s)!' + editCancelling: '§cO processo de edição de missão foi cancelado.' + edited: '§aParabéns! Editaste a missão §e{quest}§a que tem agora {quest_branches} ramo(s)!' + finished: + base: '§aParabéns! Terminaste a missão §e{quest_name}§a!' + obtain: '§aObtiveste {rewards}!' + invalidID: '§cA missão com o id {quest_id} não existe.' + started: '§aComeçaste a missão §r§e{quest_name}§o§6!' + quests: + failed: '§cVocê falhou na missão {quest_name}...' + maxLaunched: '§cVocê não pode ter mais de {quests_max_amount} missões ao mesmo tempo...' + updated: '§7Missão §e{quest_name}§7 atualizada.' + regionDoesntExists: '§cEsta região não existe. (Precisas de estar no mesmo mundo.)' + requirements: + money: '§cVocê tem que ter {money}!' + quest: '§cTens que ter terminado a missão §e{quest_name}§c!' + waitTime: '§cVocê deve esperar {time_left} antes de reiniciar esta missão!' + selectNPCToKill: '§aSeleciona o NPC para matar.' + stageMobs: + listMobs: '§aDeves matar {mobs}.' + typeCancel: '§aEscreve "cancel" para voltar ao último texto.' + writeChatMessage: '§aEscreve a mensagem necessária: (Adiciona "{SLASH}" no início, caso quiseres um comando.)' + writeCommand: '§aEscreve o comando desejado: (O comando está sem o "/" e o espaço reservado "{PLAYER}" é suportado. Ele será substituído pelo nome do executor.)' + writeConfirmMessage: '§aEscreve a mensagem de confirmação mostrada quando um jogador está prestes a iniciar a missão: (Escreve "null" se queres a mensagem padrão.)' + writeDescriptionText: '§aEscreve o texto que descreve o objetivo da etapa:' + writeHologramText: '§aEscreve o texto do holograma: (Escreve "none" se não queres um holograma e "null" se queres o texto padrão.)' + writeMobAmount: '§aEscreve a quantidade de mobs para matar:' + writeNPCText: '§aEscreve o diálogo que será dito ao jogador pelo NPC: (Escreve "help" para receber ajuda.)' + writeNpcName: '§aEscreve o nome do NPC:' + writeNpcSkinName: '§aEscreve o nome da skin do NPC:' + writeQuestDescription: '§aEscreva a descrição da missão, exibida no meno de missões do jogador.' + writeQuestName: '§aEscreve o nome da missão:' + writeQuestTimer: '§aEscreve o tempo necessário (em minutos) antes de reiniciar a missão: (Escreve "null" se desejas o temporizador padrão.)' + writeRegionName: '§aEscreve o nome da região necessária para a etapa:' + writeStageText: '§aEscreve o texto que será enviado para o jogador no início da etapa:' + writeXPGain: '§aEscreve a quantidade de pontos de experiência que o jogador obterá: (Último valor: {xp_amount})' +scoreboard: + name: '§6§lMissões' + noLaunched: '§cNenhuma missão em andamento.' + noLaunchedDescription: '§c§oA carregar' + noLaunchedName: '§c§lA carregar' + stage: + bucket: '§ePreencher §6{buckets}' + chat: '§eEscrever §6{text}' + craft: '§eCriar §6{items}' + fish: '§ePescar §6{items}' + interact: '§eClica no bloco em §6{x}' + interactMaterial: '§eClica em um bloco §6{block}§e' + items: '§eLevar itens para §6{dialog_npc_name}§e:' + location: '§eVai a §6{target_x}§e, §6{target_y}§e, §6{target_z}§e em §6{target_world}' + mine: '§eMinerar {blocks}' + mobs: '§eMatar §6{mobs}' + npc: '§eFalar com NPC §6{dialog_npc_name}' + placeBlocks: '§eColocar {blocks}' + region: '§eLocalizar região §6{region_id}' + textBetwteenBranch: '§e ou' diff --git a/core/src/main/resources/locales/ro_RO.yml b/core/src/main/resources/locales/ro_RO.yml new file mode 100755 index 00000000..ba057408 --- /dev/null +++ b/core/src/main/resources/locales/ro_RO.yml @@ -0,0 +1,91 @@ +--- +inv: + confirm: + 'no': '§cAnuleaza' + create: + bringBack: '§aAdu obiecte inapoi' + bucket: '§aUmple galeti' + cancelMessage: Anuleaza trimiterea + craft: '§aCrafteaza Iteme' + enchant: '§dEnchanteaza iteme' + findNPC: '§aGaseste NPC' + findRegion: '§aGaseste regiune' + fish: '§aPrinde pesti' + interact: '§aInteractioneaza cu blocuri' + killMobs: '§aOmoara Monstri' + location: '§aDu-te la locatie' + melt: '§6Topeste Iteme' + mineBlocks: '§aSparge blockuri' + placeBlocks: '§aPlaseaza blocuri' + playTime: '§eTimp jucat' + stageCreate: '§aCreaza un nou pas' + stageRemove: '§cSterge acest pas' + talkChat: '§aScrie in chat' +misc: + amounts: + dialogLines: '{lines_amount} linie(i)' + items: '{items_amount} item(e)' + mobs: '{mobs_amount} mob(i)' + permissions: '{permissions_amount} permisiune(i)' + bucket: + lava: Galeata cu Lava + milk: Galeata cu Lapte + snow: Galeata cu Zapada + click: + left: Click Stanga + right: Click Dreapta + shift-left: Shift Click-Stanga + shift-right: Shift Click-Dreapta +msg: + command: + downloadTranslations: + notFound: '§cLimba{lang} nu a fost gasita pentru versiunea {version}.' + syntax: '§cTrebuie sa specifici o limba pentru descarcare.Exemplu: "/quests downloadTranslations en_US".' + dialogs: + tooFar: '§7§oEsti prea departe de {npc_name}...' + editor: + textList: + added: '§aText "§7{msg}§a" adaugat.' + help: + add: '§6add <message>: §eAdauga un text.' + close: '§6close: §eValideaza textul adaugat.' + header: '§6§lBeautyQuest-uri - Ajutor editor lista' + list: '§6list: §eVezi toate textele adaugate.' + remove: '§6remove <id>: §eElimina un text.' + removed: '§aText "§7{msg}§a" sters.' + syntax: '§cSintaxa corecta: ' + number: + invalid: '§c{input} nu este un numar valid.' + notInBounds: '§cNumarul tau trebuie sa fie intre {min} si {max}.' + pools: + allCompleted: '§7Ai completat toate misiunile!' + maxQuests: '§cNu poti avea mai mult de {pool_max_quests} misiuni in acelasi timp...' + noAvailable: '§7Nu mai sunt misiuni disponibile...' + noTime: '§cTrebuie sa asteptati {time_left} inainte de a incepe o alta misiune.' + quest: + alreadyStarted: '§cAi inceput deja misiunea!' + cancelling: '§cProcesul de creare a misiunii a fost anulat.' + createCancelled: '§cCrearea sau editarea a fost anulata de un alt plugin!' + created: '§aFelicitari! Ai creat misiunea §e{quest}§a care include {quest_branches} ramura(uri)!' + editCancelling: '§cProcesul de editare al misiunii a fost anulat.' + edited: '§aFelicitari! Ai editat misiunea §e{quest}§a care include {quest_branches} ramura(uri)!' + finished: + base: '§aFelicitari! Ai terminat misiunea §e{quest_name}§a!' + obtain: '§aAi obtinut {rewards}!' + invalidID: '§cMisiunea cu id-ul {quest_id} nu exista.' + invalidPoolID: '§cGruparea {pool_id} nu exista.' + notStarted: '§cMomentan nu faci aceasta misiune.' + started: '§aAi inceput misiunea §r§e{quest_name}§o§6!' + questItem: + craft: '§cNu poti folosi un obiect de la misiuni pentru a crafta!' + drop: '§cNu poti arunca un obiect care apartine misunii!' + eat: '§cNu poti manca un obiect de quest!' + quests: + checkpoint: '§7Ai ajuns la destinatie!' + failed: '§cAi esuat misiunea {quest_name}...' + maxLaunched: '§cNu poti avea mai mult de {quests_max_amount} misiuni in acelasi timp...' + updated: '§7Misiunea §e{quest_name}§7 a fost actualizata.' + stageMobs: + listMobs: '§aTrebuie sa omori {mobs}.' + versionRequired: 'Versiune necesara: §l{version}' + writeStartMessage: '§aScrie mesajul care va fi trimis la inceputul questului, "null" dacă doresti cel implicit sau "none" dacă doresti niciunul:' diff --git a/core/src/main/resources/locales/ru_RU.yml b/core/src/main/resources/locales/ru_RU.yml index 853d03c5..891f1128 100644 --- a/core/src/main/resources/locales/ru_RU.yml +++ b/core/src/main/resources/locales/ru_RU.yml @@ -1,797 +1,755 @@ --- -msg: - quest: - finished: - base: '§aПоздравляем! Вы успешно выполнили квест §e{0}§a!' - obtain: '§aВы получили {0}!' - started: '§aВы начали квест §r§e{0}§o§6!' - created: '§aПоздравляем! Вы создали квест §е{0}§a, в который входит {1} ответвление(я)!' - edited: '§aПоздравляем! Вы отредактировали квест §е{0}§a, в который входит {1} ответвление(я)!' - createCancelled: '§cСоздание или редактирование было отменено другим плагином!' - cancelling: '§cПроцесс создания квеста был прерван.' - editCancelling: '§cПроцесс редактирования квеста был прерван.' - invalidID: '§cКвест под номером {0}, не найден.' - invalidPoolID: '§cВетка {0} не существует.' - alreadyStarted: '§cВы уже начали квест!' - notStarted: '§cВ данный момент вы не выполняете этот квест.' - quests: - maxLaunched: '§cВы не можете взять больше {0} задания(й) одновременно...' - nopStep: '§cУ этого квеста нету каких либо этапов.' - updated: '§7Квест §e{0}§7 был обновлён.' - checkpoint: '§7Квест достиг контрольной точки!' - failed: '§cВы провалили задание {0}...' - pools: - noTime: '§cВы должны подождать {0} перед выполнением другого задания.' - allCompleted: '§7Вы завершили все задания!' - noAvailable: '§7Заданий больше не осталось...' - maxQuests: '§cУ вас не может быть более {0} заданий одновременно...' - questItem: - drop: '§cВы не можете выбросить предмет из задания!' - craft: '§cВы не можете использовать предмет задания для крафта!' - eat: '§cВы не можете съесть это!' - stageMobs: - noMobs: '§cНа этом этапе не нужно убивать мобов.' - listMobs: '§aВам нужно убить {0}.' - writeNPCText: '§aНапишите диалог, который будет отправлен игроку от NPC: (Напишите "help" для помощи.)' - writeRegionName: '§aВведите название региона, необходимого для этапа:' - writeXPGain: '§aНапишите количество очков опыта, которые получит игрок: (Крайнее значение: {0})' - writeMobAmount: '§aНапишите количество мобов для убийства:' - writeMobName: '§aЗапишите Имя моба которого надо убить:' - writeChatMessage: '§aНапишите требуемое сообщение: (Добавьте "{SLASH}" в начало если вы хотите выполнить команду.)' - writeMessage: '§aНапишите сообщение, которое будет отправлено игроку' - writeStartMessage: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' - writeEndMsg: '§aНапишите сообщение, которое будет отправлено в конце квеста, "null", если вы хотите стандартное сообщение или "none", если вы не хотите никакое. Вы можете использовать "{0}", оно будет заменено на награду' - writeEndSound: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' - writeDescriptionText: '§aНапишите текст, который описывает цель этапа:' - writeStageText: '§aНапишите текст, который будет отправлен игроку в начале этапа:' - moveToTeleportPoint: '§aПерейдите к локации для телепорта.' - writeNpcName: '§aНапишите название NPC:' - writeNpcSkinName: '§aНапишите название скина NPC:' - writeQuestName: '§aНапишите название вашего квеста:' - writeCommand: '§aВведите нужную команду: (Команда без "/" и заполнения"{PLAYER} поддерживается. Оно будет заменено на имя исполнителя команды.)' - writeHologramText: '§aЗапишите текст голограммы: (Напишите "none", если вы не желаете добавлять голограмму и «null", если хотите текст по умолчанию.)' - writeQuestTimer: '§aЗапишите необходимое время (в минутах), прежде чем вы сможете перезагрузить квест: (Напишите "null", если вы хотите установить время по умолчанию.)' - writeConfirmMessage: '§aНапишите сообщение для подтверждения, которое будет показано когда игрок собирается начать задание: (Напишите "null", если вы хотите отправить сообщение по умолчанию.)' - writeQuestDescription: '§aНапишите описание квеста, которое будет отображаться в квестовом интерфейсе игрока.' - writeQuestMaterial: '§aНапишите материал квестового предмета.' - requirements: - quest: '§cВы должны выполнить квест §e{0}§c!' - level: '§cВаш уровень должен быть {0}!' - job: '§cВаш уровень для работы §e{1}должен быть {0}!' - skill: '§cВаш уровень навыка §e{1}§c должен быть {0}!' - combatLevel: '§cВаш уровень боя должен быть {0}!' - money: '§cВы должны иметь {0}!' - waitTime: '§o{0} минут(ы), прежде чем вы сможете перезапустить задание!' - experience: - edited: '§aВы изменили добычу опыта с {0} до {1} очков.' - selectNPCToKill: '§aВыберите NPC для удаления.' - npc: - remove: '§aNPC удален.' - talk: '§aПойдите и поговорите с NPC по имени §e{0}§a.' - regionDoesntExists: '§cЭтот регион не существует. (Вы должны быть в том же мире.)' - npcDoesntExist: '§cNPC с идентификатором {0} не существует.' - objectDoesntExist: '§cУказанный предмет с идентификатором {0} не существует.' - number: - negative: '§cВы должны ввести положительное число!' - zero: '§cВы должны ввести число, отличное от 0!' - invalid: '§c{0} не допустимое число.' - notInBounds: Число должно быть между {0} и {1} - errorOccurred: '§cПроизошла ошибка, свяжитесь с администратором! §4§lКод ошибки: {0}' - commandsDisabled: '§cВ настоящее время у вас нет прав на выполнение команд!' - indexOutOfBounds: '§cЧисло {0} за пределами! Оно должно между {1} и {2}.' - invalidBlockData: '§cДанные блока {0} недопустимы или несовместимы с блоком {1}.' - invalidBlockTag: '§cНедоступный блочный тег {0}.' - bringBackObjects: Принеси мне {0}. - inventoryFull: '§cВаш инвентарь переполнен, предмет выпал на землю.' - playerNeverConnected: '§cНе удалось найти информацию о игроке {0}.' - playerNotOnline: '§cИгрок {0} не в сети.' - playerDataNotFound: '§cДанные игрока {0} не найдены.' - versionRequired: 'Требуемая версия: §l{0}' - restartServer: '§7Перезагрузите сервер, чтобы увидеть изменения.' - dialogs: - skipped: '§8§o Диалог пропущен.' - tooFar: '§7§oТы слишком далеко от {0}...' - command: - downloadTranslations: - syntax: '§cНеобходимо указать язык для загрузки. Пример: "/quests downloadTranslations ru_RU".' - notFound: '§cЯзык {0} не найден для версии {1}.' - exists: '§cФайл {0} уже существует. Добавьте "-overwrite" к вашей команде, чтобы перезаписать ее. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§aЯзык {0} загружен! §7Вы должны отредактировать файл "/plugins/BeautyQuests/config.yml", чтобы изменить значение §ominecraftTranslationsFile§7 с {0}, а затем перезапустить сервер.' - checkpoint: - noCheckpoint: '§cКонтрольная точка для задания {0} не найдена.' - questNotStarted: '§cВы не выполняете это задание.' - setStage: - branchDoesntExist: '§cОтветвление с id {0} не существует.' - doesntExist: '§cЭтап с идентификатором {0} не существует.' - next: '§aЭтап пропущен.' - nextUnavailable: '§c"Пропустить" недоступно, когда игрок находится в конце ответвления.' - set: '§Этап {0} запущен.' - startDialog: - impossible: '§cНевозможно запустить диалог сейчас.' - noDialog: У игрока нет ожидающего диалога. - alreadyIn: '§cИгрок уже воспроизводит диалог.' - success: '§aЗапущен диалог для игрока {0} в квесте {1}!' - playerNeeded: '§cВы должны быть игроком, чтобы выполнить эту команду!' - incorrectSyntax: '§cНеверный синтаксис.' - noPermission: '§cУ Вас недостаточно прав для выполнения данной команды! (Требуется: {0})' - invalidCommand: - quests: '§cЭта команда не существует, напишите §e/quests help§c.' - simple: '§cЭта команда не существует, напишите §ehelp§c.' - needItem: '§cВы должны держать предмет в вашей основной руке!' - itemChanged: '§aПредмет отредактирован. Изменения вступят в силу после перезапуска.' - itemRemoved: '§aГолографический предмет удален.' - removed: '§aКвест {0} успешно удален.' - leaveAll: '§aВы принудительно завершили {0} квест(а). Ошибки: {1}' - resetPlayer: - player: '§6Все данные вашего {0} задания удалены/были удалены пользователем {1}.' - remover: '§6{0} информация о задание(ях) (и {2} этапах) {1} удалена.' - resetPlayerQuest: - player: '§6Все данные о квесте {0} были удалены пользователем {1}.' - remover: '§6{0} Данные о квесте(ах) {1} удалены.' - resetQuest: '§6Удалены данные квеста для {0} игроков.' - startQuest: '§6Вы принудительно начали задание {0} (UUID игрока: {1}).' - startQuestNoRequirements: '§cИгрок не соответствует требованиям для выполнения задания {0}... Добавьте "-overrideRequirements" в конце вашей команды, чтобы обойти проверку требований.' - cancelQuest: '§6Вы отменили квест {0}.' - cancelQuestUnavailable: '§cЗадание {0} не может быть отменено.' - backupCreated: '§6Вы успешно создали резервную копию всех квестов и информации о игроках.' - backupPlayersFailed: '§cНе удалось создать резервную копию всей информации о игроках.' - backupQuestsFailed: '§cНе удалось создать резервную копию всех квестов.' - adminModeEntered: '§aВы вошли в режим администратора.' - adminModeLeft: '§aВы вышли из режима администратора.' - resetPlayerPool: - timer: '§aВы сбросили значение таймера {0} на {1}.' - full: '§aВы сбросили данные {0} из {1}.' - scoreboard: - lineSet: '§6Вы успешно отредактировали строку {0}.' - lineReset: '§6Вы успешно сбросили строку {0}.' - lineRemoved: '§6Вы успешно удалили строку {0}.' - lineInexistant: '§cСтрока {0} не существует.' - resetAll: '§6Вы успешно сбросили табло игрока {0}.' - hidden: '§6Табло игрока {0} был скрыт.' - shown: '§6Табло игрока {0} показано.' - own: - hidden: '§6Ваше табло теперь скрыто.' - shown: '§6Снова отобразится ваше табло.' - help: - header: '§6§lBeautyQuests — Помощь' - create: '§6/{0} create: §eСоздать квест.' - edit: '§6/{0} edit: §eОтредактировать квест.' - remove: '§6/{0} remove <id>: §eУдалить квест с указанным идентификатором или нажать на NPC, если квест не будет определен.' - finishAll: '§6/{0} finishAll <игрок>: §eЗавершить все квесты игрока.' - setStage: '§6/{0} setStage <игрок> <id> [новое ответвление] [новый этап]: §eПропустить текущий этап/запустить ответвление/установить этап для ответвления.' - startDialog: '§6/{0} startDialog <player> <quest id>: Запускает ожидающий диалог для этапа NPC или начальный диалог для задания.' - resetPlayer: '§6/{0} resetPlayer <игрок>: §eУдалить всю информацию о игроке.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <игрок> [id]: §eУдалить информацию о квестах игрока.' - seePlayer: '§6/{0} seePlayer <игрок>: §e Посмотреть информацию об игроке.' - reload: '§6/{0} reload: §eСохранить и перезагрузить все настройки и файлы. (§cустарело§e)' - start: '§6/{0} start <игрок> [id]: §eПринудительно начинает квест.' - setItem: '§6/{0} setitem <talk|launch>: §eСохранить голографический предмет.' - setFirework: '§6/{0} setFirework: Отредактируйте конечный фейерверк по умолчанию.' - adminMode: '§6/{0} adminMode: §eПереключить режим администратора. (полезно для отображения небольших log сообщений.)' - version: '§6/{0} version: §eПосмотреть текущую версию плагина.' - downloadTranslations: '§6/{0} downloadTranslations <language>: §eЗагружает файл ванильного перевода' - save: '§6/{0} save: §eСохранить справочник плагина.' - list: '§6/{0} list: §eПосмотреть список заданий. (Только для поддерживаемых версий.)' - typeCancel: '§aНапишите "cancel", чтобы вернуться к прежнему тексту.' - editor: - blockAmount: '§aНапишите количество блоков:' - blockName: '§aНапишите название блока:' - blockData: '§aЗапишите данные блоков (доступные данные: {0}):' - blockTag: '§aНапишите тег блока (доступные теги: §7{0}§a):' - typeBucketAmount: '§aНапишите количество вёдер для заполнения:' - typeDamageAmount: 'Напишите количество урона, который игрок должен нанести:' - goToLocation: '§aПерейдите в нужное место для этапа.' - typeLocationRadius: '§aЗапишите требуемое расстояние от локации:' - typeGameTicks: '§aНапишите необходимое количество игровых тактов:' - already: '§cВы уже в редакторе.' - stage: - location: - typeWorldPattern: '§aНапишите регулярное выражение для мировых названий:' - enter: - title: '§6~ Режим редактирования ~' - subtitle: '§6Напишите "/quests exitEditor" чтобы принудительно закрыть редактор.' - list: '§c⚠ §7Вы вошли в режим редактирования списка. Используйте "add" для добавления новых строк. Обратитесь к "help" (без слэша) для получения помощи. §e§lВведите "close" для выхода из редактора.' - chat: '§6В настоящее время вы находитесь в режиме редактора. Напишите "/quests exitEditor", чтобы принудительно выйти из редактора. (Крайне не рекомендуется, рассмотрите возможность использования таких команд, как «close» или «cancel», чтобы вернуться к предыдущей инвентаризации.)' - npc: - enter: '§aНажмите на NPC или напишите "cancel".' - choseStarter: '§aВыберите NPC который начинает квест.' - notStarter: '§cЭтот NPC не начинает квест.' - text: - argNotSupported: '§cАргумент {0} не поддерживается.' - chooseLvlRequired: '§aНапишите необходимое количество уровней:' - chooseJobRequired: '§aНапишите имя нужной работы:' - choosePermissionRequired: '§aНапишите необходимое разрешение для запуска квеста:' - choosePermissionMessage: '§aВы можете выбрать сообщение об отказе игроку, если у него нет необходимого разрешения. (Чтобы пропустить этот шаг, напишите "null".)' - choosePlaceholderRequired: - identifier: '§aЗапишите имя необходимого плейсхолдера без процентов символов:' - value: '§aЗапишите необходимое значение для заполнителя §e%§e{0}§e%§a:' - chooseSkillRequired: '§aНапишите название необходимого навыка:' - chooseMoneyRequired: '§aНапишите количество предметов:' - reward: - permissionName: '§aЗапишите имя разрешения.' - permissionWorld: '§aНапишите мир, в котором разрешение будет отредактировано, или "null", если вы хотите быть глобальным.' - money: '§aНапишите сумму полученных денег:' - wait: '§aНапишите количество игровых тактов для ожидания: (1 секунда = 20 игровых тактов)' - random: - min: '§aНапишите минимальную сумму вознаграждений, предоставляемых игроку (включительно).' - max: 'Напишите максимальную сумму вознаграждений, выданных игроку (включительно).' - chooseObjectiveRequired: '§aЗапишите название цели.' - chooseObjectiveTargetScore: '§aНапишите целевой показатель для цели.' - chooseRegionRequired: '§aВведите название нужного региона (вы должны быть в том же мире).' - selectWantedBlock: '§aНажмите с палкой на нужном блоке для сцены.' - itemCreator: - itemType: '§aНапишите название блока для добычи:' - itemAmount: '§aНапишите количество предметов:' - itemName: '§aВведите название предмета:' - itemLore: '§aИзмените описание предмета: (Напишите "help" для помощи)' - unknownItemType: '§cНеизвестный тип предмета.' - invalidItemType: '§cНедопустимый тип предмета. (Предмет не может быть блоком.)' - unknownBlockType: '§cНеизвестный тип блока.' - invalidBlockType: '§cНедопустимый тип блока.' - dialog: - syntax: '§cCorrect syntax: {0}{1} <сообщение>' - syntaxRemove: '§cCorrect syntax: удалить <id>' - player: '§aСообщение "§7{0}§a" добавлено для игрока.' - npc: '§aСообщение "§7{0}§a" добавлено для NPC.' - noSender: '§aСообщение "§7{0}§a" добавлено без отправителя.' - messageRemoved: '§aСообщение "§7{0}§a" удалено.' - edited: '§aСообщение "§7{0}§a" отредактировано.' - soundAdded: '§aЗвук "§7{0}§a" добавлен для сообщения "§7{1}§a".' - cleared: '§a{0} удаленное(ых) сообщение(й).' - help: - header: '§6§lBeautyQuests — помощь редактора диалогов' - npc: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' - player: '§6player <сообщение>: §eДобавить сообщение, которое будет отправлено игроком.' - nothing: '§6noSender <сообщение>: §eДобавить сообщение без отправителя.' - remove: '§6remove <id>: §eУдалить сообщение.' - list: '§6close: §eПодтвердить все сообщения.' - npcInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' - playerInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' - nothingInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' - edit: '§6редактировать <id> <message>: §eРедактировать сообщение.' - addSound: '§6Добавил звук <id> <sound>: §eДобавить звук к сообщению.' - clear: '§6clear: §eУдалить все сообщения.' - close: '§6close: §eПодтвердить все сообщения.' - setTime: '§6setTime <id> <время>: §eУстановить время (в тактах) до того как следующее сообщение воспроизведется автоматически.' - npcName: '§6npcName [настраиваемое имя NPC]: §eУстановить (или сбросить) пользовательское имя NPC в диалоговом окне' - skippable: '§6skippable [true|false]: §eУстановите, можно ли пропустить диалоговое окно или нет' - timeSet: '§aВремя отредактировано для сообщения {0}: Теперь {1} тактов.' - timeRemoved: '§aВремя было удалено для сообщения {0}.' - npcName: - set: '§aПользовательское имя NPC установлено на §7{1}§a (было §7{0}§a)' - unset: '§aПользовательское имя NPC возвращено к стандартному (было §7{0}§a)' - skippable: - set: '§aСтатус пропуска диалогового окна теперь установлен на §7{1}§a (был §7{0}§a)' - unset: '§aСтатус пропуска диалогового окна сбрасывается на значение по умолчанию (был §7{0}§a)' - mythicmobs: - list: '§aСписок всех Mythic Mobs:' - isntMythicMob: '§cЭтот Mythic Mob не существует.' - disabled: '§cMythicMob отключен.' - advancedSpawnersMob: 'Напишите имя пользовательского моба-спавнера, которого нужно убить:' - textList: - syntax: '§cПравильный синтаксис: ' - added: '§aТекст "§7{0}§a" добавлен.' - removed: '§aТекст "§7{0}§a" удален.' - help: - header: '§6§lBeautyQuests — помощь редактора диалогов' - add: '§6add <сообщение>: §eДобавить текст.' - remove: '§6remove <id>: §eУдалить сообщение.' - list: '§6close: §eПодтвердить все сообщения.' - close: '§6close: §eПроверить добавленные тексты.' - availableElements: 'Доступные элементы: §e{0}' - noSuchElement: '§cНет такого элемента. Допустимые элементы: §e{0}' - invalidPattern: '§cНедопустимый шаблон регулярного выражения §4{0}§c.' - comparisonTypeDefault: '§aВыберите нужный вам тип сравнения среди {0}. Сравнение по умолчанию: §e§l{1}§r§a. Введите §onull§r§a, чтобы использовать его.' - scoreboardObjectiveNotFound: '§cНеизвестный объект таблицы.' - pool: - hologramText: 'Напишите пользовательский текст голограммы для этого бассейна (или напишите "null", если вы хотите использовать текст по умолчанию).' - maxQuests: 'Напишите максимальное количество заданий, запускаемых из этого пула.' - questsPerLaunch: 'Напишите количество заданий, которое игроки смогут получить, нажав на NPC.' - timeMsg: 'Укажите время, за которое игроки смогут выполнить новый квест. (единица измерения по умолчанию: дни)' - title: - title: 'Напишите текст заголовка (или «null», если не хотите).' - subtitle: 'Напишите текст подзаголовка (или «null», если не хотите).' - fadeIn: 'Запишите продолжительность «постепенного появления» в тиках (20 тиков = 1 секунда).' - stay: 'Запишите продолжительность «пребывания» в тиках (20 тиков = 1 секунда).' - fadeOut: 'Запишите продолжительность «постепенного исчезновения» в тиках (20 тиков = 1 секунда).' - colorNamed: 'Введите название цвета.' - color: 'Введите цвет в шестнадцатеричном формате (#XXXXX) или формате RGB (RED GRE BLU).' - invalidColor: 'Введенный вами цвет недействителен. Он должен быть либо шестнадцатеричным, либо RGB.' - firework: - invalid: 'Этот предмет не является действительным фейерверком.' - invalidHand: 'Вы должны держать фейерверк в своей основной руке.' - edited: 'Отредактировал фейерверк квеста!' - removed: 'Удален фейерверк квеста!' - writeCommandDelay: '§aНапишите нужную задержку команд в галочках.' advancement: finished: Завершено notStarted: Не начато +description: + requirement: + class: Класс {class_name} + combatLevel: Боевой уровень {short_level} + faction: Фракция {faction_name} + jobLevel: Уровень {short_level} для {job_name} + level: Уровень {short_level} + quest: Закончите квест §e{quest_name} + skillLevel: Уровень {short_level} для {skill_name} + title: '§8§lТребования:' + reward: + title: '§8§lНаграды:' +indication: + cancelQuest: '§7Вы уверены, что хотите отменить квест {quest_name}?' + closeInventory: '§7Вы уверены, что хотите закрыть этот интерфейс?' + removeQuest: '§7Вы уверены, что хотите удалить квест {quest}?' + startQuest: '§7Вы хотите начать квест {quest_name}?' inv: - validate: '§b§lПодтвердить' - cancel: '§c§lОтменить' - search: '§e§lПоиск' addObject: '§aДобавить объект' + block: + blockData: '§dБлокировать данные (дополнительно)' + material: '§eМатериал: {block_type}' + name: Выбрать блок + blockAction: + location: '§eВыберите точное место' + material: '§eВыберите материал блока' + name: Выберите действие блока + blocksList: + addBlock: '§aНажмите, чтобы добавить блок.' + name: Выбрать блок + buckets: + name: Тип ведра + cancel: '§c§lОтменить' + cancelActions: + name: Отменить действия + checkpointActions: + name: Значок контрольной точки + chooseAccount: + name: Какой аккаунт? + chooseQuest: + menu: '§aМеню квестов' + menuLore: Приведет вас к меню ваших квестов. + name: Какой квест? + classesList.name: Список классов + classesRequired.name: Требуются классы + command: + console: Консоль + delay: '§bЗадержка' + name: Команда + parse: Разбор заполнителей + value: '§eКоманда' + commandsList: + console: '§eКонсоль: {command_console}' + name: Список команд + value: '§Команды: {command_label}' confirm: name: Вы уверены? - 'yes': '§aПодтвердить' 'no': '§cОтменить' + 'yes': '§aПодтвердить' create: - stageCreate: '§aСоздать новый этап' - stageRemove: '§cУдалить этот этап' - stageUp: Переместиться выше - stageDown: Переместить ниже - stageType: '§7Тип этапа: §e{0}' - cantFinish: '§7Вы должны создать хотя бы один этап, чтобы закончить создание квеста!' - findNPC: '§aНайти NPC' + NPCSelect: '§eВыберите или создайте NPC' + NPCText: '§eОтредактировать диалог' + breedAnimals: '§aРазводите животных' bringBack: '§aВернуть предметы' - findRegion: '§aНайти регион' - killMobs: '§aУбить мобов' - mineBlocks: '§aСломать блоки' - placeBlocks: '§aПоставить блоки' - talkChat: '§aНаписать в чат' - interact: '§aВзаимодействовать с блоком' - fish: '§aНаловить рыбы' - melt: '§6Плавка предметов' - enchant: '§dЗачаровываные предметы' - craft: '§aСкрафтить предмет' bucket: '§aЗаполнить ведро' - location: '§aДойти до локации' - playTime: '§eВремя игры' - breedAnimals: '§aРазводите животных' - tameAnimals: '§aПриручите животных' - death: '§cСкончался' + cancelMessage: Отменить отправку + cantFinish: '§7Вы должны создать хотя бы один этап, чтобы закончить создание квеста!' + changeEntityType: '§eИзменить тип объекта' + changeTicksRequired: '§eТребуются изменения галочек игры' + craft: '§aСкрафтить предмет' + currentRadius: '§eТекущее расстояние: §6{radius}' dealDamage: '§cНаносить урон мобам' + death: '§cСкончался' eatDrink: '§aЕшьте или пейте пищу, зелья' - NPCText: '§eОтредактировать диалог' - dialogLines: '{0} Линия' - NPCSelect: '§eВыберите или создайте NPC' - hideClues: Скрыть частицы и голограммы - gps: Отображает компас, указанный на цель - editMobsKill: '§eСменить мобов, для убийства' - mobsKillFromAFar: Требует убийства снарядом editBlocksMine: '§eСменить блоки для разрушения' - preventBlockPlace: Запретить игрокам ломать свои блоки editBlocksPlace: '§eСменить блоки для размещения' - editMessageType: '§eРедактировать сообщение для записи' - cancelMessage: Отменить отправку - ignoreCase: Игнорировать регистр сообщения - replacePlaceholders: Заменить {PLAYER} и заполнители из PAPI - selectItems: '§eОтредактировать требуемые предметы' - selectItemsMessage: '§eРедактировать запрашивающее сообщение' - selectItemsComparisons: '§eВыбор сравнения товаров (ADVANCED) (РАСШИРЕННЫЙ)' - selectRegion: '§7Выберите регион' - toggleRegionExit: При выходе - stageStartMsg: '§eОтредактировать стартовое сообщение' - selectBlockLocation: '§eВыберите местоположение блока' - selectBlockMaterial: '§eВыбрать материал блока' - leftClick: Щелчок должен быть левой кнопкой + editBucketAmount: '§aНапишите количество вёдер для заполнения' + editBucketType: '§eРедактировать тип ведра для заполнения' editFishes: '§eРедактируйте рыбы, чтобы поймать' - editItemsToMelt: '§eОтредактируйте элементы, чтобы расплавить' - editItemsToEnchant: '§eРедактируйте предметы для зачарования' editItem: '§eРедактировать предмет для создания' - editBucketType: '§eРедактировать тип ведра для заполнения' - editBucketAmount: '§aНапишите количество вёдер для заполнения' + editItemsToEnchant: '§eРедактируйте предметы для зачарования' + editItemsToMelt: '§eОтредактируйте элементы, чтобы расплавить' editLocation: '§eРедактировать местоположение' + editMessageType: '§eРедактировать сообщение для записи' + editMobsKill: '§eСменить мобов, для убийства' editRadius: '§eРедактировать расстояние от места' - currentRadius: '§eТекущее расстояние: §6{0}' - changeTicksRequired: '§eТребуются изменения галочек игры' - changeEntityType: '§eИзменить тип объекта' + enchant: '§dЗачаровываные предметы' + findNPC: '§aНайти NPC' + findRegion: '§aНайти регион' + fish: '§aНаловить рыбы' + hideClues: Скрыть частицы и голограммы + ignoreCase: Игнорировать регистр сообщения + interact: '§aВзаимодействовать с блоком' + killMobs: '§aУбить мобов' + leftClick: Щелчок должен быть левой кнопкой + location: '§aДойти до локации' + melt: '§6Плавка предметов' + mineBlocks: '§aСломать блоки' + mobsKillFromAFar: Требует убийства снарядом + placeBlocks: '§aПоставить блоки' + playTime: '§eВремя игры' + preventBlockPlace: Запретить игрокам ломать свои блоки + replacePlaceholders: Заменить {PLAYER} и заполнители из PAPI + selectBlockLocation: '§eВыберите местоположение блока' + selectBlockMaterial: '§eВыбрать материал блока' + selectItems: '§eОтредактировать требуемые предметы' + selectItemsComparisons: '§eВыбор сравнения товаров (ADVANCED) (РАСШИРЕННЫЙ)' + selectItemsMessage: '§eРедактировать запрашивающее сообщение' + selectRegion: '§7Выберите регион' stage: - location: - worldPattern: '§aУстановить шаблон имени мира §d(ДОПОЛНИТЕЛЬНО)' - worldPatternLore: 'Если вы хотите, чтобы этап был завершен для любого мира, соответствующего определенному шаблону, введите здесь regex (регулярное выражение).' - death: - causes: '§aУстановить причины смерти §d(ДОПОЛНИТЕЛЬНО)' - anyCause: Любая причина смерти - setCauses: '{0} причина(ы) смерти' dealDamage: damage: '§eНаносить урон' targetMobs: '§cМобы, наносящие урон' + death: + anyCause: Любая причина смерти + causes: '§aУстановить причины смерти §d(ДОПОЛНИТЕЛЬНО)' + setCauses: '{causes_amount} причина(ы) смерти' eatDrink: items: '§eРедактировать предметы для еды или питья' - stages: - name: Создать этапы - nextPage: '§eСледующая страница' - laterPage: '§eПредыдущая страница' - endingItem: '§eРедактировать конечные награды' - descriptionTextItem: '§eРедактировать описание' - regularPage: '§aОбычные этапы' - branchesPage: '§dЭтапы ответвления' - previousBranch: '§eВернуться к предыдущему ответвлению' - newBranch: '§eПерейти к новому ответвлению' - validationRequirements: '§eТребования к валидации' - validationRequirementsLore: Все требования должны соответствовать игроку, который пытается завершить стадию. Если нет, стадия не может быть завершена. + location: + worldPattern: '§aУстановить шаблон имени мира §d(ДОПОЛНИТЕЛЬНО)' + worldPatternLore: Если вы хотите, чтобы этап был завершен для любого мира, соответствующего определенному шаблону, введите здесь regex (регулярное выражение). + stageCreate: '§aСоздать новый этап' + stageDown: Переместить ниже + stageRemove: '§cУдалить этот этап' + stageStartMsg: '§eОтредактировать стартовое сообщение' + stageType: '§7Тип этапа: §e{stage_type}' + stageUp: Переместиться выше + talkChat: '§aНаписать в чат' + tameAnimals: '§aПриручите животных' + toggleRegionExit: При выходе + damageCause: + name: Причина повреждения + damageCausesList: + name: Список причин повреждений details: - hologramLaunch: '§eРедактировать пункт "Launch" голограммы' - hologramLaunchLore: Когда игрок может начать квест, голограмма отображается над головой Стартового NPC. - hologramLaunchNo: '§eРедактировать голограмму "Запуск недоступен"' - hologramLaunchNoLore: Голограмма отображается над головой стартового NPC, когда игрок НЕ может начать задание. + actions: '{amount} действие(s)' + auto: Запускать автоматически при первом подключении + autoLore: Если этот параметр включен, задание будет запускаться автоматически, когда игрок впервые присоединяется к серверу. + bypassLimit: Не считайте лимит квестов + bypassLimitLore: Если этот параметр включен, квест будет запущен, даже если игрок достиг максимального количества начатых квестов. + cancelRewards: '§cОтменить действия' + cancelRewardsLore: Действия, выполняемые, когда игроки отменяют это задание. + cancellable: Отменяется игроком + cancellableLore: Позволяет игроку отменить квест через меню квестов. + createQuestLore: Вы должны определить название квеста. + createQuestName: '§lСоздать квест' customConfirmMessage: '§eОтредактировать сообщение для подтверждения квеста' customConfirmMessageLore: Сообщение, отображаемое в интерфейсе подтверждения когда игрок собирается начать квест. customDescription: '§eРедактировать описание' customDescriptionLore: Описание, показанное под названием квеста в GUI. - name: Информация о последней ошибке - multipleTime: - itemName: Переключить повтор. - itemLore: Можно ли выполнить квест несколько раз? - cancellable: Отменяется игроком - cancellableLore: Позволяет игроку отменить квест через меню квестов. - startableFromGUI: Запускается из графического интерфейса - startableFromGUILore: Позволяет игроку начать квест из меню квестов. - scoreboardItem: Включить табло - scoreboardItemLore: Если этот параметр отключен, квест не будет отслеживаться на табло. + customMaterial: '§eРедактировать материал квестового предмета ' + customMaterialLore: Предмет этого квеста в меню квестов. + defaultValue: '§f(значение по умолчанию)' + editQuestName: '§lИзменить квест' + editRequirements: '§eИзменить требования' + editRequirementsLore: Все требования должны применяться к игроку, прежде чем он сможет начать квест. + endMessage: '§eИзменить конечное сообщение' + endMessageLore: Сообщение, которое будет отправлено игроку в конце квеста. + endSound: '§eРедактировать конечный звук' + endSoundLore: Звук, который будет воспроизведен в конце квеста. + failOnDeath: Неудача при смерти + failOnDeathLore: Будет ли квест отменен после смерти игрока? + firework: '§dЗавершение Фейерверка' + fireworkLore: Фейерверк запускается, когда игрок заканчивает задание + fireworkLoreDrop: Перетащите свой собственный фейерверк здесь hideNoRequirementsItem: Скрыть когда требования не выполнены hideNoRequirementsItemLore: Если включено, задание не будет отображаться в меню заданий, когда требования не выполняются. - bypassLimit: Не считайте лимит квестов - bypassLimitLore: Если этот параметр включен, квест будет запущен, даже если игрок достиг максимального количества начатых квестов. - auto: Запускать автоматически при первом подключении - autoLore: Если этот параметр включен, задание будет запускаться автоматически, когда игрок впервые присоединяется к серверу. + hologramLaunch: '§eРедактировать пункт "Launch" голограммы' + hologramLaunchLore: Когда игрок может начать квест, голограмма отображается над головой Стартового NPC. + hologramLaunchNo: '§eРедактировать голограмму "Запуск недоступен"' + hologramLaunchNoLore: Голограмма отображается над головой стартового NPC, когда игрок НЕ может начать задание. + hologramText: '§eТекст голограммы' + hologramTextLore: Текст отображается на голограмме над головой стартового NPC. + keepDatas: Сохранять данные игроков + keepDatasLore: 'Заставить плагин сохранять данные игроков, даже если этапы были отредактированы. §c§lПРЕДУПРЕЖДЕНИЕ§c- включение этой опции может нарушить данные ваших игроков.' + loreReset: '§e§lДостижения всех игроков будут сброшены' + multipleTime: + itemLore: Можно ли выполнить квест несколько раз? + itemName: Переключить повтор. + name: Информация о последней ошибке + optionValue: '§fЗначение: §7{value}' questName: '§a§lИзменить название квеста' questNameLore: Для завершения создания квеста необходимо указать имя. - setItemsRewards: '§eРедактировать награды' + questPool: '§eБассейн заданий' + questPoolLore: Прикрепить это задание к бассейну заданий removeItemsReward: '§eУдалить предметы из инвентаря' - setXPRewards: '§eИзменить опыт вознаграждения' + requiredParameter: '§7Необходимый параметр' + requirements: '{amount} требование(я)' + rewards: '{amount} награда(ы)' + rewardsLore: Действия, выполняемые по окончании квеста. + scoreboardItem: Включить табло + scoreboardItemLore: Если этот параметр отключен, квест не будет отслеживаться на табло. + selectStarterNPC: '§e§lВыберите NPC, который будет начинать квест ' + selectStarterNPCLore: Щелчок по выбранному NPC запустит квест. + selectStarterNPCPool: '§c⚠ Выбрана группа квестов' setCheckpointReward: '§eИзменить награды контрольной точки' + setItemsRewards: '§eРедактировать награды' + setMoneyReward: '§eИзменить денежное вознаграждение' + setPermReward: '§eРедактировать разрешения' setRewardStopQuest: '§cОстановить задание' - setRewardsWithRequirements: '§eНаграды с требованиями' setRewardsRandom: '§dСлучайные награды' - setPermReward: '§eРедактировать разрешения' - setMoneyReward: '§eИзменить денежное вознаграждение' - setWaitReward: '§eИзменить награду "ждать"' + setRewardsWithRequirements: '§eНаграды с требованиями' setTitleReward: '§eИзменить название награды' - selectStarterNPC: '§e§lВыберите NPC, который будет начинать квест ' - selectStarterNPCLore: Щелчок по выбранному NPC запустит квест. - selectStarterNPCPool: '§c⚠ Выбрана группа квестов' - createQuestName: '§lСоздать квест' - createQuestLore: Вы должны определить название квеста. - editQuestName: '§lИзменить квест' - endMessage: '§eИзменить конечное сообщение' - endMessageLore: Сообщение, которое будет отправлено игроку в конце квеста. - endSound: '§eРедактировать конечный звук' - endSoundLore: Звук, который будет воспроизведен в конце квеста. - startMessage: '§eИзменить стартовое сообщение' - startMessageLore: Сообщение, которое будет отправлено игроку в начале задания. + setWaitReward: '§eИзменить награду "ждать"' + setXPRewards: '§eИзменить опыт вознаграждения' startDialog: '§eРедактировать стартовый диалог' startDialogLore: Диалог, который будет воспроизведен перед началом квестов, когда игроки нажмут на стартового NPC. - editRequirements: '§eИзменить требования' - editRequirementsLore: Все требования должны применяться к игроку, прежде чем он сможет начать квест. + startMessage: '§eИзменить стартовое сообщение' + startMessageLore: Сообщение, которое будет отправлено игроку в начале задания. startRewards: '§6Начальные награды' startRewardsLore: Действия, выполняемые при запуске квеста. - cancelRewards: '§cОтменить действия' - cancelRewardsLore: Действия, выполняемые, когда игроки отменяют это задание. - hologramText: '§eТекст голограммы' - hologramTextLore: Текст отображается на голограмме над головой стартового NPC. + startableFromGUI: Запускается из графического интерфейса + startableFromGUILore: Позволяет игроку начать квест из меню квестов. timer: '§bПерезапустить таймер' timerLore: Время до того, как игрок сможет снова начать квест. - requirements: '{0} требование(я)' - rewards: '{0} награда(ы)' - actions: '{0} действие(s)' - rewardsLore: Действия, выполняемые по окончании квеста. - customMaterial: '§eРедактировать материал квестового предмета ' - customMaterialLore: Предмет этого квеста в меню квестов. - failOnDeath: Неудача при смерти - failOnDeathLore: Будет ли квест отменен после смерти игрока? - questPool: '§eБассейн заданий' - questPoolLore: Прикрепить это задание к бассейну заданий - firework: '§dЗавершение Фейерверка' - fireworkLore: Фейерверк запускается, когда игрок заканчивает задание - fireworkLoreDrop: Перетащите свой собственный фейерверк здесь visibility: '§bВидимость задания' visibilityLore: Выберите, на каких вкладках меню будет отображаться задание, и будет ли оно отображаться на динамических картах. - keepDatas: Сохранять данные игроков - keepDatasLore: |- - Заставить плагин сохранять данные игроков, даже если этапы были отредактированы. - §c§lПРЕДУПРЕЖДЕНИЕ§c- включение этой опции может нарушить данные ваших игроков. - loreReset: '§e§lДостижения всех игроков будут сброшены' - optionValue: '§fЗначение: §7{0}' - defaultValue: '§f(значение по умолчанию)' - requiredParameter: '§7Необходимый параметр' - itemsSelect: - name: Редактировать предметы - none: |- - §aПереместите предмет здесь или - кликните, чтобы открыть редактор предметов + editTitle: + fadeIn: '§aПродолжительность постепенного появления' + fadeOut: '§aПродолжительность затухания' + name: Изменить заголовок + stay: '§bПродолжительность пребывания' + subtitle: '§eПодзаголовок' + title: '§6Заголовок' + entityType: + name: Выберите тип сущности + factionsList.name: Список фракций + factionsRequired.name: Требуются фракции + itemComparisons: + bukkit: Bukkit родное сравнение + bukkitLore: Использует систему сравнения элементов Bukkit по умолчанию. Сравнивает материал, долговечность, NBT... + customBukkit: Bukkit родное сравнение - NO NBT + customBukkitLore: Использует систему сравнения элементов Bukkit по умолчанию, но стирает теги NBT. Сравнивает материал, прочность ... + enchants: Чары предметов + enchantsLore: Сравнивает зачарованные предметы + itemLore: Описание предмета + itemLoreLore: Сравнивает данные предметов + itemName: Название предмета + itemNameLore: Сравнивает названия предметов + material: Материал предмета + materialLore: Сравнивает материал предмета (например, камень, железный меч ...) + name: Сравнение предметов + repairCost: Стоимость ремонта + repairCostLore: Сравнивает стоимость ремонта доспехов и мечей. + itemCreator: + isQuestItem: '§bQuest предмет:' + itemFlags: Вкл/выкл флаги элемента + itemLore: '§bЛор' + itemName: '§bНазвание предмета' + itemType: '§bТип предмета' + name: Создатель предмета itemSelect: name: Выбрать предмет + itemsSelect: + name: Редактировать предметы + none: '§aПереместите предмет здесь или кликните, чтобы открыть редактор предметов' + listAllQuests: + name: Квесты + listBook: + noQuests: Ранее заданий не создано. + questMultiple: Несколько раз + questName: Имя + questRewards: Награды + questStages: Этапы + questStarter: Старт + requirements: Требования + listPlayerQuests: + name: 'Задания {player_name}' + listQuests: + canRedo: '§3§oВы можете перевыполнить этот квест!' + finished: Завершенные квесты + inProgress: Квесты в процессе выполнения + loreCancelClick: '§cОтменить квест' + loreDialogsHistoryClick: '§7Просмотр диалоговых окон' + loreStart: '§a§oНажмите, чтобы начать задание.' + loreStartUnavailable: '§c§oВы не соответствуете требованиям для начала задания.' + notStarted: Не начатые квесты + timeToWaitRedo: '§3§oВы можете возобновить это задание через {time_left}.' + timesFinished: '§3задание выполнен {times_finished} раз.' + mobSelect: + boss: '§6Выберите босса' + bukkitEntityType: '§eВыберите тип объекта' + epicBoss: '§6Выберите эпического босса' + mythicMob: '§6Выберите мифический моб' + name: Установите тип моба + mobs: + name: Выберите мобов + none: '§aНажмите, чтобы добавить моба.' + setLevel: Установите минимальный уровень npcCreate: - name: Создать NPC - setName: '§eРедактировать имя NPC' - setSkin: '§eРедактировать скин NPC' - setType: '§eРедактировать тип NPC' move: - itemName: '§eПередвинуть' itemLore: '§aИзменить местоположение NPC.' + itemName: '§eПередвинуть' moveItem: '§a§lПроверить место' + name: Создать NPC + setName: '§eРедактировать имя NPC' + setSkin: '§eРедактировать скин NPC' + setType: '§eРедактировать тип NPC' npcSelect: + createStageNPC: '§eСоздать NPC' name: Выбрать или создать? selectStageNPC: '§eВыберите существующий NPC' - createStageNPC: '§eСоздать NPC' - entityType: - name: Выберите тип сущности - chooseQuest: - name: Какой квест? - menu: '§aМеню квестов' - menuLore: Приведет вас к меню ваших квестов. - mobs: - name: Выберите мобов - none: '§aНажмите, чтобы добавить моба.' - clickLore: |- - §a§lЛевый клик§a для редактирования количества. - §a§l§nShift§a§l + левый клик§a для редактирования имени моба. - §c§lПравый клик§c для удаления. - setLevel: Установите минимальный уровень - mobSelect: - name: Установите тип моба - bukkitEntityType: '§eВыберите тип объекта' - mythicMob: '§6Выберите мифический моб' - epicBoss: '§6Выберите эпического босса' - boss: '§6Выберите босса' - stageEnding: - locationTeleport: '§eРедактировать местоположение телепорта' - command: '§eРедактировать выполненную команду' - requirements: - name: Требования - rewards: - name: Награды - commands: 'Команды: {0}' - teleportation: |- - §aВыбрано: - X: {0} - Y: {1} - Z: {2} - World: {3} - random: - rewards: Редактировать награды - minMax: Редактировать минимальное и максимальное значение - checkpointActions: - name: Значок контрольной точки - cancelActions: - name: Отменить действия - rewardsWithRequirements: - name: Награды с требованиями - listAllQuests: - name: Квесты - listPlayerQuests: - name: 'Задания {0}' - listQuests: - notStarted: Не начатые квесты - finished: Завершенные квесты - inProgress: Квесты в процессе выполнения - loreDialogsHistoryClick: '§7Просмотр диалоговых окон' - loreCancelClick: '§cОтменить квест' - loreStart: '§a§oНажмите, чтобы начать задание.' - loreStartUnavailable: '§c§oВы не соответствуете требованиям для начала задания.' - timeToWaitRedo: '§3§oВы можете возобновить это задание через {0}.' - canRedo: '§3§oВы можете перевыполнить этот квест!' - timesFinished: '§3задание выполнен {0} раз.' - itemCreator: - name: Создатель предмета - itemType: '§bТип предмета' - itemFlags: Вкл/выкл флаги элемента - itemName: '§bНазвание предмета' - itemLore: '§bЛор' - isQuestItem: '§bQuest предмет:' - command: - name: Команда - value: '§eКоманда' - console: Консоль - parse: Разбор заполнителей - delay: '§bЗадержка' - chooseAccount: - name: Какой аккаунт? - listBook: - questName: Имя - questStarter: Старт - questRewards: Награды - questMultiple: Несколько раз - requirements: Требования - questStages: Этапы - noQuests: Ранее заданий не создано. - commandsList: - name: Список команд - value: '§Команды: {0}' - console: '§eКонсоль: {0}' - block: - name: Выбрать блок - material: '§eМатериал: {0}' - blockData: '§dБлокировать данные (дополнительно)' - blocksList: - name: Выбрать блок - addBlock: '§aНажмите, чтобы добавить блок.' - blockAction: - name: Выберите действие блока - location: '§eВыберите точное место' - material: '§eВыберите материал блока' - buckets: - name: Тип ведра permission: name: Выберите разрешение perm: '§aРазрешение' - world: '§aМир' - worldGlobal: '§b§lГлобальный' remove: Удалить разрешение removeLore: '§7Разрешение будет снято\n§7вместо данного.' + world: '§aМир' + worldGlobal: '§b§lГлобальный' permissionList: name: Список разрешений - removed: '§eСнятый: §6{0}' - world: '§eМир: §6{0}' - classesRequired.name: Требуются классы - classesList.name: Список классов - factionsRequired.name: Требуются фракции - factionsList.name: Список фракций - poolsManage: - name: Объединенные задания - itemName: '§aОбъединенные #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Максимум заданий: §7{0}' - poolQuestsPerLaunch: '§8Количество заданий, выдаваемых за запуск: §7{0}' - poolRedo: '§8Можно переделывать выполненные задания: §7{0}' - poolTime: '§8Время между заданиями: §7{0}' - poolHologram: '§8Текст голограммы: §7{0}' - poolAvoidDuplicates: '§8Избегайте дублирования: §7{0}' - poolQuestsList: '§7{0} §8задание(й): §7{1}' - create: '§aСоздать Объединенные задания' - edit: '§e> §6§oРедактировать Объединенные... §e<' - choose: '§e> §6§oВыберите этот список §e<' + removed: '§eСнятый: §6{permission_removed}' + world: '§eМир: §6{permission_world}' poolCreation: - name: Создание Объединенных заданий + avoidDuplicates: Избегайте дублирования + avoidDuplicatesLore: '§8> §7Старайтесь не выполнять\n одно и то же задание снова и снова.' hologramText: '§eПользовательское объединенние голограмм' maxQuests: '§aМаксимум заданий' + name: Создание Объединенных заданий questsPerLaunch: '§aКоличество заданий, выдаваемых за запуск' - time: '§bУстановить время между заданиями' redoAllowed: Повтор разрешён - avoidDuplicates: Избегайте дублирования - avoidDuplicatesLore: '§8> §7Старайтесь не выполнять\n одно и то же задание снова и снова.' requirements: '§bТребования для начала задания' + time: '§bУстановить время между заданиями' poolsList.name: Бассейны квестов - itemComparisons: - name: Сравнение предметов - bukkit: Bukkit родное сравнение - bukkitLore: "Использует систему сравнения элементов Bukkit по умолчанию.\nСравнивает материал, долговечность, NBT..." - customBukkit: Bukkit родное сравнение - NO NBT - customBukkitLore: "Использует систему сравнения элементов Bukkit по умолчанию, но стирает теги NBT.\nСравнивает материал, прочность ..." - material: Материал предмета - materialLore: 'Сравнивает материал предмета (например, камень, железный меч ...)' - itemName: Название предмета - itemNameLore: Сравнивает названия предметов - itemLore: Описание предмета - itemLoreLore: Сравнивает данные предметов - enchants: Чары предметов - enchantsLore: Сравнивает зачарованные предметы - repairCost: Стоимость ремонта - repairCostLore: Сравнивает стоимость ремонта доспехов и мечей. - editTitle: - name: Изменить заголовок - title: '§6Заголовок' - subtitle: '§eПодзаголовок' - fadeIn: '§aПродолжительность постепенного появления' - stay: '§bПродолжительность пребывания' - fadeOut: '§aПродолжительность затухания' - damageCause: - name: Причина повреждения - damageCausesList: - name: Список причин повреждений + poolsManage: + choose: '§e> §6§oВыберите этот список §e<' + create: '§aСоздать Объединенные задания' + edit: '§e> §6§oРедактировать Объединенные... §e<' + itemName: '§aОбъединенные #{pool}' + name: Объединенные задания + poolAvoidDuplicates: '§8Избегайте дублирования: §7{pool_duplicates}' + poolHologram: '§8Текст голограммы: §7{pool_hologram}' + poolMaxQuests: '§8Максимум заданий: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8задание(й): §7{pool_quests}' + poolQuestsPerLaunch: '§8Количество заданий, выдаваемых за запуск: §7{pool_quests_per_launch}' + poolRedo: '§8Можно переделывать выполненные задания: §7{pool_redo}' + poolTime: '§8Время между заданиями: §7{pool_time}' + requirements: + name: Требования + rewards: + commands: 'Команды: {amount}' + name: Награды + random: + minMax: Редактировать минимальное и максимальное значение + rewards: Редактировать награды + rewardsWithRequirements: + name: Награды с требованиями + search: '§e§lПоиск' + stageEnding: + command: '§eРедактировать выполненную команду' + locationTeleport: '§eРедактировать местоположение телепорта' + stages: + branchesPage: '§dЭтапы ответвления' + descriptionTextItem: '§eРедактировать описание' + endingItem: '§eРедактировать конечные награды' + laterPage: '§eПредыдущая страница' + name: Создать этапы + newBranch: '§eПерейти к новому ответвлению' + nextPage: '§eСледующая страница' + previousBranch: '§eВернуться к предыдущему ответвлению' + regularPage: '§aОбычные этапы' + validationRequirements: '§eТребования к валидации' + validationRequirementsLore: Все требования должны соответствовать игроку, который пытается завершить стадию. Если нет, стадия не может быть завершена. + validate: '§b§lПодтвердить' visibility: name: Видимость квеста notStarted: 'Вкладка меню "Не запущено"' -scoreboard: - name: '§6§lЗАДАНИЯ' - noLaunched: '§cНет заданий в процессе выполнения.' - noLaunchedName: '§c§lЗагрузка' - noLaunchedDescription: '§c§oЗагрузка' - textBetwteenBranch: '§e или' - asyncEnd: '§бывший' - stage: - region: '§eНайти регион §6{0}' - npc: '§eПоговорить с NPC §6{0}' - items: '§eВерните предметы:' - mobs: '§eУбить §6{0}' - mine: '§eДобыть {0}' - placeBlocks: '§eРазместить {0}' - chat: '§eНаписать §6{0}' - interact: '§eНажмите на блок в §6{0}' - interactMaterial: '§eКликните на §6{0}§e блок' - fish: '§eНаловить §6{0}' - craft: '§eСоздать §6{0}' - bucket: '§eЗаполнить §6{0}' - location: '§eИди к §6{0}§e, §6{1}§e, §6{2}§e в §6{3}' - breed: '§eПорода §6{0}' - tame: '§eПриручить §6{0}' -indication: - startQuest: '§7Вы хотите начать квест {0}?' - closeInventory: '§7Вы уверены, что хотите закрыть этот интерфейс?' - cancelQuest: '§7Вы уверены, что хотите отменить квест {0}?' - removeQuest: '§7Вы уверены, что хотите удалить квест {0}?' -description: - requirement: - title: '§8§lТребования:' - level: 'Уровень {0}' - jobLevel: 'Уровень {0} для {1}' - combatLevel: 'Боевой уровень {0}' - skillLevel: 'Уровень {0} для {1}' - class: 'Класс {0}' - faction: 'Фракция {0}' - quest: 'Закончите квест §e{0}' - reward: - title: '§8§lНаграды:' misc: + amount: '§eКоличество: {amount}' + and: и + bucket: + lava: Ведро лавы + milk: Ведро молока + water: Ведро воды + click: + left: ЛКМ + right: ПКМ + shift-left: Shift+щелчок левой + shift-right: Shift+щелчок правой + comparison: + different: отличается от {number} + equals: равно {number} + greater: строго больше {number} + greaterOrEquals: больше чем {number} + less: строго меньше {number} + lessOrEquals: меньше чем {number} + disabled: Выключено + enabled: Включено + entityType: '§eТип объекта: {entity_type}' + entityTypeAny: '§eЛюбая сущность' format: prefix: '§6<§e§lКвесты§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - offText: '§r§e{0}' - time: - weeks: '{0} недель' - days: '{0} дней' - hours: '{0} часов' - minutes: '{0} минут' - lessThanAMinute: 'меньше минуты' - stageType: - region: Найти регион - npc: Найти NPC - items: Вернуть предметы - mobs: Убивать мобов - mine: Сломать блоки - placeBlocks: Разместите блоки - chat: Пиши в чат - interact: Взаимодействовать с блоком - Fish: Ловить рыбу - Craft: Создать предмет - Bucket: Наполнить ведро - location: Найти место - playTime: Время игры - breedAnimals: Разводите животных - tameAnimals: Приручить животных - comparison: - equals: равно {0} - different: отличается от {0} - less: строго меньше {0} - lessOrEquals: меньше чем {0} - greater: строго больше {0} - greaterOrEquals: больше чем {0} + hologramText: '§8§lКвестовый NPC' + 'no': 'Нет' + notSet: '§cне установлено' + or: или + poolHologramText: '§eДоступно новое задание!' + questItemLore: '§e§oКвестовый предмет' requirement: - logicalOr: '§dЛогическое ИЛИ (требования)(requirements)' - skillAPILevel: '§bтребуемый уровень SkillAPI' class: '§bТребуются классы' - faction: '§bТребуются фракции' - jobLevel: '§bТребуемый уровень должности' combatLevel: '§bТребуется боевой уровень' experienceLevel: '§bНеобходимый уровень опыта' + faction: '§bТребуются фракции' + jobLevel: '§bТребуемый уровень должности' + logicalOr: '§dЛогическое ИЛИ (требования)(requirements)' + mcMMOSkillLevel: '§dТребуемый уровень mcMMOSkillLevel' + money: '§dТребуются деньги' permissions: '§3Требуется разрешение(а)' - scoreboard: '§dТребуется оценка' - region: '§dТребуется регион' placeholder: '§bТребуется значение placeholder' quest: '§aТребуется квест' - mcMMOSkillLevel: '§dТребуемый уровень mcMMOSkillLevel' - money: '§dТребуются деньги' - bucket: - water: Ведро воды - lava: Ведро лавы - milk: Ведро молока - click: - right: ПКМ - left: ЛКМ - shift-right: Shift+щелчок правой - shift-left: Shift+щелчок левой - ticks: '{0} тиков' - questItemLore: '§e§oКвестовый предмет' - hologramText: '§8§lКвестовый NPC' - poolHologramText: '§eДоступно новое задание!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eТип объекта: {0}' - entityTypeAny: '§eЛюбая сущность' - enabled: Включено - disabled: Выключено - unknown: неизвестно - notSet: '§cне установлено' - unused: '§2§lНеиспользованный' - used: '§a§lИспользовать' - remove: '§7СКМ, чтобы удалить' + region: '§dТребуется регион' + scoreboard: '§dТребуется оценка' + skillAPILevel: '§bтребуемый уровень SkillAPI' reset: Перезагрузка - or: или - amount: '§eКоличество: {0}' - items: Предметы - expPoints: опыта + stageType: + Bucket: Наполнить ведро + Craft: Создать предмет + Fish: Ловить рыбу + breedAnimals: Разводите животных + chat: Пиши в чат + interact: Взаимодействовать с блоком + items: Вернуть предметы + location: Найти место + mine: Сломать блоки + mobs: Убивать мобов + npc: Найти NPC + placeBlocks: Разместите блоки + playTime: Время игры + region: Найти регион + tameAnimals: Приручить животных + ticks: '{ticks} тиков' + time: + days: '{days_amount} дней' + hours: '{hours_amount} часов' + lessThanAMinute: меньше минуты + minutes: '{minutes_amount} минут' + weeks: '{weeks_amount} недель' + unknown: неизвестно 'yes': 'Да' - 'no': 'Нет' - and: и +msg: + bringBackObjects: Принеси мне {items}. + command: + adminModeEntered: '§aВы вошли в режим администратора.' + adminModeLeft: '§aВы вышли из режима администратора.' + backupCreated: '§6Вы успешно создали резервную копию всех квестов и информации о игроках.' + backupPlayersFailed: '§cНе удалось создать резервную копию всей информации о игроках.' + backupQuestsFailed: '§cНе удалось создать резервную копию всех квестов.' + cancelQuest: '§6Вы отменили квест {quest}.' + cancelQuestUnavailable: '§cЗадание {quest} не может быть отменено.' + checkpoint: + noCheckpoint: '§cКонтрольная точка для задания {quest} не найдена.' + questNotStarted: '§cВы не выполняете это задание.' + downloadTranslations: + downloaded: '§aЯзык {lang} загружен! §7Вы должны отредактировать файл "/plugins/BeautyQuests/config.yml", чтобы изменить значение §ominecraftTranslationsFile§7 с {lang}, а затем перезапустить сервер.' + exists: '§cФайл {file_name} уже существует. Добавьте "-overwrite" к вашей команде, чтобы перезаписать ее. (/quests downloadTranslations <lang> -overwrite)' + notFound: '§cЯзык {lang} не найден для версии {version}.' + syntax: '§cНеобходимо указать язык для загрузки. Пример: "/quests downloadTranslations ru_RU".' + help: + adminMode: '§6/{label} adminMode: §eПереключить режим администратора. (полезно для отображения небольших log сообщений.)' + create: '§6/{label} create: §eСоздать квест.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eЗагружает файл ванильного перевода' + edit: '§6/{label} edit: §eОтредактировать квест.' + finishAll: '§6/{label} finishAll <игрок>: §eЗавершить все квесты игрока.' + header: '§6§lBeautyQuests — Помощь' + list: '§6/{label} list: §eПосмотреть список заданий. (Только для поддерживаемых версий.)' + reload: '§6/{label} reload: §eСохранить и перезагрузить все настройки и файлы. (§cустарело§e)' + remove: '§6/{label} remove <id>: §eУдалить квест с указанным идентификатором или нажать на NPC, если квест не будет определен.' + resetPlayer: '§6/{label} resetPlayer <игрок>: §eУдалить всю информацию о игроке.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <игрок> [id]: §eУдалить информацию о квестах игрока.' + save: '§6/{label} save: §eСохранить справочник плагина.' + seePlayer: '§6/{label} seePlayer <игрок>: §e Посмотреть информацию об игроке.' + setFirework: '§6/{label} setFirework: Отредактируйте конечный фейерверк по умолчанию.' + setItem: '§6/{label} setitem <talk|launch>: §eСохранить голографический предмет.' + setStage: '§6/{label} setStage <игрок> <id> [новое ответвление] [новый этап]: §eПропустить текущий этап/запустить ответвление/установить этап для ответвления.' + start: '§6/{label} start <игрок> [id]: §eПринудительно начинает квест.' + startDialog: '§6/{label} startDialog <player> <quest id>: Запускает ожидающий диалог для этапа NPC или начальный диалог для задания.' + version: '§6/{label} version: §eПосмотреть текущую версию плагина.' + invalidCommand: + simple: '§cЭта команда не существует, напишите §ehelp§c.' + itemChanged: '§aПредмет отредактирован. Изменения вступят в силу после перезапуска.' + itemRemoved: '§aГолографический предмет удален.' + leaveAll: '§aВы принудительно завершили {success} квест(а). Ошибки: {errors}' + removed: '§aКвест {quest_name} успешно удален.' + resetPlayer: + player: '§6Все данные вашего {quest_amount} задания удалены/были удалены пользователем {deleter_name}.' + remover: '§6{quest_amount} информация о задание(ях) (и {quest_pool} этапах) {player} удалена.' + resetPlayerPool: + full: '§aВы сбросили данные {pool} из {player}.' + timer: '§aВы сбросили значение таймера {pool} на {player}.' + resetPlayerQuest: + player: '§6Все данные о квесте {quest} были удалены пользователем {deleter_name}.' + remover: '§6{player} Данные о квесте(ах) {quest} удалены.' + resetQuest: '§6Удалены данные квеста для {player_amount} игроков.' + scoreboard: + hidden: '§6Табло игрока {player_name} был скрыт.' + lineInexistant: '§cСтрока {line_id} не существует.' + lineRemoved: '§6Вы успешно удалили строку {line_id}.' + lineReset: '§6Вы успешно сбросили строку {line_id}.' + lineSet: '§6Вы успешно отредактировали строку {line_id}.' + own: + hidden: '§6Ваше табло теперь скрыто.' + shown: '§6Снова отобразится ваше табло.' + resetAll: '§6Вы успешно сбросили табло игрока {player_name}.' + shown: '§6Табло игрока {player_name} показано.' + setStage: + branchDoesntExist: '§cОтветвление с id {branch_id} не существует.' + doesntExist: '§cЭтап с идентификатором {stage_id} не существует.' + next: '§aЭтап пропущен.' + nextUnavailable: '§c"Пропустить" недоступно, когда игрок находится в конце ответвления.' + set: '§Этап {stage_id} запущен.' + startDialog: + alreadyIn: '§cИгрок уже воспроизводит диалог.' + impossible: '§cНевозможно запустить диалог сейчас.' + noDialog: У игрока нет ожидающего диалога. + success: '§aЗапущен диалог для игрока {player} в квесте {quest}!' + startQuest: '§6Вы принудительно начали задание {quest} (UUID игрока: {player}).' + startQuestNoRequirements: '§cИгрок не соответствует требованиям для выполнения задания {quest}... Добавьте "-overrideRequirements" в конце вашей команды, чтобы обойти проверку требований.' + dialogs: + skipped: '§8§o Диалог пропущен.' + tooFar: '§7§oТы слишком далеко от {npc_name}...' + editor: + advancedSpawnersMob: 'Напишите имя пользовательского моба-спавнера, которого нужно убить:' + already: '§cВы уже в редакторе.' + availableElements: 'Доступные элементы: §e{available_elements}' + blockAmount: '§aНапишите количество блоков:' + blockData: '§aЗапишите данные блоков (доступные данные: {available_datas}):' + blockName: '§aНапишите название блока:' + blockTag: '§aНапишите тег блока (доступные теги: §7{available_tags}§a):' + chat: '§6В настоящее время вы находитесь в режиме редактора. Напишите "/quests exitEditor", чтобы принудительно выйти из редактора. (Крайне не рекомендуется, рассмотрите возможность использования таких команд, как «close» или «cancel», чтобы вернуться к предыдущей инвентаризации.)' + color: 'Введите цвет в шестнадцатеричном формате (#XXXXX) или формате RGB (RED GRE BLU).' + colorNamed: Введите название цвета. + comparisonTypeDefault: '§aВыберите нужный вам тип сравнения среди {available}. Сравнение по умолчанию: §e§l{default}§r§a. Введите §onull§r§a, чтобы использовать его.' + dialog: + cleared: '§a{amount} удаленное(ых) сообщение(й).' + edited: '§aСообщение "§7{msg}§a" отредактировано.' + help: + addSound: '§6Добавил звук <id> <sound>: §eДобавить звук к сообщению.' + clear: '§6clear: §eУдалить все сообщения.' + close: '§6close: §eПодтвердить все сообщения.' + edit: '§6редактировать <id> <message>: §eРедактировать сообщение.' + header: '§6§lBeautyQuests — помощь редактора диалогов' + list: '§6close: §eПодтвердить все сообщения.' + nothing: '§6noSender <сообщение>: §eДобавить сообщение без отправителя.' + nothingInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + npc: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + npcInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + npcName: '§6npcName [настраиваемое имя NPC]: §eУстановить (или сбросить) пользовательское имя NPC в диалоговом окне' + player: '§6player <сообщение>: §eДобавить сообщение, которое будет отправлено игроком.' + playerInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + remove: '§6remove <id>: §eУдалить сообщение.' + setTime: '§6setTime <id> <время>: §eУстановить время (в тактах) до того как следующее сообщение воспроизведется автоматически.' + skippable: '§6skippable [true|false]: §eУстановите, можно ли пропустить диалоговое окно или нет' + messageRemoved: '§aСообщение "§7{msg}§a" удалено.' + noSender: '§aСообщение "§7{msg}§a" добавлено без отправителя.' + npc: '§aСообщение "§7{msg}§a" добавлено для NPC.' + npcName: + set: '§aПользовательское имя NPC установлено на §7{new_name}§a (было §7{old_name}§a)' + unset: '§aПользовательское имя NPC возвращено к стандартному (было §7{old_name}§a)' + player: '§aСообщение "§7{msg}§a" добавлено для игрока.' + skippable: + set: '§aСтатус пропуска диалогового окна теперь установлен на §7{new_state}§a (был §7{old_state}§a)' + unset: '§aСтатус пропуска диалогового окна сбрасывается на значение по умолчанию (был §7{old_state}§a)' + soundAdded: '§aЗвук "§7{sound}§a" добавлен для сообщения "§7{msg}§a".' + syntaxRemove: '§cCorrect syntax: удалить <id>' + timeRemoved: '§aВремя было удалено для сообщения {msg}.' + timeSet: '§aВремя отредактировано для сообщения {msg}: Теперь {time} тактов.' + enter: + list: '§c⚠ §7Вы вошли в режим редактирования списка. Используйте "add" для добавления новых строк. Обратитесь к "help" (без слэша) для получения помощи. §e§lВведите "close" для выхода из редактора.' + subtitle: '§6Напишите "/quests exitEditor" чтобы принудительно закрыть редактор.' + title: '§6~ Режим редактирования ~' + firework: + edited: Отредактировал фейерверк квеста! + invalid: Этот предмет не является действительным фейерверком. + invalidHand: Вы должны держать фейерверк в своей основной руке. + removed: Удален фейерверк квеста! + goToLocation: '§aПерейдите в нужное место для этапа.' + invalidColor: Введенный вами цвет недействителен. Он должен быть либо шестнадцатеричным, либо RGB. + invalidPattern: '§cНедопустимый шаблон регулярного выражения §4{input}§c.' + itemCreator: + invalidBlockType: '§cНедопустимый тип блока.' + invalidItemType: '§cНедопустимый тип предмета. (Предмет не может быть блоком.)' + itemAmount: '§aНапишите количество предметов:' + itemLore: '§aИзмените описание предмета: (Напишите "help" для помощи)' + itemName: '§aВведите название предмета:' + itemType: '§aНапишите название блока для добычи:' + unknownBlockType: '§cНеизвестный тип блока.' + unknownItemType: '§cНеизвестный тип предмета.' + mythicmobs: + disabled: '§cMythicMob отключен.' + isntMythicMob: '§cЭтот Mythic Mob не существует.' + list: '§aСписок всех Mythic Mobs:' + noSuchElement: '§cНет такого элемента. Допустимые элементы: §e{available_elements}' + npc: + choseStarter: '§aВыберите NPC который начинает квест.' + enter: '§aНажмите на NPC или напишите "cancel".' + notStarter: '§cЭтот NPC не начинает квест.' + pool: + hologramText: Напишите пользовательский текст голограммы для этого бассейна (или напишите "null", если вы хотите использовать текст по умолчанию). + maxQuests: Напишите максимальное количество заданий, запускаемых из этого пула. + questsPerLaunch: Напишите количество заданий, которое игроки смогут получить, нажав на NPC. + timeMsg: 'Укажите время, за которое игроки смогут выполнить новый квест. (единица измерения по умолчанию: дни)' + scoreboardObjectiveNotFound: '§cНеизвестный объект таблицы.' + selectWantedBlock: '§aНажмите с палкой на нужном блоке для сцены.' + stage: + location: + typeWorldPattern: '§aНапишите регулярное выражение для мировых названий:' + text: + argNotSupported: '§cАргумент {arg} не поддерживается.' + chooseJobRequired: '§aНапишите имя нужной работы:' + chooseLvlRequired: '§aНапишите необходимое количество уровней:' + chooseMoneyRequired: '§aНапишите количество предметов:' + chooseObjectiveRequired: '§aЗапишите название цели.' + chooseObjectiveTargetScore: '§aНапишите целевой показатель для цели.' + choosePermissionMessage: '§aВы можете выбрать сообщение об отказе игроку, если у него нет необходимого разрешения. (Чтобы пропустить этот шаг, напишите "null".)' + choosePermissionRequired: '§aНапишите необходимое разрешение для запуска квеста:' + choosePlaceholderRequired: + identifier: '§aЗапишите имя необходимого плейсхолдера без процентов символов:' + value: '§aЗапишите необходимое значение для заполнителя §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aВведите название нужного региона (вы должны быть в том же мире).' + chooseSkillRequired: '§aНапишите название необходимого навыка:' + reward: + money: '§aНапишите сумму полученных денег:' + permissionName: '§aЗапишите имя разрешения.' + permissionWorld: '§aНапишите мир, в котором разрешение будет отредактировано, или "null", если вы хотите быть глобальным.' + random: + max: Напишите максимальную сумму вознаграждений, выданных игроку (включительно). + min: '§aНапишите минимальную сумму вознаграждений, предоставляемых игроку (включительно).' + wait: '§aНапишите количество игровых тактов для ожидания: (1 секунда = 20 игровых тактов)' + textList: + added: '§aТекст "§7{msg}§a" добавлен.' + help: + add: '§6add <сообщение>: §eДобавить текст.' + close: '§6close: §eПроверить добавленные тексты.' + header: '§6§lBeautyQuests — помощь редактора диалогов' + list: '§6close: §eПодтвердить все сообщения.' + remove: '§6remove <id>: §eУдалить сообщение.' + removed: '§aТекст "§7{msg}§a" удален.' + syntax: '§cПравильный синтаксис: ' + title: + fadeIn: Запишите продолжительность «постепенного появления» в тиках (20 тиков = 1 секунда). + fadeOut: Запишите продолжительность «постепенного исчезновения» в тиках (20 тиков = 1 секунда). + stay: Запишите продолжительность «пребывания» в тиках (20 тиков = 1 секунда). + subtitle: Напишите текст подзаголовка (или «null», если не хотите). + title: Напишите текст заголовка (или «null», если не хотите). + typeBucketAmount: '§aНапишите количество вёдер для заполнения:' + typeDamageAmount: 'Напишите количество урона, который игрок должен нанести:' + typeGameTicks: '§aНапишите необходимое количество игровых тактов:' + typeLocationRadius: '§aЗапишите требуемое расстояние от локации:' + errorOccurred: '§cПроизошла ошибка, свяжитесь с администратором! §4§lКод ошибки: {error}' + experience: + edited: '§aВы изменили добычу опыта с {old_xp_amount} до {xp_amount} очков.' + indexOutOfBounds: '§cЧисло {index} за пределами! Оно должно между {min} и {max}.' + invalidBlockData: '§cДанные блока {block_data} недопустимы или несовместимы с блоком {block_material}.' + invalidBlockTag: '§cНедоступный блочный тег {block_tag}.' + inventoryFull: '§cВаш инвентарь переполнен, предмет выпал на землю.' + moveToTeleportPoint: '§aПерейдите к локации для телепорта.' + npcDoesntExist: '§cNPC с идентификатором {npc_id} не существует.' + number: + invalid: '§c{input} не допустимое число.' + negative: '§cВы должны ввести положительное число!' + notInBounds: Число должно быть между {min} и {max} + zero: '§cВы должны ввести число, отличное от 0!' + pools: + allCompleted: '§7Вы завершили все задания!' + maxQuests: '§cУ вас не может быть более {pool_max_quests} заданий одновременно...' + noAvailable: '§7Заданий больше не осталось...' + noTime: '§cВы должны подождать {time_left} перед выполнением другого задания.' + quest: + alreadyStarted: '§cВы уже начали квест!' + cancelling: '§cПроцесс создания квеста был прерван.' + createCancelled: '§cСоздание или редактирование было отменено другим плагином!' + created: '§aПоздравляем! Вы создали квест §е{quest}§a, в который входит {quest_branches} ответвление(я)!' + editCancelling: '§cПроцесс редактирования квеста был прерван.' + edited: '§aПоздравляем! Вы отредактировали квест §е{quest}§a, в который входит {quest_branches} ответвление(я)!' + finished: + base: '§aПоздравляем! Вы успешно выполнили квест §e{quest_name}§a!' + obtain: '§aВы получили {rewards}!' + invalidID: '§cКвест под номером {quest_id}, не найден.' + invalidPoolID: '§cВетка {pool_id} не существует.' + notStarted: '§cВ данный момент вы не выполняете этот квест.' + started: '§aВы начали квест §r§e{quest_name}§o§6!' + questItem: + craft: '§cВы не можете использовать предмет задания для крафта!' + drop: '§cВы не можете выбросить предмет из задания!' + eat: '§cВы не можете съесть это!' + quests: + checkpoint: '§7Квест достиг контрольной точки!' + failed: '§cВы провалили задание {quest_name}...' + maxLaunched: '§cВы не можете взять больше {quests_max_amount} задания(й) одновременно...' + updated: '§7Квест §e{quest_name}§7 был обновлён.' + regionDoesntExists: '§cЭтот регион не существует. (Вы должны быть в том же мире.)' + requirements: + combatLevel: '§cВаш уровень боя должен быть {long_level}!' + job: '§cВаш уровень для работы §e{job_name}должен быть {long_level}!' + level: '§cВаш уровень должен быть {long_level}!' + money: '§cВы должны иметь {money}!' + quest: '§cВы должны выполнить квест §e{quest_name}§c!' + skill: '§cВаш уровень навыка §e{skill_name}§c должен быть {long_level}!' + waitTime: '§o{time_left} минут(ы), прежде чем вы сможете перезапустить задание!' + restartServer: '§7Перезагрузите сервер, чтобы увидеть изменения.' + selectNPCToKill: '§aВыберите NPC для удаления.' + stageMobs: + listMobs: '§aВам нужно убить {mobs}.' + typeCancel: '§aНапишите "cancel", чтобы вернуться к прежнему тексту.' + versionRequired: 'Требуемая версия: §l{version}' + writeChatMessage: '§aНапишите требуемое сообщение: (Добавьте "{SLASH}" в начало если вы хотите выполнить команду.)' + writeCommand: '§aВведите нужную команду: (Команда без "/" и заполнения"{PLAYER} поддерживается. Оно будет заменено на имя исполнителя команды.)' + writeCommandDelay: '§aНапишите нужную задержку команд в галочках.' + writeConfirmMessage: '§aНапишите сообщение для подтверждения, которое будет показано когда игрок собирается начать задание: (Напишите "null", если вы хотите отправить сообщение по умолчанию.)' + writeDescriptionText: '§aНапишите текст, который описывает цель этапа:' + writeEndMsg: '§aНапишите сообщение, которое будет отправлено в конце квеста, "null", если вы хотите стандартное сообщение или "none", если вы не хотите никакое. Вы можете использовать "{rewards}", оно будет заменено на награду' + writeEndSound: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' + writeHologramText: '§aЗапишите текст голограммы: (Напишите "none", если вы не желаете добавлять голограмму и «null", если хотите текст по умолчанию.)' + writeMessage: '§aНапишите сообщение, которое будет отправлено игроку' + writeMobAmount: '§aНапишите количество мобов для убийства:' + writeMobName: '§aЗапишите Имя моба которого надо убить:' + writeNPCText: '§aНапишите диалог, который будет отправлен игроку от NPC: (Напишите "help" для помощи.)' + writeNpcName: '§aНапишите название NPC:' + writeNpcSkinName: '§aНапишите название скина NPC:' + writeQuestDescription: '§aНапишите описание квеста, которое будет отображаться в квестовом интерфейсе игрока.' + writeQuestMaterial: '§aНапишите материал квестового предмета.' + writeQuestName: '§aНапишите название вашего квеста:' + writeQuestTimer: '§aЗапишите необходимое время (в минутах), прежде чем вы сможете перезагрузить квест: (Напишите "null", если вы хотите установить время по умолчанию.)' + writeRegionName: '§aВведите название региона, необходимого для этапа:' + writeStageText: '§aНапишите текст, который будет отправлен игроку в начале этапа:' + writeStartMessage: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' + writeXPGain: '§aНапишите количество очков опыта, которые получит игрок: (Крайнее значение: {xp_amount})' +scoreboard: + asyncEnd: '§бывший' + name: '§6§lЗАДАНИЯ' + noLaunched: '§cНет заданий в процессе выполнения.' + noLaunchedDescription: '§c§oЗагрузка' + noLaunchedName: '§c§lЗагрузка' + stage: + breed: '§eПорода §6{mobs}' + bucket: '§eЗаполнить §6{buckets}' + chat: '§eНаписать §6{text}' + craft: '§eСоздать §6{items}' + fish: '§eНаловить §6{items}' + interact: '§eНажмите на блок в §6{x}' + interactMaterial: '§eКликните на §6{block}§e блок' + items: '§eВерните предметы:' + location: '§eИди к §6{target_x}§e, §6{target_y}§e, §6{target_z}§e в §6{target_world}' + mine: '§eДобыть {blocks}' + mobs: '§eУбить §6{mobs}' + npc: '§eПоговорить с NPC §6{dialog_npc_name}' + placeBlocks: '§eРазместить {blocks}' + region: '§eНайти регион §6{region_id}' + tame: '§eПриручить §6{mobs}' + textBetwteenBranch: '§e или' diff --git a/core/src/main/resources/locales/sv_SE.yml b/core/src/main/resources/locales/sv_SE.yml index d87eb858..18b6add0 100644 --- a/core/src/main/resources/locales/sv_SE.yml +++ b/core/src/main/resources/locales/sv_SE.yml @@ -1,159 +1,243 @@ --- +advancement: + finished: Slutförd + notStarted: Inte påbörjad +inv: + addObject: '§aLägg till ett objekt' + cancel: '§c§lAvbryt' + confirm: + name: Är du säker? + 'no': '§cAvbryt' + 'yes': '§aBekräfta' + create: + bringBack: '§aTa tillbaka föremål' + cantFinish: '§7Du måste skapa minst ett steg innan du slutför!' + findNPC: '§aHitta NPC' + findRegion: '§aHitta region' + killMobs: '§aDöda monster' + mineBlocks: '§aBryt block' + placeBlocks: '§aPlacera block' + stageCreate: '§aSkapa nytt steg' + stageDown: Flytta ned + stageRemove: '§cTa bort detta steg' + stageType: '§7Scentyp: §e{stage_type}' + stageUp: Flytta upp + talkChat: '§aSkriv i chatten' + search: '§e§lSök' + validate: '§b§lValidera' msg: - quest: - finished: - base: '§aGrattis! Du har genomfört uppdraget§e{0}§a!' - obtain: '§aDu tog emot {0}!' - started: '§aDu har startat uppdraget §r§e{0}§o§6!' - created: '§aGrattis! Du har skapat uppdraget §e{0}§a vilket inkluderar {1} gren(ar)!' - edited: '§aGrattis! Du har skapat uppdraget §e{0}§a vilket nu inkluderar {1} gren(ar)!' - createCancelled: '§cSkapandet eller redigeraren har blivit avbruten av ett annat tillägg!' - cancelling: '§cArbetet med uppdragsskapandet har avbrutits.' - editCancelling: '§cArbetet med uppdragsredigeringen har avbrutits.' - invalidID: '§cUppdraget med id {0} existerar inte.' - alreadyStarted: '§cDu har redan påbörjat uppdraget!' - quests: - nopStep: '§cDet här uppdraget har inga steg.' - updated: '§7Uppdrag §e{0}§7 uppdaterades.' - stageMobs: - noMobs: '§e{0}§7Det här steget behöver inga mobs att döda.' - listMobs: '§aDu måsye döda {0}.' - writeNPCText: '§aSkriv dialogen som kommer bli sagd till spelaren an NPCn: (Skriv "help" för att få hjälp.)' - writeRegionName: '§aSkriv namnet på regionen som krävs för steget:' - writeXPGain: '§aSkriv mängden erfarenhet som spelaren kommer få: (Senaste värdet {0})' - writeMobAmount: '§aSkriv antalet mobs att döda:' - writeChatMessage: '§aSkriv meddelande som krävs: (Lägg till "{SLASH}" i början om du vill ha ett kommando.)' - writeEndMessage: '§aSkriv meddelandet som ska visas i slutet av uppdraget eller steget:' - writeDescriptionText: '§aSkriv meddelandet som beskriver målet med steget:' - writeStageText: '§aSkriv texten som ska skickas till spelaren vid början av steget:' - moveToTeleportPoint: '§aGå till den teleporteringsplats som ska användas.' - writeNpcName: '§aSkriv namnet på NPCn:' - writeNpcSkinName: '§aSkriv namnet på det skin NPCn ska ha:' - writeQuestName: '§aSkriv namnet på ditt uppdrag:' - writeCommand: '§aSkriv kommndot du efterfrågar: (Kommandot är utan ett "/" och placeholdern "{PLAYER}" stöds. Det kommer bytas ut mot namnet på den det gäller.)' - writeHologramText: '§aSkriv texten på hologrammet: (Skriv "none" om du inte vill ha ett hologram och "null" om du vill ha standardtexten.)' - writeQuestTimer: '§aSkriv tiden (i minuter) som krävs innan du kan göra uppdraget igen: (Skriv "null" om du vill ha standardtiden.)' - writeConfirmMessage: '§aSkriv bekräftelsemeddelandet som visas när en spelare är på väg att starta uppdraget: (Skriv "null" om du vill ha standardmeddelandet.)' - writeQuestDescription: '§aSkriv beskrivningen av uppdraget som kommer visas i spelarens uppdrags-GUI.' - writeQuestMaterial: '§aSkriv materialet för uppdragsobjektet.' - requirements: - quest: '§aDu måste ha avslutat uppdraget §e{0}§c!' - level: '§cDin nivå måste vara {0}!' - job: '§cDin nivå för jobbet §e{1} §cmåste vara {0}!' - skill: '§cDin nivå för jobbet §e{1}§c måste vara {0}!' - combatLevel: '§cDin stridsnivå måste vara {0}!' - money: '§cDu måste ha {0}!' - wait: '§cDu måste vänta {0} minut(er) innan du kan göra om uppdraget!' - experience: - edited: '§aDu har ändrat erfarenhetförtjänst från {0} till {1} poäng.' - selectNPCToKill: '§aVälj NPCn att döda.' - npc: - remove: '§aNPC borttagen.' - talk: '§aGå och prata med NPCn som heter §e{0}§.' - regionDoesntExists: '§cDet här området finns inte. (Du måste vara i samma värld.)' - npcDoesntExist: '§cNPCn med id {0} existerar inte.' - objectDoesntExist: '§cDet specifierade objektet med id {0} existerar inte.' - number: - negative: '§cDu måste ange ett positivt nummer!' - zero: '§cDu måste ange ett annat nummer än 0!' - invalid: '§c{0} är inte ett giltigt nummer.' - errorOccurred: '§cEtt fel har inträffat. Kontakta en administratör! §4§lFelkod: {0}' - commandsDisabled: '§cDu har för närvarande inte tillåtelse att köra kommandon!' - indexOutOfBounds: '§cNumret {0} är utanför gränsen! Det måste vara mellan {1} och {2}.' - invalidBlockData: '§cBlockdata {0} är felaktig eller inte kompatibel med block {1}.' - bringBackObjects: Ta mig tillbaka {0}. - inventoryFull: '§cDitt utrymme är fullt. Objektet har släppts ner på marken.' - playerNeverConnected: '§cKunde inte hitta information om spelaren {0}.' - playerNotOnline: '§cSpelaren {0} är offline.' + bringBackObjects: Ta mig tillbaka {items}. command: - setStage: - branchDoesntExist: '§cGrenen med id {0} existerar inte.' - doesntExist: '§cSteget med id {0} existerar inte.' - next: '§cSteget har hoppats över.' - nextUnavailable: '§cValet "skip" är inte tillgängligt när spelaren är i slutet av grenen.' - set: '§cSteget {0} har körts.' - playerNeeded: '§cDu måste vara en spelare för att köra det här kommandot!' - incorrectSyntax: '§cFelaktig syntax.' - noPermission: '§cDu har inte tillräckligt med rättigheter för att köra det här kommandot! (Krävs: {0})' + adminModeEntered: '§aDu har gått in i Admin-läget.' + adminModeLeft: '§aDu har lämnat Admin-läget.' + backupCreated: '§6Du har skapat och sparat en backup av alla uppdrag och spelarinformation.' + backupPlayersFailed: '§cSkapandet av backup för all spelarinformation misslyckades.' + backupQuestsFailed: '§cSkapandet av backup för alla uppdrag misslyckades.' + cancelQuest: '§6Du har avbrutit uppdraget {quest}.' + cancelQuestUnavailable: '§cUppdraget {quest} kan inte avbrytas.' + checkpoint: + noCheckpoint: '§cIngen checkpoint hittades för uppdraget {quest}.' + questNotStarted: '§cDu utför inte detta uppdraget.' + downloadTranslations: + downloaded: '§aSpråket {lang} har hämtats! §7Du måste nu redigera filen "/plugins/BeautyQuests/config.yml" för att ändra värdet på §ominecraftTranslationsFile§7 med {lang}, starta sedan om servern.' + exists: '§cFilen {file_name} existerar redan. Lägg till "-overwite" till ditt kommando för att skriva över den. (/quests downloadTranslations <lang> -overwrite)' + notFound: '§cSpråket {lang} hittades inte för version {version}.' + syntax: '§cDu måste specificera vilket språk att ladda ner. Exempel: "/quests downloadTranslations sv_SE".' + help: + adminMode: '§7/{label} administratörsläge: §eVäxla administratörsläget. (Användbart för att visa små loggmeddelanden.)' + create: '§7/{label} create: §eSkapa ett uppdrag.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eLaddar ner en original översättningsfil' + edit: '§6/{label} edit: §eRedigera ett uppdrag.' + finishAll: '§6/{label} finishAll <player>: §eSlutför alla uppdrag för en spelare.' + header: '§6§lBeautyQuests — Hjälp' + list: '§7/{label} lista: §eSe listan över uppdrag. (Endast för versioner som stöds.)' + reload: '§7/{label} laddar om: §eSpara och ladda om alla konfigurationer och filer. (§cdeprecated§e)' + remove: '§6/{label} remove t <id>: §eTa bort ett uppdrag med ett specifikt id eller klicka på NPC när den inte definieras.' + resetPlayer: '§6/{label} resetPlayer <player>: §eTa bort all information om en spelare.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eTa bort uppdrags information från en spelare.' + save: '§7/{label} save: §eSpara manuellt pluginet.' + seePlayer: '§6/{label} seePlayer <player>: §Se information om en spelare.' + setFirework: '§7/{label} setFirework: §eÄndra avslutet för fyrverkeri.' + setItem: '§6/{label} sättObjekt <prata|kör>: §eSpara hologramobjektet.' + setStage: '§6/{label} sättSteg <spelare> <id> [ny gren] [nytt steg]: §eHoppa över det aktuella stadiet/starta grenen/sätta ett steg för en gren.' + start: '§6/{label} start <player> [id]: §eTvinga någon att starta ett uppdrag.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eStartar den väntande dialogen för en NPC-scen eller startdialogen för ett uppdrag.' + version: '§7/{label} version: §eSe den aktuella plugin-versionen.' invalidCommand: - quests: '§cDet här kommandot existerar inte. Skriv §e/quests help§c.' simple: '§cDet här kommandot existerar inte. Skriv §ehelp§c.' - needItem: '§cDu måste hålla ett objekt i huvudhanden!' itemChanged: '§cObjektet har redigerats. Förändringarna kommer gälla efter en omstart.' itemRemoved: '§aHologramobjektet har tagits bort.' - removed: '§aUppdraget {0} har tagits bort.' - leaveAll: '§aDu har tvångsavslutat {0} uppdrag. Fel: {1}' + leaveAll: '§aDu har tvångsavslutat {success} uppdrag. Fel: {errors}' + removed: '§aUppdraget {quest_name} har tagits bort.' resetPlayer: - player: '§6All information om dina {0} uppdrag har blivit borttagna av {1}.' - remover: '§a{0} uppdragsinformation av {1} har tagits bort.' + player: '§6All information om dina {quest_amount} uppdrag har blivit borttagna av {deleter_name}.' + resetPlayerPool: + full: '§aDu har återställt {pool} pooldata av {player}.' + timer: '§aDu har återställt {pool} pooltimer av {player}.' resetPlayerQuest: - player: '§6All information om uppdraget {0} har tagits bort av {1}.' - remover: '§6{0} uppdragsinformation av {1} har blivit borttaget.' - resetQuest: '§6Tog bort datan för uppdraget {0} från spelare.' - startQuest: '§6Du har tvångsstartat uppdrag {0} (Spelar UUID: {1}).' - cancelQuest: '§6Du har avbrutit uppdraget {0}.' - cancelQuestUnavailable: '§cUppdraget {0} kan inte avbrytas.' - backupCreated: '§6Du har skapat och sparat en backup av alla uppdrag och spelarinformation.' - backupPlayersFailed: '§cSkapandet av backup för all spelarinformation misslyckades.' - backupQuestsFailed: '§cSkapandet av backup för alla uppdrag misslyckades.' - adminModeEntered: '§aDu har gått in i Admin-läget.' - adminModeLeft: '§aDu har lämnat Admin-läget.' + player: '§6All information om uppdraget {quest} har tagits bort av {deleter_name}.' + remover: '§6{player} uppdragsinformation av {quest} har blivit borttaget.' + resetQuest: '§6Tog bort datan för uppdraget {player_amount} från spelare.' scoreboard: - lineSet: '§6du har framgångsrikt redigerat rad {0}.' - lineReset: '§6Du har framgångsrikt återställt rad {0}.' - lineRemoved: '§6du har framgångsrikt tagit bort rad {0}.' - lineInexistant: '§cRad {0} existerar inte.' - resetAll: '§6Du har nollställt resultattavlan för spelaren {0}.' - hidden: '§6Resultattavlan för spelaren {0} har blivit döljd.' - shown: '§6Resultattavlan för spelaren {0} har blivit visad.' - help: - header: '§6§lBeautyQuests — Hjälp' - create: '§7/{0} create: §eSkapa ett uppdrag.' - edit: '§6/{0} edit: §eRedigera ett uppdrag.' - remove: '§6/{0} remove t <id>: §eTa bort ett uppdrag med ett specifikt id eller klicka på NPC när den inte definieras.' - finishAll: '§6/{0} finishAll <player>: §eSlutför alla uppdrag för en spelare.' - setStage: '§6/{0} sättSteg <spelare> <id> [ny gren] [nytt steg]: §eHoppa över det aktuella stadiet/starta grenen/sätta ett steg för en gren.' - resetPlayer: '§6/{0} resetPlayer <player>: §eTa bort all information om en spelare.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <player> [id]: §eTa bort uppdrags information från en spelare.' - seePlayer: '§6/{0} seePlayer <player>: §Se information om en spelare.' - reload: '§7/{0} laddar om: §eSpara och ladda om alla konfigurationer och filer. (§cdeprecated§e)' - start: '§6/{0} start <player> [id]: §eTvinga någon att starta ett uppdrag.' - setItem: '§6/{0} sättObjekt <prata|kör>: §eSpara hologramobjektet.' - adminMode: '§7/{0} administratörsläge: §eVäxla administratörsläget. (Användbart för att visa små loggmeddelanden.)' - version: '§7/{0} version: §eSe den aktuella plugin-versionen.' - save: '§7/{0} save: §eSpara manuellt pluginet.' - list: '§7/{0} lista: §eSe listan över uppdrag. (Endast för versioner som stöds.)' - typeCancel: '§aSkriv "avbryt" för att komma tillbaka till den sista texten.' + hidden: '§6Resultattavlan för spelaren {player_name} har blivit döljd.' + lineInexistant: '§cRad {line_id} existerar inte.' + lineRemoved: '§6du har framgångsrikt tagit bort rad {line_id}.' + lineReset: '§6Du har framgångsrikt återställt rad {line_id}.' + lineSet: '§6du har framgångsrikt redigerat rad {line_id}.' + own: + hidden: '§7Din resultattavla är nu dold.' + shown: '§7Din resultattavla visas igen.' + resetAll: '§6Du har nollställt resultattavlan för spelaren {player_name}.' + shown: '§6Resultattavlan för spelaren {player_name} har blivit visad.' + setStage: + branchDoesntExist: '§cGrenen med id {branch_id} existerar inte.' + doesntExist: '§cSteget med id {stage_id} existerar inte.' + next: '§cSteget har hoppats över.' + nextUnavailable: '§cValet "skip" är inte tillgängligt när spelaren är i slutet av grenen.' + set: '§cSteget {stage_id} har körts.' + startDialog: + alreadyIn: '§cSpelaren har redan en dialog.' + impossible: '§cOmöjligt att starta dialogen nu.' + noDialog: '§cSpelaren har inga väntande dialogruta.' + success: '§aStartade dialog för spelare {player} i uppdraget {quest}!' + startPlayerPool: + error: Det gick inte att starta poolen {pool} för {player}. + success: 'Startade poolarna {pool} till {player}. Resultat: {result}' + startQuest: '§6Du har tvångsstartat uppdrag {quest} (Spelar UUID: {player}).' + startQuestNoRequirements: '§cSpelaren uppfyller inte kraven för uppdraget {quest}... Lägg till "-overrideRequirements" i slutet av ditt kommando för att kringgå kontrollen.' + dialogs: + skipped: '§7§o Dialog överhoppad.' + tooFar: '§7§oDu är för långt ifrån {npc_name}...' editor: + already: '§cDu är redan i editorn.' + availableElements: 'Tillgängliga element: §e{available_elements}' blockAmount: '§aSkriv mängden block:' + blockData: '§aSkriv blockdata (tillgängliga blockdata: {available_datas}):' blockName: '§aSkriv namnet på blocket:' - blockData: '§aSkriv blockdata (tillgängliga blockdata: {0}):' - typeBucketAmount: '§aSkriv mängden hinkar att fylla:' - goToLocation: '§aGå till önskad plats för steget.' - typeLocationRadius: '§aSkriv avståndet från platsen som krävs:' - typeGameTicks: '§aSkriv spel ticks som krävs (20 ticks = 1 sekund):' - already: '§cDu är redan i editorn.' + blockTag: '§aSkriv in blocktaggen (tillgängliga taggar: §7{available_tags}§a):' + comparisonTypeDefault: '§aVälj den jämförelsetyp du vill ha bland {available}. Standardjämförelsen är: §e§l{default}§r§a. Skriv §onull§r§a för att använda den.' enter: + list: '§c⚠ §7Du har kommit till en "list"-redigerare. Använd "add" för att lägga till rader. Se "help" (utan "") för hjälp. §e§lSkriv "close" för att avsluta.' + subtitle: '§6Skriv "/quests exitEditor" för att tvinga editorn att sluta.' title: '§6~ Redigeringsläge ~' - subtitle: '§6Skriv "/quests editor" för att tvinga stänga ner redigeraren.' - chat: '§6Du är för närvarande i redigeringsläget. Skriv "/quests editor" för att tvinga redigeraren att lämna redigeraren. (Rekommenderas inte. Överväg att använda kommandon som "stänga" eller "avbryt" för att komma tillbaka till det tidigare inventariet.)' + goToLocation: '§aGå till önskad plats för steget.' + invalidPattern: '§cOgiltigt regexmönster §4{input}§c.' + itemCreator: + itemAmount: '§aAnge mängden föremål():' + itemLore: '§aÄndra objektets lor: (Skriv "help" för mer hjälp.)' + itemName: '§aSkriv objektets namn:' + itemType: '§aAnge namnet på önskad typ av objekt:' + unknownItemType: '§cOkänd typ av objekt.' + noSuchElement: '§cDet finns inget sådant element. Tillåtna element är: §e{available_elements}' npc: - enter: '§aKlicka på en NPC, eller skriv "avbryt".' choseStarter: '§aVälj NPC som startar uppdraget.' + enter: '§aKlicka på en NPC, eller skriv "avbryt".' notStarter: '§cDen här NPC är inte en uppdragsstartare.' + scoreboardObjectiveNotFound: '§cOkänt mål i resultattavlan.' + stage: + location: + typeWorldPattern: '§aSkriv en regex för världsnamn:' text: - argNotSupported: '§cArgumentet {0} stöds inte.' - chooseLvlRequired: '§aSkriv det antal nivåer som krävs:' + argNotSupported: '§cArgumentet {arg} stöds inte.' chooseJobRequired: '§aSkriv namn på det önskade jobbet:' - choosePermissionRequired: '§aSkriv den behörighet som krävs för att starta uppdraget:' + chooseLvlRequired: '§aSkriv det antal nivåer som krävs:' + chooseMoneyRequired: '§aSkriv hur mycket pengar som krävs:' + chooseObjectiveRequired: '§aSkriv objektets namn.' choosePermissionMessage: '§aDu kan välja ett avvisningsmeddelande om spelaren inte har den nödvändiga behörigheten. (För att hoppa över detta steg, skriv "null".)' + choosePermissionRequired: '§aSkriv den behörighet som krävs för att starta uppdraget:' choosePlaceholderRequired: identifier: '§aSkriv ned namnet på platshållaren som krävs, utan procent-tecken:' - value: '§aSkriv värdet som krävs för platshållaren §6%{0}%§a:' chooseSkillRequired: '§aSkriv namnet på den färdighet som krävs:' - chooseMoneyRequired: '§aSkriv hur mycket pengar som krävs:' reward: + money: '§aSkriv hur mycket pengar som ska tas emot:' permissionName: '§aSkriv namnet på rättigheten.' permissionWorld: '§aSkriv den värld där rättigheten kommer att redigeras, eller "null" om du vill det sak vara globalt.' - money: '§aSkriv hur mycket pengar som ska tas emot:' - chooseObjectiveRequired: '§aSkriv objektets namn.' + textList: + help: + add: '§6add <meddelande>: §eLägg till en text.' + close: '§6close: §eValidera de tillagda texterna.' + header: '§6§lBeautyQuests — Hjälp med listredigerare' + list: '§6list: §eSe alla tillagda texter.' + remove: '§6ta bort <id>: §eTa bort en text.' + removed: '§aText "§7{msg}§a" borttagen.' + typeBucketAmount: '§aSkriv mängden hinkar att fylla:' + typeDamageAmount: 'Skriv mängden skada spelaren måste dela ut:' + typeGameTicks: '§aSkriv spel ticks som krävs (20 ticks = 1 sekund):' + typeLocationRadius: '§aSkriv avståndet från platsen som krävs:' + errorOccurred: '§cEtt fel har inträffat. Kontakta en administratör! §4§lFelkod: {error}' + experience: + edited: '§aDu har ändrat erfarenhetförtjänst från {old_xp_amount} till {xp_amount} poäng.' + indexOutOfBounds: '§cNumret {index} är utanför gränsen! Det måste vara mellan {min} och {max}.' + invalidBlockData: '§cBlockdata {block_data} är felaktig eller inte kompatibel med block {block_material}.' + invalidBlockTag: '§cOtillgänglig blocktagg {block_tag}.' + inventoryFull: '§cDitt utrymme är fullt. Objektet har släppts ner på marken.' + moveToTeleportPoint: '§aGå till den teleporteringsplats som ska användas.' + npcDoesntExist: '§cNPCn med id {npc_id} existerar inte.' + number: + invalid: '§c{input} är inte ett giltigt nummer.' + negative: '§cDu måste ange ett positivt nummer!' + notInBounds: '§cVärdet måste vara mellan {min} och {max}' + zero: '§cDu måste ange ett annat nummer än 0!' + pools: + allCompleted: '§7Du har slutfört alla uppdrag!' + maxQuests: '§cDu kan inte ha mer än {pool_max_quests} uppdrag samtidigt...' + noAvailable: '§7Det finns inget mer uppdrag tillgängligt...' + noTime: '§cDu måste vänta {time_left} innan du kan påbörja ett till uppdrag.' + quest: + alreadyStarted: '§cDu har redan påbörjat uppdraget!' + cancelling: '§cArbetet med uppdragsskapandet har avbrutits.' + createCancelled: '§cSkapandet eller redigeraren har blivit avbruten av ett annat tillägg!' + created: '§aGrattis! Du har skapat uppdraget §e{quest}§a vilket inkluderar {quest_branches} gren(ar)!' + editCancelling: '§cArbetet med uppdragsredigeringen har avbrutits.' + edited: '§aGrattis! Du har skapat uppdraget §e{quest}§a vilket nu inkluderar {quest_branches} gren(ar)!' + finished: + base: '§aGrattis! Du har genomfört uppdraget§e{quest_name}§a!' + obtain: '§aDu tog emot {rewards}!' + invalidID: '§cUppdraget med id {quest_id} existerar inte.' + notStarted: '§cDu är inte på detta uppdrag just nu.' + started: '§aDu har startat uppdraget §r§e{quest_name}§o§6!' + questItem: + craft: '§cDu kan inte använda uppdragsföremål till att tillverka!' + drop: '§cDu kan inte släppa ett uppdragsobjekt!' + eat: '§cDu kan inte äta ett uppdragsobjekt!' + quests: + checkpoint: '§7Uppdragets checkpoint har uppnåtts!' + failed: '§cDu misslyckades med uppdrag {quest_name}' + maxLaunched: '§cDu kan inte ha mer än {quests_max_amount} uppdrag samtidigt...' + updated: '§7Uppdrag §e{quest_name}§7 uppdaterades.' + regionDoesntExists: '§cDet här området finns inte. (Du måste vara i samma värld.)' + requirements: + combatLevel: '§cDin stridsnivå måste vara {long_level}!' + job: '§cDin nivå för jobbet §e{job_name} §cmåste vara {long_level}!' + level: '§cDin nivå måste vara {long_level}!' + money: '§cDu måste ha {money}!' + quest: '§aDu måste ha avslutat uppdraget §e{quest_name}§c!' + skill: '§cDin nivå för jobbet §e{skill_name}§c måste vara {long_level}!' + waitTime: '§cDu måste vänta {time_left} innan du kan starta om detta uppdraget!' + restartServer: '§7Starta om din server för att se ändringarna.' + selectNPCToKill: '§aVälj NPCn att döda.' + stageMobs: + listMobs: '§aDu måsye döda {mobs}.' + typeCancel: '§aSkriv "avbryt" för att komma tillbaka till den sista texten.' + versionRequired: 'Version som krävs: §l{version}' + writeChatMessage: '§aSkriv meddelande som krävs: (Lägg till "{SLASH}" i början om du vill ha ett kommando.)' + writeCommand: '§aSkriv kommndot du efterfrågar: (Kommandot är utan ett "/" och placeholdern "{PLAYER}" stöds. Det kommer bytas ut mot namnet på den det gäller.)' + writeConfirmMessage: '§aSkriv bekräftelsemeddelandet som visas när en spelare är på väg att starta uppdraget: (Skriv "null" om du vill ha standardmeddelandet.)' + writeDescriptionText: '§aSkriv meddelandet som beskriver målet med steget:' + writeEndMsg: '§aSkriv meddelandet som kommer att visas i slutet av uppdraget, "null" om du vill ha standard en eller "none" om du vill ha ingen. Du kan använda "{rewards}" som kommer att ersättas med erhållna belöningar.' + writeEndSound: '§aSkriv ljudnamnet som kommer att spelas till spelaren i slutet av uppdraget, "null" om du vill ha standard en eller "none" om du inte vill ha någon:' + writeHologramText: '§aSkriv texten på hologrammet: (Skriv "none" om du inte vill ha ett hologram och "null" om du vill ha standardtexten.)' + writeMessage: '§aSkriv meddelandet som kommer att visas för spelaren' + writeMobAmount: '§aSkriv antalet mobs att döda:' + writeMobName: '§aSkriv mobbens anpassade namn för att döda:' + writeNPCText: '§aSkriv dialogen som kommer bli sagd till spelaren an NPCn: (Skriv "help" för att få hjälp.)' + writeNpcName: '§aSkriv namnet på NPCn:' + writeNpcSkinName: '§aSkriv namnet på det skin NPCn ska ha:' + writeQuestDescription: '§aSkriv beskrivningen av uppdraget som kommer visas i spelarens uppdrags-GUI.' + writeQuestMaterial: '§aSkriv materialet för uppdragsobjektet.' + writeQuestName: '§aSkriv namnet på ditt uppdrag:' + writeQuestTimer: '§aSkriv tiden (i minuter) som krävs innan du kan göra uppdraget igen: (Skriv "null" om du vill ha standardtiden.)' + writeRegionName: '§aSkriv namnet på regionen som krävs för steget:' + writeStageText: '§aSkriv texten som ska skickas till spelaren vid början av steget:' + writeStartMessage: '§aSkriv meddelandet som kommer att skickas i början av uppdraget, "null" om du vill ha standarden eller "none" om du inte vill ha något:' + writeXPGain: '§aSkriv mängden erfarenhet som spelaren kommer få: (Senaste värdet {xp_amount})' diff --git a/core/src/main/resources/locales/th_TH.yml b/core/src/main/resources/locales/th_TH.yml index dbdfc8a3..2be0071f 100644 --- a/core/src/main/resources/locales/th_TH.yml +++ b/core/src/main/resources/locales/th_TH.yml @@ -1,628 +1,582 @@ --- -msg: - quest: - finished: - base: '§aยินดีด้วย! คุณได้ทำภารกิจสำเร็จแล้ว§e{0}§a!' - obtain: '§aคุณได้รับ {0}!' - started: '§aภารกิจของคุณเริ่มแล้ว §r§e{0}§o§6!' - created: '§aยินดีด้วย! คุณได้สร้างภารกิจ §e{0}§a which includes {1} branch(es)!' - edited: '§aยินดีด้วย! คุณได้แก้ไขภารกิจ §e{0}§a which includes now {1} branch(es)!' - createCancelled: '§cการสร้าง หรือแก้ไข ถูกยกเลิกโดย Plugin อื่น!' - cancelling: '§cกระบวนการสร้างเควสถูกยกเลิก.' - editCancelling: '§cการแก้ไขเควส ถูกยกเลิก.' - invalidID: '§cภารกิจ id {0} ไม่มีอยู่จริง.' - invalidPoolID: '§cThe pool {0} does not exist.' - alreadyStarted: '§cคุณเริ่มภารกิจเรียบร้อยแล้ว!' - quests: - maxLaunched: '§cไม่สามารถรับได้มากกว่า {0} quest(s) ในเวลาเดียวกัน...' - nopStep: '§cภารกิจนี้ไม่มีขั้นตอนอื่น.' - updated: '§7ภารกิจ §e{0}§7 อัพเดต.' - checkpoint: '§7ถึงจุดตรวจภารกิจแล้ว!' - failed: '§cภารกิจของคุณล้มเหลว {0}...' - pools: - noTime: '§cคุณต้องรอเวลา {0} ก่อนจะไปทำภารกิจอื่นt.' - allCompleted: '§7ภารกิจของคุณเสร็จหมดแล้ว!' - noAvailable: '§7ยังไม่มีภารกิจอื่นในตอนนี้...' - maxQuests: '§cไม่สามารถรับได้มากกว่า {0} quest(s) ในเวลาเดียวกัน...' - questItem: - drop: '§cคุณไม่สามารถทิ้ง ไอเท่ม เควสนี้ได้!' - craft: '§cไอเท่มเควสชิ้นนี้ไม่สามารถคราฟได้!' - eat: '§cผู้เล่นไม่สามารถกินของชิ้นนี้ได้!' - stageMobs: - noMobs: '§cสเตจนี้ไม่จำเป็นต้องฆ่า mobs.' - listMobs: '§aคุณต้องฆ่า {0}.' - writeNPCText: '§เขียน dialog เพื่อให้ NPC คุยกับผู้เล่น: (เขียน "help" เพื่อที่จะแสดงคำว่า help.)' - writeRegionName: '§aเขียนชื่อ region ที่ต้องการ เพื่อ step ขั้นต่อไป:' - writeXPGain: '§aกำหนดจำนวน EXP ที่ผู้เล่นจะได้รับ: (Last value: {0})' - writeMobAmount: '§aกำหนดจำนวน mobs ที่ต้องฆ่า:' - writeMobName: '§aเขียนชื่อที่กำหนดเองของ mob ที่จะฆ่า:' - writeChatMessage: '§aเขียนข้อความ: (Add "{SLASH}" หากคุณต้องการให้ใช้ command ในการเริ่มต้น.)' - writeMessage: '§aเขียนข้อความเพื่อส่งให้ผู้เล่น' - writeStartMessage: "§aWrite the message that will be sent at the beginning of the quest, \"null\" if you want the default one or \"none\" if you want none:\n" - writeEndMsg: "§aWrite the message that will be sent at the end of the quest, \"null\" if you want the default one or \"none\" if you want none. You can use \"{0}\" which will be replaced with the rewards obtained.\n" - writeDescriptionText: '§aเขียนข้อความ เพื่ออธิบายเป้าหมายของสเตจ:' - writeStageText: '§aเขียนข้อความ ที่จะส่งไปให้ผู้เล่น เมื่อเริ่ม step:' - moveToTeleportPoint: '§aไปยังจุด teleport ที่ต้องการ .' - writeNpcName: "§aเขียนชื่อ NPC:\n" - writeNpcSkinName: '§aกำหนดชื่อ skin ให้ NPC:' - writeQuestName: '§aเขียนชื่อ ภารกิจ ของคุณ:' - writeCommand: '§aเขียน command ที่ต้องการ: (command ไม่มีเครื่องหมาย "' - writeHologramText: '§aเขียนข้อความ โฮโลแกรม: (เขียน "none" ถ้าไม่ต้องการใช้ฮโลแกรมและ "null" ถ้าต้องการข้อความเริ่มต้น)' - writeQuestTimer: '§เขียนเวลาที่ต้องการให้รอ (นาที) ก่อนที่จะสามารถรีสตาร์ทภารกิจได้: (เขียน "null" หากต้องการจับเวลาเริ่มต้น)' - writeConfirmMessage: '§เขียนข้อความยืนยัน เมื่อผู้เล่นกำลังจะเริ่มภารกิจ: (เขียน "null" หากต้องการข้อความเริ่มต้น)' - writeQuestDescription: '§aเขียนคำอธิบายของภารกิจที่แสดงใน GUI ภารกิจของผู้เล่น' - writeQuestMaterial: '§aกำหนดไอเท่ม material ของภารกิจ.' - requirements: - quest: คุณต้องทำภารกิจ e {0} §c! ให้เสร็จ - level: '§cคุณต้องมีเลเวล {0}!' - job: '§cเลเวลอาชีพ §e{1}§c ต้อง {0}!' - skill: '§cเลเวลสกิล §e{1}§c ต้อง {0}!' - combatLevel: '§cเลเวล combat ต้อง {0}!' - money: "§cคุณต้องมี {0}!\n" - waitTime: '§cคุณต้องรอ {0} นาที จึงจะสามารถเริ่มภารกิจนี้ใหม่ได้!' - experience: - edited: '§คุณเปลี่ยนค่า EXP ที่ได้รับจาก {0} เป็น {1} คะแนน.' - selectNPCToKill: '§aเลือก NPC ที่จะฆ่า.' - npc: - remove: '§aลบ NPC.' - talk: "§aไปคุยกับ NPC ชื่อ §e{0}§a.\n" - regionDoesntExists: '§ไม่มี region นี้ (คุณต้องอยู่ในโลกเดียวกัน)' - npcDoesntExist: '§cไม่มี NPC ที่มี id {0}' - objectDoesntExist: '§ไม่มี ไอเท่ม ที่ระบุด้วยรหัส {0}' - number: - negative: "§cคุณต้องป้อนจำนวนบวก!\n" - zero: '§cคุณต้องป้อนตัวเลขอื่นที่ไม่ใช่ 0!' - invalid: '§c{0} ไม่ใช่ตัวเลขที่ถูกต้อง.' - errorOccurred: '§cเกิดข้อผิดพลาด โปรดติดต่อผู้ดูแลระบบ! §4§lError code: {0}' - commandsDisabled: ตอนนี้คุณไม่ได้รับอนุญาตให้ใช้ commands! - indexOutOfBounds: '§หมายเลข {0} อยู่นอกขอบเขต! ต้องอยู่ระหว่าง {1} ถึง {2}' - invalidBlockData: '§blockdata {0} ไม่ถูกต้อง หรือเข้ากันไม่ได้กับ block {1}' - invalidBlockTag: '§cแท็กบล็อกไม่พร้อมใช้งาน {0}' - bringBackObjects: พาฉันกลับมาที่ {0} - inventoryFull: '§cช่องเก็บ ไอเท่ม ของคุณเต็ม, ไอเทมหล่นลงพื้น.' - playerNeverConnected: '§cไม่สามารถค้นหาข้อมูลเกี่ยวกับผู้เล่นนี้ได้ {0}' - playerNotOnline: '§cผู้เล่น {0} offline.' - playerDataNotFound: "§cข้อมูลของผู้เล่น {0} ไม่พบ\n" - versionRequired: 'Version required: §l{0}' - restartServer: '§7รีสตาร์ทเซิร์ฟเวอร์ของคุณเพื่อดูการแก้ไข' - dialogs: - skipped: '§8§o Dialog skipped.' - tooFar: '§7§oคุณได้อยู่ห่างไกลจาก {0}...' - command: - downloadTranslations: - syntax: '§cคุณต้องระบุภาษาที่จะดาวน์โหลด ตัวอย่าง: "/quests downloadTranslations en_US"' - notFound: "§cLanguage {0} ไม่พบสำหรับรุ่น {1}\n" - downloaded: 'ดาวน์โหลด §aLanguage {0} แล้ว! §7ตอนนี้คุณต้องแก้ไขไฟล์ "/plugins/BeautyQuests/config.yml" เพื่อเปลี่ยนค่าของ §ominecraftTranslationsFile§7 ด้วย {0} จากนั้นรีสตาร์ทเซิร์ฟเวอร์' - checkpoint: - noCheckpoint: '§cไม่พบ checkpoint สำหรับภารกิจ {0}' - questNotStarted: '§cคุณไม่ได้ทำภารกิจนี้.' - setStage: - branchDoesntExist: '§cไม่มี branch ที่มี id {0}' - doesntExist: "§cไม่มี stage ที่มี id {0}\n" - next: "§a stage ถูกข้าม.\n" - nextUnavailable: '§ตัวเลือก "ข้าม" ไม่สามารถใช้ได้เมื่อผู้เล่นอยู่ในจุดสิ้นสุด branch.' - set: '§aStage {0} เริ่ม.' - startDialog: - impossible: "§cImpossible to start the dialog now.\n" - noDialog: '§cThe player has no pending dialog.' - alreadyIn: '§cผู้เล่นกำลังเล่นกล่องโต้ตอบอยู่แล้ว' - success: '§aเริ่มกล่องโต้ตอบสำหรับผู้เล่น {0} ในภารกิจ {1}!' - playerNeeded: '§cคุณต้องเป็นผู้เล่น เพื่อดำเนินการ command นี้!' - incorrectSyntax: '§csyntax ไม่ถูกต้อง.' - noPermission: '§c permissions ของคุณใช้ command นี้ไม่ได้! (Required: {0})' - invalidCommand: - quests: '§cไม่มี command นี้, เขียน §e/quests help§c.' - simple: '§cไม่มี command นี้, เขียน §help§c.' - needItem: '§cคุณต้องถือ ไอเท่ม ไว้ในมือหลัก!' - itemChanged: '§ ไอเท่ม ที่ได้รับการแก้ไข การเปลี่ยนแปลงจะมีผล หลังจากรีสตาร์ท.' - itemRemoved: '§ไอเท่ม โฮโลแกรม ถูกลบออก' - removed: '§ภารกิจ {0} ถูกลบออกเรียบร้อยแล้ว' - leaveAll: '§คุณบังคับให้สิ้นสุด {0} เควส) ข้อผิดพลาด: {1}' - resetPlayer: - player: '§6ข้อมูลทั้งหมดเกี่ยวกับภารกิจของคุณ {0} รายการได้ถูกลบโดย {1}.' - remover: '§6{0} ข้อมูลภารกิจ (และ {2} กลุ่ม) ของ {1} ถูกลบแล้ว' - resetPlayerQuest: - player: '§6ข้อมูลทั้งหมดเกี่ยวกับภารกิจ {0} ถูกลบโดย {1}' - remover: '§6 {0} ข้อมูลภารกิจของ {1} ถูกลบไปแล้ว' - resetQuest: '§6ลบข้อมูลของภารกิจสำหรับ {0} players.' - startQuest: '§6คุณบังคับให้เริ่มภารกิจ {0} (UUID ของผู้เล่น: {1})' - cancelQuest: '§6คุณได้ยกเลิกภารกิจ {0}.' - cancelQuestUnavailable: '§ภารกิจ {0} ไม่สามารถยกเลิกได้' - backupCreated: '§6คุณได้สร้างการสำรองข้อมูลของ ภารกิจ และข้อมูลผู้เล่นทั้งหมดเรียบร้อยแล้ว' - backupPlayersFailed: '§การสร้างข้อมูลสำรองสำหรับข้อมูลผู้เล่นทั้งหมดล้มเหลว' - backupQuestsFailed: '§การสร้างข้อมูลสำรองสำหรับเควสทั้งหมดล้มเหลว' - adminModeEntered: '§คุณได้เข้าสู่โหมดผู้ดูแลระบบ' - adminModeLeft: '§คุณออกจากโหมดผู้ดูแลระบบแล้ว' - resetPlayerPool: - timer: "§aคุณได้รีเซ็ต {0} ตัวจับเวลาพูลของ {1}\n" - full: '§คุณได้รีเซ็ต {0} ข้อมูลพูลของ {1}' - scoreboard: - lineSet: '§6คุณแก้ไข line เรียบร้อยแล้ว {0}' - lineReset: '§6คุณรีเซ็ต line สำเร็จแล้ว {0}' - lineRemoved: '§6คุณลบ line เรียบร้อยแล้ว {0}.' - lineInexistant: '§ไม่มี line {0}' - resetAll: '§6คุณรีเซ็ต สกอร์บอร์ด ของผู้เล่นสำเร็จแล้ว {0}' - hidden: '§6ป้ายบอกคะแนนของผู้เล่น {0} ถูกซ่อนไว้' - shown: '§6ป้ายบอกคะแนนของผู้เล่น {0} มีการแสดง.' - own: - hidden: '§6ป้ายของคุณถูกซ่อนอยู่ในขณะนี้' - shown: '§6ป้ายของคุณจะปรากฏขึ้นอีกครั้ง' - help: - header: '§6§lBeautyQuests — Help' - create: '§6/{0} create: §eสร้างภารกิจ' - edit: '§6/{0} edit: §eแก้ไขภารกิจ' - remove: '§6/{0} remove <id>: §eลบเควสด้วย id ที่ระบุหรือคลิกที่ NPC เมื่อไม่ได้กำหนดไว้' - finishAll: '§6/{0} finishAll <player>: §eจบภารกิจทั้งหมดของผู้เล่น' - setStage: '§6/{0} setStage <player> <id> [new branch] [new stage]: §eข้ามขั้นตอน stage/start the branch/set a stage สำหรับ branch.' - startDialog: '§6/{0} startDialog <player> <quest id>: §eเริ่มกล่องโต้ตอบที่รอดำเนินการสำหรับด่าน NPC หรือกล่องโต้ตอบเริ่มต้นสำหรับภารกิจ' - resetPlayer: '§6/{0} resetPlayer <player>: §eลบข้อมูลทั้งหมดเกี่ยวกับผู้เล่น' - resetPlayerQuest: '§6/{0} resetPlayerQuest <player> [id]: §eลบข้อมูลของภารกิจให้ผู้เล่น' - seePlayer: '§6/{0} seePlayer <player>: §eดูข้อมูลเกี่ยวกับผู้เล่น' - reload: '§6/{0} reload: §eSบันทึกและโหลดการกำหนดค่าและไฟล์ทั้งหมดซ้ำ. (§cdeprecated§e)' - start: '§6/{0} start <player> [id]: §eบังคับให้เริ่มเควส' - setItem: '§6/{0} setItem <talk|launch>: §eบันทึก hologram ไอเท่ม' - setFirework: '§6/{0} setFirework: §eแก้ไขจุดสิ้นสุดของดอกไม้ไฟเริ่มต้น' - adminMode: '§6/{0} adminMode: §eสลับโหมดผู้ดูแลระบบ (มีประโยชน์สำหรับการแสดงข้อความบันทึกเล็กน้อย)' - version: '§6/{0} version: §eดูเวอร์ชันปลั๊กอินปัจจุบัน' - save: '§6/{0} save: §eทำการบันทึกปลั๊กอินด้วยตนเอง' - list: '§6/{0} list: §eดูรายการเควส (สำหรับเวอร์ชันที่รองรับเท่านั้น)' - typeCancel: '§aเขียนคำว่า "cancel" เพื่อกลับไปที่ข้อความสุดท้าย' - editor: - blockAmount: '§aเขียนจำนวน blocks:' - blockName: '§aเขียนชื่อ block:' - blockData: '§aเขียน blockdata (available blockdatas: {0}):' - typeBucketAmount: '§aเขียนจำนวน buckets ที่จะเติม:' - goToLocation: '§aไปยังตำแหน่งที่ต้องการสำหรับ stage.' - typeLocationRadius: '§aเขียนระยะทางที่ต้องการจาก location:' - typeGameTicks: '§aเขียน game ticks ที่ต้องการ:' - already: '§cคุณอยู่ในเครื่องมือแก้ไขแล้ว' - enter: - title: '§6 ~ โหมดแก้ไข ~' - subtitle: พิม /quests exitEditor เพื่อออกจากโหมดแก้ไข - npc: - enter: '§aคลิกที่ NPC หรือเขียน "cancel".' - choseStarter: '§aเลือก NPC ที่เริ่มภารกิจ' - notStarter: '§cNPC ตัวนี้ไม่ใช่ตัวเริ่มต้นภารกิจ' - text: - argNotSupported: '§cThe argument {0} ไม่รองรับ.' - chooseLvlRequired: '§aเขียนระดับ levels ที่ต้องการ:' - chooseJobRequired: '§aเขียนชื่อ job ที่ต้องการ:' - choosePermissionRequired: '§aเขียน permission ที่ต้องการ เพื่อเริ่มภารกิจ:' - choosePermissionMessage: '§aคุณสามารถเลือกข้อความปฏิเสธหากผู้เล่นไม่มี permission. ที่จำเป็น (หากต้องการข้ามขั้นตอนนี้ให้เขียน "null".)' - choosePlaceholderRequired: - identifier: '§aเขียนชื่อของ placeholder ต้องการ โดยไม่ต้องมี %:' - value: '§aขียนค่าที่ต้องการสำหรับ placeholder §e%§e{0}§e%§a:' - chooseSkillRequired: '§aเขียนชื่อของ skill ที่ต้องการ:' - chooseMoneyRequired: '§aเขียนจำนวนเงินที่ต้องการ:' - reward: - permissionName: '§aเขียนชื่อ permission' - permissionWorld: '§aเขียน world ที่จะแก้ไข permission หรือเขียน "null" ถ้าคุณต้องการให้เป็นแบบ global' - money: '§aเขียนจำนวนเงินที่ได้รับ:' - chooseObjectiveRequired: '§aเขียนชื่อ objective.' - chooseObjectiveTargetScore: '§aเขียน เป้าหมาย score สำหรับ objective.' - chooseRegionRequired: '§aเขียนชื่อ region ที่ต้องการ (คุณต้องอยู่ใน world เดียวกัน).' - selectWantedBlock: '§aคลิกด้วย stick บน block สำหรับ stage.' - itemCreator: - itemType: '§aเขียนชื่อ type ไอเท่ม ที่ต้องการ:' - itemAmount: '§เขียนจำนวน ไอเท่ม(s):' - itemName: '§aเขียนชื่อ item:' - itemLore: '§aแก้ไข lore ของ ไอเท่ม: (Write "help" for help.)' - unknownItemType: '§cไม่ทราบ item type.' - invalidItemType: '§cประเภท ไอเท่ม ไม่ถูกต้อง (item ไม่สามารถ block ได้)' - unknownBlockType: '§cไม่ทราบ block type. ' - invalidBlockType: '§c block type ไม่ถูกต้อง' - dialog: - syntax: '§cCorrect syntax: {0}{1} <message>' - syntaxRemove: '§cCorrect sytax: remove <id>' - messageRemoved: '§aข้อความ "§7{0}§a" ได้ถูกลบออกเรียบร้อย' - edited: '§aข้อความ "§7{0}§a" ได้ถูกแก้ไขเรียบร้อย' - cleared: '§a {0} ข้อความที่ถูกลบ' - help: - header: '§6§lBeautyQuests — Dialog editor help' - npc: '§6npc <message>: §eเพิ่มข้อความที่ NPC พูด' - player: '§6player <ข้อความ>: §เพิ่มข้อความที่ผู้เล่นพูด.' - nothing: '§6noSender <message>: §eเพิ่มข้อความโดยไม่มีผู้ส่ง' - remove: '§6remove <id>: §ลบข้อความ' - list: '§6list: §eดูl messages ทั้งหมด.' - npcInsert: '§6npcInsert <id> <message>: §eใส่ข้อความที่ NPC พูด' - playerInsert: '§6playerInsert <id> <message>: §eใส่ข้อความที่ผู้เล่นพูด' - nothingInsert: '§6nothingInsert <id> <message>: §eใส่ข้อความโดยไม่มีคำนำหน้าใดๆ' - edit: 'แก้ไข <id> <message>:§eข้อความที่แก้ไข' - addSound: '§6addSound <id> <sound>: §เพิ่มเสียงให้กับข้อความ' - clear: '§6clear: §ลบข้อความทั้งหมด' - close: '§6close: §eตรวจสอบข้อความทั้งหมด' - setTime: '§6setTime <id> <time>: §eSetเวลา (in ticks) ก่อนที่ข้อความถัดไปจะเล่นโดยอัตโนมัติ' - timeSet: '§aTime ถูกแก้ไขสำหรับ message {0}: now {1} ticks.' - timeRemoved: '§aTime ถูกลบออกสำหรับ message {0}' - mythicmobs: - list: '§aรายการทั้งหมดของ Mythic Mobs:' - isntMythicMob: '§cMythic Mob นี้ไม่มีอยู่จริง' - disabled: '§cMythicMob ถูกปิดใช้งาน' - textList: - syntax: '§cCorrect syntax: ' - added: '§aข้อความ "§7{0}§a" ได้ถูกเพิ่มเรียบร้อย' - removed: '§aข้อความ "§7{0}§a" ได้ถูกลบออกเรียบร้อย' - help: - header: '§6§lBeautyQuests — List editor help' - add: '§6add <message>: §eเพิ่มข้อความ' - remove: '§6remove <id>: §ลบข้อความ' - list: '§6list: §eดูข้อความที่เพิ่มทั้งหมด' - close: '§6close: §eตรวจสอบข้อความที่เพิ่มเข้ามา' - noSuchElement: '§ไม่มี element ดังกล่าว element ที่อนุญาต ได้แก่ §e {0}' - scoreboardObjectiveNotFound: '§cไม่ทราบวัตถุประสงค์ของ สกอร์บอร์ด' - pool: - hologramText: 'เขียนข้อความโฮโลแกรมที่กำหนดเองสำหรับพูลนี้ (หรือ "null" ถ้าคุณต้องการใช้ค่าเริ่มต้น)' - maxQuests: 'เขียนจำนวนสูงสุดของ ภารกิจ ที่สามารถเรียกใช้งานได้จาก pool นี้' - colorNamed: 'โปรดใส่รหัสสี' - writeCommandDelay: '§aเขียนการหน่วงเวลาคำสั่งที่ต้องการ ใน ticks.' advancement: finished: เสร็จแล้ว notStarted: ยังไม่เริ่มต้น +indication: + cancelQuest: '§7คุณแน่ใจหรือไม่ว่าต้องการยกเลิกภารกิจ {quest_name}' + closeInventory: '§7คุณแน่ใจหรือไม่ว่าต้องการปิด GUI?' + removeQuest: '§7คุณแน่ใจหรือไม่ว่าต้องการลบภารกิจ {quest}' + startQuest: '§7คุณต้องการเริ่มภารกิจ {quest_name} หรือไม่?' inv: - validate: '§b§lตรวจสอบ' - cancel: '§c§lยกเลิก' - search: '§e§lค้นหา' addObject: '§aเพิ่มวัตถุ' + block: + blockData: '§dBlockdata (advanced)' + name: เลือก block + blockAction: + location: '§eเลือก location ที่แม่นยำ' + material: '§eเลือก block material' + name: เลือกการดำเนินการ block + blocksList: + addBlock: '§aคลิกเพื่อเพิ่ม block.' + name: เลือก blocks + buckets: + name: ชนิด Bucket + cancel: '§c§lยกเลิก' + checkpointActions: + name: การกระทำ Checkpoint + chooseAccount: + name: account อะไร? + chooseQuest: + name: เควสไหน? + classesList.name: Classes list + classesRequired.name: Classes ที่จำเป็น + command: + console: คอนโซล + delay: '§bดีเลย์' + name: Command + value: '§eCommand' + commandsList: + name: Command list confirm: name: คุณแน่ใจไหม? - 'yes': '§aยืนยัน' 'no': '§ยกเลิก' + 'yes': '§aยืนยัน' create: - stageCreate: '§aสร้าง step ใหม่' - stageRemove: '§cลบ step' - stageUp: เลื่อนขึ้น - stageDown: เลื่อนลง - findNPC: '§aค้นหา NPC' + NPCSelect: '§eเลือก หรือสร้าง NPC' + NPCText: '§eแก้ไข dialog' + breedAnimals: ผสมพันธ์สัตว์ bringBack: '§aนำ ไอเท่ม กลับมา' + bucket: '§aเติม buckets' + cancelMessage: ยกเลิกการส่ง + changeTicksRequired: '§eเปลี่ยน ticks ที่ต้องการของ ผู้เล่น' + craft: '§aสร้างไอเท่ม' + currentRadius: '§eระยะทางปัจจุบัน: §6 {radius}' + editBlocksMine: '§eแก้ไข blocks ที่จะทำลาย' + editBlocksPlace: '§eแก้ไขบล็อกที่จะวาง' + editBucketAmount: '§แก้ไขจำนวน buckets ที่จะเติม' + editBucketType: '§แก้ไข type ของ bucket ที่จะเติม' + editFishes: '§eแก้ไขปลาที่จะจับ' + editItem: '§แก้ไข ไอเท่ม ที่จะคราฟ' + editLocation: '§eแก้ไข location' + editMessageType: '§eแก้ไขข้อความที่จะเขียน' + editMobsKill: '§eแก้ไข mobs เพื่อฆ่า' + editRadius: '§แก้ไขระยะทางจาก location' + findNPC: '§aค้นหา NPC' findRegion: '§aค้นหา region' + fish: '§aจับปลา' + hideClues: ซ่อน particles และ holograms + ignoreCase: ไม่สนใจ case ของข้อความ + interact: '§aโต้ตอบกับ block' killMobs: '§aฆ่า mobs' + leftClick: ต้องคลิกซ้าย + location: '§aไปยัง location' mineBlocks: '§aทำลาย blocks' + mobsKillFromAFar: ต้องฆ่าด้วย rojectile placeBlocks: '§aวาง blocks' - talkChat: '§aเขียนแชท' - interact: '§aโต้ตอบกับ block' - fish: '§aจับปลา' - craft: '§aสร้างไอเท่ม' - bucket: '§aเติม buckets' - location: '§aไปยัง location' playTime: '§eเวลาเล่น' - breedAnimals: ผสมพันธ์สัตว์ - tameAnimals: '§สัตว์เลี้ยง' - NPCText: '§eแก้ไข dialog' - NPCSelect: '§eเลือก หรือสร้าง NPC' - hideClues: ซ่อน particles และ holograms - editMobsKill: '§eแก้ไข mobs เพื่อฆ่า' - mobsKillFromAFar: ต้องฆ่าด้วย rojectile - editBlocksMine: '§eแก้ไข blocks ที่จะทำลาย' preventBlockPlace: ป้องกันไม่ให้ผู้เล่นทำลาย blocks ของตัวเอง - editBlocksPlace: '§eแก้ไขบล็อกที่จะวาง' - editMessageType: '§eแก้ไขข้อความที่จะเขียน' - cancelMessage: ยกเลิกการส่ง - ignoreCase: ไม่สนใจ case ของข้อความ + selectBlockLocation: '§eเลือกตำแหน่ง block' + selectBlockMaterial: '§eเลือก block material' selectItems: '§eแก้ไข ไอเท่ม ที่ต้องการ' selectItemsMessage: แก้ไขข้อความคำถาม selectRegion: '§7เลือก region' - toggleRegionExit: เมื่อออก + stageCreate: '§aสร้าง step ใหม่' + stageDown: เลื่อนลง + stageRemove: '§cลบ step' stageStartMsg: '§eแก้ไขข้อความเริ่มต้น' - selectBlockLocation: '§eเลือกตำแหน่ง block' - selectBlockMaterial: '§eเลือก block material' - leftClick: ต้องคลิกซ้าย - editFishes: '§eแก้ไขปลาที่จะจับ' - editItem: '§แก้ไข ไอเท่ม ที่จะคราฟ' - editBucketType: '§แก้ไข type ของ bucket ที่จะเติม' - editBucketAmount: '§แก้ไขจำนวน buckets ที่จะเติม' - editLocation: '§eแก้ไข location' - editRadius: '§แก้ไขระยะทางจาก location' - currentRadius: '§eระยะทางปัจจุบัน: §6 {0}' - changeTicksRequired: '§eเปลี่ยน ticks ที่ต้องการของ ผู้เล่น' - stages: - name: สร้าง stages - nextPage: '§eหน้าต่อไป' - laterPage: '§eหน้าที่แล้ว' - endingItem: '§eแก้ไขรางวัลตอนจบ' - descriptionTextItem: '§แก้ไขคำอธิบาย' - regularPage: '§astages ปรกติ' - branchesPage: '§dBranch stages' - previousBranch: '§eกลับไปที่ branch ก่อนหน้า' - newBranch: '§eไปที่ branch ใหม่' - validationRequirements: '§eข้อกำหนดในการตรวจสอบความถูกต้อง' - validationRequirementsLore: ข้อกำหนดทั้งหมดจะต้องตรงกับผู้เล่นที่พยายามเล่นจนจบ stage หากไม่เช่นนั้น stage จะไม่เสร็จสมบูรณ์ + stageUp: เลื่อนขึ้น + talkChat: '§aเขียนแชท' + tameAnimals: '§สัตว์เลี้ยง' + toggleRegionExit: เมื่อออก details: - hologramLaunch: '§eEdit "launch" ไอเท่ม โฮโลแกรม' - hologramLaunchLore: โฮโลแกรมแสดงเหนือหัวของ Starter NPC เมื่อผู้เล่นสามารถเริ่มภารกิจได้ - hologramLaunchNo: '§eEdit "ไม่สามารถ launch" ไอเท่ม โฮโลแกรม ได้' - hologramLaunchNoLore: โฮโลแกรมแสดงเหนือหัวของ Starter NPC เมื่อผู้เล่นไม่สามารถเริ่มภารกิจได้ + actions: '{amount} ดำเนินการ หรือ action(s)' + bypassLimit: อย่านับขีดจำกัด ของภารกิจ + bypassLimitLore: หากเปิดใช้งาน ภารกิจจะเริ่มได้ แม้ว่าผู้เล่นจะทำภารกิจเริ่มต้น ถึงจำนวนสูงสุดแล้ว + cancellable: ยกเลิกได้โดยผู้เล่น + cancellableLore: อนุญาตให้ผู้เล่นยกเลิกภารกิจผ่านเมนูภารกิจ + createQuestLore: คุณต้องกำหนดชื่อภารกิจ + createQuestName: '§lสร้างภารกิจ' customConfirmMessage: '§eแก้ไข message ยืนยันเควส' customConfirmMessageLore: Message ปรากฏใน Confirmation GUI เมื่อผู้เล่นกำลังจะเริ่มภารกิจ customDescription: '§eแก้ไขคำอธิบายภารกิจ' customDescriptionLore: คำอธิบายที่แสดงด้านล่างชื่อของภารกิจใน GUI - name: รายละเอียดภารกิจสุดท้าย - multipleTime: - itemName: สลับการทำซ้ำได้ - itemLore: สามารถทำภารกิจได้หลายครั้งหรือไม่? - cancellable: ยกเลิกได้โดยผู้เล่น - cancellableLore: อนุญาตให้ผู้เล่นยกเลิกภารกิจผ่านเมนูภารกิจ - startableFromGUI: เริ่มได้จาก GUI - startableFromGUILore: อนุญาตให้ผู้เล่นเริ่มภารกิจจากเมนูเควส - scoreboardItem: เปิดใช้งาน สกอร์บอร์ด - scoreboardItemLore: หากปิดใช้งานภารกิจจะไม่ถูกติดตามผ่าน สกอร์บอร์ด + customMaterial: '§eแก้ไข material ไอเท่มเควส' + customMaterialLore: ตัวแทนไอเทมของเควสนี้ในเมนูเควส + defaultValue: '§8(default value ค่าเริ่มต้น)' + editQuestName: '§lแก้ไขเควส' + editRequirements: '§eแก้ไขข้อกำหนด' + editRequirementsLore: ข้อกำหนดทุกข้อต้อง apply กับผู้เล่นก่อน จึงจะเริ่มภารกิจได้ + endMessage: '§eแก้ไขข้อความตอนจบ' + endMessageLore: ข้อความที่จะส่งไปยังผู้เล่นเมื่อสิ้นสุดภารกิจ + failOnDeath: ล้มเหลวเมื่อเสียชีวิต + failOnDeathLore: ภารกิจจะถูกยกเลิกเมื่อผู้เล่นเสียชีวิตหรือไม่? hideNoRequirementsItem: ซ่อนเมื่อไม่เป็นไปตามข้อกำหนด hideNoRequirementsItemLore: หากเปิดใช้งาน ภารจะไม่แสดงในเมนูภารกิจ เมื่อไม่ตรงตามข้อกำหนด - bypassLimit: อย่านับขีดจำกัด ของภารกิจ - bypassLimitLore: หากเปิดใช้งาน ภารกิจจะเริ่มได้ แม้ว่าผู้เล่นจะทำภารกิจเริ่มต้น ถึงจำนวนสูงสุดแล้ว + hologramLaunch: '§eEdit "launch" ไอเท่ม โฮโลแกรม' + hologramLaunchLore: โฮโลแกรมแสดงเหนือหัวของ Starter NPC เมื่อผู้เล่นสามารถเริ่มภารกิจได้ + hologramLaunchNo: '§eEdit "ไม่สามารถ launch" ไอเท่ม โฮโลแกรม ได้' + hologramLaunchNoLore: โฮโลแกรมแสดงเหนือหัวของ Starter NPC เมื่อผู้เล่นไม่สามารถเริ่มภารกิจได้ + hologramText: '§eข้อความHologram' + hologramTextLore: ข้อความ hologram ที่แสดงบนหัวของ Starter NPC + keepDatas: เก็บรักษาข้อมูลผู้เล่น + keepDatasLore: 'บังคับให้ปลั๊กอินรักษาข้อมูลของผู้เล่นแม้ว่าจะมีการแก้ไข stages แล้วก็ตาม §c§lWARNING §c- การเปิดใช้งานตัวเลือกนี้อาจทำให้ข้อมูลผู้เล่นของคุณเสียหาย' + loreReset: '§e§lความก้าวหน้าของผู้เล่นทั้งหมดจะถูกรีเซ็ต' + multipleTime: + itemLore: สามารถทำภารกิจได้หลายครั้งหรือไม่? + itemName: สลับการทำซ้ำได้ + name: รายละเอียดภารกิจสุดท้าย questName: '§a§lแก้ไขชื่อภารกิจ' questNameLore: ต้องตั้งชื่อ เพื่อสร้างภารกิจให้เสร็จสมบูรณ์ - setItemsRewards: '§eแก้ไขรางวัล ไอเท่ม' - setXPRewards: '§eแก้ไขรางวัล exp' - setCheckpointReward: '§eแก้ไขรางวัล checkpoint' - setPermReward: '§eแก้ไข permissions' - setMoneyReward: '§eแก้ไข เงินรางวัล' + questPool: '§eQuest Pool' + questPoolLore: แนบเควสนี้กับ quest pool + requiredParameter: '§7parameterที่จำเป็น' + requirements: '{amount} ข้อกำหนด(s)' + rewards: '{amount} รางวัล(s)' + rewardsLore: ดำเนินการเมื่อภารกิจสิ้นสุดลง + scoreboardItem: เปิดใช้งาน สกอร์บอร์ด + scoreboardItemLore: หากปิดใช้งานภารกิจจะไม่ถูกติดตามผ่าน สกอร์บอร์ด selectStarterNPC: '§e§lเลือก NPC starter' selectStarterNPCLore: การคลิกที่ NPC ที่เลือก จะเป็นการเริ่มภารกิจ - createQuestName: '§lสร้างภารกิจ' - createQuestLore: คุณต้องกำหนดชื่อภารกิจ - editQuestName: '§lแก้ไขเควส' - endMessage: '§eแก้ไขข้อความตอนจบ' - endMessageLore: ข้อความที่จะส่งไปยังผู้เล่นเมื่อสิ้นสุดภารกิจ + setCheckpointReward: '§eแก้ไขรางวัล checkpoint' + setItemsRewards: '§eแก้ไขรางวัล ไอเท่ม' + setMoneyReward: '§eแก้ไข เงินรางวัล' + setPermReward: '§eแก้ไข permissions' + setXPRewards: '§eแก้ไขรางวัล exp' startDialog: '§แก้ไข dialog ตอนเริ่ม' startDialogLore: Dialog ที่จะแสดงขึ้นมาก่อนที่เควสจะเริ่ม เมื่อผู้เล่นคลิกที่ Starter NPC - editRequirements: '§eแก้ไขข้อกำหนด' - editRequirementsLore: ข้อกำหนดทุกข้อต้อง apply กับผู้เล่นก่อน จึงจะเริ่มภารกิจได้ startRewards: '§6เริ่มรางวัล' startRewardsLore: ดำเนินการเมื่อภารกิจเริ่มต้นขึ้น - hologramText: '§eข้อความHologram' - hologramTextLore: ข้อความ hologram ที่แสดงบนหัวของ Starter NPC + startableFromGUI: เริ่มได้จาก GUI + startableFromGUILore: อนุญาตให้ผู้เล่นเริ่มภารกิจจากเมนูเควส timer: '§bเริ่มจับเวลาใหม่' timerLore: เวลาก่อนที่ผู้เล่นจะสามารถเริ่มภารกิจได้อีกครั้ง - requirements: '{0} ข้อกำหนด(s)' - rewards: '{0} รางวัล(s)' - actions: '{0} ดำเนินการ หรือ action(s)' - rewardsLore: ดำเนินการเมื่อภารกิจสิ้นสุดลง - customMaterial: '§eแก้ไข material ไอเท่มเควส' - customMaterialLore: ตัวแทนไอเทมของเควสนี้ในเมนูเควส - failOnDeath: ล้มเหลวเมื่อเสียชีวิต - failOnDeathLore: ภารกิจจะถูกยกเลิกเมื่อผู้เล่นเสียชีวิตหรือไม่? - questPool: '§eQuest Pool' - questPoolLore: แนบเควสนี้กับ quest pool - keepDatas: เก็บรักษาข้อมูลผู้เล่น - keepDatasLore: |- - บังคับให้ปลั๊กอินรักษาข้อมูลของผู้เล่นแม้ว่าจะมีการแก้ไข stages แล้วก็ตาม - §c§lWARNING §c- การเปิดใช้งานตัวเลือกนี้อาจทำให้ข้อมูลผู้เล่นของคุณเสียหาย - loreReset: '§e§lความก้าวหน้าของผู้เล่นทั้งหมดจะถูกรีเซ็ต' - optionValue: '§8Value: §7{0}' - defaultValue: '§8(default value ค่าเริ่มต้น)' - requiredParameter: '§7parameterที่จำเป็น' - itemsSelect: - name: แก้ไขไอเท่ม - none: |- - §aย้าย ไอเท่ม มาที่นี่ - หรือคลิก เพื่อเปิดตัวแก้ไข ไอเท่ม - itemSelect: - name: เลือก ไอเท่ม - npcCreate: - name: สร้าง NPC - setName: '§eแก้ไขชื่อ NPC' - setSkin: '§eแก้ไข สกิน NPC' - setType: '§eแก้ไข type ของ NPC' - move: - itemName: '§eย้าย' - itemLore: '§เปลี่ยนตำแหน่ง NPC' - moveItem: '§a§lตรวจสอบ place' - npcSelect: - name: เลือกหรือสร้าง? - selectStageNPC: '§eเลือก NPC ที่มีอยู่เดิม' - createStageNPC: '§eสร้าง NPC' entityType: name: เลือก entity type - chooseQuest: - name: เควสไหน? - mobs: - name: เลือก mobs - none: '§aคลิกเพื่อเพิ่ม mob' - clickLore: |- - §a§left-click§aเพื่อแก้ไขจำนวนเงิน - §a§l§nShift§a§l + คลิกซ้าย a เพื่อแก้ไขชื่อม็อบ - §c§คลิกขวา c เพื่อลบ - mobSelect: - name: เลือก mob type - bukkitEntityType: '§eเลือก entity type' - mythicMob: '§6เลือก Mythic Mob' - epicBoss: '§6เลือก Epic Boss' - boss: '§6เลือก a Boss' - stageEnding: - locationTeleport: '§eแก้ไข teleport location' - command: '§eแก้ไข executed command' - requirements: - name: ข้อกำหนด - rewards: - name: รางวัล - commands: 'คำสั่ง: {0}' - teleportation: |- - §aเลือก: - X: {0} - Y: {1} - Z: {2} - World: {3} - checkpointActions: - name: การกระทำ Checkpoint + factionsList.name: Factions list + factionsRequired.name: Factions ที่จำเป็น + itemComparisons: + enchants: ตีบวกอาวุธ + enchantsLore: เปรียบเทียบไอเทมตีบวก + itemLore: คำอธิบายไอเทม + itemLoreLore: เปรียบเทียบคำอธิบายไอเทม + itemName: ชื่อไอเทม + itemNameLore: เปรียบเทียบชื่อไอเทม + repairCost: ค่าซ่อมแซม + repairCostLore: เปรียบเทียบค่าซ่อมกับชุดเกราะและดาบ + itemCreator: + isQuestItem: '§bไอเท่มภารกิจ:' + itemFlags: สลับ ไอเท่ม flags + itemLore: '§b lore ไอเท่ม' + itemName: '§bชื่อไอเท่ม' + itemType: '§b type ไอเท่ม' + name: สร้างไอเท่ม + itemSelect: + name: เลือก ไอเท่ม + itemsSelect: + name: แก้ไขไอเท่ม + none: '§aย้าย ไอเท่ม มาที่นี่ หรือคลิก เพื่อเปิดตัวแก้ไข ไอเท่ม' listAllQuests: name: ภารกิจ + listBook: + noQuests: ไม่เคยสร้างภารกิจมาก่อน + questMultiple: หลายครั้ง + questName: ชื่อ + questRewards: รางวัล + questStages: ขั้นตอน + questStarter: เริ่มต้น + requirements: ข้อกำหนด listPlayerQuests: - name: '{0}''s ภารกิจ' + name: '{player_name}''s ภารกิจ' listQuests: - notStarted: ยังไม่เริ่มเควส + canRedo: '§3§คุณสามารถเริ่มภารกิจนี้ใหม่ได้!' finished: ภารกิจเสร็จสิ้นแล้ว inProgress: ภารกิจกำลังดำเนินการ loreStart: คลิกเพื่อเริ่มภารกิจ loreStartUnavailable: notc§oคุณมีคุณสมบัติไม่ตรงตามข้อกำหนดในการเริ่มภารกิจ - canRedo: '§3§คุณสามารถเริ่มภารกิจนี้ใหม่ได้!' - itemCreator: - name: สร้างไอเท่ม - itemType: '§b type ไอเท่ม' - itemFlags: สลับ ไอเท่ม flags - itemName: '§bชื่อไอเท่ม' - itemLore: '§b lore ไอเท่ม' - isQuestItem: '§bไอเท่มภารกิจ:' - command: - name: Command - value: '§eCommand' - console: คอนโซล - delay: '§bดีเลย์' - chooseAccount: - name: account อะไร? - listBook: - questName: ชื่อ - questStarter: เริ่มต้น - questRewards: รางวัล - questMultiple: หลายครั้ง - requirements: ข้อกำหนด - questStages: ขั้นตอน - noQuests: ไม่เคยสร้างภารกิจมาก่อน - commandsList: - name: Command list - value: '§eCommand: {0}' - console: '§eConsole: {0}' - block: - name: เลือก block - material: '§eMaterial: {0}' - blockData: '§dBlockdata (advanced)' - blocksList: - name: เลือก blocks - addBlock: '§aคลิกเพื่อเพิ่ม block.' - blockAction: - name: เลือกการดำเนินการ block - location: '§eเลือก location ที่แม่นยำ' - material: '§eเลือก block material' - buckets: - name: ชนิด Bucket + notStarted: ยังไม่เริ่มเควส + mobSelect: + boss: '§6เลือก a Boss' + bukkitEntityType: '§eเลือก entity type' + epicBoss: '§6เลือก Epic Boss' + mythicMob: '§6เลือก Mythic Mob' + name: เลือก mob type + mobs: + name: เลือก mobs + none: '§aคลิกเพื่อเพิ่ม mob' + npcCreate: + move: + itemLore: '§เปลี่ยนตำแหน่ง NPC' + itemName: '§eย้าย' + moveItem: '§a§lตรวจสอบ place' + name: สร้าง NPC + setName: '§eแก้ไขชื่อ NPC' + setSkin: '§eแก้ไข สกิน NPC' + setType: '§eแก้ไข type ของ NPC' + npcSelect: + createStageNPC: '§eสร้าง NPC' + name: เลือกหรือสร้าง? + selectStageNPC: '§eเลือก NPC ที่มีอยู่เดิม' permission: name: เลือก permission perm: '§aPermission' - world: '§aWorld' - worldGlobal: '§b§lGlobal' remove: ลบ permission removeLore: '§7Permission จะถูกปิด\n§7ให้แทนที่' + world: '§aWorld' + worldGlobal: '§b§lGlobal' permissionList: name: Permissions list - removed: '§eเอาออก: §6{0}' - world: '§eWorld: §6{0}' - classesRequired.name: Classes ที่จำเป็น - classesList.name: Classes list - factionsRequired.name: Factions ที่จำเป็น - factionsList.name: Factions list - poolsManage: - name: Quest Pools - itemName: '§aPool #{0}' - create: '§aสร้าง pool กลุ่มภารกิจ' + removed: '§eเอาออก: §6{permission_removed}' poolCreation: - name: การสร้างเควสพูล hologramText: '§ePool custom hologram' maxQuests: '§aเควสสูงสุด' - time: '§bตั้งเวลาระหว่างเควส' + name: การสร้างเควสพูล redoAllowed: อนุญาตให้ทำซ้ำ + time: '§bตั้งเวลาระหว่างเควส' poolsList.name: Quest pools - itemComparisons: - itemName: ชื่อไอเทม - itemNameLore: เปรียบเทียบชื่อไอเทม - itemLore: คำอธิบายไอเทม - itemLoreLore: เปรียบเทียบคำอธิบายไอเทม - enchants: ตีบวกอาวุธ - enchantsLore: เปรียบเทียบไอเทมตีบวก - repairCost: ค่าซ่อมแซม - repairCostLore: เปรียบเทียบค่าซ่อมกับชุดเกราะและดาบ -scoreboard: - name: '§6§lQเควส' - noLaunched: '§cไม่มีภารกิจอยู่ในระหว่างดำเนินการ' - noLaunchedName: '§c§lกำลังโหลด' - noLaunchedDescription: '§c§oกำลังโหลด' - textBetwteenBranch: '§e หรือ' - stage: - region: '§eค้นหา region §6{0}' - npc: '§eคุยกับ NPC §6{0}' - items: '§eส่ง ไอเท่ม ให้ §6{0}§e:' - mobs: '§eฆ่า §6{0}' - mine: '§eขุด {0}' - placeBlocks: '§eวาง {0}' - chat: '§eเขียน §6{0}' - interact: '§eคลิก block ที่ §6{0}' - interactMaterial: '§eคลิกที่ §6{0}§e block' - fish: '§eปลา §6{0}' - craft: '§eสร้าง §6{0}' - bucket: '§eเติม §6{0}' - location: '§eไปที่ §6{0}§e, §6{1}§e, §6{2}§e ใน §6{3}' - breed: ผสมพันธ์ §6{0} - tame: ทำให้เชื่อง §6{0} -indication: - startQuest: '§7คุณต้องการเริ่มภารกิจ {0} หรือไม่?' - closeInventory: '§7คุณแน่ใจหรือไม่ว่าต้องการปิด GUI?' - cancelQuest: '§7คุณแน่ใจหรือไม่ว่าต้องการยกเลิกภารกิจ {0}' - removeQuest: '§7คุณแน่ใจหรือไม่ว่าต้องการลบภารกิจ {0}' + poolsManage: + create: '§aสร้าง pool กลุ่มภารกิจ' + itemName: '§aPool #{pool}' + name: Quest Pools + requirements: + name: ข้อกำหนด + rewards: + commands: 'คำสั่ง: {amount}' + name: รางวัล + search: '§e§lค้นหา' + stageEnding: + command: '§eแก้ไข executed command' + locationTeleport: '§eแก้ไข teleport location' + stages: + branchesPage: '§dBranch stages' + descriptionTextItem: '§แก้ไขคำอธิบาย' + endingItem: '§eแก้ไขรางวัลตอนจบ' + laterPage: '§eหน้าที่แล้ว' + name: สร้าง stages + newBranch: '§eไปที่ branch ใหม่' + nextPage: '§eหน้าต่อไป' + previousBranch: '§eกลับไปที่ branch ก่อนหน้า' + regularPage: '§astages ปรกติ' + validationRequirements: '§eข้อกำหนดในการตรวจสอบความถูกต้อง' + validationRequirementsLore: ข้อกำหนดทั้งหมดจะต้องตรงกับผู้เล่นที่พยายามเล่นจนจบ stage หากไม่เช่นนั้น stage จะไม่เสร็จสมบูรณ์ + validate: '§b§lตรวจสอบ' misc: + amount: '§eจำนวนt: {amount}' + and: และ + bucket: + lava: ถังลาวา + milk: ถังนม + water: ถังน้ำ + comparison: + different: แตกต่างจาก {number} + equals: เท่ากับ {number} + greater: มากกว่า {number} อย่างเคร่งครัด + greaterOrEquals: มากกว่า {number} + less: น้อยกว่า {number} อย่างเคร่งครัด + lessOrEquals: น้อยกว่า {number} + disabled: ปิดการใช้งาน + enabled: เปิดการใช้งาน + entityType: '§eประเภท Entity : {entity_type}' + entityTypeAny: สิ่งมีชีวิตตัวไหนก็ได้ format: prefix: '§6<§e§lภารกิจ§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - offText: '§r§e{0}' - time: - days: '{0} วัน' - hours: '{0} ชั่วโมง' - minutes: '{0} นาที' - stageType: - region: ค้นหา region - npc: ค้นหา NPC - items: นำ ไอเท่ม กลับมา - mobs: ฆ่า mobs - mine: ทำลาย blocks - placeBlocks: วาง blocks - chat: เขียนในแชท - interact: โต้ตอบกับบล็อก - Fish: จับปลา - Craft: สร้างไอเท่ม - Bucket: เติม bucket - location: ค้นหา location - playTime: เวลาเล่น - breedAnimals: ผสมพันธ์สัตว์ - tameAnimals: สัตว์เลี้ยง - comparison: - equals: เท่ากับ {0} - different: แตกต่างจาก {0} - less: น้อยกว่า {0} อย่างเคร่งครัด - lessOrEquals: น้อยกว่า {0} - greater: มากกว่า {0} อย่างเคร่งครัด - greaterOrEquals: มากกว่า {0} + hologramText: '§8§lภารกิจ NPC' + 'no': 'ไม่' + notSet: '§cไม่ได้ตั้งค่า' + or: หรือ + poolHologramText: '§eภารกิจใหม่มาแล้ว!' + questItemLore: '§e§oภารกิจไอเท่ม' requirement: class: '§bClass (es) ที่จำเป็น' - faction: '§bFaction(s) ที่จำเป็น' - jobLevel: '§bJob เลเวล ที่จำเป็น' combatLevel: '§bCombat เลเวล ที่จำเป็น' experienceLevel: '§bEXP เลเวล ที่จำเป็น' + faction: '§bFaction(s) ที่จำเป็น' + jobLevel: '§bJob เลเวล ที่จำเป็น' + mcMMOSkillLevel: '§dSkill เลเวล ที่จำเป็น' + money: '§dเงิน ที่จำเป็น' permissions: '§3Permission(s) ที่จำเป็น' - scoreboard: '§dScore ที่จำเป็น' - region: '§dRegion ที่จำเป็น' placeholder: '§bPlaceholder value ที่จำเป็น' quest: '§aภารกิจ ที่จำเป็น' - mcMMOSkillLevel: '§dSkill เลเวล ที่จำเป็น' - money: '§dเงิน ที่จำเป็น' - bucket: - water: ถังน้ำ - lava: ถังลาวา - milk: ถังนม - questItemLore: '§e§oภารกิจไอเท่ม' - hologramText: '§8§lภารกิจ NPC' - poolHologramText: '§eภารกิจใหม่มาแล้ว!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eประเภท Entity : {0}' - entityTypeAny: สิ่งมีชีวิตตัวไหนก็ได้ - enabled: เปิดการใช้งาน - disabled: ปิดการใช้งาน + region: '§dRegion ที่จำเป็น' + scoreboard: '§dScore ที่จำเป็น' + stageType: + Bucket: เติม bucket + Craft: สร้างไอเท่ม + Fish: จับปลา + breedAnimals: ผสมพันธ์สัตว์ + chat: เขียนในแชท + interact: โต้ตอบกับบล็อก + items: นำ ไอเท่ม กลับมา + location: ค้นหา location + mine: ทำลาย blocks + mobs: ฆ่า mobs + npc: ค้นหา NPC + placeBlocks: วาง blocks + playTime: เวลาเล่น + region: ค้นหา region + tameAnimals: สัตว์เลี้ยง + time: + days: '{days_amount} วัน' + hours: '{hours_amount} ชั่วโมง' + minutes: '{minutes_amount} นาที' unknown: ไม่ทราบ - notSet: '§cไม่ได้ตั้งค่า' - unused: ไม่ได้ใช้ - used: '§a§lใช้แล้ว' - remove: '§7คลิ๊กเมาท์กลางเพื่อลบ' - or: หรือ - amount: '§eจำนวนt: {0}' - items: ไอเท่ม - expPoints: ค่าประสบการณ์ 'yes': 'ใช่' - 'no': 'ไม่' - and: และ +msg: + bringBackObjects: พาฉันกลับมาที่ {items} + command: + adminModeEntered: '§คุณได้เข้าสู่โหมดผู้ดูแลระบบ' + adminModeLeft: '§คุณออกจากโหมดผู้ดูแลระบบแล้ว' + backupCreated: '§6คุณได้สร้างการสำรองข้อมูลของ ภารกิจ และข้อมูลผู้เล่นทั้งหมดเรียบร้อยแล้ว' + backupPlayersFailed: '§การสร้างข้อมูลสำรองสำหรับข้อมูลผู้เล่นทั้งหมดล้มเหลว' + backupQuestsFailed: '§การสร้างข้อมูลสำรองสำหรับเควสทั้งหมดล้มเหลว' + cancelQuest: '§6คุณได้ยกเลิกภารกิจ {quest}.' + cancelQuestUnavailable: '§ภารกิจ {quest} ไม่สามารถยกเลิกได้' + checkpoint: + noCheckpoint: '§cไม่พบ checkpoint สำหรับภารกิจ {quest}' + questNotStarted: '§cคุณไม่ได้ทำภารกิจนี้.' + downloadTranslations: + downloaded: ดาวน์โหลด §aLanguage {lang} แล้ว! §7ตอนนี้คุณต้องแก้ไขไฟล์ "/plugins/BeautyQuests/config.yml" เพื่อเปลี่ยนค่าของ §ominecraftTranslationsFile§7 ด้วย {lang} จากนั้นรีสตาร์ทเซิร์ฟเวอร์ + notFound: '§cLanguage {lang} ไม่พบสำหรับรุ่น {version} ' + syntax: '§cคุณต้องระบุภาษาที่จะดาวน์โหลด ตัวอย่าง: "/quests downloadTranslations en_US"' + help: + adminMode: '§6/{label} adminMode: §eสลับโหมดผู้ดูแลระบบ (มีประโยชน์สำหรับการแสดงข้อความบันทึกเล็กน้อย)' + create: '§6/{label} create: §eสร้างภารกิจ' + edit: '§6/{label} edit: §eแก้ไขภารกิจ' + finishAll: '§6/{label} finishAll <player>: §eจบภารกิจทั้งหมดของผู้เล่น' + header: '§6§lBeautyQuests — Help' + list: '§6/{label} list: §eดูรายการเควส (สำหรับเวอร์ชันที่รองรับเท่านั้น)' + reload: '§6/{label} reload: §eSบันทึกและโหลดการกำหนดค่าและไฟล์ทั้งหมดซ้ำ. (§cdeprecated§e)' + remove: '§6/{label} remove <id>: §eลบเควสด้วย id ที่ระบุหรือคลิกที่ NPC เมื่อไม่ได้กำหนดไว้' + resetPlayer: '§6/{label} resetPlayer <player>: §eลบข้อมูลทั้งหมดเกี่ยวกับผู้เล่น' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eลบข้อมูลของภารกิจให้ผู้เล่น' + save: '§6/{label} save: §eทำการบันทึกปลั๊กอินด้วยตนเอง' + seePlayer: '§6/{label} seePlayer <player>: §eดูข้อมูลเกี่ยวกับผู้เล่น' + setFirework: '§6/{label} setFirework: §eแก้ไขจุดสิ้นสุดของดอกไม้ไฟเริ่มต้น' + setItem: '§6/{label} setItem <talk|launch>: §eบันทึก hologram ไอเท่ม' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eข้ามขั้นตอน stage/start the branch/set a stage สำหรับ branch.' + start: '§6/{label} start <player> [id]: §eบังคับให้เริ่มเควส' + startDialog: '§6/{label} startDialog <player> <quest id>: §eเริ่มกล่องโต้ตอบที่รอดำเนินการสำหรับด่าน NPC หรือกล่องโต้ตอบเริ่มต้นสำหรับภารกิจ' + version: '§6/{label} version: §eดูเวอร์ชันปลั๊กอินปัจจุบัน' + invalidCommand: + simple: '§cไม่มี command นี้, เขียน §help§c.' + itemChanged: '§ ไอเท่ม ที่ได้รับการแก้ไข การเปลี่ยนแปลงจะมีผล หลังจากรีสตาร์ท.' + itemRemoved: '§ไอเท่ม โฮโลแกรม ถูกลบออก' + leaveAll: '§คุณบังคับให้สิ้นสุด {success} เควส) ข้อผิดพลาด: {errors}' + removed: '§ภารกิจ {quest_name} ถูกลบออกเรียบร้อยแล้ว' + resetPlayer: + player: '§6ข้อมูลทั้งหมดเกี่ยวกับภารกิจของคุณ {quest_amount} รายการได้ถูกลบโดย {deleter_name}.' + remover: '§6{quest_amount} ข้อมูลภารกิจ (และ {quest_pool} กลุ่ม) ของ {player} ถูกลบแล้ว' + resetPlayerPool: + full: '§คุณได้รีเซ็ต {pool} ข้อมูลพูลของ {player}' + timer: '§aคุณได้รีเซ็ต {pool} ตัวจับเวลาพูลของ {player} ' + resetPlayerQuest: + player: '§6ข้อมูลทั้งหมดเกี่ยวกับภารกิจ {quest} ถูกลบโดย {deleter_name}' + remover: '§6 {player} ข้อมูลภารกิจของ {quest} ถูกลบไปแล้ว' + resetQuest: '§6ลบข้อมูลของภารกิจสำหรับ {player_amount} players.' + scoreboard: + hidden: '§6ป้ายบอกคะแนนของผู้เล่น {player_name} ถูกซ่อนไว้' + lineInexistant: '§ไม่มี line {line_id}' + lineRemoved: '§6คุณลบ line เรียบร้อยแล้ว {line_id}.' + lineReset: '§6คุณรีเซ็ต line สำเร็จแล้ว {line_id}' + lineSet: '§6คุณแก้ไข line เรียบร้อยแล้ว {line_id}' + own: + hidden: '§6ป้ายของคุณถูกซ่อนอยู่ในขณะนี้' + shown: '§6ป้ายของคุณจะปรากฏขึ้นอีกครั้ง' + resetAll: '§6คุณรีเซ็ต สกอร์บอร์ด ของผู้เล่นสำเร็จแล้ว {player_name}' + shown: '§6ป้ายบอกคะแนนของผู้เล่น {player_name} มีการแสดง.' + setStage: + branchDoesntExist: '§cไม่มี branch ที่มี id {branch_id}' + doesntExist: '§cไม่มี stage ที่มี id {stage_id} ' + next: '§a stage ถูกข้าม. ' + nextUnavailable: '§ตัวเลือก "ข้าม" ไม่สามารถใช้ได้เมื่อผู้เล่นอยู่ในจุดสิ้นสุด branch.' + set: '§aStage {stage_id} เริ่ม.' + startDialog: + alreadyIn: '§cผู้เล่นกำลังเล่นกล่องโต้ตอบอยู่แล้ว' + impossible: '§cImpossible to start the dialog now. ' + noDialog: '§cThe player has no pending dialog.' + success: '§aเริ่มกล่องโต้ตอบสำหรับผู้เล่น {player} ในภารกิจ {quest}!' + startQuest: '§6คุณบังคับให้เริ่มภารกิจ {quest} (UUID ของผู้เล่น: {player})' + dialogs: + skipped: '§8§o Dialog skipped.' + tooFar: '§7§oคุณได้อยู่ห่างไกลจาก {npc_name}...' + editor: + already: '§cคุณอยู่ในเครื่องมือแก้ไขแล้ว' + blockAmount: '§aเขียนจำนวน blocks:' + blockData: '§aเขียน blockdata (available blockdatas: {available_datas}):' + blockName: '§aเขียนชื่อ block:' + colorNamed: โปรดใส่รหัสสี + dialog: + cleared: '§a {amount} ข้อความที่ถูกลบ' + edited: '§aข้อความ "§7{msg}§a" ได้ถูกแก้ไขเรียบร้อย' + help: + addSound: '§6addSound <id> <sound>: §เพิ่มเสียงให้กับข้อความ' + clear: '§6clear: §ลบข้อความทั้งหมด' + close: '§6close: §eตรวจสอบข้อความทั้งหมด' + edit: 'แก้ไข <id> <message>:§eข้อความที่แก้ไข' + header: '§6§lBeautyQuests — Dialog editor help' + list: '§6list: §eดูl messages ทั้งหมด.' + nothing: '§6noSender <message>: §eเพิ่มข้อความโดยไม่มีผู้ส่ง' + nothingInsert: '§6nothingInsert <id> <message>: §eใส่ข้อความโดยไม่มีคำนำหน้าใดๆ' + npc: '§6npc <message>: §eเพิ่มข้อความที่ NPC พูด' + npcInsert: '§6npcInsert <id> <message>: §eใส่ข้อความที่ NPC พูด' + player: '§6player <ข้อความ>: §เพิ่มข้อความที่ผู้เล่นพูด.' + playerInsert: '§6playerInsert <id> <message>: §eใส่ข้อความที่ผู้เล่นพูด' + remove: '§6remove <id>: §ลบข้อความ' + setTime: '§6setTime <id> <time>: §eSetเวลา (in ticks) ก่อนที่ข้อความถัดไปจะเล่นโดยอัตโนมัติ' + messageRemoved: '§aข้อความ "§7{msg}§a" ได้ถูกลบออกเรียบร้อย' + syntaxRemove: '§cCorrect sytax: remove <id>' + timeRemoved: '§aTime ถูกลบออกสำหรับ message {msg}' + timeSet: '§aTime ถูกแก้ไขสำหรับ message {msg}: now {time} ticks.' + enter: + subtitle: พิม /quests exitEditor เพื่อออกจากโหมดแก้ไข + title: '§6 ~ โหมดแก้ไข ~' + goToLocation: '§aไปยังตำแหน่งที่ต้องการสำหรับ stage.' + itemCreator: + invalidBlockType: '§c block type ไม่ถูกต้อง' + invalidItemType: '§cประเภท ไอเท่ม ไม่ถูกต้อง (item ไม่สามารถ block ได้)' + itemAmount: '§เขียนจำนวน ไอเท่ม(s):' + itemLore: '§aแก้ไข lore ของ ไอเท่ม: (Write "help" for help.)' + itemName: '§aเขียนชื่อ item:' + itemType: '§aเขียนชื่อ type ไอเท่ม ที่ต้องการ:' + unknownBlockType: '§cไม่ทราบ block type. ' + unknownItemType: '§cไม่ทราบ item type.' + mythicmobs: + disabled: '§cMythicMob ถูกปิดใช้งาน' + isntMythicMob: '§cMythic Mob นี้ไม่มีอยู่จริง' + list: '§aรายการทั้งหมดของ Mythic Mobs:' + noSuchElement: '§ไม่มี element ดังกล่าว element ที่อนุญาต ได้แก่ §e {available_elements}' + npc: + choseStarter: '§aเลือก NPC ที่เริ่มภารกิจ' + enter: '§aคลิกที่ NPC หรือเขียน "cancel".' + notStarter: '§cNPC ตัวนี้ไม่ใช่ตัวเริ่มต้นภารกิจ' + pool: + hologramText: เขียนข้อความโฮโลแกรมที่กำหนดเองสำหรับพูลนี้ (หรือ "null" ถ้าคุณต้องการใช้ค่าเริ่มต้น) + maxQuests: เขียนจำนวนสูงสุดของ ภารกิจ ที่สามารถเรียกใช้งานได้จาก pool นี้ + scoreboardObjectiveNotFound: '§cไม่ทราบวัตถุประสงค์ของ สกอร์บอร์ด' + selectWantedBlock: '§aคลิกด้วย stick บน block สำหรับ stage.' + text: + argNotSupported: '§cThe argument {arg} ไม่รองรับ.' + chooseJobRequired: '§aเขียนชื่อ job ที่ต้องการ:' + chooseLvlRequired: '§aเขียนระดับ levels ที่ต้องการ:' + chooseMoneyRequired: '§aเขียนจำนวนเงินที่ต้องการ:' + chooseObjectiveRequired: '§aเขียนชื่อ objective.' + chooseObjectiveTargetScore: '§aเขียน เป้าหมาย score สำหรับ objective.' + choosePermissionMessage: '§aคุณสามารถเลือกข้อความปฏิเสธหากผู้เล่นไม่มี permission. ที่จำเป็น (หากต้องการข้ามขั้นตอนนี้ให้เขียน "null".)' + choosePermissionRequired: '§aเขียน permission ที่ต้องการ เพื่อเริ่มภารกิจ:' + choosePlaceholderRequired: + identifier: '§aเขียนชื่อของ placeholder ต้องการ โดยไม่ต้องมี %:' + value: '§aขียนค่าที่ต้องการสำหรับ placeholder §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aเขียนชื่อ region ที่ต้องการ (คุณต้องอยู่ใน world เดียวกัน).' + chooseSkillRequired: '§aเขียนชื่อของ skill ที่ต้องการ:' + reward: + money: '§aเขียนจำนวนเงินที่ได้รับ:' + permissionName: '§aเขียนชื่อ permission' + permissionWorld: '§aเขียน world ที่จะแก้ไข permission หรือเขียน "null" ถ้าคุณต้องการให้เป็นแบบ global' + textList: + added: '§aข้อความ "§7{msg}§a" ได้ถูกเพิ่มเรียบร้อย' + help: + add: '§6add <message>: §eเพิ่มข้อความ' + close: '§6close: §eตรวจสอบข้อความที่เพิ่มเข้ามา' + header: '§6§lBeautyQuests — List editor help' + list: '§6list: §eดูข้อความที่เพิ่มทั้งหมด' + remove: '§6remove <id>: §ลบข้อความ' + removed: '§aข้อความ "§7{msg}§a" ได้ถูกลบออกเรียบร้อย' + syntax: '§cCorrect syntax: ' + typeBucketAmount: '§aเขียนจำนวน buckets ที่จะเติม:' + typeGameTicks: '§aเขียน game ticks ที่ต้องการ:' + typeLocationRadius: '§aเขียนระยะทางที่ต้องการจาก location:' + errorOccurred: '§cเกิดข้อผิดพลาด โปรดติดต่อผู้ดูแลระบบ! §4§lError code: {error}' + experience: + edited: '§คุณเปลี่ยนค่า EXP ที่ได้รับจาก {old_xp_amount} เป็น {xp_amount} คะแนน.' + indexOutOfBounds: '§หมายเลข {index} อยู่นอกขอบเขต! ต้องอยู่ระหว่าง {min} ถึง {max}' + invalidBlockData: '§blockdata {block_data} ไม่ถูกต้อง หรือเข้ากันไม่ได้กับ block {block_material}' + invalidBlockTag: '§cแท็กบล็อกไม่พร้อมใช้งาน {block_tag}' + inventoryFull: '§cช่องเก็บ ไอเท่ม ของคุณเต็ม, ไอเทมหล่นลงพื้น.' + moveToTeleportPoint: '§aไปยังจุด teleport ที่ต้องการ .' + npcDoesntExist: '§cไม่มี NPC ที่มี id {npc_id}' + number: + invalid: '§c{input} ไม่ใช่ตัวเลขที่ถูกต้อง.' + negative: '§cคุณต้องป้อนจำนวนบวก! ' + zero: '§cคุณต้องป้อนตัวเลขอื่นที่ไม่ใช่ 0!' + pools: + allCompleted: '§7ภารกิจของคุณเสร็จหมดแล้ว!' + maxQuests: '§cไม่สามารถรับได้มากกว่า {pool_max_quests} quest(s) ในเวลาเดียวกัน...' + noAvailable: '§7ยังไม่มีภารกิจอื่นในตอนนี้...' + noTime: '§cคุณต้องรอเวลา {time_left} ก่อนจะไปทำภารกิจอื่นt.' + quest: + alreadyStarted: '§cคุณเริ่มภารกิจเรียบร้อยแล้ว!' + cancelling: '§cกระบวนการสร้างเควสถูกยกเลิก.' + createCancelled: '§cการสร้าง หรือแก้ไข ถูกยกเลิกโดย Plugin อื่น!' + created: '§aยินดีด้วย! คุณได้สร้างภารกิจ §e{quest}§a which includes {quest_branches} branch(es)!' + editCancelling: '§cการแก้ไขเควส ถูกยกเลิก.' + edited: '§aยินดีด้วย! คุณได้แก้ไขภารกิจ §e{quest}§a which includes now {quest_branches} branch(es)!' + finished: + base: '§aยินดีด้วย! คุณได้ทำภารกิจสำเร็จแล้ว§e{quest_name}§a!' + obtain: '§aคุณได้รับ {rewards}!' + invalidID: '§cภารกิจ id {quest_id} ไม่มีอยู่จริง.' + started: '§aภารกิจของคุณเริ่มแล้ว §r§e{quest_name}§o§6!' + questItem: + craft: '§cไอเท่มเควสชิ้นนี้ไม่สามารถคราฟได้!' + drop: '§cคุณไม่สามารถทิ้ง ไอเท่ม เควสนี้ได้!' + eat: '§cผู้เล่นไม่สามารถกินของชิ้นนี้ได้!' + quests: + checkpoint: '§7ถึงจุดตรวจภารกิจแล้ว!' + failed: '§cภารกิจของคุณล้มเหลว {quest_name}...' + maxLaunched: '§cไม่สามารถรับได้มากกว่า {quests_max_amount} quest(s) ในเวลาเดียวกัน...' + updated: '§7ภารกิจ §e{quest_name}§7 อัพเดต.' + regionDoesntExists: '§ไม่มี region นี้ (คุณต้องอยู่ในโลกเดียวกัน)' + requirements: + combatLevel: '§cเลเวล combat ต้อง {long_level}!' + job: '§cเลเวลอาชีพ §e{job_name}§c ต้อง {long_level}!' + level: '§cคุณต้องมีเลเวล {long_level}!' + money: '§cคุณต้องมี {money}! ' + quest: คุณต้องทำภารกิจ e {quest_name} §c! ให้เสร็จ + skill: '§cเลเวลสกิล §e{skill_name}§c ต้อง {long_level}!' + waitTime: '§cคุณต้องรอ {time_left} นาที จึงจะสามารถเริ่มภารกิจนี้ใหม่ได้!' + restartServer: '§7รีสตาร์ทเซิร์ฟเวอร์ของคุณเพื่อดูการแก้ไข' + selectNPCToKill: '§aเลือก NPC ที่จะฆ่า.' + stageMobs: + listMobs: '§aคุณต้องฆ่า {mobs}.' + typeCancel: '§aเขียนคำว่า "cancel" เพื่อกลับไปที่ข้อความสุดท้าย' + writeChatMessage: '§aเขียนข้อความ: (Add "{SLASH}" หากคุณต้องการให้ใช้ command ในการเริ่มต้น.)' + writeCommand: '§aเขียน command ที่ต้องการ: (command ไม่มีเครื่องหมาย "' + writeCommandDelay: '§aเขียนการหน่วงเวลาคำสั่งที่ต้องการ ใน ticks.' + writeConfirmMessage: '§เขียนข้อความยืนยัน เมื่อผู้เล่นกำลังจะเริ่มภารกิจ: (เขียน "null" หากต้องการข้อความเริ่มต้น)' + writeDescriptionText: '§aเขียนข้อความ เพื่ออธิบายเป้าหมายของสเตจ:' + writeEndMsg: '§aWrite the message that will be sent at the end of the quest, "null" if you want the default one or "none" if you want none. You can use "{rewards}" which will be replaced with the rewards obtained. ' + writeHologramText: '§aเขียนข้อความ โฮโลแกรม: (เขียน "none" ถ้าไม่ต้องการใช้ฮโลแกรมและ "null" ถ้าต้องการข้อความเริ่มต้น)' + writeMessage: '§aเขียนข้อความเพื่อส่งให้ผู้เล่น' + writeMobAmount: '§aกำหนดจำนวน mobs ที่ต้องฆ่า:' + writeMobName: '§aเขียนชื่อที่กำหนดเองของ mob ที่จะฆ่า:' + writeNPCText: '§เขียน dialog เพื่อให้ NPC คุยกับผู้เล่น: (เขียน "help" เพื่อที่จะแสดงคำว่า help.)' + writeNpcName: '§aเขียนชื่อ NPC: ' + writeNpcSkinName: '§aกำหนดชื่อ skin ให้ NPC:' + writeQuestDescription: '§aเขียนคำอธิบายของภารกิจที่แสดงใน GUI ภารกิจของผู้เล่น' + writeQuestMaterial: '§aกำหนดไอเท่ม material ของภารกิจ.' + writeQuestName: '§aเขียนชื่อ ภารกิจ ของคุณ:' + writeQuestTimer: '§เขียนเวลาที่ต้องการให้รอ (นาที) ก่อนที่จะสามารถรีสตาร์ทภารกิจได้: (เขียน "null" หากต้องการจับเวลาเริ่มต้น)' + writeRegionName: '§aเขียนชื่อ region ที่ต้องการ เพื่อ step ขั้นต่อไป:' + writeStageText: '§aเขียนข้อความ ที่จะส่งไปให้ผู้เล่น เมื่อเริ่ม step:' + writeStartMessage: '§aWrite the message that will be sent at the beginning of the quest, "null" if you want the default one or "none" if you want none: ' + writeXPGain: '§aกำหนดจำนวน EXP ที่ผู้เล่นจะได้รับ: (Last value: {xp_amount})' +scoreboard: + name: '§6§lQเควส' + noLaunched: '§cไม่มีภารกิจอยู่ในระหว่างดำเนินการ' + noLaunchedDescription: '§c§oกำลังโหลด' + noLaunchedName: '§c§lกำลังโหลด' + stage: + breed: ผสมพันธ์ §6{mobs} + bucket: '§eเติม §6{buckets}' + chat: '§eเขียน §6{text}' + craft: '§eสร้าง §6{items}' + fish: '§eปลา §6{items}' + interact: '§eคลิก block ที่ §6{x}' + interactMaterial: '§eคลิกที่ §6{block}§e block' + items: '§eส่ง ไอเท่ม ให้ §6{dialog_npc_name}§e:' + location: '§eไปที่ §6{target_x}§e, §6{target_y}§e, §6{target_z}§e ใน §6{target_world}' + mine: '§eขุด {blocks}' + mobs: '§eฆ่า §6{mobs}' + npc: '§eคุยกับ NPC §6{dialog_npc_name}' + placeBlocks: '§eวาง {blocks}' + region: '§eค้นหา region §6{region_id}' + tame: ทำให้เชื่อง §6{mobs} + textBetwteenBranch: '§e หรือ' diff --git a/core/src/main/resources/locales/tr_TR.yml b/core/src/main/resources/locales/tr_TR.yml new file mode 100755 index 00000000..1347677c --- /dev/null +++ b/core/src/main/resources/locales/tr_TR.yml @@ -0,0 +1,799 @@ +--- +advancement: + finished: Bitti + notStarted: Başlatılmadı +description: + requirement: + class: Sınıf {class_name} + combatLevel: Dövüş seviyesi {short_level} + faction: Grup {faction_name} + jobLevel: '{job_name} için Seviye {short_level}' + level: Seviye {short_level} + quest: '§e{quest_name} §rGörevini bitir' + skillLevel: '{skill_name} için Seviye {short_level}' + title: '§8§lGereksinimler:' + reward: + title: '§8§lÖdüller:' +indication: + cancelQuest: '§7{quest_name} görevini iptal etmek istediğinizden emin misiniz?' + closeInventory: Arayüzü(GUI'yi) kapatmak istediğinizden emin misiniz? + removeQuest: '§7{quest} görevini kaldırmak istediğinizden emin misiniz?' + startQuest: '§7{quest_name} görevini başlatmak istiyor musunuz?' +inv: + addObject: '§aBir nesne ekle' + block: + blockData: '§dBlokverisi (GELİŞMİŞ)' + blockName: '§bÖzel blok adı' + blockTag: '§dTag (gelişmiş)' + blockTagLore: Olası blokların listesini açıklayan bir etiket seçin. Etiketler, veri paketleri kullanılarak özelleştirilebilir. Etiketlerin listesini Minecraft wiki'sinde bulabilirsiniz. + material: '§eMateryal: {block_type}' + materialNotItemLore: Seçilen blok bir öğe olarak görüntülenemez. Hâlâ {block_material} olarak doğru bir şekilde saklanıyor. + name: Blok seç + blockAction: + location: Kesin bir konum seçin + material: '§eBlok malzemesini seçin' + name: Blok eylemini seçin + blocksList: + addBlock: '§aBir Blok eklemek için tıklayın.' + name: Blokları seçin + buckets: + name: Kova türü + cancel: '§c§lİptal et' + cancelActions: + name: İşlemi iptal et + checkpointActions: + name: Kontrol noktası eylemleri + chooseAccount: + name: What account? + chooseQuest: + menu: '§aGörevler Menüsü' + menuLore: Sizi Görevler Menünüze götürür. + name: Hangi görev? + classesList.name: Sınıfların listesi + classesRequired.name: Gerekli sınıflar + command: + console: Konsol + delay: '§bGecikme' + name: Komut + parse: Placeholders Ayrıştırma + value: '§eKomut' + commandsList: + console: '§eKonsol: {command_console}' + name: Komut Listesi + value: '§eKomut: {command_label}' + confirm: + name: Emin misin? + 'no': '§cİptal et' + 'yes': '§aOnayla' + create: + NPCSelect: '§eNPC''yi seçin veya oluşturun' + NPCText: '§eDiyaloğu düzenle' + breedAnimals: '§aHayvanları çiftleştir' + bringBack: '§aEşyaları geri getir' + bucket: '§aKovayı doldur' + cancelMessage: Göndermeyi iptal et + cantFinish: '§7Görev oluşturmayı tamamlamadan önce en az bir aşama oluşturmalısınız!' + changeEntityType: '§eVarlık türünü değiştir' + changeTicksRequired: '§eGerekli ticks miktarını değiştirin' + craft: '§aEşyayı Üret' + currentRadius: '§eMevcut uzaklık: §6{radius}' + dealDamage: '§cMoblara hasar verin' + death: '§cÖl' + eatDrink: '§aYiyecek veya iksir yiyin veya için' + editBlocksMine: '§eKırılacak blokları düzenleyin' + editBlocksPlace: '§eKoyulacak blokları düzenleyin' + editBucketAmount: '§eDoldurulacak kova miktarını düzenleyin' + editBucketType: '§eDoldurulacak kova türünü düzenleyin' + editFishes: '§eYakalanacak balıkları düzenleyin' + editItem: '§eOluşturulacak öğeyi düzenleyin' + editItemsToEnchant: '§eBüyülenecek öğeleri düzenleyin' + editItemsToMelt: '§eEritilecek öğeleri düzenleyin' + editLocation: '§eKonumunu düzenle' + editMessageType: '§eYazılacak mesajı düzenleyin' + editMobsKill: '§eÖldürülecek mobları düzenleyin' + editRadius: '§eKonuma olan uzaklığı düzenleyin' + enchant: '§dEşyaları büyüle' + findNPC: '§aNPC''yi bul' + findRegion: '§aBölge bul' + fish: '§aBalık tut' + hideClues: Parçacıkları ve hologramları gizleyin + ignoreCase: Mesajın büyük/küçük harf durumunu yoksay + interact: '§aBlok ile etkileşime gir' + killMobs: '§aMobları öldür' + leftClick: Tıklama sol tıklama olmalıdır + location: '§aKonuma git' + melt: '§6Eşyaları ısıt' + mineBlocks: '§aBlokları kır' + mobsKillFromAFar: fırlatılan bir eşya ile öldürülmesi gerekiyor + placeBlocks: '§aBlokları koy' + playTime: '§eOynama süresi' + preventBlockPlace: Oyuncuların kendi bloklarını kırmalarını önleyin + replacePlaceholders: PAPI'den {PLAYER} ve yer tutucularını değiştirin + selectBlockLocation: '§eBlok konumunu seçin' + selectBlockMaterial: '§eBlok malzemesini seçin' + selectItems: '§eGerekli eşyaları düzenle' + selectItemsComparisons: '§eÜrün karşılaştırmalarını seçin (GELİŞMİŞ)' + selectItemsMessage: '§eSorma mesajını düzenle' + selectRegion: '§7Bölge seç' + stage: + dealDamage: + damage: '§eVerilecek hasar' + targetMobs: '§cMoblara verilecek zarar' + death: + anyCause: Herhangi bir ölüm nedeni + causes: '§aÖlüm nedenlerini ayarla §d(GELİŞMİŞ)' + setCauses: '{causes_amount} ölüm nedeni' + eatDrink: + items: '§eYiyecek veya içecek eşyalarını düzenleyin' + location: + worldPattern: '§aDünya adı kalıbını ayarla §d(GELİŞMİŞ)' + worldPatternLore: Belirli bir kalıpla eşleşen herhangi bir dünya için aşamanın tamamlanmasını istiyorsanız, buraya bir normal ifade (regular expression) girin. + stageCreate: '§aYeni bir adım oluştur' + stageDown: Aşağı taşı + stageRemove: '§cBu adımı sil' + stageStartMsg: '§eBaşlangıç mesajını düzenle' + stageType: '§7Aşama tipi: §e{stage_type}' + stageUp: Yukarı taşı + talkChat: '§aSohbete yaz' + tameAnimals: '§aHayvanları besle' + toggleRegionExit: Çıkışta + damageCause: + name: Hasar nedeni + damageCausesList: + name: Hasar nedenlerinin listesi + details: + actions: '{amount} işlem' + auto: İlk katılımda otomatik olarak başlat + autoLore: Etkinleştirilirse, oyuncu sunucuya ilk kez katıldığında görev otomatik olarak başlatılacaktır. + bypassLimit: Görev sınırını sayma + bypassLimitLore: Etkinleştirilirse, oyuncu maksimum başlatılan görev sayısına ulaşmış olsa bile görev başlatılabilir. + cancelRewards: '§cEylemleri iptal et' + cancelRewardsLore: Oyuncular bu görevi iptal ettiğinde gerçekleştirilen eylemler. + cancellable: Oyuncu tarafından iptal edilebilir + cancellableLore: Oyuncunun, Görevler Menüsü aracılığıyla görevi iptal etmesine izin verir. + createQuestLore: Bir görev adı tanımlamanız gerekir. + createQuestName: '§lGörev oluştur' + customConfirmMessage: '§eGörev onay mesajını düzenle' + customConfirmMessageLore: Bir oyuncu göreve başlamak üzereyken Onay GUI'sinde görüntülenen mesaj. + customDescription: '§eGörev açıklamasını düzenle' + customDescriptionLore: GUI'lerde görev adının altında gösterilen açıklama. + customMaterial: '§eGörev öğesi malzemesini düzenle' + customMaterialLore: Görevler Menüsünde bu görevin temsilcisi olan öğe. + defaultValue: '§8(varsayılan değer)' + editQuestName: '§lGörevi düzenle' + editRequirements: '§eGereksinimleri düzenle' + editRequirementsLore: Göreve başlayabilmesi için her gereksinim oyuncuya uygulanmalıdır. + endMessage: '§eBitiş mesajını düzenle' + endMessageLore: Görevin sonunda oyuncuya gönderilecek mesaj. + endSound: '§eBitiş sesini düzenle' + endSoundLore: Görevin sonunda çalınacak ses. + failOnDeath: Ölümde başarısızlık + failOnDeathLore: Oyuncu öldüğünde görev iptal edilecek mi? + firework: '§dHavai Fişekleri Bitirmek' + fireworkLore: Oyuncu görevi bitirdiğinde havai fişek fırlatılır + fireworkLoreDrop: Özel havai fişeklerinizi buraya bırakın + hideNoRequirementsItem: Gereksinimler karşılanmadığında gizle + hideNoRequirementsItemLore: Etkinleştirilirse, gereksinimler karşılanmadığında görev, Görevler Menüsünde görüntülenmez. + hologramLaunch: '§e"launch" yazarak hologram öğesini düzenleyin' + hologramLaunchLore: Oyuncu bir göreve başlayabileceğinde, başlayan NPC'nin başının üzerinde görüntülenen hologram. + hologramLaunchNo: '§e"launch unavailable" hologram öğesini düzenleyin' + hologramLaunchNoLore: Oyuncu göreve BAŞLAMADIĞINDA, Başlangıç NPC'sinin başının üzerinde görüntülenen hologram. + hologramText: '§eHologram metni' + hologramTextLore: Başlangıç NPC'sinin başının üzerindeki hologramda görüntülenen metin. + keepDatas: Oyuncu verilerini koru + keepDatasLore: 'Aşamalar düzenlenmiş olsa bile eklentiyi oyuncu verilerini korumaya zorlayın. §c§lUYARI §c- bu seçeneğin etkinleştirilmesi oyuncularınızın verilerini bozabilir.' + loreReset: '§e§lTüm oyuncuların ilerlemesi sıfırlanacak' + multipleTime: + itemLore: Görev birkaç kez yapılabilir mi? + itemName: Tekrarlanabilirliği değiştir + name: Son görev detayları + optionValue: '§8Değer: §7{value}' + questName: '§a§lGörev adını düzenle' + questNameLore: Görev oluşturmayı tamamlamak için bir ad belirlenmelidir. + questPool: '§eGörev Grubu' + questPoolLore: Bu görevi bir görev grubuna ekle + removeItemsReward: '§eÖğeleri envanterden kaldır' + requiredParameter: '§7Gerekli parametre' + requirements: '{amount} gereksinim' + rewards: '{amount} ödül' + rewardsLore: Görev sona erdiğinde gerçekleştirilen eylemler. + scoreboardItem: Scoreboard'ı etkinleştir + scoreboardItemLore: Devre dışı bırakılırsa, görev scoreboardta izlenmeyecektir. + selectStarterNPC: '§e§lNPC başlatıcıyı seçin' + selectStarterNPCLore: Seçilen NPC'ye tıklamak görevi başlatacaktır. + selectStarterNPCPool: '§c⚠ Bir görev grubu seçildi' + setCheckpointReward: '§eKontrol noktası ödüllerini düzenle' + setItemsRewards: '§eÖdül eşyalarını düzenle' + setMoneyReward: '§ePara ödülünü düzenle' + setPermReward: '§eİzinleri düzenle' + setRewardStopQuest: '§cGörevi durdur' + setRewardsRandom: '§dRastgele ödüller' + setRewardsWithRequirements: '§eGereksinimlere sahip ödüller' + setTitleReward: '§eBaşlık ödülünü düzenle' + setWaitReward: '§e"wait" ödülünü düzenle' + setXPRewards: '§eÖdül deneyimini düzenle' + startDialog: '§eBaşlangıç diyaloğunu düzenle' + startDialogLore: Görevler başlamadan önce oyuncular Başlangıç NPC'ye tıkladığında başlayacak olan diyalog. + startMessage: '§eBaşlama mesajını düzenle' + startMessageLore: Görevin başında oyuncuya gönderilecek mesaj. + startRewards: '§6Ödülleri başlat' + startRewardsLore: Görev başladığında gerçekleştirilen eylemler. + startableFromGUI: GUI'den başlatılabilir + startableFromGUILore: Oyuncunun görevi Görevler Menüsünden başlatmasına izin verir. + timer: '§bZamanlayıcıyı yeniden başlat' + timerLore: Oyuncunun göreve yeniden başlayabilmesi için geçen süre. + visibility: '§bGörev görünürlüğü' + visibilityLore: Görevin menünün hangi sekmelerinde gösterileceğini ve görevin dinamik haritalarda görünüp görünmeyeceğini seçin. + editTitle: + fadeIn: '§aFade-in süresi' + fadeOut: '§aFade-out süresi' + name: Başlığı düzenle + stay: '§bBekleme süresi' + subtitle: '§eAlt yazı' + title: '§6Başlık' + entityType: + name: Varlık türünü seç + equipmentSlots: + name: Ekipman slotları + factionsList.name: ' Grupların listesi' + factionsRequired.name: Gruplar gerekli + itemComparisons: + bukkit: Bukkit yerel karşılaştırması + bukkitLore: Bukkit varsayılan öğe karşılaştırma sistemini kullanır. Malzemeyi, dayanıklılığı, nbt etiketlerini karşılaştırır... + customBukkit: Bukkit yerel karşılaştırması - NBT YOK + customBukkitLore: Bukkit varsayılan öğe karşılaştırma sistemini kullanır, ancak NBT etiketlerini siler. Malzemeyi, dayanıklılığı karşılaştırır... + enchants: Eşyaların büyüleri + enchantsLore: Büyülü öğeleri karşılaştırır + itemLore: Eşya bilgisi + itemLoreLore: Öğelerin bilgisini karşılaştırır + itemName: Eşya adı + itemNameLore: Öğe adlarını karşılaştırır + itemsAdder: ItemsAdder + itemsAdderLore: ItemsAdder ID'lerini karşılaştırır + material: Öğe malzemesi + materialLore: Öğe malzemesini karşılaştırır (ör. taş, demir kılıç...) + name: Ürün karşılaştırmaları + repairCost: Onarım maliyeti + repairCostLore: Zırhlar ve kılıçlar için onarım maliyetlerini karşılaştırır + itemCreator: + isQuestItem: '§bGörev eşyası:' + itemFlags: Öğe işaretlerini değiştir + itemLore: '§bEşya bilgisi' + itemName: '§bÖğe adı' + itemType: '§bEşya türü' + name: Eşya oluşturucu + itemSelect: + name: Ögeleri seçin + itemsSelect: + name: Ürünleri Düzenle + none: '§aBir öğeyi buraya taşıyın veya öğe düzenleyiciyi açmak için tıklayın.' + listAllQuests: + name: Görevler + listBook: + noQuests: Daha önce hiçbir görev oluşturulmadı. + questMultiple: Birkaç defa + questName: Ad + questRewards: Ödüller + questStages: Aşamalar/Evreler + questStarter: Başlangıç + requirements: Gereksinimler + listPlayerQuests: + name: '{player_name}''in görevleri' + listQuests: + canRedo: '§3§oBu görevi yeniden başlatabilirsiniz!' + finished: Biten görevler + inProgress: Devam eden görevler + loreCancelClick: '§cGörevi iptal et' + loreDialogsHistoryClick: '§7Diyalogları görüntüle' + loreStart: '§a§oGörevi başlatmak için tıklayın.' + loreStartUnavailable: '§c§oGörevi başlatmak için gereksinimleri karşılamıyorsunuz.' + notStarted: Başlatılmamış görevler + timeToWaitRedo: '§3§oBu göreve {time_left} içinde yeniden başlatabilirsiniz.' + timesFinished: '§3Görev {times_finished} defa tamamlandı.' + mobSelect: + boss: '§6Boss seçin' + bukkitEntityType: '§eVarlık türünü seçin' + epicBoss: '§6Epic Boss''u seçin' + mythicMob: '§6Mythic Mob''u seçin' + name: Mob türünü seçin + mobs: + name: Mob seçin + none: '§aBir mob eklemek için tıklayın.' + setLevel: Minimum seviyeyi ayarla + npcCreate: + move: + itemLore: '§aNPC konumunu değiştirin.' + itemName: '§eHareket' + moveItem: '§a§lYeri doğrula' + name: NPC Oluştur + setName: '§eNPC adını düzenle' + setSkin: '§eNPC cildini düzenle' + setType: '§eNPC türünü düzenle' + npcSelect: + createStageNPC: '§eNpc oluştur' + name: Seç veya oluştur + selectStageNPC: '§eMevcut NPC''yi seçin' + particleEffect: + color: '§bParçacık rengi' + name: Parçacık efekti oluştur + shape: '§dParçacık şekli' + type: '§eParçacık türü' + particleList: + colored: Renklendirimiş parçacık + name: Parçacıkların listesi + permission: + name: İzinleri seç + perm: '§aİzin' + remove: İzni Kaldır + removeLore: '§7İzin vermek yerine çıkarılacak.' + world: '§aDünya' + worldGlobal: '§b§lKüresel' + permissionList: + name: İzin Listesi + removed: '§eÇıkarılan: §6{permission_removed}' + world: '§eDünya: §6{permission_world}' + poolCreation: + avoidDuplicates: Kopyalardan kaçının + avoidDuplicatesLore: '§8> §7Aynı görevi tekrar\n tekrar yapmaktan kaçınmaya çalışın' + hologramText: '§eÖzel grup hologramı' + maxQuests: '§8Maks. görevler' + name: Görev grubu oluşturma + questsPerLaunch: '§aBaşlatma başına başlatılan görevler' + redoAllowed: Yinelemeye izin veriliyor mu? + requirements: '§bGörev başlatmak için gerekenler' + time: '§bGörevler arasındaki süreyi ayarlayın' + poolsList.name: Görev grupları + poolsManage: + choose: '§e> §6§oBu grubu seç §e<' + create: '§aBir görev grubu oluşturun' + edit: '§e> §6§oGrubu düzenle... §e<' + itemName: '§aGrup #{pool}' + name: Görev grupları + poolAvoidDuplicates: '§8Kopyalardan kaçının: §7{pool_duplicates}' + poolHologram: '§8Hologram metni: §7{pool_hologram}' + poolMaxQuests: '§8Maks. görevler: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8Görev: §7{pool_quests}' + poolQuestsPerLaunch: '§8Başlatma başına verilen görevler: §7{pool_quests_per_launch}' + poolRedo: '§8Tamamlanan görevleri yeniden yapabilir: §7{pool_redo}' + poolTime: '§8Görevler arasındaki süre: §7{pool_time}' + requirements: + name: Gereksinimler + rewards: + commands: 'Komutan: {amount}' + name: Ödüller + random: + minMax: Minimum ve maksimumu düzenle + rewards: Ödülleri düzenle + rewardsWithRequirements: + name: Gereksinimlere sahip ödüller + search: '§e§lAra' + stageEnding: + command: '§eYürütülen komutu düzenle' + locationTeleport: '§eIşınlanma konumunu düzenle' + stages: + branchesPage: '§dİş Aşamaları' + descriptionTextItem: '§eAçıklamayı düzenle' + endingItem: '§eBitiş ödüllerini düzenle' + laterPage: '&eÖnceki sayfaya dön' + name: Aşamaları oluştur + newBranch: '§eyeni işe git' + nextPage: '&eSonraki sayfaya ilerle' + previousBranch: '§eÖnceki işe dön' + regularPage: '§aDüzenli aşamalar' + validationRequirements: '§eDoğrulama gereksinimleri' + validationRequirementsLore: Tüm gereksinimler, aşamayı tamamlamaya çalışan oyuncuyla eşleşmelidir. Değilse, aşama tamamlanamaz. + validate: '§b§lDoğrula' + visibility: + finished: '"Bitti" menüsünün sekmesi' + inProgress: '"Devam etmekte" menüsünün sekmesi' + maps: Haritalar (dynmap veya BlueMap gibi) + name: Görev görünürlüğü + notStarted: '"Başlatılmadı" menüsünün sekmesi' +misc: + amount: '§eMiktar: {amount}' + amounts: + comparisons: '{comparisons_amount} karşılaştırma' + dialogLines: '{lines_amount} satır' + items: '{items_amount} öğe' + mobs: '{mobs_amount} mob' + permissions: '{permissions_amount} yetki' + and: ve + bucket: + lava: Lav kovası + milk: Süt kovası + snow: Kar kovası + water: Su kovası + click: + left: Sol tık + middle: Tekerleğe tıkla + right: Sağ tık + shift-left: Shift + sol tıkla + shift-right: Shift + sağ tıkla + comparison: + different: '{number}''dan farklıdır' + equals: '{number}''a eşittir' + greater: kesinlikle {number} değerinden daha fazla + greaterOrEquals: '{number}''dan daha fazla' + less: kesinlikle {number} değerinden daha az + lessOrEquals: '{number} miktarından daha az' + disabled: Devre dışı + enabled: Etkin + entityType: '§eVarlık türü: {entity_type}' + entityTypeAny: '§eHer hangi bir varlık' + format: + prefix: '§6<§e§lGörevler§r§6> §r' + hologramText: '§8§lGörev Adamı' + 'no': 'Hayır' + notSet: '§cayarlanmadı' + or: veya + poolHologramText: '§eYeni görev mevcut!' + questItemLore: '§e§oGörev Eşyası' + removeRaw: Kaldır + requirement: + class: '§bGerekli Sınıf(lar)' + combatLevel: '§bDövüş seviyesi gerekli' + equipment: '§eGerekli ekipman' + experienceLevel: '§bDeneyim seviyeleri gerekli' + faction: '§bGrup(lar) gerekli' + jobLevel: '§İş seviyesi gerekli' + logicalOr: Mantıksal VEYA (gereksinimler) + mcMMOSkillLevel: '§dYetenek seviyesi gerekli' + money: '§dPara gerekli' + permissions: '§3Yetki(ler) gerekli' + placeholder: '§bPlaceholder değeri gerekli' + quest: '§aGörev gerekli' + region: '§dBölge gerekli' + scoreboard: '§dPuan gerekli' + skillAPILevel: SkillAPI seviyesi gerekli + reset: Sıfırla + stageType: + Bucket: Kovayı doldur + Craft: Eşyayı Üret + Enchant: Eşyaları büyüle + Fish: Balık tut + Melt: Eşyaları ısıt + breedAnimals: Hayvanları çiftleştir + chat: Sohbete yaz + dealDamage: Hasar ver + die: Öl + eatDrink: Ye yada iç + interact: Blok ile etkileşime gir + items: Eşyaları geri getir + location: Konumu bul + mine: Blokları kır + mobs: Mobları öldür + npc: NPC Bul + placeBlocks: Blokları koy + playTime: Oynama süresi + region: Bölge bul + tameAnimals: Hayvanları besle + time: + days: '{days_amount} gün' + hours: '{hours_amount} saat' + lessThanAMinute: bir dakikadan az bir sürede + minutes: '{minutes_amount} dakika' + weeks: '{weeks_amount} hafta' + unknown: bilinmeyen + 'yes': 'Evet' +msg: + bringBackObjects: '{items} geri getir.' + command: + adminModeEntered: '§aYönetici Moduna girdiniz.' + adminModeLeft: '§aYönetici Modundan ayrıldınız.' + backupCreated: '§6Tüm görevlerin ve oyuncu bilgilerinin yedeklerini başarıyla oluşturdunuz.' + backupPlayersFailed: '§cTüm oyuncu bilgileri için bir yedek oluşturma başarısız oldu.' + backupQuestsFailed: '§cTüm görevler için bir yedek oluşturma başarısız oldu.' + cancelQuest: '§6{quest} görevini iptal ettin.' + cancelQuestUnavailable: '§c{quest} görevi iptal edilemez.' + checkpoint: + noCheckpoint: '§c{quest} görevi için kontrol noktası bulunamadı.' + questNotStarted: '§cBu görevi yapmıyorsunuz.' + downloadTranslations: + downloaded: '§a{lang} dili indirildi! §f§oMinecraftTranslationsFile''ın §7değerini {lang} ile değiştirmek için "/plugins/BeautyQuests/config.yml" dosyasını düzenlemeli ve ardından sunucuyu yeniden başlatmalısınız.' + exists: '§c{file_name} dosyası zaten var. Üzerine yazmak için komutunuza "-overwrite" ekleyin. (/quests downloadTranslations <lang> -overwrite)' + notFound: '{version} sürümü için {lang} dili bulunamadı.' + syntax: '§cİndirmek için bir dil belirtmelisiniz. Örnek: "/quests downloadTranslations tr_TR".' + help: + adminMode: '§6/{label} adminMode: §eYönetici Modunu değiştirin. (Küçük günlük mesajlarını görüntülemek için kullanışlıdır.)' + create: '§6/{label} create: §eKullanarak bir görev oluşturun.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eBir vanilla çeviri dosyası indirir.' + edit: '§6/{label} düzenle: §eKullanarak bir görevi düzenleyin.' + finishAll: '§6/{label} finishAll <oyuncu>: §eBir oyuncunun tüm görevlerini tamamlayın.' + header: '§6§lBeautyQuests — Yardım' + list: '§6/{label} list: §eGörev listesine bakın. (Yalnızca desteklenen sürümler için.)' + reload: '§6/{label} reload: §eTüm yapılandırmaları ve dosyaları kaydedin ve yeniden yükleyin. (§ckullanımdan kaldırıldı§e)' + remove: '§6/{label} remove <id>: §eBelirli bir ID''ye sahip bir görevi silin veya tanımlanmamışsa NPC''ye tıklayın.' + resetPlayer: '§6/{label} resetPlayer <oyuncu>: §eBir oyuncuyla ilgili tüm bilgileri kaldırın.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <oyuncu> [id]: §eBir oyuncu için bir görevin bilgilerini silin.' + save: '§6/{label} save: §eManuel bir eklenti kaydetme yapın.' + seePlayer: '§6/{label} seePlayer <oyuncu>: §eBir oyuncu hakkındaki bilgileri görüntüleyin.' + setFirework: '§6/{label} setFirework: §eVarsayılan biten havai fişekleri düzenleyin.' + setItem: '§6/{label} setItem <talk|launch>: §eHologram öğesini kaydedin.' + setStage: '§6/{label} setStage <oyuncu> <id> [yeni iş] [yeni aşama]: §eGeçerli aşamayı atla, iş için bir aşama ayarla.' + start: '§6/{label} start <oyuncu> [id]: §eBir görevin başlamasını zorla.' + startDialog: '§6/{label} startDialog <oyuncu> <görev id''si>: §eBir NPC aşaması için bekleyen diyaloğu veya bir görev için başlangıç diyaloğunu başlatır.' + version: '§6/{label} version: §eGeçerli eklenti sürümüne bakın.' + invalidCommand: + simple: '§cBu komut mevcut değil,§e help §cyazın.' + itemChanged: '§aÖğe düzenlendi. Değişiklikler yeniden başlatmanın ardından etkili olacaktır.' + itemRemoved: '§aHologram öğesi kaldırıldı.' + leaveAll: '§a{success} görev(ler)inin bitirilmesini zorladınız. Hatalar: {errors}' + removed: '§a{quest_name} görevi başarıyla kaldırıldı.' + resetPlayer: + player: '§6{quest_amount} görevinizin tüm bilgileri {deleter_name} tarafından silindi.' + remover: '{quest_amount} görev bilgisi (ve {quest_pool} grupları) {player} silindi.' + resetPlayerPool: + full: '§a{pool} grup verilerini {player}''den sıfırlarsınız.' + timer: '§a{pool} grubunun zamanlayıcısını {player}''den sıfırlarsınız.' + resetPlayerQuest: + player: '§6{quest} göreviyle ilgili tüm bilgiler {deleter_name} tarafından silindi.' + remover: '§6{quest} adlı kişinin {player} görev bilgisi silindi.' + resetQuest: '§6{player_amount} oyuncu için görevin verileri kaldırıldı.' + scoreboard: + hidden: '§6{player_name} oyuncusunun puan tablosu gizlendi.' + lineInexistant: '§c{line_id} satırı mevcut değil.' + lineRemoved: '§6{line_id} satırını başarıyla kaldırdınız.' + lineReset: '§6{line_id} satırını başarıyla sıfırladınız.' + lineSet: '§6{line_id} satırını başarıyla düzenlediniz.' + own: + hidden: '§6Puan tablonuz artık gizlidir.' + shown: '§6Puan tablonuz tekrar görünür.' + resetAll: '§6{player_name} adlı oyuncunun puan tablosunu başarıyla sıfırladınız.' + shown: '§6{player_name} oyuncusunun scoreboard''ı gösterildi.' + setStage: + branchDoesntExist: '§c{branch_id} adlı id''ye sahip bir iş mevcut değil.' + doesntExist: '§c{stage_id} adlı id''ye sahip bir sahne mevcut değil.' + next: '§aAşama atlandı.' + nextUnavailable: Oyuncu bir işin sonundayken "skip" seçeneği kullanılamaz. + set: '§aAşama {stage_id} başlatıldı.' + startDialog: + alreadyIn: '§cOyuncu zaten bir diyalogda.' + impossible: '§cDiyaloğu şimdi başlatmak imkansız.' + noDialog: '§cOyuncunun beklenen bir diyaloğu yok.' + success: '§a{quest} görevinde {player} oyuncusu için diyalog başlatıldı!' + startPlayerPool: + error: '{player} için {pool} grubu başlatılamadı.' + success: '{player} için {pool} grubu başladı. Sonuç: {result}' + startQuest: '§6{quest} görevinin başlatılmasını zorunlu kıldınız (Oyuncu UUID: {player}).' + startQuestNoRequirements: '§cOyuncu, {quest} görevinin gereksinimlerini karşılamıyor... Gereksinim kontrolünü atlamak için komutunuzun sonuna "-overrideRequirements" ifadesini ekleyin.' + dialogs: + skipped: '§8§oDiyalog atlandı.' + tooFar: '{npc_name}''den çok uzaktasınız...' + editor: + advancedSpawnersMob: 'Öldürmek için özel spawnerın mob''unun adını yazın' + already: '§cZaten editördesiniz.' + availableElements: 'Kullanılabilir elementler: §e{available_elements}' + blockAmount: '§aBlokların sayısını yazın:' + blockData: '§aBlok verilerini yaz (kullanılabilir blok veriler: §7{available_datas}§a):' + blockName: '§aBloğun ismini yazın:' + blockTag: '§aBlok etiketini yazın (mevcut etiketler: §7{available_tags}§a):' + chat: '§6Şu anda Editör Modundasınız. Düzenleyiciden ayrılmaya zorlamak için "/quests exitEditor" yazın. (Kesinlikle tavsiye edilmez, önceki envantere geri dönmek için "close" veya "cancel" gibi komutları kullanmayı deneyin.)' + color: 'Onaltılık biçimde (#XXXXX) veya RGB biçiminde (KIRMIZI YEŞİL MAVİ) bir renk girin.' + colorNamed: Bir rengin adını girin. + comparisonTypeDefault: '§a{available} arasından istediğiniz karşılaştırma türünü seçin. Varsayılan karşılaştırma: §e§l{default}§r§a. Kullanmak için §onull§r§a yazın.' + dialog: + cleared: '§2§l{amount}§a mesaj kaldırıldı.' + edited: '§a"§7{msg}§a" mesajı düzenlendi.' + help: + addSound: '§6addSound <id> <ses>: §eBir mesaja ses ekleyin.' + clear: '§6clear: §eTüm mesajları kaldır.' + close: '§6close: §eTüm mesajları doğrular.' + edit: '§6edit <id> <mesaj>: §eBir mesajı düzenleyin.' + header: '§6§lBeautyQuests — Diyalog düzenleyici yardımı' + list: '§6list: §eTüm mesajları görüntüleyin.' + nothing: '§6noSender <message>: §eGöndereni olmayan bir mesaj ekleyin.' + nothingInsert: '§6nothingInsert <id> <mesaj>: §eHerhangi bir ön ek olmadan bir mesaj ekleyin.' + npc: '§6npc <mesaj>: §eNPC tarafından söylenen bir mesaj ekleyin.' + npcInsert: '§6npcInsert <id> <mesaj>: §eNPC tarafından söylenen bir mesaj ekleyin.' + npcName: '§6npcName [özel NPC adı]: §eDiyalogdaki NPC''nin özel adını ayarlayın (veya varsayılana sıfırlayın).' + player: '§6player <mesaj>: §eOyuncu tarafından söylenen bir mesaj ekleyin.' + playerInsert: '§6playerInsert <id> <mesaj>: §eOyuncu tarafından söylenen bir mesaj ekleyin.' + remove: '§6<id> öğesini kaldır: §eBir mesajı kaldırın.' + setTime: '§6setTime <id> <zaman>: §eBir sonraki mesaj otomatik olarak oynatılmadan önceki süreyi (ticks ile) ayarlayın.' + skippable: '§6skippable [true|false]: §eDiyaloğun atlanıp atlanamayacağını ayarlayın.' + messageRemoved: '§a"§7{msg}§a" mesajı kaldırıldı.' + noSender: '§a"§7{msg}§a" mesajı, gönderen olmadan eklendi.' + npc: '§aNPC için "§7{msg}§a" mesajı eklendi.' + npcName: + set: '§aÖzel NPC adı §7{new_name}§a olarak ayarlandı (önceden §7{old_name}§a idi)' + unset: '§aÖzel NPC adı varsayılana sıfırlandı (önceden §7{old_name}§a idi)' + player: '§aOyuncu için "§7{msg}§a" mesajı eklendi.' + skippable: + set: '§aDiyaloğun atlanabilirlik durumu artık §7{new_state}§a olarak ayarlandı (önceden §7{old_state}§a idi)' + unset: '§aDiyaloğun atlanabilirlik durumu varsayılana sıfırlandı (önceden {old_state} idi)' + soundAdded: '§a"§7{msg}§a" mesajına "§7{sound}§a" sesi eklendi.' + syntaxRemove: '§cDoğru sözdizimi(syntax): remove <id>' + timeRemoved: '§a{msg} mesajı için zaman kaldırıldı.' + timeSet: '§a{msg} mesajı için zaman düzenlendi: şimdi {time} ticks.' + enter: + list: '§c⚠ §7Bir "liste" düzenleyicisine girdiniz. Satır eklemek için "add"''ı kullanın. Yardım için "help" (eğik çizgi olmadan) bakın. §e§lDüzenleyiciden çıkmak için "close" yazın.' + subtitle: '§6Düzenleyiciden çıkmaya zorlamak için "/quests exitEditor" yazın.' + title: '§6~ Editör Modu ~' + firework: + edited: Havai fişek görevi düzenlendi! + invalid: Bu öğe geçerli bir havai fişek değil. + invalidHand: Ana elinizde bir havai fişek tutmalısınız. + removed: Havai fişek görevi kaldırıldı! + goToLocation: '§aAşama için istenen konuma gidin.' + invalidColor: Girdiğiniz renk geçersiz. Onaltılık veya RGB olmalıdır. + invalidPattern: '§cGeçersiz normal ifade kalıbı §4{input}§c.' + itemCreator: + invalidBlockType: '§cGeçersiz blok türü.' + invalidItemType: '§cGeçersiz eşya türü. (Öğe bir blok olamaz.)' + itemAmount: '§aEşyanın miktarını yazın:' + itemLore: '§aEşya bilgisini değiştirin: (Yardım için "help" yazın.)' + itemName: '§aEşyanın adını yazın:' + itemType: '§aİstenen öğe türünün adını yazın:' + unknownBlockType: '§cBilinmeyen blok türü' + unknownItemType: '§cBilinmeyen eşya türü.' + mythicmobs: + disabled: '§cMythicMob devre dışı bırakıldı.' + isntMythicMob: '§cBu MythicMob mevcut değil.' + list: '§aTüm Mythic Mobs''un listesi:' + noSuchElement: '§cBöyle bir unsur yoktur. İzin verilen öğeler: §e{available_elements}' + npc: + choseStarter: '§aGörevi başlatan NPC''yi seçin.' + enter: '§aBir NPC''ye tıklayın veya "cancel" yazın.' + notStarter: '§cBu NPC bir görev başlatıcı değil.' + pool: + hologramText: Bu grup için özel hologram metnini yazın (veya varsayılanı istiyorsanız "null"). + maxQuests: Bu grupta başlatılabilecek maksimum görev sayısını yazın. + questsPerLaunch: Oyuncular NPC'ye tıkladığında verilen görev miktarını yazın. + timeMsg: 'Oyuncuların yeni bir göreve başlamadan önceki zamanı yazın. (varsayılan birim: gün)' + scoreboardObjectiveNotFound: '§cBilinmeyen scoreboard hedefi.' + selectWantedBlock: '§aAşama için aranan bloğun üzerine çubukla tıklayın.' + stage: + location: + typeWorldPattern: '§aDünya adları için bir normal ifade yazın:' + text: + argNotSupported: '§c{arg} bağımsız değişkeni desteklenmiyor.' + chooseJobRequired: '§aAranan işin adını yazın:' + chooseLvlRequired: '§aGerekli seviye miktarını yazın:' + chooseMoneyRequired: '§aGerekli para miktarını yazın:' + chooseObjectiveRequired: '§aHedefin adını yazın.' + chooseObjectiveTargetScore: '§aHedef için hedef puanı yazın.' + choosePermissionMessage: '§aOyuncu gerekli izne sahip değilse bir ret mesajı seçebilirsiniz. (Bu adımı atlamak için "null" yazın.)' + choosePermissionRequired: '§aGörevi başlatmak için gerekli izni yazın:' + choosePlaceholderRequired: + identifier: '§aGerekli placeholder adını yüzde işareti olmadan yazın:' + value: '§a{placeholder} Placeholder için gereken değeri yazın:' + chooseRegionRequired: '§aGerekli bölgenin adını yazın (aynı dünyada olmalısınız).' + chooseSkillRequired: '§aGerekli yeteneğin adını yazın:' + reward: + money: '§aAlınan paranın miktarını yazın:' + permissionName: '§aYetki izninin adını yazın.' + permissionWorld: '§aİznin düzenlenmesi gereken dünyayı yazın, eğer genel olması gerekiyorsa "null" değerini girin.' + random: + max: Oyuncuya verilen maksimum ödül miktarını (dahil) yazın. + min: Oyuncuya verilen minimum ödül miktarını (dahil) yazın. + wait: '§aBeklenecek ticks miktarını yazın: (1 saniye = 20 ticks)' + textList: + added: '§a"§7{msg}§a" metni eklendi.' + help: + add: '§6add <mesaj>: §eBir metin ekleyin.' + close: '§6close: §eEklenen metinleri doğrular.' + header: '§6§lBeautyQuests — Liste düzenleyici yardımı' + list: '§6list: §eEklenen tüm metinleri görüntüleyin.' + remove: '§6remove <id>: §eBir metni kaldırın.' + removed: '§a"§7{msg}§a" metni kaldırılıdı.' + syntax: '§cDoğru sözdizimi(Syntax):' + title: + fadeIn: '"Fade-in" süresini ticks cinsinden yazın (20 ticks = 1 saniye).' + fadeOut: '"Fade-out" süresini ticks halinde yazın (20 ticks = 1 saniye).' + stay: '"stay" süresini ticks olarak yazın (20 ticks = 1 saniye).' + subtitle: Altyazı metnini yazın (veya istemiyorsanız "null"). + title: Başlık metnini yazın (veya istemiyorsanız "null"). + typeBucketAmount: '§aDoldurulacak kova miktarını yazın:' + typeDamageAmount: 'Oyuncunun vermesi gereken hasar miktarını yazın:' + typeGameTicks: '§aGerekli oyun ticks''ini yazın:' + typeLocationRadius: '§aKonumdan gereken mesafeyi yazın:' + errorOccurred: '§cBir hata oluştu, bir yönetici ile iletişime geçin! Hata kodu: {error}' + experience: + edited: '§aDeneyim kazanımını {old_xp_amount}''''den {xp_amount} puana yükselttiniz.' + indexOutOfBounds: '§c{index} sayısı sınırların dışında! {min} ile {max} arasında olmalıdır.' + invalidBlockData: '§c{block_data} blok verileri geçersiz veya {block_material} bloğuyla uyumsuz.' + invalidBlockTag: '{block_tag} adlı blok etiketi kullanılamıyor.' + inventoryFull: '§cEnvanteriniz dolu, bu yüzden eşya yere düştü.' + moveToTeleportPoint: '§aİstenilen ışınlanma konumuna gidin.' + npcDoesntExist: '§c{npc_id} adlı id''ye sahip bir NPC mevcut değil.' + number: + invalid: '§c{input} geçersiz bir sayıdır.' + negative: '§cPozitif bir sayı girmelisin!' + notInBounds: '§cSayınız {min} ile {max} arasında olmalıdır.' + zero: '§c0 dışında bir sayı girmelisiniz!' + pools: + allCompleted: '§7Tüm görevleri tamamladın!' + maxQuests: '§cBir seferde {pool_max_quests} görev(ler)den fazlasına sahip olamazsın...' + noAvailable: '§7Daha fazla görev kalmadı...' + noTime: '§cBaşka bir görev yapmadan önce {time_left} beklemelisin.' + quest: + alreadyStarted: '§cGöreve zaten başladınız!' + cancelling: '§cGörev oluşturma süreci iptal edildi.' + createCancelled: '§cOluşturma veya düzenleme başka bir eklenti tarafından iptal edildi!' + created: '§aTebrikler! {quest_branches} sınıfını içeren §e{quest}§a görevini oluşturdun!' + editCancelling: '§cGörev düzenleme süreci iptal edildi.' + edited: '§aTebrikler! {quest_branches} sınıfını içeren §e{quest}§a görevini düzenledin!' + finished: + base: '§aTebrikler! §e{quest_name}§a görevini bitirdiniz!' + obtain: '§a{rewards} elde ettin!' + invalidID: '§c{quest_id} adlı id''ye sahip bir görev mevcut değil.' + invalidPoolID: '§c{pool_id} grubu mevcut değil.' + notStarted: '&cŞu anda bu görevi yapamazsın.' + started: '§e{quest_name}§a görevine başladın§o§6!' + questItem: + craft: '§cÜretim yapmak için görev eşyasını kullanamazsın!' + drop: '§cBir görev eşyasını yere atamazsın!' + eat: '§cGörev eşyalarını yemek niyetine yiyemezsin!' + quests: + checkpoint: '§7Görev kontrol noktasına ulaşıldı!' + failed: '§c{quest_name} görevinde başarısız oldun...' + maxLaunched: '§cBir seferde {quests_max_amount} görev(ler)den fazlasına sahip olamazsın...' + updated: '§e{quest_name}§7 adlı görev güncellendi.' + regionDoesntExists: '§cBöyle bir bölge mevcut değil. (Aynı dünyada olmalısınız.)' + requirements: + combatLevel: '§cDövüş seviyeniz {long_level} olmalıdır!' + job: '§e{job_name}§c işi için seviyeniz {long_level} olmalıdır!' + level: '§cSeviyen {long_level} olmalıdır!' + money: '§c{money} sahibi olmalısın!' + quest: '§e{quest_name}§c görevini tamamlamış olmalısın!' + skill: '§e{skill_name}§c yeteneği için seviyeniz {long_level} olmalıdır!' + waitTime: '§cBu görevi yeniden başlatabilmek için {time_left} süre boyunca beklemelisiniz!' + restartServer: '§7Değişiklikleri görmek için sunucunuzu yeniden başlatın.' + selectNPCToKill: '§aNPC''yi öldürmek için seçim yap.' + stageMobs: + listMobs: '§a{mobs} öldürmelisiniz.' + typeCancel: '§aSon metne geri dönmek için "cancel" yazın.' + versionRequired: 'Gerekli versiyon: §l{version}' + writeChatMessage: '§aGerekli mesajı yazın: (Bir komut eklemek istiyorsanız başına "{SLASH}" ekleyin.)' + writeCommand: '§aKomutu yazın: ("/" yazmayın; "{PLAYER}" yer tutucusu desteklidir. Yürütücü oyuncunun adıyla değiştirilecektir.)' + writeCommandDelay: '§aİstenen komut gecikmesini ticks halinde yazın.' + writeConfirmMessage: '§aBir oyuncu göreve başlamak üzereyken gösterilen onay mesajını yazın: (Varsayılan mesajı istiyorsanız "null" yazın.)' + writeDescriptionText: '§aAşamanın amacını açıklayan bir metin yazın:' + writeEndMsg: Görev sonunda gönderilecek mesajı varsayılan olarak istiyorsanız "null", istemiyorsanız "none" olarak yazın. Elde edilen ödüllerle değiştirilecekse "{rewards}" yazabilirsiniz. + writeEndSound: '§aGörevin sonunda oyuncuya çalınacak ses adını varsayılan olarak istiyorsanız "null", istemiyorsanız "none" olarak yazın:' + writeHologramText: '§aHologramın metnini yazın: (Bir hologram istemiyorsanız "none", varsayılan metni istiyorsanız "null" yazın.)' + writeMessage: '§aOyuncuya gönderilecek mesajı yazın.' + writeMobAmount: '§aÖldürülecek canlıların miktarını yazın:' + writeMobName: '§aÖldürülecek canlının özel adını yazın:' + writeNPCText: '§aOyuncuya NPC tarafından söylenecek olan diyaloğu yazın: (Yardım almak için "help" yazın.)' + writeNpcName: '§aNPC''nin adını yazın:' + writeNpcSkinName: '§aNPC''nin cildini değiştirmek için cildin adını yazın:' + writeQuestDescription: '§aOyuncunun görev arayüzünde(GUI) görüntülenecek bir görev açıklaması yazın.' + writeQuestMaterial: '§aGörev öğesinin materyalini yazın.' + writeQuestName: '§aGörevinizin ismini yazın:' + writeQuestTimer: '§aGörevi yeniden başlatmadan önce gerekli zamanı (dakika olarak) yazın: (Varsayılan zamanlayıcıyı istiyorsanız "null" yazın.)' + writeRegionName: '§aAdım için gerekli bölgenin adını yazın:' + writeStageText: '§aAşamanın başında oyuncuya gönderilecek metni yazın:' + writeStartMessage: '§aGörevin başında gönderilecek mesajı varsayılan olarak göndermek istiyorsanız "null", istemiyorsanız "none" olarak yazın:' + writeXPGain: '§aOyuncunun elde edeceği deneyim puanı miktarını yazın: (Son değer: {xp_amount})' +scoreboard: + asyncEnd: '§ex' + name: '§6§lGörevler' + noLaunched: '§cDevam eden görev yok.' + noLaunchedDescription: '§c§oYükleniyor' + noLaunchedName: '§c§lYükleniyor' + stage: + breed: '§6{mobs} §eÇiftleştir' + bucket: '§6{buckets}§e''yı doldurun' + chat: '§6{text}§e''yı yazın' + craft: '§eÜretim §6{items}' + dealDamage: + any: '§c{damage_remaining} hasar ver' + mobs: '§c{target_mobs} kişiye {damage_remaining} hasar verin' + die: '§cÖl' + eatDrink: '{§60} §eTüket' + enchant: '§eBüyü §6{items}' + fish: '§eBalık §6{items}' + interact: '§6{x}§e''daki bloğa tıklayın' + interactMaterial: '§eBir §6{block}§e bloğa tıklayın' + items: '§eÖğeleri §6{dialog_npc_name}§e''e getirin:' + location: '§6{target_x}§e, §6{target_y}§e, §6{target_z}§e, §6{target_world}''ya git.' + melt: '§eEritme §6{items}' + mine: '§e{blocks} Kaz' + mobs: '§6{mobs}§e''yı öldür' + npc: '§eNPC §6{dialog_npc_name}§e ile konuşun' + placeBlocks: '§e{blocks}''yı Koy' + playTimeFormatted: '§eOyna §6{time_remaining_human}' + region: '§6{region_id}§e bölgesini bulun' + tame: '§eEvcilleştirme §6{mobs}' + textBetwteenBranch: '§e veya' diff --git a/core/src/main/resources/locales/uk_UA.yml b/core/src/main/resources/locales/uk_UA.yml index ca9d959e..e0f78df5 100644 --- a/core/src/main/resources/locales/uk_UA.yml +++ b/core/src/main/resources/locales/uk_UA.yml @@ -1,831 +1,800 @@ --- -msg: - quest: - finished: - base: '§aПоздоровляємо! Ви закінчили квест §e{0}§a!' - obtain: '§aВи отримали {0}!' - started: '§aВи почали квест §r§e{0}§o§6!' - created: '§aПоздоровляємо! Ви створили квест §a{0}§a що містить {1} гілку(-ок)!' - edited: '§aПоздоровляємо! Ви відредагували квест §a{0}§a що містить {1} гілку(-ок)!' - createCancelled: '§cСтворення або редагування було скасовано іншим плагіном!' - cancelling: '§cПроцес створення квесту скасовано.' - editCancelling: '§cПроцес редагування квесту скасовано.' - invalidID: '§cКвест з ідентифікатором {0} не існує.' - invalidPoolID: '§cПул {0} не існує.' - alreadyStarted: '§cВи вже почали квест!' - quests: - maxLaunched: '§cВи не можете виконувати більше {0} квестів одночасно...' - nopStep: '§cЦей квест не має жодного завдання.' - updated: '§7Квест §e{0}§7 оновлено.' - checkpoint: '§7Досягнута контрольна точка квесту!' - failed: '§cВи провалили квест {0}...' - pools: - noTime: '§cВи повинні зачекати {0} перед виконанням іншого квесту.' - allCompleted: '§7Ви завершили всі квести!' - noAvailable: '§7Більше немає доступних квестів...' - maxQuests: '§cВи не можете мати більше {0} квестів одночасно...' - questItem: - drop: '§cВи не можете викинути квестовий предмет!' - craft: '§cВи не можете використати квестовий предмет, для крафту!' - eat: '§cВи не можете з''їсти квестовий предмет!' - stageMobs: - noMobs: '§cЦе завдання не потребує вбивств мобів.' - listMobs: '§aВи повинні вбити {0}.' - writeNPCText: '§aНапишіть повідомлення, яке NPC буде казати гравцям: (Напишіть "help", щоб отримати допомогу.)' - writeRegionName: '§aНапишіть назву регіону потрібну для кроку:' - writeXPGain: '§aНапишіть кількість досвіду, який отримає гравець: (Останнє значення: {0})' - writeMobAmount: '§aНапишіть кількість мобів, яких потрібно вбити:' - writeMobName: '§aНапишіть кастомне ім''я моба, якого потрібно вбити:' - writeChatMessage: '§aНапишіть необхідне повідомлення: (Додайте "{SLASH}" на початку, якщо хочете вказати команду.)' - writeMessage: '§aНапишіть повідомлення, яке буде відправлено гравцю' - writeStartMessage: '§aНапишіть повідомлення, яке буде відправлено на початку квесту, "null" якщо ви хочете залишити стандартне, або "none" якщо не хочете вказувати:' - writeEndMsg: '§aНапишіть повідомлення, яке буде відправлено в кінці завдання, "null" якщо ви хочете, щоб відправилось стандартне повідомлення, або "none", якщо ви не хочете відправляти жодного повідомлення. Ви можете використати "{0}", який буде замінено на нагороду.' - writeEndSound: '§aНапишіть назву звуку, який буде відтворюватись гравцю на прикінці квесту, "null", якщо ви хочете залишити стандартний, або "none" якщо не хочете вказувати:' - writeDescriptionText: '§aНапишіть текст, що описує ціль стадії:' - writeStageText: '§aНапишіть текст, який буде відправлено гравцю на початку стадії:' - moveToTeleportPoint: '§aЙдіть до бажаного розташування телепорту.' - writeNpcName: '§aНапишіть ім''я NPC:' - writeNpcSkinName: '§aНапишіть нік скіна для NPC:' - writeQuestName: '§aНапишіть назву свого квесту:' - writeCommand: '§aВведіть потрібну команду: (Команда без "/" і заповнення"{PLAYER}" підтримується. Воно буде замінено ім''ям виконавця.)' - writeHologramText: '§aЗапишіть текст голограми: (Напишіть "none", якщо вам не потрібна голограма, або "null", якщо ви хочете звичайний текст.)' - writeQuestTimer: '§aНапишіть необхідний час (у хвилинах), для перепроходження квесту: (Напишіть "null", якщо ви хочете встановити таймер за замовчуванням.)' - writeConfirmMessage: '§aНапишіть повідомлення для підтвердження, яке гравець має написати, щоб запустити завдання: (Напишіть, "null", якщо ви хочете встановити повідомлення за замовчуванням.)' - writeQuestDescription: '§aНапишіть опис завдання, який буде показано гравцю під час виконання.' - writeQuestMaterial: '§aНапишіть матеріали для квестових предметів.' - requirements: - quest: '§cВи повинні закінчити квест §e{0}§c!' - level: '§cВаш рівень має бути {0}!' - job: '§cВаш рівень роботи§e{1}§c має бути {0}!' - skill: '§cВаш рівень вмінь §e{1}§c має бути {0}!' - combatLevel: '§cВаш рівень битви повинен бути {0}!' - money: '§aВи повинні мати {0}!' - waitTime: '§cВи повинні зачекати {0} перед повторним виконанням цього квесту!' - experience: - edited: '§aВи змінили приріст досвіду від {0} до {1} очок.' - selectNPCToKill: '§aВиберіть NPC, якого потрібно вбити.' - npc: - remove: '§aNPC видалено.' - talk: '§aЙдіть і поговоріть з NPC по імені §e{0}.' - regionDoesntExists: '§cЦей регіон не існує. (Ви повинні бути в тому ж світі, що й регіон.)' - npcDoesntExist: '§cNPC з ідентифікатором {0} не існує.' - objectDoesntExist: '§cВказаний предмет з ідентифікатором {0} не існує.' - number: - negative: '§cВи повинні ввести додатнє число!' - zero: '§cВи повинні ввести номер більший за 0!' - invalid: '§c{0} не є правильним числом.' - notInBounds: '§cВаш номер повинен бути від {0} до {1}.' - errorOccurred: '§cСталася помилка, зв''яжіться з адміністратором! §4§lКод помилки: {0}' - commandsDisabled: '§cЗараз ви не можете виконувати команди!' - indexOutOfBounds: '§cЧисло {0} за межами діапазону! Воно повинна бути між {1} і {2}.' - invalidBlockData: '§cБлоки {0} є недійсними або несумісними з блоком {1}.' - invalidBlockTag: '§cНедоступний тег блоку {0}.' - bringBackObjects: Поверніть мене назад {0}. - inventoryFull: '§cВаш інвентар повний, предмет був скинутий на підлогу.' - playerNeverConnected: '§cНеможливо знайти інформацію про гравця {0}.' - playerNotOnline: '§cГравець {0} офлайн.' - playerDataNotFound: '§cДані гравця {0} не знайдено.' - versionRequired: 'Потрібна версія: §l{0}' - restartServer: '§7Перезавантажте сервер, щоб застосувати зміни.' - dialogs: - skipped: '§8§o Діалог пропущено.' - tooFar: '§7§oВи занадто далеко від {0}...' - command: - downloadTranslations: - syntax: '§cви повинні вказати мову для завантаження. Приклад: "/quests downloadTranslations en_US".' - notFound: '§cМова {0} не знайдена для версії {1}.' - exists: '§cФайл {0} вже існує. Додавайте «-overwrite» до вашої команди, щоб перезаписати його. (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§aМову {0} було завантажено! §7Тепер ви повинні відредагувати файл "/plugins/BeautyQuests/config.yml", щоб змінити значення §ominecraftTranslationsFile§7 з {0}, а потім перезапустити сервер.' - checkpoint: - noCheckpoint: '§cНе знайдено жодної контрольної точки для квесту {0}.' - questNotStarted: '§cВи не виконуєте цей квест.' - setStage: - branchDoesntExist: '§cГілка з ідентифікатором {0} не існує.' - doesntExist: '§cЕтап з ідентифікатором {0} не існує.' - next: '§aЕтап пропущено.' - nextUnavailable: '§cРпція "Пропустити" недоступна, коли гравець знаходиться у кінці гілки.' - set: '§aЕтап {0} запущено.' - startDialog: - impossible: '§cНеможливо зараз почати діалог.' - noDialog: '§cГравець не має діалогового вікна, що очікує на розгляд.' - alreadyIn: '§cГравець вже бачить діалог.' - success: '§aРозпочате діалогове вікно для гравця {0} в квесті {1}!' - playerNeeded: '§cВи повинні бути гравцем для виконання цієї команди!' - incorrectSyntax: '§cНевірний синтаксис.' - noPermission: '§cУ вас недостатньо прав для виконання цієї команди! (Потрібно: {0})' - invalidCommand: - quests: '§cЦя команда не існує, напишіть §e/quests help§c.' - simple: '§cЦя команда не існує, напишіть §ehelp§c.' - needItem: '§cВи повинні тримати предмет у головній руці!' - itemChanged: '§aЕлемент було відредаговано. Зміни буде застосовано після перезапуску.' - itemRemoved: '§aГолограма була видалена.' - removed: '§aКвест {0} успішно видалено.' - leaveAll: '§aВи примусово завершили {0} квест(и). Помилок: {1}' - resetPlayer: - player: '§6Всі відомості про ваші {0} квест(и) було видалено {1}.' - remover: '§6{0} інформація про квест (і {2} пули) з {1} було видалено.' - resetPlayerQuest: - player: '§6Всі відомості про квест {0} було видалено {1}.' - remover: '§6{0} інформація про квест {1} була видалена.' - resetQuest: '§6Видалені дані квесту для {0} гравців.' - startQuest: '§6Ви примусово запустили квест {0} (UUID Гравця: {1}).' - startQuestNoRequirements: '§cГравець не відповідає вимогам квесту {0}... Долучайтесь до "-overrideRequires" наприкінці вашої команди для обходу вимог.' - cancelQuest: '§6Ви відмінили квест {0}.' - cancelQuestUnavailable: '§cКвест {0} не може бути скасовано.' - backupCreated: '§6Ви успішно створили бекапи для всіх завдань та інформації про гравця.' - backupPlayersFailed: '§cСтворення резервної копії для всіх даних гравця зазнало невдачі.' - backupQuestsFailed: '§cСтворення резервної копії для всіх квестів невдале.' - adminModeEntered: '§aВи увійшли в Режим Адміністратора.' - adminModeLeft: '§aВи вийшли з Режиму Адміністратора.' - resetPlayerPool: - timer: '§aВи скинули {0} таймер пулу в {1}.' - full: '§aВи скинули {0} дані пулу з {1}.' - scoreboard: - lineSet: '§6Ви успішно відредагували рядок {0}.' - lineReset: '§6Ви успішно змінили рядок {0}.' - lineRemoved: '§6Ви успішно видалили рядок {0}.' - lineInexistant: '§cРядок {0} не існує.' - resetAll: '§6Ви успішно скинули таблицю гравця {0}.' - hidden: '§6Таблицю гравця {0} було приховано.' - shown: '§6Таблицю гравця {0} було показано.' - own: - hidden: '§6Ваша таблиця прихована.' - shown: '§6Ваша таблиця показана знову.' - help: - header: '§6§lBeautyQuests - Допомога' - create: '§6/{0} create: §eСтворити квест.' - edit: '§6/{0} edit: §eРедагувати квест.' - remove: '§6/{0} remove<id>: §eВидалити квест з зазначеним id або натисніть на NPC якщо не визначено.' - finishAll: '§6/{0} finishAll <player>: §eЗавершіть всі квести гравця.' - setStage: '§6/{0} setStage <player> <id> [нова гілка] [нова стадія]: §eПропустити поточний етап/почати етап для гілки.' - startDialog: '§6/{0} startDialog <player> <quest id>: §eЗапустити діалогове вікно для етапу NPC або початкове діалогове вікно для квесту.' - resetPlayer: '§6/{0} resetPlayer <player>: §eВидалити всі відомості про гравця.' - resetPlayerQuest: '§6/{0} resetPlayerQuest <player> [id]: §eВидалити інформацію про квест для гравця.' - seePlayer: '§6/{0} seePlayer <player>: §eПереглянути інформацію про гравця.' - reload: '§6/{0} reload: §eЗберегти і перезавантажити всі конфігурації і файли. (§cзастарілий§e)' - start: '§6/{0} start <player> [id]: §eПримусовий початок завдання.' - setItem: '§6/{0} setItem <talk|launch>: §eЗберегти предмет голограми.' - setFirework: '§6/{0} setFirework: §eРедагувати стандартний завершальний феєрверк.' - adminMode: '§6/{0} adminMode: §eПеремикання режиму адміністратора. (Використовується для відображення невеликих повідомлень журналу.)' - version: '§6/{0} version: §eПереглянути поточну версію плагіна.' - downloadTranslations: '§6/{0} downloadTranslations <language>: §eЗавантажує стандартний файл перекладу' - save: '§6/{0} save: §eРучне збереження змін плагіну' - list: '§6/{0} list: §eЩоб відобразити список квестів (Лише для підтримуваних версій.)' - typeCancel: '§aНапишіть "cancel", щоб повернутися до останнього тексту.' - editor: - blockAmount: '§aНапишіть кількість блоків:' - blockName: '§aНапишіть назву блоку:' - blockData: '§aНапишіть блокові дані (доступні дані блоків: §7{0}§a):' - blockTag: '§aЗапишіть тег блоку (доступні теги: §7{0}§a):' - typeBucketAmount: '§aНапишіть кількість відер для заповнення:' - typeDamageAmount: 'Напишіть кількість дамагу, який повинен нанести гравець:' - goToLocation: '§aЙдіть до бажаного місця для етапу.' - typeLocationRadius: '§aНапишіть потрібну відстань від місця розташування:' - typeGameTicks: '§aНапишіть кількість ігрових тіків:' - already: '§cВи вже в редакторі.' - stage: - location: - typeWorldPattern: '§aНапишіть регулярний вираз для назв світів:' - enter: - title: '§6~ Режим Редактора ~' - subtitle: '§6Напишіть "/quests exitEditor" щоб примусово вийти з редактора.' - list: '§c⚠ §7Ви увійшли до редактора "списків". Для додавання рядків використовуйте "add". Перейдіть до довідки "help" (без слешу). §e§lНапишіть "close" для виходу з редактора.' - chat: '§6Ви перебуваєте в режимі редактора. Напишіть "/quests exitEditor", щоб примусово вийти з редактора. (Не рекомендується, розгляньте можливість використання таких команд, як "close" або "cancel", щоб повернутися до попереднього інвентарю.)' - npc: - enter: '§aНатисніть на NPC, або напишіть "cancel".' - choseStarter: '§aОберіть NPC, який почне завдання.' - notStarter: '§cЦей NPC — не починає квести.' - text: - argNotSupported: '§cАргумент {0} не підтримується.' - chooseLvlRequired: '§aНапишіть необхідну кількість рівнів:' - chooseJobRequired: '§aНапишіть ім''я потрібної роботи:' - choosePermissionRequired: '§aНапишіть необхідні права, щоб розпочати квест:' - choosePermissionMessage: '§aВи можете вказати повідомлення про відхилення, якщо гравець не має обов''язкового дозволу. (Щоб пропустити цей крок, напишіть "null".)' - choosePlaceholderRequired: - identifier: '§aНапишіть ім''я потрібного заповнювача без відсоткових символів:' - value: '§aНапишіть необхідне значення для наповнювача §e%§e{0}§e%§a:' - chooseSkillRequired: '§aНапишіть обов''язкові навички:' - chooseMoneyRequired: '§aНапишіть кількість необхідних грошей:' - reward: - permissionName: '§aНапиши ім''я дозволу.' - permissionWorld: '§aНапишіть світ, в якому дозвіл буде відредаговано, або "null", якщо ви хочете застосувати глобально.' - money: '§aНапишіть кількість отриманих грошей:' - wait: '§aНапиши кількість ігрових тіків для очікування: (1 секунда = 20 ігрових тіків)' - random: - min: '§aНапишіть мінімальну кількість нагород, що буде видано гравцю (включно).' - max: '§aНапишіть максимальну кількість нагород, що буде видано гравцю (включно).' - chooseObjectiveRequired: '§aНапишіть ім''я цілі.' - chooseObjectiveTargetScore: '§aНапишіть кінцеву ціль для завдання.' - chooseRegionRequired: '§aНапишіть назву потрібного регіону (ви повинні бути в одному світі).' - selectWantedBlock: '§aНатисніть з паличкою на потрібному блоці для етапу.' - itemCreator: - itemType: '§aНапишіть ім''я потрібного типу предмету:' - itemAmount: '§aНапишіть кількість предметів:' - itemName: '§aНапишіть назву предмету:' - itemLore: '§aЗмінити опис предмета: (Напишіть "help" для допомоги)' - unknownItemType: '§cНевідомий тип предмета.' - invalidItemType: '§cНедійсний тип предмета. (Елемент не може бути блоком)' - unknownBlockType: '&cНевідомий тип блоку' - invalidBlockType: '§cНедійсний тип блока.' - dialog: - syntax: '§cПравильний синтаксис: {0}{1} <message>' - syntaxRemove: '§cПравильний синтаксис: remove <id>' - player: '§aПовідомлення "§7{0}§a" додано для гравця.' - npc: '§aПовідомлення "§7{0}§a" додано для NPC.' - noSender: '§aПовідомлення "§7{0}§a" додано без відправника.' - messageRemoved: '§aПовідомлення "§7{0}§a" видалено.' - edited: '§aПовідомлення "§7{0}§a" відредаговане.' - soundAdded: '§aЗвук "§7{0}§a" додано для повідомлення: "§7{1}§a".' - cleared: '§aВидалено §2§l{0}§a повідомлення.' - help: - header: '§6§lBeautyQuest - Довідник редактору діалогів' - npc: '§6npc <message>: §eДодати повідомлення, написане NPC.' - player: '§6player <message>: §eДодати повідомлення, написане гравцем.' - nothing: '§6noSender <message>: §eДодати повідомлення без відправника.' - remove: '§6remove <id>: §eВидалити повідомлення.' - list: '§6list: §eПереглянути всі повідомлення.' - npcInsert: '§6npcInsert <id> <message>: §eВставити повідомлення, яке буде сказано NPC.' - playerInsert: '§6playerInsert <id> <message>: §eВставте повідомлення сказане гравцем.' - nothingInsert: '§6nothingInsert <id> <message>: §eВставте повідомлення без префікса.' - edit: '§6edit <id> <message>: §eРедагування повідомлення.' - addSound: '§6addSound <id> <sound>: §eДодати звук до повідомлення.' - clear: '§6clear: §eВидалити всі повідомлення.' - close: '§6close: §eПеревірити всі повідомлення.' - setTime: '§6setTime <id> <time>: §eВстановіть час (у тіках) перед тим як автоматично буде написано наступне повідомлення.' - npcName: '§6npcName [користувальницьке ім''я NPC]: §eВстановити (або скинути за замовчуванням) користувацьке ім''я NPC у діалоговому вікні' - skippable: '§6skippable [true|false]: §eВстановити діалогове вікно можна пропустити чи ні' - timeSet: '§aЧас було відредаговано для повідомлення {0}: тепер {1} тіків.' - timeRemoved: '§aЧас було видалено для повідомлення {0}.' - npcName: - set: '§aІм''я NPC встановлено на §7{1}§a (було §7{0}§a)' - unset: '§aІм''я NPC скинуто до стандартного (було §7{0}§a)' - skippable: - set: '§aМожливість пропустити діалог тепер встановлено на §7{1}§a (було §7{0}§a)' - unset: '§aМожливість пропуску діалогу скинуто до стандартного значення (було §7{0}§a)' - mythicmobs: - list: '§aСписок усіх міфічних мобів:' - isntMythicMob: '§cЦього міфічного моба не існує.' - disabled: '§cMythicMob вимкнено.' - advancedSpawnersMob: 'Напишіть назву користувальницького спавнерного мобів для вбивства:' - textList: - syntax: '§cКоректний синтаксис: ' - added: '§aТекст "§7{0}§a" додано.' - removed: '§aТекст "§7{0}§a" видалено.' - help: - header: '§6§lBeautyQuest— Перегляд довідки редактора' - add: '§6add <message>: §eДодати текст.' - remove: '§6remove <id>: §eВидалити текст.' - list: '§6list: §eПереглянути всі додані тексти.' - close: '§6close: §eПеревірити додані текста.' - availableElements: 'Доступні елементи: §e{0}' - noSuchElement: '§cНемає такого елемента. Дозволені елементи: §e{0}' - invalidPattern: '§cНевірний шаблон регулярного виразу §4{0}§c.' - comparisonTypeDefault: '§aОберіть тип порівняння, який Ви хочете серед {0}. порівняння за замовчуванням: §e§l{1}§r§a. Введіть §onull§r§a щоб використати його.' - scoreboardObjectiveNotFound: '§cНевідомий об''єкт таблиці.' - pool: - hologramText: 'Запишіть власний голограмний текст для цього пулу(або "null", якщо ви хочете використовувати стандартну).' - maxQuests: 'Напишіть максимальну кількість квестів, дя запуску з цього пулу.' - questsPerLaunch: 'Напишіть кількість квестів, отриманих коли гравці натискають на NPC.' - timeMsg: 'Напишіть час КД перед повторним виконанням квесту гравцями (стандартна одиниця: дні)' - title: - title: 'Напишіть текст заголовку (або «null», якщо бажаєте вимкнути заголовок).' - subtitle: 'Напишіть текст субтитрів (або «null», якщо ви не бажаєте).' - fadeIn: 'Запишіть тривалість "fade-in", в тіках (20 тіків = 1 секунду).' - stay: 'Напишіть "stay" тривалість, в тіках (20 тіків = 1 секунда).' - fadeOut: 'Запишіть тривалість "fade-out", в тіках (20 тіків = 1 секунда).' - colorNamed: 'Введіть назву кольору.' - color: 'Введіть колір у шістнадцятковому форматі (#XXXXX) або RGB формат (RED GRE BLU).' - invalidColor: 'Введено некоректний колір. Він має бути шістнадцятковим або RGB.' - firework: - invalid: 'Цей предмет не є дійсним феєрверком.' - invalidHand: 'Ви повинні тримати феєрверк у головній руці.' - edited: 'Змінено феєрверк квесту!' - removed: 'Видалено феєрверк квесту!' - writeCommandDelay: '§aНапишіть бажану затримку команди, в тіках.' advancement: finished: Завершено notStarted: Не розпочато +description: + requirement: + class: Клас {class_name} + combatLevel: Бойовий рівень {short_level} + faction: Фракція {faction_name} + jobLevel: Рівень {short_level} для {job_name} + level: Рівень {short_level} + quest: Закінчити квест §e{quest_name} + skillLevel: Рівень {short_level} для {skill_name} + title: '§8§lВимоги:' + reward: + title: '§8§lНагороди:' +indication: + cancelQuest: '§7Ви впевнені, що хочете скасувати квест {quest_name}?' + closeInventory: '§7Ви впевнені, що хочете закрити меню?' + removeQuest: '§7Ви впевнені, що хочете видалити квест {quest}?' + startQuest: '§7Ви хочете розпочати виконання квесту {quest_name}?' inv: - validate: '§b§lПідтвердити' - cancel: '§c§lВідмінити' - search: '§e§lПошук' addObject: '§aДодати об''єкт' + block: + blockData: '§dДані про блок (розширено)' + blockName: '§bКористувацьке ім''я блоку' + blockTag: '§dТег (розширено)' + blockTagLore: Виберіть тег, що описує список можливих блоків. Теги можна налаштувати за допомогою датапаків. Список тегів можна знайти у вікі Minecraft. + material: '§eМатеріал: {block_type}' + materialNotItemLore: Вибраний блок не може бути відображений як предмет. Він все ще збережений як {block_material}. + name: Оберіть блок + blockAction: + location: '§eВиберіть точне розташування' + material: '§eОбрати матеріал блоку' + name: Оберіть дію з блоками + blocksList: + addBlock: '§aНатисніть, щоб додати блок.' + name: Оберіть блоки + buckets: + name: Тип відра + cancel: '§c§lВідмінити' + cancelActions: + name: Скасувати дії + checkpointActions: + name: Дії при контрольній точці + chooseAccount: + name: Який обліковий запис? + chooseQuest: + menu: '§aМеню Квестів' + menuLore: Відкриває вам, ваше Меню Квестів. + name: Який квест? + classesList.name: Список класів + classesRequired.name: Необхідні класи + command: + console: Консоль + delay: '§bЗатримка' + name: Команда + parse: Розбір заповнювачів + value: '§eКоманда' + commandsList: + console: '§eКонсоль: {command_console}' + name: Список команд + value: '§Команда: {command_label}' confirm: name: Ви впевнені? - 'yes': '§aПідтвердити' 'no': '§cСкасувати' + 'yes': '§aПідтвердити' create: - stageCreate: '§aСтворити новий крок' - stageRemove: '§cВидалити цей крок' - stageUp: Перемістити вгору - stageDown: Перемістити вниз - stageType: '§7Тип етапа: §e{0}' - cantFinish: '§7Ви повинні створити принаймні один етап, перш ніж закінчити створення квесту!' - findNPC: '§aЗнайти NPC' + NPCSelect: '§eВибрати або створити NPC' + NPCText: '§eРедагувати діалог' + breedAnimals: '§aРозвести тварин' bringBack: '§aПовернути предмети' - findRegion: '§aЗнайти регіон' - killMobs: '§aВбити мобів' - mineBlocks: '§aЗламати блоки' - placeBlocks: '§aРозмістити блоки' - talkChat: '§aНаписати в чат' - interact: '§aВзаємодіяти з блоком' - fish: '§6Наловити риби' - melt: '§6Переплавити предмети' - enchant: '§dЗачарувати предмети' - craft: '§aСтворити предмети' bucket: '§aНаповнити відра' - location: '§aПерейти до місця розташування' - playTime: '§6Час гри' - breedAnimals: '§aРозвести тварин' - tameAnimals: '§aПриручити тварин' - death: '§cВмерти' + cancelMessage: Скасувати надсилання + cantFinish: '§7Ви повинні створити принаймні один етап, перш ніж закінчити створення квесту!' + changeEntityType: '§eЗмінити тип ентіті' + changeTicksRequired: '§eЗмінити кількість потрібних тіків гравця' + craft: '§aСтворити предмети' + currentRadius: '§eПоточна відстань: §6{radius}' dealDamage: '§cНанести дамагу мобам' + death: '§cВмерти' eatDrink: '§aЗ''їсти, або випити їжу чи зілля' - NPCText: '§eРедагувати діалог' - dialogLines: '{0} рядків' - NPCSelect: '§eВибрати або створити NPC' - hideClues: Приховати частинки та голограми - gps: Відображає компас у напрямку цілі - editMobsKill: '§eРедагуйте мобів для вбивств' - mobsKillFromAFar: Потрібно вбити снарядом editBlocksMine: '§eРедагуйте блоки для ламання' - preventBlockPlace: Заборонити гравцям ламати власні блоки editBlocksPlace: '§eРедагуйте блоки для розміщення' - editMessageType: '§eРедагувати повідомлення для запису' - cancelMessage: Скасувати надсилання - ignoreCase: Ігнорувати випадок повідомлення - replacePlaceholders: Замінити {PLAYER} і наповнювачі з PAPI - selectItems: '§eРедагування необхідних предметів' - selectItemsMessage: '§eРедагувати повідомлення для запиту' - selectItemsComparisons: '§6Виберіть порівняння предметів(РОЗШИРЕНО)' - selectRegion: '§7Виберіть регіон' - toggleRegionExit: При виході - stageStartMsg: '§eЗмінити початкове повідомлення' - selectBlockLocation: '§6Вибрати місце розташування блоку' - selectBlockMaterial: '§6Вибрати матеріал блоку' - leftClick: Клікнути потрібно лівою кнопкою миші + editBucketAmount: '§eРедагуйте кількість відрер для заповнення' + editBucketType: '§eРедагування типу відра для наповнення' editFishes: '§eРедагування риб, щоб зловити' - editItemsToMelt: '§eРедагування предметів для плавлення' - editItemsToEnchant: '§eРедагувати предметів для зачарування' editItem: '§eРедагувати предметів для створення' - editBucketType: '§eРедагування типу відра для наповнення' - editBucketAmount: '§eРедагуйте кількість відрер для заповнення' + editItemsToEnchant: '§eРедагувати предметів для зачарування' + editItemsToMelt: '§eРедагування предметів для плавлення' editLocation: '§eРедагувати розташування' + editMessageType: '§eРедагувати повідомлення для запису' + editMobsKill: '§eРедагуйте мобів для вбивств' editRadius: '§eРедагувати відстань від місця' - currentRadius: '§eПоточна відстань: §6{0}' - changeTicksRequired: '§eЗмінити кількість потрібних тіків гравця' - changeEntityType: '§eЗмінити тип ентіті' + enchant: '§dЗачарувати предмети' + findNPC: '§aЗнайти NPC' + findRegion: '§aЗнайти регіон' + fish: '§6Наловити риби' + hideClues: Приховати частинки та голограми + ignoreCase: Ігнорувати випадок повідомлення + interact: '§aВзаємодіяти з блоком' + killMobs: '§aВбити мобів' + leftClick: Клікнути потрібно лівою кнопкою миші + location: '§aПерейти до місця розташування' + melt: '§6Переплавити предмети' + mineBlocks: '§aЗламати блоки' + mobsKillFromAFar: Потрібно вбити снарядом + placeBlocks: '§aРозмістити блоки' + playTime: '§6Час гри' + preventBlockPlace: Заборонити гравцям ламати власні блоки + replacePlaceholders: Замінити {PLAYER} і наповнювачі з PAPI + selectBlockLocation: '§6Вибрати місце розташування блоку' + selectBlockMaterial: '§6Вибрати матеріал блоку' + selectItems: '§eРедагування необхідних предметів' + selectItemsComparisons: '§6Виберіть порівняння предметів(РОЗШИРЕНО)' + selectItemsMessage: '§eРедагувати повідомлення для запиту' + selectRegion: '§7Виберіть регіон' stage: - location: - worldPattern: '§aВстановити шаблон назви світу §d(РОЗШИРЕНО)' - worldPatternLore: 'Якщо ви хочете, щоб сцена була завершена для будь-якого світу, підходячи до конкретного шаблону, введіть тут регулярний вираз.' - death: - causes: '§aВстановити причини смерті §d(РОЗШИРЕНО)' - anyCause: Будь-яка причина смерті - setCauses: '{0} причина смерті(-ей)' dealDamage: damage: '§eДамаг для угоди' targetMobs: '§cДамагу мобам' + death: + anyCause: Будь-яка причина смерті + causes: '§aВстановити причини смерті §d(РОЗШИРЕНО)' + setCauses: '{causes_amount} причина смерті(-ей)' eatDrink: items: '§eРедагувати предмети для того щоб з''їсти, або випити' - stages: - name: Створити стадії - nextPage: '§eНаступна сторінка' - laterPage: '§eПопередня сторінка' - endingItem: '§eРедагувати кінцеві нагороди' - descriptionTextItem: '§eРедагування опису квесту' - regularPage: '§aРегулярні стадії' - branchesPage: '§dСтадія гілки' - previousBranch: '§eПовернутися до попередньої гілки' - newBranch: '§eЙти до нової гілки' - validationRequirements: '§eНеобхідне підтвердження' - validationRequirementsLore: Всі вимоги повинні відповідати гравцю, який намагається завершити етап. Якщо ні, то етап не може бути завершено. + location: + worldPattern: '§aВстановити шаблон назви світу §d(РОЗШИРЕНО)' + worldPatternLore: Якщо ви хочете, щоб сцена була завершена для будь-якого світу, підходячи до конкретного шаблону, введіть тут регулярний вираз. + stageCreate: '§aСтворити новий крок' + stageDown: Перемістити вниз + stageRemove: '§cВидалити цей крок' + stageStartMsg: '§eЗмінити початкове повідомлення' + stageType: '§7Тип етапа: §e{stage_type}' + stageUp: Перемістити вгору + talkChat: '§aНаписати в чат' + tameAnimals: '§aПриручити тварин' + toggleRegionExit: При виході + damageCause: + name: Причина пошкодження + damageCausesList: + name: Список причин пошкодження details: - hologramLaunch: '§eВідредагуйте "launch" предмет голограми' - hologramLaunchLore: Голограма відображається над головою Стартового NPC, коли гравець може запускати квест. - hologramLaunchNo: '§eРедагування пункту "launch unavailable" предмету голограми' - hologramLaunchNoLore: Голограма відображається над головою Стартового NPC, коли гравець не може запускати квест. + actions: '{amount} дій' + auto: Запускати автоматично при першому вході + autoLore: Якщо увімкнено, квест буде запускатися автоматично, коли гравець вперше приєднується до сервера. + bypassLimit: Не рахуйте ліміт квестів + bypassLimitLore: Якщо увімкнуто, завдання будуть запущені, навіть якщо гравець досяг максимальної кількості одночасно виконуваних квестів. + cancelRewards: '§cСкасувати дії' + cancelRewardsLore: Виконані дії під час скасування цього завдання. + cancellable: Скасовано гравцем + cancellableLore: Дозволяє гравцю скасувати квест через Меню Завдань. + createQuestLore: Ви повинні визначити назву квесту. + createQuestName: '§lСтворити квест' customConfirmMessage: '§eРедагування запиту на підтвердження квесту' customConfirmMessageLore: Повідомлення, що відображається в меню Підтвердження коли гравець збирається запустити квест. customDescription: '§eРедагування опису квесту' customDescriptionLore: Опис розміщений під назвою квесту в GUI. - name: Деталі останнього квесту - multipleTime: - itemName: Увімкнути повторне проходження - itemLore: Чи можна проходити квест кілька разів? - cancellable: Скасовано гравцем - cancellableLore: Дозволяє гравцю скасувати квест через Меню Завдань. - startableFromGUI: Запускається з GUI інтерфейсу - startableFromGUILore: Дозволяє гравцю запустити квест через Меню Завдань. - scoreboardItem: Увімкнути таблицю - scoreboardItemLore: Якщо вимкнено, то завдання не будуть відстежуватися через таблицю. + customMaterial: '§eРедагування матеріалу квестового предмету' + customMaterialLore: Предмет цього квесту в Меню Завдань. + defaultValue: '§8(значення за замовчуванням)' + editQuestName: '§lРедагувати квест' + editRequirements: '§eРедагування вимог' + editRequirementsLore: Всі вимоги повинні застосовуватися до гравця перед запуском квесту. + endMessage: '§eРедагування кінцевого повідомлення' + endMessageLore: Повідомлення, яке буде надіслано гравцю наприкінці квесту. + endSound: '§6Редагувати кінцевий звук' + endSoundLore: Звук, який буде відтворюватися в кінці квесту. + failOnDeath: Провал квесту при смерті + failOnDeathLore: Чи буде відмінено квест, коли гравець помре? + firework: '§dЗавершальний феєрверк' + fireworkLore: Феєрверк запущено, коли гравець завершує квест + fireworkLoreDrop: Перетягніть ваш феєрверк сюди hideNoRequirementsItem: Приховувати коли вимоги не відповідають hideNoRequirementsItemLore: Якщо включено, завдання не будуть відображатися в Меню Завдань, коли вимоги не виконуються. - bypassLimit: Не рахуйте ліміт квестів - bypassLimitLore: Якщо увімкнуто, завдання будуть запущені, навіть якщо гравець досяг максимальної кількості одночасно виконуваних квестів. - auto: Запускати автоматично при першому вході - autoLore: Якщо увімкнено, квест буде запускатися автоматично, коли гравець вперше приєднується до сервера. + hologramLaunch: '§eВідредагуйте "launch" предмет голограми' + hologramLaunchLore: Голограма відображається над головою Стартового NPC, коли гравець може запускати квест. + hologramLaunchNo: '§eРедагування пункту "launch unavailable" предмету голограми' + hologramLaunchNoLore: Голограма відображається над головою Стартового NPC, коли гравець не може запускати квест. + hologramText: '§eТекст голограми' + hologramTextLore: Текст, що відображається на голограмі над головою Starter NPC. + keepDatas: Зберігати дані гравців + keepDatasLore: 'Примусово керувати плагіном для збереження даних гравців, незважаючи на те, що стадії були відредаговані. §c§lПОПЕРЕДЖЕННЯ §c- увімкнення цієї опції може зламати дані ваших гравців.' + loreReset: '§e§lДосягнення всіх гравців буде скинуто' + multipleTime: + itemLore: Чи можна проходити квест кілька разів? + itemName: Увімкнути повторне проходження + name: Деталі останнього квесту + optionValue: '§8Значення: §7{value}' questName: '§a§lРедагувати назву квесту' questNameLore: Назва має бути встановлена для завершення створення квесту. - setItemsRewards: '§eЗмінити нагороди' + questPool: '§eПул квестів' + questPoolLore: Прикріпити цей квест до квест-пулу removeItemsReward: '§eПрибрати предмети з інвентарю' - setXPRewards: '§eРедагувати винагороду досвіду' + requiredParameter: '§7Необхідний параметр' + requirements: '{amount} вимог' + rewards: '{amount} нагород' + rewardsLore: Виконані дії при завершенні квесту. + scoreboardItem: Увімкнути таблицю + scoreboardItemLore: Якщо вимкнено, то завдання не будуть відстежуватися через таблицю. + selectStarterNPC: '§e§lВыберіть NPC, який буде починати квест' + selectStarterNPCLore: Натискання на обраного NPC запустить квест. + selectStarterNPCPool: '§c⚠ Пул квестів обрано' setCheckpointReward: '§eРедагувати винагороду контрольних точок' + setItemsRewards: '§eЗмінити нагороди' + setMoneyReward: '§6Редагувати грошову винагороду' + setPermReward: '§eРедагувати права доступу' setRewardStopQuest: '§cЗупинити квест' - setRewardsWithRequirements: '§eНагороди з вимогами' setRewardsRandom: '§dВипадкові нагороди' - setPermReward: '§eРедагувати права доступу' - setMoneyReward: '§6Редагувати грошову винагороду' - setWaitReward: '§eРедагувати "wait" винагороду' + setRewardsWithRequirements: '§eНагороди з вимогами' setTitleReward: '§6Редагувати заголовок винагороди' - selectStarterNPC: '§e§lВыберіть NPC, який буде починати квест' - selectStarterNPCLore: Натискання на обраного NPC запустить квест. - selectStarterNPCPool: '§c⚠ Пул квестів обрано' - createQuestName: '§lСтворити квест' - createQuestLore: Ви повинні визначити назву квесту. - editQuestName: '§lРедагувати квест' - endMessage: '§eРедагування кінцевого повідомлення' - endMessageLore: Повідомлення, яке буде надіслано гравцю наприкінці квесту. - endSound: '§6Редагувати кінцевий звук' - endSoundLore: Звук, який буде відтворюватися в кінці квесту. - startMessage: '§6Редагувати початкове повідомлення' - startMessageLore: Повідомлення, яке буде надіслано гравцю на початку завдання. + setWaitReward: '§eРедагувати "wait" винагороду' + setXPRewards: '§eРедагувати винагороду досвіду' startDialog: '§eРедагування початкового діалогу' startDialogLore: Діалог який буде відтворюватись до початку квесту, коли гравці натискають на Стартового NPC. - editRequirements: '§eРедагування вимог' - editRequirementsLore: Всі вимоги повинні застосовуватися до гравця перед запуском квесту. + startMessage: '§6Редагувати початкове повідомлення' + startMessageLore: Повідомлення, яке буде надіслано гравцю на початку завдання. startRewards: '§6Винагорода за початок' startRewardsLore: Виконані дії при початку квесту. - cancelRewards: '§cСкасувати дії' - cancelRewardsLore: Виконані дії під час скасування цього завдання. - hologramText: '§eТекст голограми' - hologramTextLore: Текст, що відображається на голограмі над головою Starter NPC. + startableFromGUI: Запускається з GUI інтерфейсу + startableFromGUILore: Дозволяє гравцю запустити квест через Меню Завдань. timer: '§bПерезапустити таймер' timerLore: Час до того, як гравець зможе знову розпочати квест. - requirements: '{0} вимог' - rewards: '{0} нагород' - actions: '{0} дій' - rewardsLore: Виконані дії при завершенні квесту. - customMaterial: '§eРедагування матеріалу квестового предмету' - customMaterialLore: Предмет цього квесту в Меню Завдань. - failOnDeath: Провал квесту при смерті - failOnDeathLore: Чи буде відмінено квест, коли гравець помре? - questPool: '§eПул квестів' - questPoolLore: Прикріпити цей квест до квест-пулу - firework: '§dЗавершальний феєрверк' - fireworkLore: Феєрверк запущено, коли гравець завершує квест - fireworkLoreDrop: Перетягніть ваш феєрверк сюди visibility: '§bВидимість квесту' visibilityLore: Виберіть, які вкладки меню буде показано, і якщо пошук є видимим на динамічних картах. - keepDatas: Зберігати дані гравців - keepDatasLore: |- - Примусово керувати плагіном для збереження даних гравців, незважаючи на те, що стадії були відредаговані. - §c§lПОПЕРЕДЖЕННЯ §c- увімкнення цієї опції може зламати дані ваших гравців. - loreReset: '§e§lДосягнення всіх гравців буде скинуто' - optionValue: '§8Значення: §7{0}' - defaultValue: '§8(значення за замовчуванням)' - requiredParameter: '§7Необхідний параметр' - itemsSelect: - name: Редагувати предмет - none: |- - §aПеремістіть предмет сюди або - натисніть, щоб відкрити редактор предметів. - itemSelect: - name: 'Виберіть предмет:' - npcCreate: - name: Створити NPC - setName: '§eРедагувати ім''я NPC' - setSkin: '§eРедагувати скін NPC' - setType: '§eРедагувати тип NPC' - move: - itemName: '§eРухатись' - itemLore: '§aЗмінити розташування NPC.' - moveItem: '§a§lПоточне місце' - npcSelect: - name: Вибрати або створити? - selectStageNPC: '§eВиберіть існуючий NPC' - createStageNPC: '§eСтворити NPC' + editTitle: + fadeIn: '§aТривалість затемнення' + fadeOut: '§aТривалість затухання' + name: Редагувати заголовок + stay: '§bТривалість перебування' + subtitle: '§eПідзаголовок' + title: '§6Заголовок' entityType: name: Виберіть тип ентіті - chooseQuest: - name: Який квест? - menu: '§aМеню Квестів' - menuLore: Відкриває вам, ваше Меню Квестів. - mobs: - name: Виберіть мобів - none: '§aНатисніть, щоб додати моба.' - clickLore: |- - §a§lЛівий Клік§a для редагування суми. - §a§l§nShift§a§l + Лівий Клік для редагування імені мобів. - §c§lПравий Клік§c для видалення. - mobSelect: - name: Виберіть тип моба - bukkitEntityType: '§eОберіть тип ентіті' - mythicMob: '§6Оберіть міфічного моба' - epicBoss: '§6Оберіть Епічного Боса' - boss: '§6Оберіть Боса' - stageEnding: - locationTeleport: '§6Змінити розташування телепорту' - command: '§eРедагування виконуваної команди' - requirements: - name: Вимоги - rewards: - name: Нагороди - commands: 'Команди: {0}' - teleportation: |- - §aОбрано: - X: {0} - Y: {1} - Z: {2} - Світ: {3} - random: - rewards: Редагувати нагороди - minMax: Редагувати мін. і макс - checkpointActions: - name: Дії при контрольній точці - cancelActions: - name: Скасувати дії - rewardsWithRequirements: - name: Нагороди з вимогами - listAllQuests: - name: Квести - listPlayerQuests: - name: '{0} квести' - listQuests: - notStarted: Не запущені квести - finished: Завершені квести - inProgress: Квести в процесі - loreDialogsHistoryClick: '§7Переглянути діалоги' - loreCancelClick: '§cСкасувати квест' - loreStart: '§a§aНатисни, щоб розпочати квест.' - loreStartUnavailable: '§c§oВи не відповідаєте вимогам, щоб розпочати завдання.' - timeToWaitRedo: '§3§oВи можете перепройти цей квест через {0}.' - canRedo: '§3§oВи можете перепройти цей квест!' - timesFinished: '§3Квест виконано {0} разів.' + equipmentSlots: + name: Слоти обладнання + factionsList.name: Список фракцій + factionsRequired.name: Фракції необхідні + itemComparisons: + bukkit: Порівняння інтерфейсу Bukkit + bukkitLore: Використовує систему порівняння предметів Bukkit за замовчуванням. Порівняє матеріали, довготривалі теги... + customBukkit: Власне порівняння Bukkit - NO NBT + customBukkitLore: Використовує систему порівняння предметів Bukkit за замовчуванням, але очищує теги NBT. Порівняє матеріальну, довговічність... + enchants: Зачарування предметів + enchantsLore: Порівнює зачарування предметів + itemLore: Опис предмету + itemLoreLore: Порівнює описи предметів + itemName: Назва предмету + itemNameLore: Порівнює назви предметів + itemsAdder: ItemsAdder + itemsAdderLore: Порівняння ID з ItemsAdder + material: Матеріали предметів + materialLore: Порівнює матеріали предметів (і. камінь, залізний меч...) + name: Порівняння предметів + repairCost: Вартість ремонту + repairCostLore: Порівнює вартість ремонту броні та мечів itemCreator: - name: Створення предмета - itemType: '§bТип предмету' + isQuestItem: '§bКвестовий предмет:' itemFlags: Увімкнути флаги предмету - itemName: '§bНазва предмету' itemLore: '§bОпис предмету' - isQuestItem: '§bКвестовий предмет:' - command: - name: Команда - value: '§eКоманда' - console: Консоль - parse: Розбір заповнювачів - delay: '§bЗатримка' - chooseAccount: - name: Який обліковий запис? + itemName: '§bНазва предмету' + itemType: '§bТип предмету' + name: Створення предмета + itemSelect: + name: 'Виберіть предмет:' + itemsSelect: + name: Редагувати предмет + none: '§aПеремістіть предмет сюди або натисніть, щоб відкрити редактор предметів.' + listAllQuests: + name: Квести listBook: + noQuests: Не було створено жодного квесту. + questMultiple: Декілька разів questName: Назва - questStarter: Початківець questRewards: Нагороди - questMultiple: Декілька разів - requirements: Вимоги questStages: Етапи - noQuests: Не було створено жодного квесту. - commandsList: - name: Список команд - value: '§Команда: {0}' - console: '§eКонсоль: {0}' - block: - name: Оберіть блок - material: '§eМатеріал: {0}' - materialNotItemLore: 'Вибраний блок не може бути відображений як предмет. Він все ще збережений як {0}.' - blockData: '§dДані про блок (розширено)' - blockTag: '§dТег (розширено)' - blockTagLore: 'Виберіть тег, що описує список можливих блоків. Теги можна налаштувати за допомогою датапаків. Список тегів можна знайти у вікі Minecraft.' - blocksList: - name: Оберіть блоки - addBlock: '§aНатисніть, щоб додати блок.' - blockAction: - name: Оберіть дію з блоками - location: '§eВиберіть точне розташування' - material: '§eОбрати матеріал блоку' - buckets: - name: Тип відра + questStarter: Початківець + requirements: Вимоги + listPlayerQuests: + name: '{player_name} квести' + listQuests: + canRedo: '§3§oВи можете перепройти цей квест!' + finished: Завершені квести + inProgress: Квести в процесі + loreCancelClick: '§cСкасувати квест' + loreDialogsHistoryClick: '§7Переглянути діалоги' + loreStart: '§a§aНатисни, щоб розпочати квест.' + loreStartUnavailable: '§c§oВи не відповідаєте вимогам, щоб розпочати завдання.' + notStarted: Не запущені квести + timeToWaitRedo: '§3§oВи можете перепройти цей квест через {time_left}.' + timesFinished: '§3Квест виконано {times_finished} разів.' + mobSelect: + boss: '§6Оберіть Боса' + bukkitEntityType: '§eОберіть тип ентіті' + epicBoss: '§6Оберіть Епічного Боса' + mythicMob: '§6Оберіть міфічного моба' + name: Виберіть тип моба + mobs: + name: Виберіть мобів + none: '§aНатисніть, щоб додати моба.' + setLevel: Встановити мінімальний рівень + npcCreate: + move: + itemLore: '§aЗмінити розташування NPC.' + itemName: '§eРухатись' + moveItem: '§a§lПоточне місце' + name: Створити NPC + setName: '§eРедагувати ім''я NPC' + setSkin: '§eРедагувати скін NPC' + setType: '§eРедагувати тип NPC' + npcSelect: + createStageNPC: '§eСтворити NPC' + name: Вибрати або створити? + selectStageNPC: '§eВиберіть існуючий NPC' + particleEffect: + color: '§bКолір частинок' + name: Створити ефект частинок + shape: '§dФорма частинок' + type: '§eТип частинок' + particleList: + colored: Кольорова частинка + name: Список частинок permission: name: Виберіть права доступу perm: '§aДозвіл' - world: '§aСвіт' - worldGlobal: '§b§lГлобально' remove: Видалити дозвіл removeLore: '§7Дозвіл буде знято\n§7замість даного.' + world: '§aСвіт' + worldGlobal: '§b§lГлобально' permissionList: name: Список дозволів - removed: '§eЗайнятий: §6{0}' - world: '§eСвіт: §6{0}' - classesRequired.name: Необхідні класи - classesList.name: Список класів - factionsRequired.name: Фракції необхідні - factionsList.name: Список фракцій - poolsManage: - name: Пул квестів - itemName: '§aПул #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Макс квестів: §7{0}' - poolQuestsPerLaunch: '§8Кветів дано за запуск: §7{0}' - poolRedo: '§8Можливе перевиконання квестів: §7{0}' - poolTime: '§8Час між квестами: §7{0}' - poolHologram: '§8Текст голограми: §7{0}' - poolAvoidDuplicates: '§8Уникайте дублікатів: §7{0}' - poolQuestsList: '§7{0} §8квест(и): §7{1}' - create: '§aСтворення пулу квестів' - edit: '§e> §6§oРедагувати пул... §e<' - choose: '§e> §6§oОберіть цей пул§e<' + removed: '§eЗайнятий: §6{permission_removed}' + world: '§eСвіт: §6{permission_world}' poolCreation: - name: Створення пулу квестів + avoidDuplicates: Уникати дублікатів + avoidDuplicatesLore: '§8> §7Спробуйте уникати виконання\n тих самих завдань знову і знову' hologramText: '§eКористувацька голограма пулу' maxQuests: '§aМакс. квестів' + name: Створення пулу квестів questsPerLaunch: '§aКвестів розпочато за запуск' - time: '§bВстановлення часу між квестами' redoAllowed: Чи дозволено повторення - avoidDuplicates: Уникати дублікатів - avoidDuplicatesLore: '§8> §7Спробуйте уникати виконання\n тих самих завдань знову і знову' requirements: '§bВимоги для початку квесту' + time: '§bВстановлення часу між квестами' poolsList.name: Пул квестів - itemComparisons: - name: Порівняння предметів - bukkit: Порівняння інтерфейсу Bukkit - bukkitLore: "Використовує систему порівняння предметів Bukkit за замовчуванням.\nПорівняє матеріали, довготривалі теги..." - customBukkit: Власне порівняння Bukkit - NO NBT - customBukkitLore: "Використовує систему порівняння предметів Bukkit за замовчуванням, але очищує теги NBT.\nПорівняє матеріальну, довговічність..." - material: Матеріали предметів - materialLore: 'Порівнює матеріали предметів (і. камінь, залізний меч...)' - itemName: Назва предмету - itemNameLore: Порівнює назви предметів - itemLore: Опис предмету - itemLoreLore: Порівнює описи предметів - enchants: Зачарування предметів - enchantsLore: Порівнює зачарування предметів - repairCost: Вартість ремонту - repairCostLore: Порівнює вартість ремонту броні та мечів - editTitle: - name: Редагувати заголовок - title: '§6Заголовок' - subtitle: '§eПідзаголовок' - fadeIn: '§aТривалість затемнення' - stay: '§bТривалість перебування' - fadeOut: '§aТривалість затухання' - particleEffect: - name: Створити ефект частинок - shape: '§dФорма частинок' - type: '§eТип частинок' - color: '§bКолір частинок' - particleList: - name: Список частинок - colored: Кольорова частинка - damageCause: - name: Причина пошкодження - damageCausesList: - name: Список причин пошкодження + poolsManage: + choose: '§e> §6§oОберіть цей пул§e<' + create: '§aСтворення пулу квестів' + edit: '§e> §6§oРедагувати пул... §e<' + itemName: '§aПул #{pool}' + name: Пул квестів + poolAvoidDuplicates: '§8Уникайте дублікатів: §7{pool_duplicates}' + poolHologram: '§8Текст голограми: §7{pool_hologram}' + poolMaxQuests: '§8Макс квестів: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8квест(и): §7{pool_quests}' + poolQuestsPerLaunch: '§8Кветів дано за запуск: §7{pool_quests_per_launch}' + poolRedo: '§8Можливе перевиконання квестів: §7{pool_redo}' + poolTime: '§8Час між квестами: §7{pool_time}' + requirements: + name: Вимоги + rewards: + commands: 'Команди: {amount}' + name: Нагороди + random: + minMax: Редагувати мін. і макс + rewards: Редагувати нагороди + rewardsWithRequirements: + name: Нагороди з вимогами + search: '§e§lПошук' + stageEnding: + command: '§eРедагування виконуваної команди' + locationTeleport: '§6Змінити розташування телепорту' + stages: + branchesPage: '§dСтадія гілки' + descriptionTextItem: '§eРедагування опису квесту' + endingItem: '§eРедагувати кінцеві нагороди' + laterPage: '§eПопередня сторінка' + name: Створити стадії + newBranch: '§eЙти до нової гілки' + nextPage: '§eНаступна сторінка' + previousBranch: '§eПовернутися до попередньої гілки' + regularPage: '§aРегулярні стадії' + validationRequirements: '§eНеобхідне підтвердження' + validationRequirementsLore: Всі вимоги повинні відповідати гравцю, який намагається завершити етап. Якщо ні, то етап не може бути завершено. + validate: '§b§lПідтвердити' visibility: + finished: 'Вкладка меню "Завершено"' + inProgress: 'Вкладка меню "В процесі"' + maps: Карти (такі як dynmap чи BlueMap) name: Видимість квесту notStarted: 'Вкладка меню "Не запущено"' - inProgress: 'Вкладка меню "В процесі"' - finished: 'Вкладка меню "Завершено"' - maps: 'Карти (такі як dynmap чи BlueMap)' - equipmentSlots: - name: Слоти обладнання -scoreboard: - name: '§6§lКвести' - noLaunched: '§cНемає квестів в процесі.' - noLaunchedName: '§c§lЗавантаження' - noLaunchedDescription: '§c§oЗавантаження' - textBetwteenBranch: '§e або' - asyncEnd: '§ex' - stage: - region: '§eЗнайти регіон §6{0}' - npc: '§eПоговорити з NPC §6{0}' - items: '§eПринесіть речі §6{0}§e:' - mobs: '§eВбийте §6{0}' - mine: '§eВикопайте {0}' - placeBlocks: '§6Розмістіть {0}' - chat: '§eНапишіть §6{0}' - interact: '§eНатисніть на блок на §6{0}' - interactMaterial: '§eНатисніть на §6{0}§e блок' - fish: '§eРиба §6{0}' - melt: '§eПереплавте §6{0}' - enchant: '§eЗачаруйте §6{0}' - craft: '§eСтворіть §6{0}' - bucket: '§eЗаповніть §6{0}' - location: '§eЙдіть до §6{0}§6{1}§, §6{2}§e в §6{3}' - playTimeFormatted: '§eГрайте §6{0}' - breed: '§eРозмножте §6{0}' - tame: '§eПриручіть §6{0}' - die: '§cВмерти' - dealDamage: - any: '§cЗавдати {0} дамагу' - mobs: '§cЗавдати {0} дамагу {1}' - eatDrink: '§eСпожити §6{0}' -indication: - startQuest: '§7Ви хочете розпочати виконання квесту {0}?' - closeInventory: '§7Ви впевнені, що хочете закрити меню?' - cancelQuest: '§7Ви впевнені, що хочете скасувати квест {0}?' - removeQuest: '§7Ви впевнені, що хочете видалити квест {0}?' -description: - requirement: - title: '§8§lВимоги:' - level: 'Рівень {0}' - jobLevel: 'Рівень {0} для {1}' - combatLevel: 'Бойовий рівень {0}' - skillLevel: 'Рівень {0} для {1}' - class: 'Клас {0}' - faction: 'Фракція {0}' - quest: 'Закінчити квест §e{0}' - reward: - title: '§8§lНагороди:' misc: - format: - prefix: '§6<§e§lКвести§r§6> §r' - time: - weeks: '{0} тижнів' - days: '{0} днів' - hours: '{0} годин' - minutes: '{0} хвилин' - lessThanAMinute: 'менше хвилини' - stageType: - region: Знайти регіон - npc: Знайти NPC - items: Повернути назад предмети - mobs: Вбивати мобів - mine: Ламати блоки - placeBlocks: Поставити блоки - chat: Писати у чат - interact: Взаємодіяти з блоком - Fish: Ловити рибу - Melt: Переплавляти предмети - Enchant: Зачарувати предмети - Craft: Створити предмети - Bucket: Наповнити відро - location: Знайти локацію - playTime: Час гри - breedAnimals: Розвести тварин - tameAnimals: Приручити тварин - die: Смерть - dealDamage: Завдавання шкоди - eatDrink: Їж чи пий - comparison: - equals: дорівнює {0} - different: різне з {0} - less: цілком менше, ніж {0} - lessOrEquals: менше ніж {0} - greater: точно, більше ніж {0} - greaterOrEquals: більше, ніж {0} - requirement: - logicalOr: '§dЛогічне OR (потребується)' - skillAPILevel: '§bSkillAPI необхідний рівень навичок' - class: '§bКласи необхідні' - faction: '§bФракція(-і) обов''язкові' - jobLevel: '§bРівень роботи необхідно' - combatLevel: '§bНеобхідний рівень битви' - experienceLevel: '§bНеобхідно рівень досвіду' - permissions: '§3Потребуються права доступу' - scoreboard: '§dПотрібна оцінка' - region: '§dПотрібен регіон' - placeholder: '§bЗначення placeholder потребується' - quest: '§aВимоги квесту' - mcMMOSkillLevel: '§bРівень навичок необхідний' - money: '§dНеобхідні гроші' - equipment: '§eНеобхідне обладнання' + amount: '§6Кількість: {amount}' + amounts: + comparisons: '{comparisons_amount} порівняння(нь)' + dialogLines: '{lines_amount} рядків' + items: '{items_amount} предмет(ів)' + mobs: '{mobs_amount} мобів' + permissions: '{permissions_amount} прав' + and: і bucket: - water: Відро води lava: Відро лави milk: Відро молока snow: Відро снігу + water: Відро води click: - right: ПКМ left: ЛКМ - shift-right: Shift — ПКМ - shift-left: Shift — ЛКМ middle: СКМ - amounts: - items: '{0} предмет(ів)' - comparisons: '{0} порівняння(нь)' - dialogLines: '{0} рядків' - permissions: '{0} прав' - mobs: '{0} мобів' - ticks: '{0} тіків' - questItemLore: '§e§oКвестовий Предмет' - hologramText: '§8§lКвестовий NPC' - poolHologramText: '§eНові квести доступні!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eТип ентіті: {0}' - entityTypeAny: '§eБудь-яка сутність' - enabled: Увімкнено + right: ПКМ + shift-left: Shift — ЛКМ + shift-right: Shift — ПКМ + comparison: + different: різне з {number} + equals: дорівнює {number} + greater: точно, більше ніж {number} + greaterOrEquals: більше, ніж {number} + less: цілком менше, ніж {number} + lessOrEquals: менше ніж {number} disabled: Вимкнено - unknown: невідомо + enabled: Увімкнено + entityType: '§eТип ентіті: {entity_type}' + entityTypeAny: '§eБудь-яка сутність' + format: + prefix: '§6<§e§lКвести§r§6> §r' + hologramText: '§8§lКвестовий NPC' + 'no': 'Ні' notSet: '§cне встановлено' - unused: '§2§lНе використано' - used: '§a§lВикористано' - remove: '§7СКМ, щоб видалити' + or: або + poolHologramText: '§eНові квести доступні!' + questItemLore: '§e§oКвестовий Предмет' removeRaw: Видалити + requirement: + class: '§bКласи необхідні' + combatLevel: '§bНеобхідний рівень битви' + equipment: '§eНеобхідне обладнання' + experienceLevel: '§bНеобхідно рівень досвіду' + faction: '§bФракція(-і) обов''язкові' + jobLevel: '§bРівень роботи необхідно' + logicalOr: '§dЛогічне OR (потребується)' + mcMMOSkillLevel: '§bРівень навичок необхідний' + money: '§dНеобхідні гроші' + permissions: '§3Потребуються права доступу' + placeholder: '§bЗначення placeholder потребується' + quest: '§aВимоги квесту' + region: '§dПотрібен регіон' + scoreboard: '§dПотрібна оцінка' + skillAPILevel: '§bSkillAPI необхідний рівень навичок' reset: Скинути - or: або - amount: '§6Кількість: {0}' - items: предмети - expPoints: очки досвіду + stageType: + Bucket: Наповнити відро + Craft: Створити предмети + Enchant: Зачарувати предмети + Fish: Ловити рибу + Melt: Переплавляти предмети + breedAnimals: Розвести тварин + chat: Писати у чат + dealDamage: Завдавання шкоди + die: Смерть + eatDrink: Їж чи пий + interact: Взаємодіяти з блоком + items: Повернути назад предмети + location: Знайти локацію + mine: Ламати блоки + mobs: Вбивати мобів + npc: Знайти NPC + placeBlocks: Поставити блоки + playTime: Час гри + region: Знайти регіон + tameAnimals: Приручити тварин + ticks: '{ticks} тіків' + time: + days: '{days_amount} днів' + hours: '{hours_amount} годин' + lessThanAMinute: менше хвилини + minutes: '{minutes_amount} хвилин' + weeks: '{weeks_amount} тижнів' + unknown: невідомо 'yes': 'Так' - 'no': 'Ні' - and: і +msg: + bringBackObjects: Поверніть мене назад {items}. + command: + adminModeEntered: '§aВи увійшли в Режим Адміністратора.' + adminModeLeft: '§aВи вийшли з Режиму Адміністратора.' + backupCreated: '§6Ви успішно створили бекапи для всіх завдань та інформації про гравця.' + backupPlayersFailed: '§cСтворення резервної копії для всіх даних гравця зазнало невдачі.' + backupQuestsFailed: '§cСтворення резервної копії для всіх квестів невдале.' + cancelQuest: '§6Ви відмінили квест {quest}.' + cancelQuestUnavailable: '§cКвест {quest} не може бути скасовано.' + checkpoint: + noCheckpoint: '§cНе знайдено жодної контрольної точки для квесту {quest}.' + questNotStarted: '§cВи не виконуєте цей квест.' + downloadTranslations: + downloaded: '§aМову {lang} було завантажено! §7Тепер ви повинні відредагувати файл "/plugins/BeautyQuests/config.yml", щоб змінити значення §ominecraftTranslationsFile§7 з {lang}, а потім перезапустити сервер.' + exists: '§cФайл {file_name} вже існує. Додавайте «-overwrite» до вашої команди, щоб перезаписати його. (/quests downloadTranslations <lang> -overwrite)' + notFound: '§cМова {lang} не знайдена для версії {version}.' + syntax: '§cви повинні вказати мову для завантаження. Приклад: "/quests downloadTranslations en_US".' + help: + adminMode: '§6/{label} adminMode: §eПеремикання режиму адміністратора. (Використовується для відображення невеликих повідомлень журналу.)' + create: '§6/{label} create: §eСтворити квест.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eЗавантажує стандартний файл перекладу' + edit: '§6/{label} edit: §eРедагувати квест.' + finishAll: '§6/{label} finishAll <player>: §eЗавершіть всі квести гравця.' + header: '§6§lBeautyQuests - Допомога' + list: '§6/{label} list: §eЩоб відобразити список квестів (Лише для підтримуваних версій.)' + reload: '§6/{label} reload: §eЗберегти і перезавантажити всі конфігурації і файли. (§cзастарілий§e)' + remove: '§6/{label} remove<id>: §eВидалити квест з зазначеним id або натисніть на NPC якщо не визначено.' + resetPlayer: '§6/{label} resetPlayer <player>: §eВидалити всі відомості про гравця.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eВидалити інформацію про квест для гравця.' + save: '§6/{label} save: §eРучне збереження змін плагіну' + seePlayer: '§6/{label} seePlayer <player>: §eПереглянути інформацію про гравця.' + setFirework: '§6/{label} setFirework: §eРедагувати стандартний завершальний феєрверк.' + setItem: '§6/{label} setItem <talk|launch>: §eЗберегти предмет голограми.' + setStage: '§6/{label} setStage <player> <id> [нова гілка] [нова стадія]: §eПропустити поточний етап/почати етап для гілки.' + start: '§6/{label} start <player> [id]: §eПримусовий початок завдання.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eЗапустити діалогове вікно для етапу NPC або початкове діалогове вікно для квесту.' + version: '§6/{label} version: §eПереглянути поточну версію плагіна.' + invalidCommand: + simple: '§cЦя команда не існує, напишіть §ehelp§c.' + itemChanged: '§aЕлемент було відредаговано. Зміни буде застосовано після перезапуску.' + itemRemoved: '§aГолограма була видалена.' + leaveAll: '§aВи примусово завершили {success} квест(и). Помилок: {errors}' + removed: '§aКвест {quest_name} успішно видалено.' + resetPlayer: + player: '§6Всі відомості про ваші {quest_amount} квест(и) було видалено {deleter_name}.' + remover: '§6{quest_amount} інформація про квест (і {quest_pool} пули) з {player} було видалено.' + resetPlayerPool: + full: '§aВи скинули {pool} дані пулу з {player}.' + timer: '§aВи скинули {pool} таймер пулу в {player}.' + resetPlayerQuest: + player: '§6Всі відомості про квест {quest} було видалено {deleter_name}.' + remover: '§6{player} інформація про квест {quest} була видалена.' + resetQuest: '§6Видалені дані квесту для {player_amount} гравців.' + scoreboard: + hidden: '§6Таблицю гравця {player_name} було приховано.' + lineInexistant: '§cРядок {line_id} не існує.' + lineRemoved: '§6Ви успішно видалили рядок {line_id}.' + lineReset: '§6Ви успішно змінили рядок {line_id}.' + lineSet: '§6Ви успішно відредагували рядок {line_id}.' + own: + hidden: '§6Ваша таблиця прихована.' + shown: '§6Ваша таблиця показана знову.' + resetAll: '§6Ви успішно скинули таблицю гравця {player_name}.' + shown: '§6Таблицю гравця {player_name} було показано.' + setStage: + branchDoesntExist: '§cГілка з ідентифікатором {branch_id} не існує.' + doesntExist: '§cЕтап з ідентифікатором {stage_id} не існує.' + next: '§aЕтап пропущено.' + nextUnavailable: '§cРпція "Пропустити" недоступна, коли гравець знаходиться у кінці гілки.' + set: '§aЕтап {stage_id} запущено.' + startDialog: + alreadyIn: '§cГравець вже бачить діалог.' + impossible: '§cНеможливо зараз почати діалог.' + noDialog: '§cГравець не має діалогового вікна, що очікує на розгляд.' + success: '§aРозпочате діалогове вікно для гравця {player} в квесті {quest}!' + startPlayerPool: + error: Не вдалося запустити голосування {pool} для {player}. + success: 'Початок голосування {pool} до {player}. Результат: {result}' + startQuest: '§6Ви примусово запустили квест {quest} (UUID Гравця: {player}).' + startQuestNoRequirements: '§cГравець не відповідає вимогам квесту {quest}... Долучайтесь до "-overrideRequires" наприкінці вашої команди для обходу вимог.' + dialogs: + skipped: '§8§o Діалог пропущено.' + tooFar: '§7§oВи занадто далеко від {npc_name}...' + editor: + advancedSpawnersMob: 'Напишіть назву користувальницького спавнерного мобів для вбивства:' + already: '§cВи вже в редакторі.' + availableElements: 'Доступні елементи: §e{available_elements}' + blockAmount: '§aНапишіть кількість блоків:' + blockData: '§aНапишіть блокові дані (доступні дані блоків: §7{available_datas}§a):' + blockName: '§aНапишіть назву блоку:' + blockTag: '§aЗапишіть тег блоку (доступні теги: §7{available_tags}§a):' + chat: '§6Ви перебуваєте в режимі редактора. Напишіть "/quests exitEditor", щоб примусово вийти з редактора. (Не рекомендується, розгляньте можливість використання таких команд, як "close" або "cancel", щоб повернутися до попереднього інвентарю.)' + color: 'Введіть колір у шістнадцятковому форматі (#XXXXX) або RGB формат (RED GRE BLU).' + colorNamed: Введіть назву кольору. + comparisonTypeDefault: '§aОберіть тип порівняння, який Ви хочете серед {available}. порівняння за замовчуванням: §e§l{default}§r§a. Введіть §onull§r§a щоб використати його.' + dialog: + cleared: '§aВидалено §2§l{amount}§a повідомлення.' + edited: '§aПовідомлення "§7{msg}§a" відредаговане.' + help: + addSound: '§6addSound <id> <sound>: §eДодати звук до повідомлення.' + clear: '§6clear: §eВидалити всі повідомлення.' + close: '§6close: §eПеревірити всі повідомлення.' + edit: '§6edit <id> <message>: §eРедагування повідомлення.' + header: '§6§lBeautyQuest - Довідник редактору діалогів' + list: '§6list: §eПереглянути всі повідомлення.' + nothing: '§6noSender <message>: §eДодати повідомлення без відправника.' + nothingInsert: '§6nothingInsert <id> <message>: §eВставте повідомлення без префікса.' + npc: '§6npc <message>: §eДодати повідомлення, написане NPC.' + npcInsert: '§6npcInsert <id> <message>: §eВставити повідомлення, яке буде сказано NPC.' + npcName: '§6npcName [користувальницьке ім''я NPC]: §eВстановити (або скинути за замовчуванням) користувацьке ім''я NPC у діалоговому вікні' + player: '§6player <message>: §eДодати повідомлення, написане гравцем.' + playerInsert: '§6playerInsert <id> <message>: §eВставте повідомлення сказане гравцем.' + remove: '§6remove <id>: §eВидалити повідомлення.' + setTime: '§6setTime <id> <time>: §eВстановіть час (у тіках) перед тим як автоматично буде написано наступне повідомлення.' + skippable: '§6skippable [true|false]: §eВстановити діалогове вікно можна пропустити чи ні' + messageRemoved: '§aПовідомлення "§7{msg}§a" видалено.' + noSender: '§aПовідомлення "§7{msg}§a" додано без відправника.' + npc: '§aПовідомлення "§7{msg}§a" додано для NPC.' + npcName: + set: '§aІм''я NPC встановлено на §7{new_name}§a (було §7{old_name}§a)' + unset: '§aІм''я NPC скинуто до стандартного (було §7{old_name}§a)' + player: '§aПовідомлення "§7{msg}§a" додано для гравця.' + skippable: + set: '§aМожливість пропустити діалог тепер встановлено на §7{new_state}§a (було §7{old_state}§a)' + unset: '§aМожливість пропуску діалогу скинуто до стандартного значення (було §7{old_state}§a)' + soundAdded: '§aЗвук "§7{sound}§a" додано для повідомлення: "§7{msg}§a".' + syntaxRemove: '§cПравильний синтаксис: remove <id>' + timeRemoved: '§aЧас було видалено для повідомлення {msg}.' + timeSet: '§aЧас було відредаговано для повідомлення {msg}: тепер {time} тіків.' + enter: + list: '§c⚠ §7Ви увійшли до редактора "списків". Для додавання рядків використовуйте "add". Перейдіть до довідки "help" (без слешу). §e§lНапишіть "close" для виходу з редактора.' + subtitle: '§6Напишіть "/quests exitEditor" щоб примусово вийти з редактора.' + title: '§6~ Режим Редактора ~' + firework: + edited: Змінено феєрверк квесту! + invalid: Цей предмет не є дійсним феєрверком. + invalidHand: Ви повинні тримати феєрверк у головній руці. + removed: Видалено феєрверк квесту! + goToLocation: '§aЙдіть до бажаного місця для етапу.' + invalidColor: Введено некоректний колір. Він має бути шістнадцятковим або RGB. + invalidPattern: '§cНевірний шаблон регулярного виразу §4{input}§c.' + itemCreator: + invalidBlockType: '§cНедійсний тип блока.' + invalidItemType: '§cНедійсний тип предмета. (Елемент не може бути блоком)' + itemAmount: '§aНапишіть кількість предметів:' + itemLore: '§aЗмінити опис предмета: (Напишіть "help" для допомоги)' + itemName: '§aНапишіть назву предмету:' + itemType: '§aНапишіть ім''я потрібного типу предмету:' + unknownBlockType: '&cНевідомий тип блоку' + unknownItemType: '§cНевідомий тип предмета.' + mythicmobs: + disabled: '§cMythicMob вимкнено.' + isntMythicMob: '§cЦього міфічного моба не існує.' + list: '§aСписок усіх міфічних мобів:' + noSuchElement: '§cНемає такого елемента. Дозволені елементи: §e{available_elements}' + npc: + choseStarter: '§aОберіть NPC, який почне завдання.' + enter: '§aНатисніть на NPC, або напишіть "cancel".' + notStarter: '§cЦей NPC — не починає квести.' + pool: + hologramText: Запишіть власний голограмний текст для цього пулу(або "null", якщо ви хочете використовувати стандартну). + maxQuests: Напишіть максимальну кількість квестів, дя запуску з цього пулу. + questsPerLaunch: Напишіть кількість квестів, отриманих коли гравці натискають на NPC. + timeMsg: 'Напишіть час КД перед повторним виконанням квесту гравцями (стандартна одиниця: дні)' + scoreboardObjectiveNotFound: '§cНевідомий об''єкт таблиці.' + selectWantedBlock: '§aНатисніть з паличкою на потрібному блоці для етапу.' + stage: + location: + typeWorldPattern: '§aНапишіть регулярний вираз для назв світів:' + text: + argNotSupported: '§cАргумент {arg} не підтримується.' + chooseJobRequired: '§aНапишіть ім''я потрібної роботи:' + chooseLvlRequired: '§aНапишіть необхідну кількість рівнів:' + chooseMoneyRequired: '§aНапишіть кількість необхідних грошей:' + chooseObjectiveRequired: '§aНапишіть ім''я цілі.' + chooseObjectiveTargetScore: '§aНапишіть кінцеву ціль для завдання.' + choosePermissionMessage: '§aВи можете вказати повідомлення про відхилення, якщо гравець не має обов''язкового дозволу. (Щоб пропустити цей крок, напишіть "null".)' + choosePermissionRequired: '§aНапишіть необхідні права, щоб розпочати квест:' + choosePlaceholderRequired: + identifier: '§aНапишіть ім''я потрібного заповнювача без відсоткових символів:' + value: '§aНапишіть необхідне значення для наповнювача §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aНапишіть назву потрібного регіону (ви повинні бути в одному світі).' + chooseSkillRequired: '§aНапишіть обов''язкові навички:' + reward: + money: '§aНапишіть кількість отриманих грошей:' + permissionName: '§aНапиши ім''я дозволу.' + permissionWorld: '§aНапишіть світ, в якому дозвіл буде відредаговано, або "null", якщо ви хочете застосувати глобально.' + random: + max: '§aНапишіть максимальну кількість нагород, що буде видано гравцю (включно).' + min: '§aНапишіть мінімальну кількість нагород, що буде видано гравцю (включно).' + wait: '§aНапиши кількість ігрових тіків для очікування: (1 секунда = 20 ігрових тіків)' + textList: + added: '§aТекст "§7{msg}§a" додано.' + help: + add: '§6add <message>: §eДодати текст.' + close: '§6close: §eПеревірити додані текста.' + header: '§6§lBeautyQuest— Перегляд довідки редактора' + list: '§6list: §eПереглянути всі додані тексти.' + remove: '§6remove <id>: §eВидалити текст.' + removed: '§aТекст "§7{msg}§a" видалено.' + syntax: '§cКоректний синтаксис: ' + title: + fadeIn: Запишіть тривалість "fade-in", в тіках (20 тіків = 1 секунду). + fadeOut: Запишіть тривалість "fade-out", в тіках (20 тіків = 1 секунда). + stay: Напишіть "stay" тривалість, в тіках (20 тіків = 1 секунда). + subtitle: Напишіть текст субтитрів (або «null», якщо ви не бажаєте). + title: Напишіть текст заголовку (або «null», якщо бажаєте вимкнути заголовок). + typeBucketAmount: '§aНапишіть кількість відер для заповнення:' + typeDamageAmount: 'Напишіть кількість дамагу, який повинен нанести гравець:' + typeGameTicks: '§aНапишіть кількість ігрових тіків:' + typeLocationRadius: '§aНапишіть потрібну відстань від місця розташування:' + errorOccurred: '§cСталася помилка, зв''яжіться з адміністратором! §4§lКод помилки: {error}' + experience: + edited: '§aВи змінили приріст досвіду від {old_xp_amount} до {xp_amount} очок.' + indexOutOfBounds: '§cЧисло {index} за межами діапазону! Воно повинна бути між {min} і {max}.' + invalidBlockData: '§cБлоки {block_data} є недійсними або несумісними з блоком {block_material}.' + invalidBlockTag: '§cНедоступний тег блоку {block_tag}.' + inventoryFull: '§cВаш інвентар повний, предмет був скинутий на підлогу.' + moveToTeleportPoint: '§aЙдіть до бажаного розташування телепорту.' + npcDoesntExist: '§cNPC з ідентифікатором {npc_id} не існує.' + number: + invalid: '§c{input} не є правильним числом.' + negative: '§cВи повинні ввести додатнє число!' + notInBounds: '§cВаш номер повинен бути від {min} до {max}.' + zero: '§cВи повинні ввести номер більший за 0!' + pools: + allCompleted: '§7Ви завершили всі квести!' + maxQuests: '§cВи не можете мати більше {pool_max_quests} квестів одночасно...' + noAvailable: '§7Більше немає доступних квестів...' + noTime: '§cВи повинні зачекати {time_left} перед виконанням іншого квесту.' + quest: + alreadyStarted: '§cВи вже почали квест!' + cancelling: '§cПроцес створення квесту скасовано.' + createCancelled: '§cСтворення або редагування було скасовано іншим плагіном!' + created: '§aПоздоровляємо! Ви створили квест §a{quest}§a що містить {quest_branches} гілку(-ок)!' + editCancelling: '§cПроцес редагування квесту скасовано.' + edited: '§aПоздоровляємо! Ви відредагували квест §a{quest}§a що містить {quest_branches} гілку(-ок)!' + finished: + base: '§aПоздоровляємо! Ви закінчили квест §e{quest_name}§a!' + obtain: '§aВи отримали {rewards}!' + invalidID: '§cКвест з ідентифікатором {quest_id} не існує.' + invalidPoolID: '§cПул {pool_id} не існує.' + notStarted: '§cНаразі ви не виконуєте цей квест.' + started: '§aВи почали квест §r§e{quest_name}§o§6!' + questItem: + craft: '§cВи не можете використати квестовий предмет, для крафту!' + drop: '§cВи не можете викинути квестовий предмет!' + eat: '§cВи не можете з''їсти квестовий предмет!' + quests: + checkpoint: '§7Досягнута контрольна точка квесту!' + failed: '§cВи провалили квест {quest_name}...' + maxLaunched: '§cВи не можете виконувати більше {quests_max_amount} квестів одночасно...' + updated: '§7Квест §e{quest_name}§7 оновлено.' + regionDoesntExists: '§cЦей регіон не існує. (Ви повинні бути в тому ж світі, що й регіон.)' + requirements: + combatLevel: '§cВаш рівень битви повинен бути {long_level}!' + job: '§cВаш рівень роботи§e{job_name}§c має бути {long_level}!' + level: '§cВаш рівень має бути {long_level}!' + money: '§aВи повинні мати {money}!' + quest: '§cВи повинні закінчити квест §e{quest_name}§c!' + skill: '§cВаш рівень вмінь §e{skill_name}§c має бути {long_level}!' + waitTime: '§cВи повинні зачекати {time_left} перед повторним виконанням цього квесту!' + restartServer: '§7Перезавантажте сервер, щоб застосувати зміни.' + selectNPCToKill: '§aВиберіть NPC, якого потрібно вбити.' + stageMobs: + listMobs: '§aВи повинні вбити {mobs}.' + typeCancel: '§aНапишіть "cancel", щоб повернутися до останнього тексту.' + versionRequired: 'Потрібна версія: §l{version}' + writeChatMessage: '§aНапишіть необхідне повідомлення: (Додайте "{SLASH}" на початку, якщо хочете вказати команду.)' + writeCommand: '§aВведіть потрібну команду: (Команда без "/" і заповнення"{PLAYER}" підтримується. Воно буде замінено ім''ям виконавця.)' + writeCommandDelay: '§aНапишіть бажану затримку команди, в тіках.' + writeConfirmMessage: '§aНапишіть повідомлення для підтвердження, яке гравець має написати, щоб запустити завдання: (Напишіть, "null", якщо ви хочете встановити повідомлення за замовчуванням.)' + writeDescriptionText: '§aНапишіть текст, що описує ціль стадії:' + writeEndMsg: '§aНапишіть повідомлення, яке буде відправлено в кінці завдання, "null" якщо ви хочете, щоб відправилось стандартне повідомлення, або "none", якщо ви не хочете відправляти жодного повідомлення. Ви можете використати "{rewards}", який буде замінено на нагороду.' + writeEndSound: '§aНапишіть назву звуку, який буде відтворюватись гравцю на прикінці квесту, "null", якщо ви хочете залишити стандартний, або "none" якщо не хочете вказувати:' + writeHologramText: '§aЗапишіть текст голограми: (Напишіть "none", якщо вам не потрібна голограма, або "null", якщо ви хочете звичайний текст.)' + writeMessage: '§aНапишіть повідомлення, яке буде відправлено гравцю' + writeMobAmount: '§aНапишіть кількість мобів, яких потрібно вбити:' + writeMobName: '§aНапишіть кастомне ім''я моба, якого потрібно вбити:' + writeNPCText: '§aНапишіть повідомлення, яке NPC буде казати гравцям: (Напишіть "help", щоб отримати допомогу.)' + writeNpcName: '§aНапишіть ім''я NPC:' + writeNpcSkinName: '§aНапишіть нік скіна для NPC:' + writeQuestDescription: '§aНапишіть опис завдання, який буде показано гравцю під час виконання.' + writeQuestMaterial: '§aНапишіть матеріали для квестових предметів.' + writeQuestName: '§aНапишіть назву свого квесту:' + writeQuestTimer: '§aНапишіть необхідний час (у хвилинах), для перепроходження квесту: (Напишіть "null", якщо ви хочете встановити таймер за замовчуванням.)' + writeRegionName: '§aНапишіть назву регіону потрібну для кроку:' + writeStageText: '§aНапишіть текст, який буде відправлено гравцю на початку стадії:' + writeStartMessage: '§aНапишіть повідомлення, яке буде відправлено на початку квесту, "null" якщо ви хочете залишити стандартне, або "none" якщо не хочете вказувати:' + writeXPGain: '§aНапишіть кількість досвіду, який отримає гравець: (Останнє значення: {xp_amount})' +scoreboard: + asyncEnd: '§ex' + name: '§6§lКвести' + noLaunched: '§cНемає квестів в процесі.' + noLaunchedDescription: '§c§oЗавантаження' + noLaunchedName: '§c§lЗавантаження' + stage: + breed: '§eРозмножте §6{mobs}' + bucket: '§eЗаповніть §6{buckets}' + chat: '§eНапишіть §6{text}' + craft: '§eСтворіть §6{items}' + dealDamage: + any: '§cЗавдати {damage_remaining} дамагу' + mobs: '§cЗавдати {damage_remaining} дамагу {target_mobs}' + die: '§cВмерти' + eatDrink: '§eСпожити §6{items}' + enchant: '§eЗачаруйте §6{items}' + fish: '§eРиба §6{items}' + interact: '§eНатисніть на блок на §6{x}' + interactMaterial: '§eНатисніть на §6{block}§e блок' + items: '§eПринесіть речі §6{dialog_npc_name}§e:' + location: '§eЙдіть до §6{target_x}§6{target_y}§, §6{target_z}§e в §6{target_world}' + melt: '§eПереплавте §6{items}' + mine: '§eВикопайте {blocks}' + mobs: '§eВбийте §6{mobs}' + npc: '§eПоговорити з NPC §6{dialog_npc_name}' + placeBlocks: '§6Розмістіть {blocks}' + playTimeFormatted: '§eГрайте §6{time_remaining_human}' + region: '§eЗнайти регіон §6{region_id}' + tame: '§eПриручіть §6{mobs}' + textBetwteenBranch: '§e або' diff --git a/core/src/main/resources/locales/vi_VN.yml b/core/src/main/resources/locales/vi_VN.yml index a33f1149..0b53ede0 100644 --- a/core/src/main/resources/locales/vi_VN.yml +++ b/core/src/main/resources/locales/vi_VN.yml @@ -1,810 +1,763 @@ --- -msg: - quest: - finished: - base: '§aChúc mừng! Bạn đã hoàn thành nhiệm vụ §e{0}§a!' - obtain: '§aBạn nhận được &e{0}!' - started: '§aBạn đã bắt đầu quest §r§e{0}§o§6!' - created: '§aXin chúc mừng! Bạn đã chỉnh sửa nhiệm vụ §e{0}§a với {1} giai đoạn!' - edited: '§aXin chúc mừng! Bạn đã chỉnh sửa nhiệm vụ §e{0}§a bảo gồm {1} giai đoạn!' - createCancelled: '§cViệc tạo hoặc chỉnh sửa đã bị hủy bởi một plugin khác!' - cancelling: '§cQuá trình tạo nhiệm vụ đã bị hủy.' - editCancelling: '§cQuy trình của phiên bản nhiệm vụ bị hủy.' - invalidID: '§cNhiệm vụ với id {0} không tồn tại.' - invalidPoolID: '§cDòng {0} không tồn tại' - alreadyStarted: '§cNhiệm vụ này đã được bắt đầu!' - quests: - maxLaunched: '§cBạn không thể làm nhiềm hơn {0} nhiệm vụ cùng một lúc...' - nopStep: '§cNhiệm vụ này không có yêu cầu nào.' - updated: '§7Đã cập nhật quest §e{0}§7.' - checkpoint: '§7Đã đạt đến điểm kiểm tra nhiệm vụ!' - failed: '§cBạn đã thất bại trong nhiệm vụ {0}...' - pools: - noTime: '§cBạn phải chờ {0} trước khi làm nhiệm vụ khác' - allCompleted: '§7Bạn đã hoàn thành tất cả nhiệm vụ!' - noAvailable: '§7Không có nhiệm vụ nào tồn tại' - maxQuests: '§cBạn không thể làm nhiều hơn {0} nhiệm vụ cùng một lúc...' - questItem: - drop: '§cBạn không thể làm rớt vật phẩm nhiệm vụ!' - craft: '§cBạn không thể dùng vật phẩm nhiệm vụ để chế tạo!' - eat: '§cBạn không thể ăn vật phẩm nhiệm vụ!' - stageMobs: - noMobs: '§cGiai đoạn này không cần giết quái nào.' - listMobs: '§aBạn phải giết {0}.' - writeNPCText: '§aViết hộp thoại mà NPC sẽ nói với người chơi: (Viết "help" để nhận được sự giúp đỡ.)' - writeRegionName: '§aViết tên của khu vực cần thiết cho giai đoạn tiếp theo:' - writeXPGain: '§aViết số điểm kinh nghiệm mà người chơi sẽ nhận được: (Giá trị cuối cùng: {0})' - writeMobAmount: '§aViết số lượng mob cần tiêu diệt:' - writeMobName: '§aViết tên của mobs phải giết' - writeChatMessage: '§aViết tin nhắn bắt buộc: (Thêm "/" ngay từ đầu nếu bạn muốn một lệnh.)' - writeMessage: '§aViết tin nhắn sẽ gửi đến người chơi' - writeStartMessage: '§aViết thông báo sẽ gửi khi bắt đầu nhiệm vụ, "null" nếu bạn muốn là 1 thông báo bình thường hoặc "none" nếu bạn không muốn' - writeEndMsg: '§aViết tin nhắn sẽ gửi khi nhiệm vụ kết thúc, "null" nếu bạn muốn một cái bình thường hoặc "none" nếu bạn không muốn gì hết. Bạn cso thể dùng "{0}" để thay thể với thông báo phần thưởng' - writeEndSound: '§aGhi tên của âm thanh sẽ được phát cho người chơi khi nhiệm vụ kết thúc, "null" nếu bạn muốn dùng cái mặc định hoặc "none" nếu bạn muốn không:' - writeDescriptionText: '§aViết văn bản mô tả mục tiêu của giai đoạn:' - writeStageText: '§aViết văn bản sẽ được gửi đến người chơi lúc đầu của giai đoạn:' - moveToTeleportPoint: '§aĐi đến địa điểm muốn đến.' - writeNpcName: '§aViết tên của NPC:' - writeNpcSkinName: '§aTên skin của NPC:' - writeQuestName: '§aTên của nhiệm vụ:' - writeCommand: '§aViết lệnh yêu cầu: (Lệnh không có dấu "/" và placeholder "{PLAYER}" được hỗ trợ. Nó sẽ được thay thế bằng tên của người thi hành.)' - writeHologramText: '§aViết văn bản của holographic display: (Viết "non" nếu bạn không muốn một holographic display và "null" nếu bạn muốn văn bản mặc định.)' - writeQuestTimer: '§aViết thời gian cần thiết (tính bằng phút) trước khi bạn có thể khởi động lại nhiệm vụ: (Viết "null" nếu bạn muốn bộ đếm thời gian mặc định.) ' - writeConfirmMessage: '§aViết thông báo xác nhận được hiển thị khi một người chơi để bắt đầu nhiệm vụ: (Viết "null" nếu bạn muốn thông báo mặc định.)' - writeQuestDescription: '§aViết mô tả về nhiệm vụ, hiển thị trong gui nhận nhiệm vụ.' - writeQuestMaterial: '§aViết vật liệu của item nhiệm vụ.' - requirements: - quest: '§cBạn chưa hoàn thành nhiệm vụ §e{0}§c!' - level: '§cCấp độ bạn phải ở {0}!' - job: '§cCấp độ nghề nghiệp §e{1}§c phải đạt cấp {0}!' - skill: '§cCấp độ kĩ năng §e{1}§c phải đạt cấp {0}!' - combatLevel: '§cCấp độ đánh nhau của bạn phải đạt {0}!' - money: '§cBạn phải có {0}!' - waitTime: '§cBạn phải chờ {0} trước khi làm lại nhiệm vụ!' - experience: - edited: '§aBạn nhận được kinh nghiệm từ nhiệm vụ {0} với {1} điểm.' - selectNPCToKill: '§aChọn NPC để tiêu diệt.' - npc: - remove: '§aXóa NPC.' - talk: '§aĐi tìm và nói chuyện với NPC §e{0}§a.' - regionDoesntExists: '§cKhu vực này không tồn tại. (Bạn phải ở trong cùng một thế giới.)' - npcDoesntExist: '§cNPC với id {0} không tồn tại.' - objectDoesntExist: '§cMục được chỉ định với id {0} không tồn tại.' - number: - negative: '§cBạn phải nhập một số dương!' - zero: '§cBạn phải nhập một số khác với 0!' - invalid: '§c{0} không phải là con số.' - notInBounds: '§cSố của bạn phải nằm ở giữa {0} và {1}.' - errorOccurred: '§cĐã xảy ra lỗi, hãy liên hệ với quản trị viên! §4§lMã lỗi: {0}' - commandsDisabled: '§cHiện tại bạn không được phép thực hiện lệnhs!' - indexOutOfBounds: '§cSố {0} nằm ngoài giới hạn! Nó phải nằm trong khoảng từ {1} đến {2}.' - invalidBlockData: '§cDữ liệu khối {0} không hợp lệ hoặc không tương thích với khối {1}.' - invalidBlockTag: '§cBlock tag không tồn tại {0}' - bringBackObjects: Giao cho tôi {0}. - inventoryFull: '§cTúi đồ của bạn đã đầy, vật phẩm đã bị rơi xuống sàn.' - playerNeverConnected: '§cKhông thể tìm thấy thông tin về người chơi {0}.' - playerNotOnline: '§cNgười chơi {0} đang ngoại tuyến.' - playerDataNotFound: '§aDữ liệu người chơi {0} không tồn tại' - versionRequired: 'Phiên bản yêu cầu: §l{0}' - restartServer: '§7Khởi động lại máy chủ để thấy sửa đổi' - dialogs: - skipped: '§8§oLời thoại được bỏ qua' - tooFar: '§7§oBạn đang ở quá xa {0}...' - command: - downloadTranslations: - syntax: '§cBạn cần phải tải file ngôn ngữ. Ví dụ: "/quests downloadTranslations vi_VN"' - notFound: '§cNgôn ngữ {0} không tìm thấy cho phiên bản {1}' - exists: '§cFile {0} đã tồn tại, Nối "true" vào lệnh của bạn để ghi đè nó. (/quests downlaodTranslations <lang> true)' - downloaded: '§aNgôn ngữ {0} đã được tải! §7Bạn cần chỉnh sửa file config.yml, đổi §ominecraftTranslationsFile§7 với {0}, sau đó khởi động lại máy chủ.' - checkpoint: - noCheckpoint: '§cKhông tìm thấy trạm kiểm soát nào cho nhiệm vụ {0}.' - questNotStarted: '§cBạn không làm nhiệm vụ này.' - setStage: - branchDoesntExist: '§cNhánh có id {0} không tồn tại.' - doesntExist: '§cGia đoạn có id {0} không tồn tại.' - next: '§aGiai đoạn đã bị bỏ qua.' - nextUnavailable: '§cTùy chọn "skip" không khả dụng khi người chơi ở phần cuối của một nhánh.' - set: '§aGiai đoạn {0} được khởi chạy.' - startDialog: - impossible: '§cKhông thể bắt đầu lời thoại trong lúc này' - noDialog: '§cNgười chơi không có lời thoại nào đang chờ' - alreadyIn: '§cNgười chơi đang có cuộc hội thoại' - success: '§aBắt đầu cuộc hội thoại cho người chơi {0} ở nhiệm vụ {1}' - playerNeeded: '§cBạn phải là người chơi để thực hiện lệnh này!' - incorrectSyntax: '§cCú pháp không chính xác.' - noPermission: '§cBạn không có đủ quyền để thực hiện lệnh này! (Cần thiết: {0})' - invalidCommand: - quests: '§cLệnh này không tồn tại, hãy viết §e/quests help§c.' - simple: '§cLệnh này không tồn tại, hãy viết §ehelp§c.' - needItem: '§cBạn phải cầm một món đồ trong tay chính của mình!' - itemChanged: '§aMục đã được chỉnh sửa. Các thay đổi sẽ ảnh hưởng sau khi khởi động lại.' - itemRemoved: '§aMục ảnh ba chiều đã bị xóa.' - removed: '§aNhiệm vụ {0} đã được xóa thành công.' - leaveAll: '§aBạn đã buộc phải kết thúc {0} nhiệm vụ. Lỗi: {1}' - resetPlayer: - player: '§6Tất cả thông tin nhiệm vụ của bạn (bao gồm {0} nhiệm vụ) đã bị xóa bởi {1}' - remover: '§6{0} quest information(s) of {1} has/have been deleted.' - resetPlayerQuest: - player: '§6Tất cả thông tin về nhiệm vụ {0} của bạn đã bị xóa bởi {1}' - remover: '§6Các thông tin nhiệm vụ {0} đã bị {1} xóa' - resetQuest: '§6Xóa toàn bộ dữ liệu nhiệm vụ của {0} người chơi' - startQuest: '§6Bạn đã buộc phải bắt đầu nhiệm vụ {0} (UUID của người chơi: {1}).' - startQuestNoRequirements: '§cNgười chơi không đủ điều kiện đề làm nhiệm vụ {0}.... Nối tiếp "true" ở cuối câu lệnh để vượt qua kiểm tra điều kiện' - cancelQuest: '§6Bạn đã thoát khởi nhiệm vụ {0}' - cancelQuestUnavailable: '§6Không thể thoát khỏi nhiệm vụ {0}' - backupCreated: '§6Bạn đã tạo thành công file backup toàn bộ thông tin nhiệm vụ và thông tin người chơi' - backupPlayersFailed: '§cTạo backup cho toàn bộ thông tin người chơi thất bại' - backupQuestsFailed: '§cTạo backup cho toàn bộ nhiệm vụ thất bại' - adminModeEntered: '§aBạn đã kích hoạt chế độ admin' - adminModeLeft: '§aBạn đã thoát khỏi chế độ admin' - resetPlayerPool: - timer: '§aBạn đã đặt lại {0} bộ hẹn giờ của {1}.' - full: '§aBạn đã đặt lại {0} dữ liệu của {1}.' - scoreboard: - lineSet: '§6Bạn đã chỉnh sửa thành công dòng {0}' - lineReset: '§6Bạn đã loại cài lại dòng {0}' - lineRemoved: '§6Bạn đã loại bỏ dòng {0} thành công' - lineInexistant: '§cDòng {0} không tồn tại' - resetAll: '§6Bạn đã đặt lại bảng nhiệm vụ của người chơi {0}' - hidden: '§6Bảng nhiệm vụ của người chơi {0} đã bị ẩn' - shown: '§6Bảng nhiệm vụ của người chơi {0} đã được đặt lại' - own: - hidden: '§6Bảng thông tin của bạn hiện tại đã bị ẩn.' - shown: '§6Bảng thông tin của bạn hiện đã được hiển thị lại.' - help: - header: '§6§lBeautyQuest - Help' - create: '§6/{0} create: §eTạo nhiệm vụ mới' - edit: '§6/{0} edit: §eChỉnh sửa nhiệm vụ' - remove: '§6/{0} remove <id nhiệm vụ>: §eXóa nhiệm vụ với id của nó hoặc click vào NPC khi chưa xác định' - finishAll: '§6/{0} fisnishAll <tên người chơi>: §e Hoàn thành tất cả nhiệm vụ mà người chơi đó đang nhận' - setStage: '§6/{0} setStage <tên người chơi> <id nhiệm vụ> [nhánh nhiệm vụ mới] [giai đoạn mới]: §eBỏ qua giai đoạn hiện tại để bắt đầu một nhanh nhiệm vụ mới' - startDialog: '§6/{0} startDialog <Người chơi> <Mã nhiệm vụ>: §eBắt đầu hộp thoại đang chờ xử lý cho một giai đoạn của NPC hoặc hộp thoại bắt đầu cho một nhiệm vụ.' - resetPlayer: '§6/{0} resetPlayer <tên người chơi>: §eXóa toàn bộ thông tin người chơi' - resetPlayerQuest: '§6/{0} resetPlayerQuest <tên người chơi> [id nhiệm vụ] §eXóa thông tin nhiệm vụ từ người chơi' - seePlayer: '§6/{0} seePlayer <player>: §eXem thông tin của người chơi' - reload: '§6/{0} reload : §eLưu và tải lại tất cả mọi thứ §c(Lệnh này có thể mang lại lỗi cho máy chủ bạn đến 99.9% nên hãy restart lại máy chủ)' - start: '§6/{0} start <tên người chơi> [id nhiệm vụ]:§e Bắt buộc người chơi bắt đầu nhiệm vụ' - setItem: '§6/{0} setItem <talk|laucher>:§e Lưu vật phẩm hologram' - setFirework: '§6/{0} setFirework: §eChỉnh sửa pháo hoa mặc định lúc kết thúc.' - adminMode: '§6/{0} adminMode:§e Bật/tắt chế độ admin (Nó khá hữu dụng cho hiện một vài thông tin log)' - version: '§6/{0} version: §eKiểm tra phiên bản của plugins' - downloadTranslations: '§6/{0} downloadTranslations <Ngôn ngữ>: §eTải xuống một tệp bản dịch vanilla' - save: '§6/{0} save: §eLưu plugins cách thủ công' - list: '§6/{0} list:§e Xem tất cả các nhiệm vụ (Chỉ cho phiên bản được hỗ trợ)' - typeCancel: '§aGõ "cancel" để trở lại dòng tin nhắn cuối cùng' - editor: - blockAmount: '§aViết số lượng khối' - blockName: '§aViết tên của khối' - blockData: '§aViết blockdata (blockdatas có sẵn: {0}):' - blockTag: '§aViết blockdata (blockdatas có sẵn: {0}):' - typeBucketAmount: '§aViết số lượng xô nước cần làm đầy' - goToLocation: '§aĐi đến vị trí muốn đến cho giai đoạn' - typeLocationRadius: '§aViết yêu cầu tầm xa từ vị trí đã đặt' - typeGameTicks: '§aViết các dấu tích trò chơi cần thiết:' - already: '§cBạn đã ở sẵn trong chế độ chỉnh sửa' - stage: - location: - typeWorldPattern: '§aViết regex cho tên của các thế giới:' - enter: - title: '§6- Chế Độ Chỉnh Sửa -' - subtitle: '§6Dùng "/quests exitEditor" để cưỡng chế thoát.' - list: '§c⚠ §7Bạn đã nhập trình chỉnh sửa "list". Dùng "add" để thêm dòng. Hãy tham khảo "help" (với không dấu gạch chéo) để được trợ giúp. §e§lNhập "close" để thoát khỏi trình chỉnh sửa.' - chat: '§6Bạn đang ở trong chế độ chỉnh sửa. Dùng "/quests exitEditor" để cưỡng chế thoát. (Không khuyết khích, thay vào đó hãy dùng "close" hoặc "cancel" để trở lại.)' - npc: - enter: '§aNhấn vào NPC, hoặc gõ "cancel"' - choseStarter: '§aChọn NPC để bắt đầu nhiệm vụ' - notStarter: '§cNPC này không phải NPC Nhiệm Vụ' - text: - argNotSupported: '§c{0} không được hỗ trợ' - chooseLvlRequired: '§aViết yêu cầu cấp độ của bạn' - chooseJobRequired: '§aViết tên công việc muốn:' - choosePermissionRequired: '§aViết yêu cầu quyền để bắt đầu nhiệm vụ' - choosePermissionMessage: '§aBạn có thể chọn thông báo từ chối nếu người chơi không có quyền cần thiết. (Để bỏ qua bước này, hãy viết "null".)' - choosePlaceholderRequired: - identifier: '§aViết tên của placeholder mà không có ký tự phần trăm:' - value: '§aViết yêu cầu placeholder §e%§e{0}§e%§a:' - chooseSkillRequired: '§aViết tên kĩ năng yêu cầu' - chooseMoneyRequired: '§aViết số tiền yêu cầu' - reward: - permissionName: '§aViết tên quyền' - permissionWorld: '§aViết thế giới trong đó quyền sẽ được chỉnh sửa hoặc "null" nếu bạn muốn là toàn cầu.' - money: '§aViết số tiền sẽ nhận được' - wait: '§aViết thời gian game để chờ: (1 giây = 20 game ticks)' - random: - min: '§aViết số lượng tối thiểu của phần thưởng được gửi tới người chơi (bao gồm).' - max: '§aViết số lượng tối đa của phần thưởng được gửi tới người chơi (bao gồm).' - chooseObjectiveRequired: '§aViết tên dự án.' - chooseObjectiveTargetScore: '§aGhi điểm mục tiêu cho vật (Target Score For The Objective).' - chooseRegionRequired: '§aViết tên yêu cầu của khu vực (Bạn phải ở cùng 1 thế giới)' - selectWantedBlock: '§aNhấn với cây gậy đến khối mong muốn cho giai đoạn tiếp theo' - itemCreator: - itemType: '§aViết loại vật phẩm yêu cầu' - itemAmount: "§aViết số lượng vật phẩm\n" - itemName: '§aViết tên của vật phẩm:' - itemLore: '§aViết lore vật phẩm (Viết "help" để nhận sự giúp đỡ)' - unknownItemType: '§cLoại vật phẩm không rõ' - invalidItemType: '§cLoại vật phẩm không rõ' - unknownBlockType: '§aLoại khối không rõ' - invalidBlockType: '§aLoại khối không hợp lệ' - dialog: - syntax: '§cĐúng cú pháp: {0}{1} <tin nhắn>' - syntaxRemove: '§cĐúng cú pháp: remove <mã id>' - player: '§aTin nhắn "{0}" đã thêm vào cho người chơi' - npc: '§aThêm tin nhắn "{0}" vào cho NPC' - noSender: '§aTin nhắn "{0}" đã thêm nhưng không có thông tin người gửi' - messageRemoved: '§aLoại bỏ tin nhắn "{0}"' - edited: '§aChỉnh sửa tin nhắn "{0}"' - soundAdded: '§aÂm thanh "{0}" đã thêm vào cho "{1}"' - cleared: '§aLoại bỏ tin nhắn {0}' - help: - header: '§6§lBeautyQuests - Giúp đỡ chỉnh sửa đoạn hội thoại' - npc: '§6npc <tin nhắn>: §eThêm tin nhắn được nói bởi NPC' - player: '§6player <tin nhắn>: §eThêm tin nhắn được nói bởi người chơi' - nothing: '§6noSender <tin nhắn>: §eThêm tin nhắn với không có thông tin người gửi' - remove: '§6remove <mã id>: §eLoại bỏ tin nhắn' - list: '§6list: §eXem tất cả tin nhắn' - npcInsert: '§6playerInsert <id> <message>: §eThêm một tin nhắn cho NPC nói.' - playerInsert: '§6playerInsert <id> <message>: §eThêm một tin nhắn cho người chơi nói.' - nothingInsert: '§6nothingInsert <id> <message>: §eThêm một tin nhắn với không có chủ ngữ.' - edit: 'Chỉnh sửa tin nhắn' - addSound: '§6addSound <id> <sound>: §eThêm âm thanh khi tin nhắn hiển thị.' - clear: '§6clear: §eXóa toàn bộ tin nhắn.' - close: '§6Đóng: §eXác thực tất cả tin nhắn.' - setTime: '§6setTime <Mã> <Thời gian>: §eĐặt tốc độ (trong ticks) trước tin nhắn tiếp theo được phát tự động.' - npcName: '§6npcName [Tên NPC tùy chỉnh]: §eĐặt (hoặc đặt lại về mặc định) tên tùy chỉnh của NPC trong hộp thoại.' - skippable: '§6skippable [true|false]: §eĐặt hộp thoại có thể được bỏ qua hay không' - timeSet: '§aThời gian đã được chỉnh sửa cho tin nhắn {0}: hiện tại là {1} ticks.' - timeRemoved: '§aThời gian đã được xóa cho tin nhắn {0}.' - npcName: - set: '§aTên NPC tùy chỉnh đã được đặt thành §7{1}§a (trước đó là §7{0}§a)' - unset: '§aCustom NPC đã được đổi tên về mặc định (§7{0}§a)' - skippable: - set: '§eTrạng thái bỏ qua hộp thoại hiện tại đã được đặt thành §7{1}§a (trước đó là §7{0}§a)' - unset: '§aTrạng thái bỏ qua hộp thoại hiện đã được đặt về mặc định (trước đó là §7{0}§a)' - mythicmobs: - list: '§aDanh sách tất cả Mythic Mobs:' - isntMythicMob: '§cMythic Mob không tồn tại.' - disabled: '§cMythicMob đã tắt' - epicBossDoesntExist: '§cEpic Boss không tồn tại.' - textList: - syntax: '§cCú pháp chính xác: ' - added: '§aĐã thêm vào văn bản "§7{0}§a"' - removed: '§aĐã loại bỏ văn bản "§7{0}§a"' - help: - header: '§6§lBeautyQuests - Giúp đỡ chỉnh sửa đoạn hội thoại' - add: '§6add <Tin nhắn>: §eThêm một văn bản.' - remove: '§6remove <Mã>: §eLoại bỏ một văn bản.' - list: '§6list: §eXem tất cả văn bản đã thêm.' - close: '§6close: §eKiểm tra chữ đã thêm.' - availableElements: 'Đối tượng khả dụng: §e{0}' - noSuchElement: '§cKhông tồn tại. Phần hợp lệ chỉ có: §e{0}' - invalidPattern: '§cMẫu regex không hợp lệ §4{0}§c.' - comparisonTypeDefault: '§aChọn kiểu bạn muốn: {0}. Mặc định là: §e§l{1}§r§a. Gõ §onull§r§a để sử dụng.' - scoreboardObjectiveNotFound: '§cKhông rõ scoreboard' - pool: - hologramText: 'Viết Hologram tùy chỉnh cho Pool này (hoặc gõ "null" nếu bạn muốn sử dụng loại mặc định)' - maxQuests: 'Viết số lượng nhiệm vụ tối đa có thể khởi chạy cho Pool này.' - questsPerLaunch: 'Viết số lượng nhiệm vụ được giao khi click vào NPC.' - timeMsg: 'Viết thời gian trước khi người chơi có thể nhận một nhiệm vụ mới. (đơn vị: days).' - title: - title: 'Thêm một tiêu đề (để "null" nếu bạn muốn để trống)' - subtitle: 'Thêm một phụ đề (để "null" nếu bạn muốn để trống)' - fadeIn: 'Viết thời gian "fade-in", đơn vị: Ticks (20 ticks = 1 giây)' - stay: 'Viết thời gian "stay", đơn vị: Ticks (20 ticks = 1 giây).' - fadeOut: 'Viết thời gian "fade-out", đơn vị: Ticks (20 ticks = 1 giây).' - colorNamed: 'Nhập tên của màu' - color: 'Nhập định dạng màu. Định dạng Hexadecimal (#XXXXX) hoặc định dạng RGB (RED GRE BLU).' - invalidColor: 'Định dạng màu bạn nhập không hợp lệ. Bắt buộc phải là định dạng Hexadecimal hoặc RGB.' - firework: - invalid: 'Pháo hoa này không hợp lệ.' - invalidHand: 'Bạn phải cầm pháo ra ở tay chính.' - edited: 'Đã chỉnh sửa Quest Firework thành công!' - removed: 'Đã xóa Quest Firework thành công!' - writeCommandDelay: '§aViết độ trễ của lệnh. Đơn vị: Ticks.' advancement: finished: Đã Hoàn Thành notStarted: Chưa bắt đầu +description: + requirement: + combatLevel: Cấp độ đánh nhau {short_level} + jobLevel: Cấp {short_level} cho {job_name} + level: Cấp {short_level} + quest: Hoàn thành nhiệm vụ §e{quest_name} + skillLevel: Cấp {short_level} cho {skill_name} + title: '§8§lYêu cầu:' + reward: + title: '§8§lPhần thưởng:' +indication: + cancelQuest: '§7Bạn có chắc chắn muốn hủy nhiệm vụ này {quest_name}?' + closeInventory: '§7Bạn có chắc bạn muốn đóng GUI?' + removeQuest: '§7Bạn có chắc chắn muốn xóa nhiệm vụ này {quest}?' + startQuest: '§7Bạn có muốn bắt đầu nhiệm vụ {quest_name}?' inv: - validate: '§b§lXác nhận' - cancel: '§c§lHủy bỏ' - search: '§e§lTìm Kiếm' addObject: '§aThêm một dự án' + block: + blockData: '§bDữ liệu khối (nâng cao)' + blockTag: '§dThẻ (nâng cao)' + blockTagLore: Chọn thẻ mô tả danh sách các khối khả dụng. Các thẻ có thể tùy chỉnh bằng gói dữ liệu. Bạn có thể tìm thấy danh sách thẻ trên Minecraft wiki. + material: '§eVật phẩm: {block_type}' + materialNotItemLore: Khối được chọn không thể hiển thị như là một vật phẩm. Nó vẫn có thể lưu trữ như một {block_material}. + name: Chọn khối + blockAction: + location: '§eChọn vị trí chỉnh xác' + material: '§eChọn một khối' + name: Chọn hành động khối + blocksList: + addBlock: '§aẤn vào để thêm một khối' + name: Chọn khối + buckets: + name: Loại xô + cancel: '§c§lHủy bỏ' + cancelActions: + name: Hủy bỏ hành động + checkpointActions: + name: Thiết lập checkpoint + chooseAccount: + name: Tài khoản nào? + chooseQuest: + menu: '§aMenu Nhiệm vụ' + menuLore: Đưa bạn đến Menu Nhiệm vụ của bạn. + name: Nhiệm vụ nào? + classesList.name: Danh sách class + classesRequired.name: Class yêu cầu + command: + console: Console + delay: '§bThời gian chờ' + name: Lệnh + parse: Phân tích placeholder + value: '§eLệnh' + commandsList: + name: Danh sách lệnh + value: '§eLệnh: {command_label}' confirm: name: Bạn có chắc chắn?? - 'yes': '§aXác Nhận' 'no': '§cThoát' + 'yes': '§aXác Nhận' create: - stageCreate: '§aTạo giai đoạn mới' - stageRemove: '§cXóa giai đoạn này' - stageUp: Lên - stageDown: Xuống - stageType: '§7Loại giai đoạn: §e{0}' + NPCSelect: '§eChọn hoặc tạo NPC' + NPCText: '§eChỉnh sửa cuộc hội thoại' + breedAnimals: '§aLàm no động vật' + bringBack: '§aMang 1 vật phẩm trả lại !' + bucket: '§aLàm đầy cái xô' + cancelMessage: Hủy bỏ gửi cantFinish: '§7Bạn phải tạo ít nhất một giai đoạn trước khi hoàn thành tạo nhiệm vụ!' + changeEntityType: '§eThay đổi loại quái' + changeTicksRequired: '§eChỉnh sửa yêu cầu thời gian đã chơi (ticks)' + craft: '§aChế tạo vật phẩm' + currentRadius: '§ePhạm vi hiện tại: §6{radius}' + death: '§cChết' + eatDrink: '§aĂn thức ăn hoặc uống thuốc' + editBlocksMine: '§eChỉnh block để đào' + editBlocksPlace: '§eChỉnh block để đặt' + editBucketAmount: '§eChỉnh sửa số lượng xô làm đầy' + editBucketType: '§eChỉnh sửa loại xô muốn làm đầy' + editFishes: '§eChỉnh sửa cá muốn bắt' + editItem: '§eChỉnh sửa vật phẩm muốn chế tạo' + editItemsToEnchant: '§eChỉnh sửa vật phẩm muốn cường hóa' + editItemsToMelt: '§eChỉnh sửa vật phẩm muốn nung' + editLocation: '§eChỉnh sửa địa điểm' + editMessageType: '§eChỉnh tin nhắn để viết' + editMobsKill: '§eChỉnh sửa mobs bị tiêu diệt' + editRadius: '§eChỉnh sửa phạm vi từ vị trí' + enchant: '§dVật phẩm cường hóa' findNPC: '§aTìm NPC' - bringBack: '§aMang 1 vật phẩm trả lại !' findRegion: '§aTìm khu vực' + fish: '§aBắt cá' + hideClues: Ẩn particles và holograms + ignoreCase: Bỏ qua trường hợp tin nhắn + interact: '§aTương tác với khối' killMobs: '§aGiết quái' + leftClick: Nhấn phải bằng chuột trái + location: '§aĐến địa điểm' + melt: '§6Vật phẩm tan chảy' mineBlocks: '§aPhá khối' + mobsKillFromAFar: Cần phải tiêu diệt bằng vật thể bay (VD:Mũi tên, cầu tuyết, trứng, ...) placeBlocks: '§aĐặt khối' - talkChat: '§aNhắn tin trên thanh trò chuyện' - interact: '§aTương tác với khối' - fish: '§aBắt cá' - melt: '§6Vật phẩm tan chảy' - enchant: '§dVật phẩm cường hóa' - craft: '§aChế tạo vật phẩm' - bucket: '§aLàm đầy cái xô' - location: '§aĐến địa điểm' playTime: '§aThời gian chơi' - breedAnimals: '§aLàm no động vật' - tameAnimals: '§aThuần phục động vật' - death: '§cChết' - NPCText: '§eChỉnh sửa cuộc hội thoại' - dialogLines: '{0} dòng' - NPCSelect: '§eChọn hoặc tạo NPC' - hideClues: Ẩn particles và holograms - gps: Hiện thị la bàn hướng tới mục tiêu - editMobsKill: '§eChỉnh sửa mobs bị tiêu diệt' - mobsKillFromAFar: Cần phải tiêu diệt bằng vật thể bay (VD:Mũi tên, cầu tuyết, trứng, ...) - editBlocksMine: '§eChỉnh block để đào' preventBlockPlace: Ngăn người chơi phá block của họ - editBlocksPlace: '§eChỉnh block để đặt' - editMessageType: '§eChỉnh tin nhắn để viết' - cancelMessage: Hủy bỏ gửi - ignoreCase: Bỏ qua trường hợp tin nhắn replacePlaceholders: Thay thế {PLAYER} and placeholder từ PAPI + selectBlockLocation: '§eChọn vị trí khối' + selectBlockMaterial: '§Chọn khối' selectItems: '§eChỉnh sửa yêu cầu vật phẩm' - selectItemsMessage: '§eChỉnh sửa thông báo bắt đầu' selectItemsComparisons: '§eChọn vật phẩm so sánh (NÂNG CAO)' + selectItemsMessage: '§eChỉnh sửa thông báo bắt đầu' selectRegion: '§7Chọn khu vực' - toggleRegionExit: Khi kết thúc nhiệm vụ - stageStartMsg: '§eChỉnh sửa thông báo khi bắt đầu' - selectBlockLocation: '§eChọn vị trí khối' - selectBlockMaterial: '§Chọn khối' - leftClick: Nhấn phải bằng chuột trái - editFishes: '§eChỉnh sửa cá muốn bắt' - editItemsToMelt: '§eChỉnh sửa vật phẩm muốn nung' - editItemsToEnchant: '§eChỉnh sửa vật phẩm muốn cường hóa' - editItem: '§eChỉnh sửa vật phẩm muốn chế tạo' - editBucketType: '§eChỉnh sửa loại xô muốn làm đầy' - editBucketAmount: '§eChỉnh sửa số lượng xô làm đầy' - editLocation: '§eChỉnh sửa địa điểm' - editRadius: '§eChỉnh sửa phạm vi từ vị trí' - currentRadius: '§ePhạm vi hiện tại: §6{0}' - changeTicksRequired: '§eChỉnh sửa yêu cầu thời gian đã chơi (ticks)' - changeEntityType: '§eThay đổi loại quái' stage: - location: - worldPattern: '§aChỉnh sửa tên thế giới §d(NÂNG CAO)' - worldPatternLore: 'Nếu bạn muốn giai đoạn hoàn thành ở bất kì thế giới nào với một mẫu cụ thể, nhập một regex (mẫu regex) ở đây.' death: - causes: '§aĐặt nguyên nhân chết §d(NÂNG CAO)' anyCause: Bất kì nguyên nhân chết nào - setCauses: '{0} nguyên nhân chết' - stages: - name: Tạo giai đoạn mới - nextPage: '§eTrang tiếp theo' - laterPage: '§eTrang trước' - endingItem: '§eChỉnh sửa phần thưởng kết thúc' - descriptionTextItem: '§eChỉnh sửa mô tả' - regularPage: '§aCác giai đoạn thông thường' - branchesPage: '§dCác nhánh giai đoạn' - previousBranch: '§eTrở lại nhánh trước đó' - newBranch: '§eĐến nhánh mới' - validationRequirements: '§eCác yêu cầu cần xác nhận' - validationRequirementsLore: Tất cả các yêu cầu phải phù hợp với người chơi hoàn thành giai đoạn. Nếu không giai đoạn không thể hoàn thành. + causes: '§aĐặt nguyên nhân chết §d(NÂNG CAO)' + setCauses: '{causes_amount} nguyên nhân chết' + location: + worldPattern: '§aChỉnh sửa tên thế giới §d(NÂNG CAO)' + worldPatternLore: Nếu bạn muốn giai đoạn hoàn thành ở bất kì thế giới nào với một mẫu cụ thể, nhập một regex (mẫu regex) ở đây. + stageCreate: '§aTạo giai đoạn mới' + stageDown: Xuống + stageRemove: '§cXóa giai đoạn này' + stageStartMsg: '§eChỉnh sửa thông báo khi bắt đầu' + stageType: '§7Loại giai đoạn: §e{stage_type}' + stageUp: Lên + talkChat: '§aNhắn tin trên thanh trò chuyện' + tameAnimals: '§aThuần phục động vật' + toggleRegionExit: Khi kết thúc nhiệm vụ + damageCause: + name: Nguyên nhân thiệt hại + damageCausesList: + name: Danh sách nguyên nhân thiệu hại details: - hologramLaunch: '§eChỉnh sửa "launch" vật phẩm hologram' - hologramLaunchLore: Hologram hiển thị bên trên đầu NPC khởi đầu khi người chơi bắt đầu nhiệm vụ. - hologramLaunchNo: '§eChỉnh sửa "launch unavailable" vật phẩm hologram' - hologramLaunchNoLore: Hologram hiển thị bên trên đầu của NPC khởi đầu khi người chơi không bắt đầu nhiệm vụ. + actions: '{amount} hành động' + auto: Tự động bắt đầu khi lần đầu tham gia + autoLore: Nếu bật, nhiệm vụ sẽ tự động được nhận khi người chơi đó lần đầu tiên tham gia máy chủ. + bypassLimit: Không giới hạn nhiệm vụ + bypassLimitLore: Nếu bật, người chơi có thể nhận nhiệm vụ cho dù đã đạt số lượng nhiệm vụ đã nhận tối đa. + cancelRewards: '§cHủy bỏ hành động' + cancelRewardsLore: Hành động được thực hiện khi người chơi hủy bỏ nhiệm vụ này. + cancellable: Có thể hủy bỏ bởi người chơi + cancellableLore: Cho phép người chơi hủy bỏ nhiệm vụ thông qua Menu Nhiệm vụ + createQuestLore: Bạn phải đặt một tên cho nhiệm vụ. + createQuestName: '§lTạo nhiệm vụ' customConfirmMessage: '§eChỉnh sửa cấu hình tin nhắn' customConfirmMessageLore: Tin nhắn hiển thị ở GUI Xác nhận khi người chơi muốn bắt đầu nhiệm vụ. customDescription: '§eChỉnh sửa mô tả nhiệm vụ' customDescriptionLore: Mô tả hiển thị bên dưới tên của nhiệm vụ trong GUI. - name: Thông tin nhiệm vụ gần đây - multipleTime: - itemName: Bật/Tắt có thể lặp lại - itemLore: Nhiệm vụ có thể thực hiện nhiều lần? - cancellable: Có thể hủy bỏ bởi người chơi - cancellableLore: Cho phép người chơi hủy bỏ nhiệm vụ thông qua Menu Nhiệm vụ - startableFromGUI: Có thể bắt đầu từ GUI - startableFromGUILore: Cho phép người chơi bắt đầu nhiệm vụ từ Menu Nhiệm vụ - scoreboardItem: Bật scoreboard - scoreboardItemLore: Nếu tắt, nhiệm vụ sẽ không hiển thị thông qua scoreboard. - hideItem: Ẩn menu và dynmap - hideItemLore: Nếu bật, nhiệm vụ sẽ không hiển thị trên dynmap hoặc trên Menu Nhiệm vụ. + customMaterial: '§eChỉnh sửa vật phẩm nhiệm vụ' + customMaterialLore: Vật phẩm biểu thị cho nhiệm vụ này trong Menu Nhiệm vụ. + defaultValue: '§8(giá trị mặc định)' + editQuestName: '§lChỉnh sửa nhiệm vụ' + editRequirements: '§eChỉnh sửa yêu cầu' + editRequirementsLore: Mỗi yêu cầu phải phù hợp với người chơi trước khi nó có thể bắt đầu nhiệm vụ. + endMessage: '§eChỉnh sửa thông báo kết thúc' + endMessageLore: Tin nhắn sẽ được gửi đến nhười chơi khi hết nhiệm vụ. + endSound: '§eChỉnh sửa âm thanh kết thúc' + endSoundLore: Âm thanh sẽ reo lên khi kết thúc nhiệm vụ. + failOnDeath: Thất bại khi chết + failOnDeathLore: Nhiệm vụ sẽ bị hủy bỏ khi người chơi chết? + firework: '§dPháo hoa kết thúc' + fireworkLore: Pháo hoa sẽ xuất hiện khi người chơi hoàn thành nhiệm vụ + fireworkLoreDrop: Vứt pháo hoa tùy chỉnh của bạn vào đây hideNoRequirementsItem: Ẩn khi không đạt các yêu cầu hideNoRequirementsItemLore: Nếu bật, nhiệm vụ sẽ không hiện lên Quests Menu nếu không đạt các yêu cầu. - bypassLimit: Không giới hạn nhiệm vụ - bypassLimitLore: Nếu bật, người chơi có thể nhận nhiệm vụ cho dù đã đạt số lượng nhiệm vụ đã nhận tối đa. - auto: Tự động bắt đầu khi lần đầu tham gia - autoLore: Nếu bật, nhiệm vụ sẽ tự động được nhận khi người chơi đó lần đầu tiên tham gia máy chủ. + hologramLaunch: '§eChỉnh sửa "launch" vật phẩm hologram' + hologramLaunchLore: Hologram hiển thị bên trên đầu NPC khởi đầu khi người chơi bắt đầu nhiệm vụ. + hologramLaunchNo: '§eChỉnh sửa "launch unavailable" vật phẩm hologram' + hologramLaunchNoLore: Hologram hiển thị bên trên đầu của NPC khởi đầu khi người chơi không bắt đầu nhiệm vụ. + hologramText: '§eChữ hologram' + hologramTextLore: Chữ bay được hiển thị trên đầu NPC. + keepDatas: Bảo tồn dữ liệu người chơi + keepDatasLore: 'Bắt buộc plugin bảo tồn dữ liệu người chơi, ngay cả khi giai đoạn đã bị chỉnh sửa. §c§lCẢNH BÁO §c- bật lựa chọn này có thể phá hủy dữ liệu của người chơi.' + loreReset: '§e§lTất cả thành tựu của người chơi sẽ bị đặt lại' + multipleTime: + itemLore: Nhiệm vụ có thể thực hiện nhiều lần? + itemName: Bật/Tắt có thể lặp lại + name: Thông tin nhiệm vụ gần đây + optionValue: '§8Giá trị: §7{value}' questName: '§a§lChỉnh tên nhiệm vụ' questNameLore: Bắt buộc phải đặt tên để hoành thành chỉnh sửa nhiệm vụ - setItemsRewards: '§eChỉnh phần thưởng' + questPool: '§eNhóm Nhiệm vụ' + questPoolLore: Gắn nhiệm vụ này với một nhóm nhiệm vụ removeItemsReward: '§eXóa vật phẩm khỏi kho đồ' - setXPRewards: '§eChỉnh phần thưởng. kinh nghiệm' + requiredParameter: '§7Yêu cầu tham số' + requirements: '{amount} yêu cầu' + rewards: '{amount} phần thưởng' + rewardsLore: Hành động được thực hiện khi nhiệm vụ kết thúc. + scoreboardItem: Bật scoreboard + scoreboardItemLore: Nếu tắt, nhiệm vụ sẽ không hiển thị thông qua scoreboard. + selectStarterNPC: '§e§lChọn NPC khởi đầu' + selectStarterNPCLore: Nhấn vào NPC đã chọn sẽ bắt đầu nhiệm vụ. + selectStarterNPCPool: '§c⚠ Một nhóm nhiệm vụ đã được chọn' setCheckpointReward: '§eChỉnh sửa kiểm soát phần thưởng' + setItemsRewards: '§eChỉnh phần thưởng' + setMoneyReward: '§eChỉnh sửa phần thưởng tiền' + setPermReward: '§eChỉnh sửa quyền' setRewardStopQuest: '§cDừng nhiệm vụ' - setRewardsWithRequirements: '§ePhần thưởng với yêu cầu' setRewardsRandom: '§dPhần thưởng ngẫu nhiên' - setPermReward: '§eChỉnh sửa quyền' - setMoneyReward: '§eChỉnh sửa phần thưởng tiền' - setWaitReward: '§eChỉnh sửa thời gian chờ phần thưởng' + setRewardsWithRequirements: '§ePhần thưởng với yêu cầu' setTitleReward: '§eChỉnh sửa tiêu đề phần thưởng' - selectStarterNPC: '§e§lChọn NPC khởi đầu' - selectStarterNPCLore: Nhấn vào NPC đã chọn sẽ bắt đầu nhiệm vụ. - selectStarterNPCPool: '§c⚠ Một nhóm nhiệm vụ đã được chọn' - createQuestName: '§lTạo nhiệm vụ' - createQuestLore: Bạn phải đặt một tên cho nhiệm vụ. - editQuestName: '§lChỉnh sửa nhiệm vụ' - endMessage: '§eChỉnh sửa thông báo kết thúc' - endMessageLore: Tin nhắn sẽ được gửi đến nhười chơi khi hết nhiệm vụ. - endSound: '§eChỉnh sửa âm thanh kết thúc' - endSoundLore: Âm thanh sẽ reo lên khi kết thúc nhiệm vụ. - startMessage: '§eChỉnh sửa tin nhắn bắt đầu' - startMessageLore: Tin nhắn sẽ gửi đến người chơi khi bắt đầu nhiệm vụ. + setWaitReward: '§eChỉnh sửa thời gian chờ phần thưởng' + setXPRewards: '§eChỉnh phần thưởng. kinh nghiệm' startDialog: '§eChỉnh sửa hội thoại bắt đầu' startDialogLore: Hội thoại sẽ được thực hiện trước khi nhiệm vụ bắt đầu khi người chơi nhấn vào NPC. - editRequirements: '§eChỉnh sửa yêu cầu' - editRequirementsLore: Mỗi yêu cầu phải phù hợp với người chơi trước khi nó có thể bắt đầu nhiệm vụ. + startMessage: '§eChỉnh sửa tin nhắn bắt đầu' + startMessageLore: Tin nhắn sẽ gửi đến người chơi khi bắt đầu nhiệm vụ. startRewards: '§6Bắt đầu phần thưởng' startRewardsLore: Hành động được thực hiện khi nhiệm vụ bắt đầu. - cancelRewards: '§cHủy bỏ hành động' - cancelRewardsLore: Hành động được thực hiện khi người chơi hủy bỏ nhiệm vụ này. - hologramText: '§eChữ hologram' - hologramTextLore: Chữ bay được hiển thị trên đầu NPC. + startableFromGUI: Có thể bắt đầu từ GUI + startableFromGUILore: Cho phép người chơi bắt đầu nhiệm vụ từ Menu Nhiệm vụ timer: '§bBắt đầu lại bộ đếm' timerLore: Thời gian trước khi người chơi có thể bắt đầu nhiệm vụ lần nữa. - requirements: '{0} yêu cầu' - rewards: '{0} phần thưởng' - actions: '{0} hành động' - rewardsLore: Hành động được thực hiện khi nhiệm vụ kết thúc. - customMaterial: '§eChỉnh sửa vật phẩm nhiệm vụ' - customMaterialLore: Vật phẩm biểu thị cho nhiệm vụ này trong Menu Nhiệm vụ. - failOnDeath: Thất bại khi chết - failOnDeathLore: Nhiệm vụ sẽ bị hủy bỏ khi người chơi chết? - questPool: '§eNhóm Nhiệm vụ' - questPoolLore: Gắn nhiệm vụ này với một nhóm nhiệm vụ - firework: '§dPháo hoa kết thúc' - fireworkLore: Pháo hoa sẽ xuất hiện khi người chơi hoàn thành nhiệm vụ - fireworkLoreDrop: Vứt pháo hoa tùy chỉnh của bạn vào đây - keepDatas: Bảo tồn dữ liệu người chơi - keepDatasLore: |- - Bắt buộc plugin bảo tồn dữ liệu người chơi, ngay cả khi giai đoạn đã bị chỉnh sửa. - §c§lCẢNH BÁO §c- bật lựa chọn này có thể phá hủy dữ liệu của người chơi. - loreReset: '§e§lTất cả thành tựu của người chơi sẽ bị đặt lại' - optionValue: '§8Giá trị: §7{0}' - defaultValue: '§8(giá trị mặc định)' - requiredParameter: '§7Yêu cầu tham số' - itemsSelect: - name: Chỉnh sửa vật phẩm - none: |- - §aDi chuyển vật phẩm vào đây - hoặc mở trình chỉnh sửa vật phẩm. + editTitle: + fadeIn: '§aThời gian mờ dần' + fadeOut: '§aThời gian mờ dần' + name: Chỉnh sửa tiêu đề + stay: '§bThời gian hiển thị' + subtitle: '§eTiêu đề con' + title: '§6Tiêu đề' + entityType: + name: Chọn loại sinh vật + factionsList.name: Danh sách faction + factionsRequired.name: Faction yêu cầu + itemComparisons: + bukkit: Bukkit so sánh + customBukkit: Bukkit so sánh - KHÔNG NBT + enchants: Vật phẩm phù phép + enchantsLore: So sánh phù phép vật phẩm + itemLore: Lore vật phẩm + itemLoreLore: So sánh lore vật phẩm + itemName: Tên vật phẩm + itemNameLore: So sánh tên vật phẩm + material: Vật phẩm + materialLore: 'So sánh vật phẩm (ví dụ: stone, iron sword,...)' + name: So sánh vật phẩm + repairCost: 'Giá sửa chữa:' + repairCostLore: So sánh giá sửa giáp và kiếm + itemCreator: + isQuestItem: '§bVật phẩm nhiệm vụ:' + itemFlags: Chuyển đổi cờ vật phẩm + itemLore: '§bLore vật phẩm' + itemName: '§bTên vật phẩm' + itemType: '§bLoại vật phẩm' + name: Trình tạo vật phẩm itemSelect: name: Chọn vật phẩm + itemsSelect: + name: Chỉnh sửa vật phẩm + none: '§aDi chuyển vật phẩm vào đây hoặc mở trình chỉnh sửa vật phẩm.' + listAllQuests: + name: Các nhiệm vụ + listBook: + noQuests: Không có nhiệm vụ nào đã được tạo trước đó. + questMultiple: Một số lần + questName: Tên + questRewards: Phần Thưởng + questStages: Các giai đoạn + questStarter: Bắt đầu + requirements: Yêu cầu + listPlayerQuests: + name: 'Nhiệm vụ của {player_name}' + listQuests: + canRedo: '§3§oBạn có thể bắt đầu lại nhiệm vụ này!' + finished: Nhiệm Vụ Đã Hoàn Thành + inProgress: Nhiệm Vụ Đang Thực Hiện + loreCancelClick: '§cHủy bỏ nhiệm vụ' + loreDialogsHistoryClick: '§7Xem hội thoại' + loreStart: '§a§oNhấn để bắt đầu nhiệm vụ.' + loreStartUnavailable: '§c§oBạn không đạt được yêu cầu để làm nhiệm vụ này.' + notStarted: Chưa Bắt Đầu Nhiệm Vụ + timeToWaitRedo: '§3§cBạn có thể bắt đầu lại nhiệm vụ này sau {time_left}.' + timesFinished: '§3Nhiệm vụ đã hoàn thành {times_finished} lần.' + mobSelect: + boss: '§6Chọn một Boss' + bukkitEntityType: '§eChọn loại sinh vật' + epicBoss: '§6Chọn Epic Boss' + mythicMob: '§6Chọn quái của Mythic Mob' + name: Chọn loại mob + mobs: + name: Chọn các loại quái + none: '§aẤn vào để thêm quái' npcCreate: + move: + itemLore: '§aThay đổi vị trí NPC.' + itemName: '§eDi Chuyển' + moveItem: '§a§lXác minh địa điểm' name: Tạo NPC setName: '§eChỉnh sửa tên NPC' setSkin: '§eChỉnh sửa trang phục của NPC' setType: '§eChỉnh sửa loại NPC' - move: - itemName: '§eDi Chuyển' - itemLore: '§aThay đổi vị trí NPC.' - moveItem: '§a§lXác minh địa điểm' npcSelect: + createStageNPC: '§eTạo NPC' name: Chọn hay tạo? selectStageNPC: '§eChọn một NPC đã tồn tại' - createStageNPC: '§eTạo NPC' - entityType: - name: Chọn loại sinh vật - chooseQuest: - name: Nhiệm vụ nào? - menu: '§aMenu Nhiệm vụ' - menuLore: Đưa bạn đến Menu Nhiệm vụ của bạn. - mobs: - name: Chọn các loại quái - none: '§aẤn vào để thêm quái' - clickLore: |- - §a§lChuột trái§a để chỉnh sửa số lượng - §a§l§nShift§a§l + chuột trái§a để chỉnh sửa tên quái - §c§lChuột phải§c để xóa - mobSelect: - name: Chọn loại mob - bukkitEntityType: '§eChọn loại sinh vật' - mythicMob: '§6Chọn quái của Mythic Mob' - epicBoss: '§6Chọn Epic Boss' - boss: '§6Chọn một Boss' - stageEnding: - locationTeleport: '§eChỉnh sửa vị trí dịch chuyển' - command: '§eChỉnh sửa lệnh thực hiện' - requirements: - name: Yêu cầu - rewards: - name: Phần Thưởng - commands: 'Lệnh: {0}' - teleportation: |- - §aChọn: - X: {0} - Y: {1} - Z: {2} - Thế giới: {3} - random: - rewards: Chỉnh sửa phần thưởng - minMax: Chỉnh sửa thấp nhất và cao nhất - checkpointActions: - name: Thiết lập checkpoint - cancelActions: - name: Hủy bỏ hành động - rewardsWithRequirements: - name: Phần thưởng với yêu cầu - listAllQuests: - name: Các nhiệm vụ - listPlayerQuests: - name: 'Nhiệm vụ của {0}' - listQuests: - notStarted: Chưa Bắt Đầu Nhiệm Vụ - finished: Nhiệm Vụ Đã Hoàn Thành - inProgress: Nhiệm Vụ Đang Thực Hiện - loreDialogsHistoryClick: '§7Xem hội thoại' - loreCancelClick: '§cHủy bỏ nhiệm vụ' - loreStart: '§a§oNhấn để bắt đầu nhiệm vụ.' - loreStartUnavailable: '§c§oBạn không đạt được yêu cầu để làm nhiệm vụ này.' - timeToWaitRedo: '§3§cBạn có thể bắt đầu lại nhiệm vụ này sau {0}.' - canRedo: '§3§oBạn có thể bắt đầu lại nhiệm vụ này!' - timesFinished: '§3Nhiệm vụ đã hoàn thành {0} lần.' - itemCreator: - name: Trình tạo vật phẩm - itemType: '§bLoại vật phẩm' - itemFlags: Chuyển đổi cờ vật phẩm - itemName: '§bTên vật phẩm' - itemLore: '§bLore vật phẩm' - isQuestItem: '§bVật phẩm nhiệm vụ:' - command: - name: Lệnh - value: '§eLệnh' - console: Console - parse: Phân tích placeholder - delay: '§bThời gian chờ' - chooseAccount: - name: Tài khoản nào? - listBook: - questName: Tên - questStarter: Bắt đầu - questRewards: Phần Thưởng - questMultiple: Một số lần - requirements: Yêu cầu - questStages: Các giai đoạn - noQuests: Không có nhiệm vụ nào đã được tạo trước đó. - commandsList: - name: Danh sách lệnh - value: '§eLệnh: {0}' - console: '§eConsole: {0}' - block: - name: Chọn khối - material: '§eVật phẩm: {0}' - materialNotItemLore: 'Khối được chọn không thể hiển thị như là một vật phẩm. Nó vẫn có thể lưu trữ như một {0}.' - blockData: '§bDữ liệu khối (nâng cao)' - blockTag: '§dThẻ (nâng cao)' - blockTagLore: 'Chọn thẻ mô tả danh sách các khối khả dụng. Các thẻ có thể tùy chỉnh bằng gói dữ liệu. Bạn có thể tìm thấy danh sách thẻ trên Minecraft wiki.' - blocksList: - name: Chọn khối - addBlock: '§aẤn vào để thêm một khối' - blockAction: - name: Chọn hành động khối - location: '§eChọn vị trí chỉnh xác' - material: '§eChọn một khối' - buckets: - name: Loại xô + particleEffect: + color: '§bMàu hiệu ứng' + name: Tạo hiệu ứng + shape: '§dHình dạng hiệu ứng' + type: '§eLoại hiệu ứng' + particleList: + colored: Màu hiệu ứng + name: Danh sách hiệu ứng permission: name: Chọn quyền perm: '§aQuyền' - world: '§aThế giới' - worldGlobal: '§d§lToàn cầu' remove: Xóa quyền removeLore: '§7Quyền sẽ được lấy mất\n§7thay vì được cho.' + world: '§aThế giới' + worldGlobal: '§d§lToàn cầu' permissionList: name: Danh sách quyền - removed: '§eĐã lấy: §6{0}' - world: '§eThế giới: §6{0}' - classesRequired.name: Class yêu cầu - classesList.name: Danh sách class - factionsRequired.name: Faction yêu cầu - factionsList.name: Danh sách faction - poolsManage: - name: Nhóm Nhiệm vụ - itemName: '§aNhóm #{0}' - poolNPC: '§8NPC: §7{0}' - poolMaxQuests: '§8Nhiệm vụ tối đa: §7{0}' - poolQuestsPerLaunch: '§8Nhiệm vụ được cho mỗi lần chạy: §7{0}' - poolRedo: '§8Có thể hoàn tác nhiệm vụ đã hoàn thành: §7{0}' - poolTime: '§8Thời gian giữa các nhiệm vụ: §7{0}' - poolHologram: '§8Chữ hologram: §7{0}' - poolAvoidDuplicates: '§8Tránh trừng lặp: §7{0}' - poolQuestsList: '§7{0} §8nhiệm vụ: §7{1}' - create: '§aTạo nhóm nhiệm vụ' - edit: '§e> §6§oChỉnh sửa nhóm... §e<' - choose: '§e> §6§oChọn nhóm này §e<' + removed: '§eĐã lấy: §6{permission_removed}' + world: '§eThế giới: §6{permission_world}' poolCreation: - name: Tạo nhóm nhiệm vụ + avoidDuplicates: Tránh trùng lặp + avoidDuplicatesLore: '§8> §7Cố gắng làm nhiệm vụ\n lặp đi lặp lại' hologramText: '§eNhóm tùy chỉnh hologram' maxQuests: '§aNhiệm vụ tối đa' + name: Tạo nhóm nhiệm vụ questsPerLaunch: '§aNhiệm vụ bắt đầu mỗi lần chạy' - time: '§bĐặt thời gian giữa các nhiệm vụ' redoAllowed: Hoàn tác có được phép không - avoidDuplicates: Tránh trùng lặp - avoidDuplicatesLore: '§8> §7Cố gắng làm nhiệm vụ\n lặp đi lặp lại' requirements: '§bYêu cầu để bắt đầu nhiệm vụ' + time: '§bĐặt thời gian giữa các nhiệm vụ' poolsList.name: Nhóm nhiệm vụ - itemComparisons: - name: So sánh vật phẩm - bukkit: Bukkit so sánh - bukkitLore: 'Uses Bukkit default item comparison system.\nCompares material, durability, nbt tags...' - customBukkit: Bukkit so sánh - KHÔNG NBT - customBukkitLore: 'Uses Bukkit default item comparison system, but wipes out NBT tags.\nCompares material, durability...' - material: Vật phẩm - materialLore: 'So sánh vật phẩm (ví dụ: stone, iron sword,...)' - itemName: Tên vật phẩm - itemNameLore: So sánh tên vật phẩm - itemLore: Lore vật phẩm - itemLoreLore: So sánh lore vật phẩm - enchants: Vật phẩm phù phép - enchantsLore: So sánh phù phép vật phẩm - repairCost: 'Giá sửa chữa:' - repairCostLore: So sánh giá sửa giáp và kiếm - editTitle: - name: Chỉnh sửa tiêu đề - title: '§6Tiêu đề' - subtitle: '§eTiêu đề con' - fadeIn: '§aThời gian mờ dần' - stay: '§bThời gian hiển thị' - fadeOut: '§aThời gian mờ dần' - particleEffect: - name: Tạo hiệu ứng - shape: '§dHình dạng hiệu ứng' - type: '§eLoại hiệu ứng' - color: '§bMàu hiệu ứng' - particleList: - name: Danh sách hiệu ứng - colored: Màu hiệu ứng - damageCause: - name: Nguyên nhân thiệt hại - damageCausesList: - name: Danh sách nguyên nhân thiệu hại -scoreboard: - name: '§6§lNhiệm vụ' - noLaunched: '§cKhông có nhiệm vụ đang thực hiện.' - noLaunchedName: '§c§lĐang tải' - noLaunchedDescription: '§c§oĐang tải' - textBetwteenBranch: '§e hoặc' - asyncEnd: '§ví dụ' - stage: - region: '§eĐi đến §6{0}' - npc: '§eNói chuyện với §6{0}' - items: '§eMang cho §6{0}§e:' - mobs: '§eTiêu diệt §6{0}' - mine: '§eĐào {0}' - placeBlocks: '§eĐặt{0}' - chat: '§eViết §6{0}' - interact: '§eNhấn vào khối tại §6{0}' - interactMaterial: '§eNhấn vào khối §6{0}' - fish: '§eCâu §6{0}' - melt: '§eNung §6{0}' - enchant: '§ePhù phép §6{0}' - craft: '§eChế tạo §6{0}' - bucket: '§eLàm đầy §6{0}' - location: '§eĐi đên §6{0}§e, §6{1}§e, §6{2}§e in §6{3}' - playTimeFormatted: '§ePhát §6{0}' - breed: '§eChăn §6{0}' - tame: '§eThuần phục §6{0}' - die: '§cChết' -indication: - startQuest: '§7Bạn có muốn bắt đầu nhiệm vụ {0}?' - closeInventory: '§7Bạn có chắc bạn muốn đóng GUI?' - cancelQuest: '§7Bạn có chắc chắn muốn hủy nhiệm vụ này {0}?' - removeQuest: '§7Bạn có chắc chắn muốn xóa nhiệm vụ này {0}?' -description: - requirement: - title: '§8§lYêu cầu:' - level: 'Cấp {0}' - jobLevel: 'Cấp {0} cho {1}' - combatLevel: 'Cấp độ đánh nhau {0}' - skillLevel: 'Cấp {0} cho {1}' - class: 'Class {0}' - faction: 'Faction {0}' - quest: 'Hoàn thành nhiệm vụ §e{0}' - reward: - title: '§8§lPhần thưởng:' + poolsManage: + choose: '§e> §6§oChọn nhóm này §e<' + create: '§aTạo nhóm nhiệm vụ' + edit: '§e> §6§oChỉnh sửa nhóm... §e<' + itemName: '§aNhóm #{pool}' + name: Nhóm Nhiệm vụ + poolAvoidDuplicates: '§8Tránh trừng lặp: §7{pool_duplicates}' + poolHologram: '§8Chữ hologram: §7{pool_hologram}' + poolMaxQuests: '§8Nhiệm vụ tối đa: §7{pool_max_quests}' + poolQuestsList: '§7{pool_quests_amount} §8nhiệm vụ: §7{pool_quests}' + poolQuestsPerLaunch: '§8Nhiệm vụ được cho mỗi lần chạy: §7{pool_quests_per_launch}' + poolRedo: '§8Có thể hoàn tác nhiệm vụ đã hoàn thành: §7{pool_redo}' + poolTime: '§8Thời gian giữa các nhiệm vụ: §7{pool_time}' + requirements: + name: Yêu cầu + rewards: + commands: 'Lệnh: {amount}' + name: Phần Thưởng + random: + minMax: Chỉnh sửa thấp nhất và cao nhất + rewards: Chỉnh sửa phần thưởng + rewardsWithRequirements: + name: Phần thưởng với yêu cầu + search: '§e§lTìm Kiếm' + stageEnding: + command: '§eChỉnh sửa lệnh thực hiện' + locationTeleport: '§eChỉnh sửa vị trí dịch chuyển' + stages: + branchesPage: '§dCác nhánh giai đoạn' + descriptionTextItem: '§eChỉnh sửa mô tả' + endingItem: '§eChỉnh sửa phần thưởng kết thúc' + laterPage: '§eTrang trước' + name: Tạo giai đoạn mới + newBranch: '§eĐến nhánh mới' + nextPage: '§eTrang tiếp theo' + previousBranch: '§eTrở lại nhánh trước đó' + regularPage: '§aCác giai đoạn thông thường' + validationRequirements: '§eCác yêu cầu cần xác nhận' + validationRequirementsLore: Tất cả các yêu cầu phải phù hợp với người chơi hoàn thành giai đoạn. Nếu không giai đoạn không thể hoàn thành. + validate: '§b§lXác nhận' misc: - format: - prefix: '§f[§aQuests§r§f] §r' - npcText: '§e§l{0}:§r§e {1}' - offText: '§r§e {0}' - time: - weeks: '{0} tuần' - days: '{0} ngày' - hours: '{0} giờ' - minutes: '{0} phút' - lessThanAMinute: 'ít hơn một phút' - stageType: - region: Tìm khu vực - npc: Tìm NPC - items: Mang vật phẩm trở lại - mobs: Giết Mobs - mine: Phá khối - placeBlocks: Đặt khối - chat: Nhắn tin trên thanh trò chuyện - interact: Tương tác với khối - Fish: Bắt cá - Melt: Nung vật phẩm - Enchant: Cường hóa vật phẩm - Craft: Chế tạo vật phẩm - Bucket: Làm đầy cái xô - location: Tìm tọa độ - playTime: Thời gian chơi - breedAnimals: Làm no động vật - tameAnimals: Thuần phục động vật - die: Chết - comparison: - equals: bằng với {0} - different: khắc với {0} - less: ít hơn {0} - lessOrEquals: Ít hơn {0} - greater: lớn hơn {0} - greaterOrEquals: lớn hơn {0} - requirement: - logicalOr: '§dLogic HOẶC (bắt buộc)' - skillAPILevel: '§dYêu cầu cấp SkillAPI' - class: '§bClass(es) yêu cầu' - faction: '§dYêu cầu Faction' - jobLevel: '§bYêu cầu cấp độ Job' - combatLevel: '§dYêu cầu cấp độ Combat' - experienceLevel: '§bYêu cầu cấp độ' - permissions: '§3Yêu cầu quyền' - scoreboard: '§dYêu cầu điểm' - region: '§dYêu cầu khu vực' - placeholder: '§dYêu cầu giá trị Placeholder' - quest: '§aNhiệm vụ yêu cầu' - mcMMOSkillLevel: '§dYêu cầu cấp độ kĩ năng' - money: '§dYêu cầu tiền' + amount: '§eSố lượng: {amount}' + amounts: + comparisons: '{comparisons_amount} sự so sánh' + dialogLines: '{lines_amount} dòng' + items: '{items_amount} vật phẩm' + mobs: '{mobs_amount} mob' + permissions: '{permissions_amount} quyền' + and: và bucket: - water: Xô nước lava: Xô nhung nham milk: Xô sữa bò snow: Xô tuyết + water: Xô nước click: - right: Chuột phải left: Chuột trái - shift-right: Shift-Chuột phải - shift-left: Shift-Chuột trái middle: Chuột giữa - amounts: - items: '{0} vật phẩm' - comparisons: '{0} sự so sánh' - dialogLines: '{0} dòng' - permissions: '{0} quyền' - mobs: '{0} mob' - ticks: '{0} ticks' - questItemLore: '§e§oVật phẩm nhiệm vụ' - hologramText: '§8§lNPC Nhiệm vụ' - poolHologramText: '§eNhiệm vụ khả dụng' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§eLoại sinh vật: {0}' - entityTypeAny: '§eBất kì sinh vật nào' - enabled: Bật + right: Chuột phải + shift-left: Shift-Chuột trái + shift-right: Shift-Chuột phải + comparison: + different: khắc với {number} + equals: bằng với {number} + greater: lớn hơn {number} + greaterOrEquals: lớn hơn {number} + less: ít hơn {number} + lessOrEquals: Ít hơn {number} disabled: Tắt - unknown: Không rõ + enabled: Bật + entityType: '§eLoại sinh vật: {entity_type}' + entityTypeAny: '§eBất kì sinh vật nào' + format: + npcText: '§e§l{npc_name_message}:§r§e {text}' + offText: '§r§e {message}' + prefix: '§f[§aQuests§r§f] §r' + hologramText: '§8§lNPC Nhiệm vụ' + 'no': 'Không' notSet: '§cchưa thiết lập' - unused: '§2§lKhông sử dụng' - used: '§a§lSử dụng' - remove: '§7Chuột giữa để xóa' + or: hoặc + poolHologramText: '§eNhiệm vụ khả dụng' + questItemLore: '§e§oVật phẩm nhiệm vụ' removeRaw: Xóa + requirement: + class: '§bClass(es) yêu cầu' + combatLevel: '§dYêu cầu cấp độ Combat' + experienceLevel: '§bYêu cầu cấp độ' + faction: '§dYêu cầu Faction' + jobLevel: '§bYêu cầu cấp độ Job' + logicalOr: '§dLogic HOẶC (bắt buộc)' + mcMMOSkillLevel: '§dYêu cầu cấp độ kĩ năng' + money: '§dYêu cầu tiền' + permissions: '§3Yêu cầu quyền' + placeholder: '§dYêu cầu giá trị Placeholder' + quest: '§aNhiệm vụ yêu cầu' + region: '§dYêu cầu khu vực' + scoreboard: '§dYêu cầu điểm' + skillAPILevel: '§dYêu cầu cấp SkillAPI' reset: Đặt lại - or: hoặc - amount: '§eSố lượng: {0}' - items: các vật phẩm - expPoints: Điểm Kinh nghiệm + stageType: + Bucket: Làm đầy cái xô + Craft: Chế tạo vật phẩm + Enchant: Cường hóa vật phẩm + Fish: Bắt cá + Melt: Nung vật phẩm + breedAnimals: Làm no động vật + chat: Nhắn tin trên thanh trò chuyện + die: Chết + interact: Tương tác với khối + items: Mang vật phẩm trở lại + location: Tìm tọa độ + mine: Phá khối + mobs: Giết Mobs + npc: Tìm NPC + placeBlocks: Đặt khối + playTime: Thời gian chơi + region: Tìm khu vực + tameAnimals: Thuần phục động vật + time: + days: '{days_amount} ngày' + hours: '{hours_amount} giờ' + lessThanAMinute: ít hơn một phút + minutes: '{minutes_amount} phút' + weeks: '{weeks_amount} tuần' + unknown: Không rõ 'yes': 'Có' - 'no': 'Không' - and: và +msg: + bringBackObjects: Giao cho tôi {items}. + command: + adminModeEntered: '§aBạn đã kích hoạt chế độ admin' + adminModeLeft: '§aBạn đã thoát khỏi chế độ admin' + backupCreated: '§6Bạn đã tạo thành công file backup toàn bộ thông tin nhiệm vụ và thông tin người chơi' + backupPlayersFailed: '§cTạo backup cho toàn bộ thông tin người chơi thất bại' + backupQuestsFailed: '§cTạo backup cho toàn bộ nhiệm vụ thất bại' + cancelQuest: '§6Bạn đã thoát khởi nhiệm vụ {quest}' + cancelQuestUnavailable: '§6Không thể thoát khỏi nhiệm vụ {quest}' + checkpoint: + noCheckpoint: '§cKhông tìm thấy trạm kiểm soát nào cho nhiệm vụ {quest}.' + questNotStarted: '§cBạn không làm nhiệm vụ này.' + downloadTranslations: + downloaded: '§aNgôn ngữ {lang} đã được tải! §7Bạn cần chỉnh sửa file config.yml, đổi §ominecraftTranslationsFile§7 với {lang}, sau đó khởi động lại máy chủ.' + exists: asd + notFound: '§cNgôn ngữ {lang} không tìm thấy cho phiên bản {version}' + syntax: '§cBạn cần phải tải file ngôn ngữ. Ví dụ: "/quests downloadTranslations vi_VN"' + help: + adminMode: '§6/{label} adminMode:§e Bật/tắt chế độ admin (Nó khá hữu dụng cho hiện một vài thông tin log)' + create: '§6/{label} create: §eTạo nhiệm vụ mới' + downloadTranslations: '§6/{label} downloadTranslations <Ngôn ngữ>: §eTải xuống một tệp bản dịch vanilla' + edit: '§6/{label} edit: §eChỉnh sửa nhiệm vụ' + finishAll: '§6/{label} fisnishAll <tên người chơi>: §e Hoàn thành tất cả nhiệm vụ mà người chơi đó đang nhận' + header: '§6§lBeautyQuest - Help' + list: '§6/{label} list:§e Xem tất cả các nhiệm vụ (Chỉ cho phiên bản được hỗ trợ)' + reload: '§6/{label} reload : §eLưu và tải lại tất cả mọi thứ §c(Lệnh này có thể mang lại lỗi cho máy chủ bạn đến 99.9% nên hãy restart lại máy chủ)' + remove: '§6/{label} remove <id nhiệm vụ>: §eXóa nhiệm vụ với id của nó hoặc click vào NPC khi chưa xác định' + resetPlayer: '§6/{label} resetPlayer <tên người chơi>: §eXóa toàn bộ thông tin người chơi' + resetPlayerQuest: '§6/{label} resetPlayerQuest <tên người chơi> [id nhiệm vụ] §eXóa thông tin nhiệm vụ từ người chơi' + save: '§6/{label} save: §eLưu plugins cách thủ công' + seePlayer: '§6/{label} seePlayer <player>: §eXem thông tin của người chơi' + setFirework: '§6/{label} setFirework: §eChỉnh sửa pháo hoa mặc định lúc kết thúc.' + setItem: '§6/{label} setItem <talk|laucher>:§e Lưu vật phẩm hologram' + setStage: '§6/{label} setStage <tên người chơi> <id nhiệm vụ> [nhánh nhiệm vụ mới] [giai đoạn mới]: §eBỏ qua giai đoạn hiện tại để bắt đầu một nhanh nhiệm vụ mới' + start: '§6/{label} start <tên người chơi> [id nhiệm vụ]:§e Bắt buộc người chơi bắt đầu nhiệm vụ' + startDialog: '§6/{label} startDialog <Người chơi> <Mã nhiệm vụ>: §eBắt đầu hộp thoại đang chờ xử lý cho một giai đoạn của NPC hoặc hộp thoại bắt đầu cho một nhiệm vụ.' + version: '§6/{label} version: §eKiểm tra phiên bản của plugins' + invalidCommand: + simple: '§cLệnh này không tồn tại, hãy viết §ehelp§c.' + itemChanged: '§aMục đã được chỉnh sửa. Các thay đổi sẽ ảnh hưởng sau khi khởi động lại.' + itemRemoved: '§aMục ảnh ba chiều đã bị xóa.' + leaveAll: '§aBạn đã buộc phải kết thúc {success} nhiệm vụ. Lỗi: {errors}' + removed: '§aNhiệm vụ {quest_name} đã được xóa thành công.' + resetPlayer: + player: '§6Tất cả thông tin nhiệm vụ của bạn (bao gồm {quest_amount} nhiệm vụ) đã bị xóa bởi {deleter_name}' + remover: '§6{quest_amount} quest information(s) of {player} has/have been deleted.' + resetPlayerPool: + full: '§aBạn đã đặt lại {pool} dữ liệu của {player}.' + timer: '§aBạn đã đặt lại {pool} bộ hẹn giờ của {player}.' + resetPlayerQuest: + player: '§6Tất cả thông tin về nhiệm vụ {quest} của bạn đã bị xóa bởi {deleter_name}' + remover: '§6Các thông tin nhiệm vụ {player} đã bị {quest} xóa' + resetQuest: '§6Xóa toàn bộ dữ liệu nhiệm vụ của {player_amount} người chơi' + scoreboard: + hidden: '§6Bảng nhiệm vụ của người chơi {player_name} đã bị ẩn' + lineInexistant: '§cDòng {line_id} không tồn tại' + lineRemoved: '§6Bạn đã loại bỏ dòng {line_id} thành công' + lineReset: '§6Bạn đã loại cài lại dòng {line_id}' + lineSet: '§6Bạn đã chỉnh sửa thành công dòng {line_id}' + own: + hidden: '§6Bảng thông tin của bạn hiện tại đã bị ẩn.' + shown: '§6Bảng thông tin của bạn hiện đã được hiển thị lại.' + resetAll: '§6Bạn đã đặt lại bảng nhiệm vụ của người chơi {player_name}' + shown: '§6Bảng nhiệm vụ của người chơi {player_name} đã được đặt lại' + setStage: + branchDoesntExist: '§cNhánh có id {branch_id} không tồn tại.' + doesntExist: '§cGia đoạn có id {stage_id} không tồn tại.' + next: '§aGiai đoạn đã bị bỏ qua.' + nextUnavailable: '§cTùy chọn "skip" không khả dụng khi người chơi ở phần cuối của một nhánh.' + set: '§aGiai đoạn {stage_id} được khởi chạy.' + startDialog: + alreadyIn: '§cNgười chơi đang có cuộc hội thoại' + impossible: '§cKhông thể bắt đầu lời thoại trong lúc này' + noDialog: '§cNgười chơi không có lời thoại nào đang chờ' + success: '§aBắt đầu cuộc hội thoại cho người chơi {player} ở nhiệm vụ {quest}' + startQuest: '§6Bạn đã buộc phải bắt đầu nhiệm vụ {quest} (UUID của người chơi: {player}).' + dialogs: + skipped: '§8§oLời thoại được bỏ qua' + tooFar: '§7§oBạn đang ở quá xa {npc_name}...' + editor: + already: '§cBạn đã ở sẵn trong chế độ chỉnh sửa' + availableElements: 'Đối tượng khả dụng: §e{available_elements}' + blockAmount: '§aViết số lượng khối' + blockData: '§aViết blockdata (blockdatas có sẵn: {available_datas}):' + blockName: '§aViết tên của khối' + blockTag: '§aViết blockdata (blockdatas có sẵn: {available_tags}):' + chat: '§6Bạn đang ở trong chế độ chỉnh sửa. Dùng "/quests exitEditor" để cưỡng chế thoát. (Không khuyết khích, thay vào đó hãy dùng "close" hoặc "cancel" để trở lại.)' + color: 'Nhập định dạng màu. Định dạng Hexadecimal (#XXXXX) hoặc định dạng RGB (RED GRE BLU).' + colorNamed: Nhập tên của màu + comparisonTypeDefault: '§aChọn kiểu bạn muốn: {available}. Mặc định là: §e§l{default}§r§a. Gõ §onull§r§a để sử dụng.' + dialog: + cleared: '§aLoại bỏ tin nhắn {amount}' + edited: '§aChỉnh sửa tin nhắn "{msg}"' + help: + addSound: '§6addSound <id> <sound>: §eThêm âm thanh khi tin nhắn hiển thị.' + clear: '§6clear: §eXóa toàn bộ tin nhắn.' + close: '§6Đóng: §eXác thực tất cả tin nhắn.' + edit: 'Chỉnh sửa tin nhắn' + header: '§6§lBeautyQuests - Giúp đỡ chỉnh sửa đoạn hội thoại' + list: '§6list: §eXem tất cả tin nhắn' + nothing: '§6noSender <tin nhắn>: §eThêm tin nhắn với không có thông tin người gửi' + nothingInsert: '§6nothingInsert <id> <message>: §eThêm một tin nhắn với không có chủ ngữ.' + npc: '§6npc <tin nhắn>: §eThêm tin nhắn được nói bởi NPC' + npcInsert: '§6playerInsert <id> <message>: §eThêm một tin nhắn cho NPC nói.' + npcName: '§6npcName [Tên NPC tùy chỉnh]: §eĐặt (hoặc đặt lại về mặc định) tên tùy chỉnh của NPC trong hộp thoại.' + player: '§6player <tin nhắn>: §eThêm tin nhắn được nói bởi người chơi' + playerInsert: '§6playerInsert <id> <message>: §eThêm một tin nhắn cho người chơi nói.' + remove: '§6remove <mã id>: §eLoại bỏ tin nhắn' + setTime: '§6setTime <Mã> <Thời gian>: §eĐặt tốc độ (trong ticks) trước tin nhắn tiếp theo được phát tự động.' + skippable: '§6skippable [true|false]: §eĐặt hộp thoại có thể được bỏ qua hay không' + messageRemoved: '§aLoại bỏ tin nhắn "{msg}"' + noSender: '§aTin nhắn "{msg}" đã thêm nhưng không có thông tin người gửi' + npc: '§aThêm tin nhắn "{msg}" vào cho NPC' + npcName: + set: '§aTên NPC tùy chỉnh đã được đặt thành §7{new_name}§a (trước đó là §7{old_name}§a)' + unset: '§aCustom NPC đã được đổi tên về mặc định (§7{old_name}§a)' + player: '§aTin nhắn "{msg}" đã thêm vào cho người chơi' + skippable: + set: '§eTrạng thái bỏ qua hộp thoại hiện tại đã được đặt thành §7{new_state}§a (trước đó là §7{old_state}§a)' + unset: '§aTrạng thái bỏ qua hộp thoại hiện đã được đặt về mặc định (trước đó là §7{old_state}§a)' + soundAdded: '§aÂm thanh "{sound}" đã thêm vào cho "{msg}"' + syntaxRemove: '§cĐúng cú pháp: remove <mã id>' + timeRemoved: '§aThời gian đã được xóa cho tin nhắn {msg}.' + timeSet: '§aThời gian đã được chỉnh sửa cho tin nhắn {msg}: hiện tại là {time} ticks.' + enter: + list: '§c⚠ §7Bạn đã nhập trình chỉnh sửa "list". Dùng "add" để thêm dòng. Hãy tham khảo "help" (với không dấu gạch chéo) để được trợ giúp. §e§lNhập "close" để thoát khỏi trình chỉnh sửa.' + subtitle: '§6Dùng "/quests exitEditor" để cưỡng chế thoát.' + title: '§6- Chế Độ Chỉnh Sửa -' + firework: + edited: Đã chỉnh sửa Quest Firework thành công! + invalid: Pháo hoa này không hợp lệ. + invalidHand: Bạn phải cầm pháo ra ở tay chính. + removed: Đã xóa Quest Firework thành công! + goToLocation: '§aĐi đến vị trí muốn đến cho giai đoạn' + invalidColor: Định dạng màu bạn nhập không hợp lệ. Bắt buộc phải là định dạng Hexadecimal hoặc RGB. + invalidPattern: '§cMẫu regex không hợp lệ §4{input}§c.' + itemCreator: + invalidBlockType: '§aLoại khối không hợp lệ' + invalidItemType: '§cLoại vật phẩm không rõ' + itemAmount: '§aViết số lượng vật phẩm ' + itemLore: '§aViết lore vật phẩm (Viết "help" để nhận sự giúp đỡ)' + itemName: '§aViết tên của vật phẩm:' + itemType: '§aViết loại vật phẩm yêu cầu' + unknownBlockType: '§aLoại khối không rõ' + unknownItemType: '§cLoại vật phẩm không rõ' + mythicmobs: + disabled: '§cMythicMob đã tắt' + isntMythicMob: '§cMythic Mob không tồn tại.' + list: '§aDanh sách tất cả Mythic Mobs:' + noSuchElement: '§cKhông tồn tại. Phần hợp lệ chỉ có: §e{available_elements}' + npc: + choseStarter: '§aChọn NPC để bắt đầu nhiệm vụ' + enter: '§aNhấn vào NPC, hoặc gõ "cancel"' + notStarter: '§cNPC này không phải NPC Nhiệm Vụ' + pool: + hologramText: Viết Hologram tùy chỉnh cho Pool này (hoặc gõ "null" nếu bạn muốn sử dụng loại mặc định) + maxQuests: Viết số lượng nhiệm vụ tối đa có thể khởi chạy cho Pool này. + questsPerLaunch: Viết số lượng nhiệm vụ được giao khi click vào NPC. + timeMsg: 'Viết thời gian trước khi người chơi có thể nhận một nhiệm vụ mới. (đơn vị: days).' + scoreboardObjectiveNotFound: '§cKhông rõ scoreboard' + selectWantedBlock: '§aNhấn với cây gậy đến khối mong muốn cho giai đoạn tiếp theo' + stage: + location: + typeWorldPattern: '§aViết regex cho tên của các thế giới:' + text: + argNotSupported: '§c{arg} không được hỗ trợ' + chooseJobRequired: '§aViết tên công việc muốn:' + chooseLvlRequired: '§aViết yêu cầu cấp độ của bạn' + chooseMoneyRequired: '§aViết số tiền yêu cầu' + chooseObjectiveRequired: '§aViết tên dự án.' + chooseObjectiveTargetScore: '§aGhi điểm mục tiêu cho vật (Target Score For The Objective).' + choosePermissionMessage: '§aBạn có thể chọn thông báo từ chối nếu người chơi không có quyền cần thiết. (Để bỏ qua bước này, hãy viết "null".)' + choosePermissionRequired: '§aViết yêu cầu quyền để bắt đầu nhiệm vụ' + choosePlaceholderRequired: + identifier: '§aViết tên của placeholder mà không có ký tự phần trăm:' + value: '§aViết yêu cầu placeholder §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§aViết tên yêu cầu của khu vực (Bạn phải ở cùng 1 thế giới)' + chooseSkillRequired: '§aViết tên kĩ năng yêu cầu' + reward: + money: '§aViết số tiền sẽ nhận được' + permissionName: '§aViết tên quyền' + permissionWorld: '§aViết thế giới trong đó quyền sẽ được chỉnh sửa hoặc "null" nếu bạn muốn là toàn cầu.' + random: + max: '§aViết số lượng tối đa của phần thưởng được gửi tới người chơi (bao gồm).' + min: '§aViết số lượng tối thiểu của phần thưởng được gửi tới người chơi (bao gồm).' + wait: '§aViết thời gian game để chờ: (1 giây = 20 game ticks)' + textList: + added: '§aĐã thêm vào văn bản "§7{msg}§a"' + help: + add: '§6add <Tin nhắn>: §eThêm một văn bản.' + close: '§6close: §eKiểm tra chữ đã thêm.' + header: '§6§lBeautyQuests - Giúp đỡ chỉnh sửa đoạn hội thoại' + list: '§6list: §eXem tất cả văn bản đã thêm.' + remove: '§6remove <Mã>: §eLoại bỏ một văn bản.' + removed: '§aĐã loại bỏ văn bản "§7{msg}§a"' + syntax: '§cCú pháp chính xác: ' + title: + fadeIn: 'Viết thời gian "fade-in", đơn vị: Ticks (20 ticks = 1 giây)' + fadeOut: 'Viết thời gian "fade-out", đơn vị: Ticks (20 ticks = 1 giây).' + stay: 'Viết thời gian "stay", đơn vị: Ticks (20 ticks = 1 giây).' + subtitle: Thêm một phụ đề (để "null" nếu bạn muốn để trống) + title: Thêm một tiêu đề (để "null" nếu bạn muốn để trống) + typeBucketAmount: '§aViết số lượng xô nước cần làm đầy' + typeGameTicks: '§aViết các dấu tích trò chơi cần thiết:' + typeLocationRadius: '§aViết yêu cầu tầm xa từ vị trí đã đặt' + errorOccurred: '§cĐã xảy ra lỗi, hãy liên hệ với quản trị viên! §4§lMã lỗi: {error}' + experience: + edited: '§aBạn nhận được kinh nghiệm từ nhiệm vụ {old_xp_amount} với {xp_amount} điểm.' + indexOutOfBounds: '§cSố {index} nằm ngoài giới hạn! Nó phải nằm trong khoảng từ {min} đến {max}.' + invalidBlockData: '§cDữ liệu khối {block_data} không hợp lệ hoặc không tương thích với khối {block_material}.' + invalidBlockTag: '§cBlock tag không tồn tại {block_tag}' + inventoryFull: '§cTúi đồ của bạn đã đầy, vật phẩm đã bị rơi xuống sàn.' + moveToTeleportPoint: '§aĐi đến địa điểm muốn đến.' + npcDoesntExist: '§cNPC với id {npc_id} không tồn tại.' + number: + invalid: '§c{input} không phải là con số.' + negative: '§cBạn phải nhập một số dương!' + notInBounds: '§cSố của bạn phải nằm ở giữa {min} và {max}.' + zero: '§cBạn phải nhập một số khác với 0!' + pools: + allCompleted: '§7Bạn đã hoàn thành tất cả nhiệm vụ!' + maxQuests: '§cBạn không thể làm nhiều hơn {pool_max_quests} nhiệm vụ cùng một lúc...' + noAvailable: '§7Không có nhiệm vụ nào tồn tại' + noTime: '§cBạn phải chờ {time_left} trước khi làm nhiệm vụ khác' + quest: + alreadyStarted: '§cNhiệm vụ này đã được bắt đầu!' + cancelling: '§cQuá trình tạo nhiệm vụ đã bị hủy.' + createCancelled: '§cViệc tạo hoặc chỉnh sửa đã bị hủy bởi một plugin khác!' + created: '§aXin chúc mừng! Bạn đã chỉnh sửa nhiệm vụ §e{quest}§a với {quest_branches} giai đoạn!' + editCancelling: '§cQuy trình của phiên bản nhiệm vụ bị hủy.' + edited: '§aXin chúc mừng! Bạn đã chỉnh sửa nhiệm vụ §e{quest}§a bảo gồm {quest_branches} giai đoạn!' + finished: + base: '§aChúc mừng! Bạn đã hoàn thành nhiệm vụ §e{quest_name}§a!' + obtain: '§aBạn nhận được &e{rewards}!' + invalidID: '§cNhiệm vụ với id {quest_id} không tồn tại.' + invalidPoolID: '§cDòng {pool_id} không tồn tại' + notStarted: '§cBạn đang không làm nhiệm vụ này.' + started: '§aBạn đã bắt đầu quest §r§e{quest_name}§o§6!' + questItem: + craft: '§cBạn không thể dùng vật phẩm nhiệm vụ để chế tạo!' + drop: '§cBạn không thể làm rớt vật phẩm nhiệm vụ!' + eat: '§cBạn không thể ăn vật phẩm nhiệm vụ!' + quests: + checkpoint: '§7Đã đạt đến điểm kiểm tra nhiệm vụ!' + failed: '§cBạn đã thất bại trong nhiệm vụ {quest_name}...' + maxLaunched: '§cBạn không thể làm nhiềm hơn {quests_max_amount} nhiệm vụ cùng một lúc...' + updated: '§7Đã cập nhật quest §e{quest_name}§7.' + regionDoesntExists: '§cKhu vực này không tồn tại. (Bạn phải ở trong cùng một thế giới.)' + requirements: + combatLevel: '§cCấp độ đánh nhau của bạn phải đạt {long_level}!' + job: '§cCấp độ nghề nghiệp §e{job_name}§c phải đạt cấp {long_level}!' + level: '§cCấp độ bạn phải ở {long_level}!' + money: '§cBạn phải có {money}!' + quest: '§cBạn chưa hoàn thành nhiệm vụ §e{quest_name}§c!' + skill: '§cCấp độ kĩ năng §e{skill_name}§c phải đạt cấp {long_level}!' + waitTime: '§cBạn phải chờ {time_left} trước khi làm lại nhiệm vụ!' + restartServer: '§7Khởi động lại máy chủ để thấy sửa đổi' + selectNPCToKill: '§aChọn NPC để tiêu diệt.' + stageMobs: + listMobs: '§aBạn phải giết {mobs}.' + typeCancel: '§aGõ "cancel" để trở lại dòng tin nhắn cuối cùng' + versionRequired: 'Phiên bản yêu cầu: §l{version}' + writeChatMessage: '§aViết tin nhắn bắt buộc: (Thêm "{SLASH}" ngay từ đầu nếu bạn muốn một lệnh.)' + writeCommand: '§aViết lệnh yêu cầu: (Lệnh không có dấu "/" và placeholder "{PLAYER}" được hỗ trợ. Nó sẽ được thay thế bằng tên của người thi hành.)' + writeCommandDelay: '§aViết độ trễ của lệnh. Đơn vị: Ticks.' + writeConfirmMessage: '§aViết thông báo xác nhận được hiển thị khi một người chơi để bắt đầu nhiệm vụ: (Viết "null" nếu bạn muốn thông báo mặc định.)' + writeDescriptionText: '§aViết văn bản mô tả mục tiêu của giai đoạn:' + writeEndMsg: '§aViết tin nhắn sẽ gửi khi nhiệm vụ kết thúc, "null" nếu bạn muốn một cái bình thường hoặc "none" nếu bạn không muốn gì hết. Bạn cso thể dùng "{rewards}" để thay thể với thông báo phần thưởng' + writeEndSound: '§aGhi tên của âm thanh sẽ được phát cho người chơi khi nhiệm vụ kết thúc, "null" nếu bạn muốn dùng cái mặc định hoặc "none" nếu bạn muốn không:' + writeHologramText: '§aViết văn bản của holographic display: (Viết "non" nếu bạn không muốn một holographic display và "null" nếu bạn muốn văn bản mặc định.)' + writeMessage: '§aViết tin nhắn sẽ gửi đến người chơi' + writeMobAmount: '§aViết số lượng mob cần tiêu diệt:' + writeMobName: '§aViết tên của mobs phải giết' + writeNPCText: '§aViết hộp thoại mà NPC sẽ nói với người chơi: (Viết "help" để nhận được sự giúp đỡ.)' + writeNpcName: '§aViết tên của NPC:' + writeNpcSkinName: '§aTên skin của NPC:' + writeQuestDescription: '§aViết mô tả về nhiệm vụ, hiển thị trong gui nhận nhiệm vụ.' + writeQuestMaterial: '§aViết vật liệu của item nhiệm vụ.' + writeQuestName: '§aTên của nhiệm vụ:' + writeQuestTimer: '§aViết thời gian cần thiết (tính bằng phút) trước khi bạn có thể khởi động lại nhiệm vụ: (Viết "null" nếu bạn muốn bộ đếm thời gian mặc định.) ' + writeRegionName: '§aViết tên của khu vực cần thiết cho giai đoạn tiếp theo:' + writeStageText: '§aViết văn bản sẽ được gửi đến người chơi lúc đầu của giai đoạn:' + writeStartMessage: '§aViết thông báo sẽ gửi khi bắt đầu nhiệm vụ, "null" nếu bạn muốn là 1 thông báo bình thường hoặc "none" nếu bạn không muốn' + writeXPGain: '§aViết số điểm kinh nghiệm mà người chơi sẽ nhận được: (Giá trị cuối cùng: {xp_amount})' +scoreboard: + asyncEnd: '§ví dụ' + name: '§6§lNhiệm vụ' + noLaunched: '§cKhông có nhiệm vụ đang thực hiện.' + noLaunchedDescription: '§c§oĐang tải' + noLaunchedName: '§c§lĐang tải' + stage: + breed: '§eChăn §6{mobs}' + bucket: '§eLàm đầy §6{buckets}' + chat: '§eViết §6{text}' + craft: '§eChế tạo §6{items}' + die: '§cChết' + enchant: '§ePhù phép §6{items}' + 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:' + 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}' + mobs: '§eTiêu diệt §6{mobs}' + npc: '§eNói chuyện với §6{dialog_npc_name}' + placeBlocks: '§eĐặt{blocks}' + playTimeFormatted: '§ePhát §6{time_remaining_human}' + region: '§eĐi đến §6{region_id}' + tame: '§eThuần phục §6{mobs}' + textBetwteenBranch: '§e hoặc' diff --git a/core/src/main/resources/locales/zh_CN.yml b/core/src/main/resources/locales/zh_CN.yml index 1611b4e3..72baa334 100644 --- a/core/src/main/resources/locales/zh_CN.yml +++ b/core/src/main/resources/locales/zh_CN.yml @@ -1,836 +1,801 @@ --- -msg: - quest: - finished: - base: '§a恭喜你完成了任务 §o§6{0}§r§a!' - obtain: '§a你获得了 {0}!' - started: '§a你接受了任务 §r§e{0}§o§6!' - created: '§a你成功地创建了 "§e{0}§a" 任务, 包含 {1} 个阶段!' - edited: '§a你成功地修改了 "§e{0}§a", 包含 {1} 个阶段!' - createCancelled: '§c抱歉,任务创建/编辑已被其他插件取消...' - cancelling: '§c已取消创建任务.' - editCancelling: '§c已取消编辑任务.' - invalidID: '§cID为 {0} 的任务不存在.' - invalidPoolID: '§c任务池{0}不存在。' - alreadyStarted: '§c你已经接受了这个任务!' - notStarted: '§c你未执行这个任务。' - quests: - maxLaunched: '§c你不能同时进行多于{0}个任务……' - nopStep: '§c这个任务没有任何阶段... :-)' - updated: '§7已更新任务 {0} !' - checkpoint: '§7已到达任务记录点!' - failed: '§6任务{0}失败……' - pools: - noTime: '§c你必须先等待一会儿才能执行其它任务。' - allCompleted: '§7你已完成所有任务!' - noAvailable: '§7没有更多可用的任务……' - maxQuests: '§c你不能同时进行多于 {0}个任务……' - questItem: - drop: '§c你不能丢弃任务物品!' - craft: '§c你不能用任务物品来合成物品!' - eat: '§c你不能吃下任务物品!' - stageMobs: - noMobs: '§c这个任务阶段没有要杀的怪物 :-)' - listMobs: '§a你需要杀死 {0}.' - writeNPCText: '输入玩家需要对NPC说的话. 输入 "help" 来获取帮助. (指令不需要输入 /)' - writeRegionName: '输入任务阶段所需前往的区域名.' - writeXPGain: '输入玩家获得的经验点. 最终获得: §a{0}' - writeMobAmount: '输入要击杀的怪物数.' - writeMobName: '§a请输入要击杀的自定义怪物名称:' - writeChatMessage: '要玩家输入的消息 (在开头加上 {SLASH} 来让玩家输入指令).' - writeMessage: '§a输入发送给玩家的消息' - writeStartMessage: '§a输入在开始任务时发送给玩家的消息,输入“null”则发送默认消息,输入“none”则不发送消息:' - writeEndMsg: '§a输入任务结束时发送的消息,输入“null” 则发送默认消息,输入“none”则不发送。你可以使用 "{0}"显示获得的奖励。' - writeEndSound: '§a输入在任务结束时播放给玩家的音效名,输入“null”则使用默认音效,输入“none”则不播放音效:' - writeDescriptionText: '任务阶段目标描述.' - writeStageText: '任务开始时发送的消息.' - moveToTeleportPoint: 前往指定的传送点. - writeNpcName: '§a请输入NPC名称:' - writeNpcSkinName: '§a请输入NPC皮肤名:' - writeQuestName: '§a输入任务名:' - writeCommand: '§a输入指令. (开头无需加上斜杠/) 你可以用 {PLAYER}来代表玩家名.' - writeHologramText: "§a输入全息文字. (输入 \"none\" 则不显示, 输入 \"null\" 显示默认文本)\n" - writeQuestTimer: '§a输入重新开始任务的冷却时间 (单位为分钟)(输入 "null" 则使用默认值)' - writeConfirmMessage: '§a请输入玩家确认加入任务的消息: (输入 "null" 则显示默认消息)' - writeQuestDescription: '§a请输入显示在玩家任务菜单内的任务描述。' - writeQuestMaterial: '§a请输入任务物品材料名。' - requirements: - quest: '§c你必须先完成任务§e "{0}"§c!' - level: '§c你的等级必须是{0}!' - job: '§c你的职业等级§e{1}§c必须是{0}!' - skill: '§c你的技能等级§e{1}§c必须是{0}!' - combatLevel: '§c你的战力等级必须是{0}!' - money: '§c你必须拥有{0}!' - waitTime: '§c你必须等待{0}才能重启该任务!' - experience: - edited: '已编辑获得的经验: {0}pts. 改为 {1}pts.' - selectNPCToKill: 选择要击杀的NPC. - npc: - remove: '§a已删除NPC.' - talk: '§a和§e{0}§a谈话.' - regionDoesntExists: '§c这个区域不存在... (你必须在目标区域同一世界内)' - npcDoesntExist: '§cID为{0}的NPC不存在.' - objectDoesntExist: '§c特殊物品 (ID为{0}) 不存在.' - number: - negative: '§c你必须输入正数!' - zero: '§c你必须输入大于0的数!' - invalid: '§c"{0}" 不是有效的数字.' - notInBounds: '§c你的数字必须介于{0}和{1}之间。' - errorOccurred: '§c插件发生错误,请联系管理员!错误代码为: {0}' - commandsDisabled: '§c你不能在这时输入指令.' - indexOutOfBounds: '§c数字 ({0}) 超过了区间 [{1}, {2}].' - invalidBlockData: '§c方块数据{0} 无效或者不兼容方块{1}。' - invalidBlockTag: '§c无法使用方块标签{0}。' - bringBackObjects: 把 {0} 带回给我. - inventoryFull: '§c你的背包已满, 任务奖励已掉落在地上.' - playerNeverConnected: '§c在玩家{0}身上找不到数据.' - playerNotOnline: '§c玩家 {0} 不在线.' - playerDataNotFound: '§c找不到玩家{0}的数据。' - versionRequired: '需要版本:§l{0}' - restartServer: '§7重启服务器查看修改。' - dialogs: - skipped: '§8§o已跳过对话。' - tooFar: '§7§o你离{0}太远了...' - command: - downloadTranslations: - syntax: '§c你必须指定要下载的语言。例如:"/quests downloadTranslations en_US"。' - notFound: '§c找不到{1}版本的{0}语言。' - exists: '§c文件 {0} 已存在。在你的指令后加上 "-overwrite" 覆盖文件。 (/quests downloadTranslations <lang> -overwrite)' - downloaded: '§a已下载语言{0}!§7你现在必须打开文件"/plugins/BeautyQuests/config.yml",更改§ominecraftTranslationsFile§7的值为{0},然后重启服务器。' - checkpoint: - noCheckpoint: '§c未找到任务{0}的记录点。' - questNotStarted: '§c你没有接受这个任务。' - setStage: - branchDoesntExist: '§cid为{0}的任务分支不存在。' - doesntExist: '§cID为{0}的任务阶段不存在.' - next: '§a已跳过该任务阶段.' - nextUnavailable: '§c"skip"选项在玩家到达任务分支结尾时无法使用。' - set: '§a已进入任务阶段 {0} .' - startDialog: - impossible: '§c现在无法开始对话。' - noDialog: '§c玩家没有待定对话。' - alreadyIn: '§c已对玩家播放对话。' - success: '§a已为玩家{0}播放任务{1}的对话!' - playerNeeded: '§c你必须是玩家才能使用这个指令.' - incorrectSyntax: '§c错误用法.' - noPermission: '§c你没有足够的权限以执行这个指令! (需要权限: {0})' - invalidCommand: - quests: '§c指令不存在, 输入 §e/quests help 查看帮助§c.' - simple: '§c指令不存在, 输入 §ehelp §c查看帮助(不需要 /)' - needItem: '§c你必须在主手手持该物品!' - itemChanged: '§a已编辑物品. 更改会在重启后生效.' - itemRemoved: '§a已删除全息物品.' - removed: '§a成功删除任务 {0}。' - leaveAll: '§e你强制结束了{0}个任务. §c出现{1}个错误.' - resetPlayer: - player: '§6你的所有任务数据 ({0}) 被 {1} 删除了.' - remover: '§6已删除{1}的{0}任务信息(和{2}任务池)。' - resetPlayerQuest: - player: '§6任务数据 {0} 已被 {1} 删除.' - remover: '§6{1} 的 {0} 条任务信息已被删除.' - resetQuest: '§6已移除{0}的任务数据。' - startQuest: '§6你接受了任务 {0} (UUID: {1}).' - startQuestNoRequirements: '§c玩家不满足任务{0}的需求……在指令结尾加上 "-overrideRequirements" 无视需求检测。' - cancelQuest: '§6你放弃了任务 {0}.' - cancelQuestUnavailable: '§c无法取消任务 {0} .' - backupCreated: '§6你成功地创建了任务和玩家数据的备份文件.' - backupPlayersFailed: '§c创建玩家数据备份失败.' - backupQuestsFailed: '§c创建任务数据备份失败.' - adminModeEntered: '§a你已进入管理员模式.' - adminModeLeft: '§a你退出了管理员模式.' - resetPlayerPool: - timer: '§a你已重置{0}任务池计时器{1}。' - full: '§a你重置了{0}任务池的{1}数据。' - scoreboard: - lineSet: '§6你成功地编辑了第 {0} 行.' - lineReset: '§6你成功地重置了第 {0} 行.' - lineRemoved: '§6你成功地删除了第 {0} 行.' - lineInexistant: '§c第 {0} 行不存在.' - resetAll: '§6你成功地清空了 {0} 的计分版.' - hidden: '§6已隐藏{0}的计分版.' - shown: '§6已重新显示{0}的计分版。' - own: - hidden: '§6已隐藏你的计分板。' - shown: '§6已显示你的计分板。' - help: - header: '§6§lBeautyQuests - §6帮助§r' - create: '§6/{0} create: §a创建任务' - edit: '§6/{0} edit: §a编辑任务' - remove: '§6/{0} remove [id]: §a删除ID为 [id] 的任务或点击任务NPC来删除' - finishAll: '§6/{0} finishAll <玩家名>: §a结束一名玩家所有进行中的任务。' - setStage: '§6/{0} setStage <玩家名> <id> [新任务分支] [新任务阶段]: §e跳过玩家当前的任务阶段/开始任务分支/s为任务分支设置任务阶段。' - startDialog: '§6/{0} startDialog <player> <quest id>: §e播放NPC任务阶段的待定对话或任务起始对话。' - resetPlayer: '§6/{0} resetPlayer <玩家名>: §e删除一名玩家的所有任务数据。' - resetPlayerQuest: '§6/{0} resetPlayerQuest <玩家名> [id]: §e删除一名玩家的一个任务数据' - seePlayer: '§6/{0} seePlayer <玩家名>: §a查看玩家的任务数据。' - reload: '§e/{0} reload: §a保存并重载配置和插件数据 - §c§o不推荐使用' - start: '§6/{0} start <玩家名> [id] : §e强制玩家接受任务.' - setItem: '§6/{0} setItem <talk|launch> : §e保存全息物品到数据文件内.' - setFirework: '§6/{0} setFirework: §e编辑默认结束烟花。' - adminMode: '§6/{0} adminMode : §e切换管理员模式 (显示消息)' - version: '§6/{0} version: §e查看插件版本.' - downloadTranslations: '§6/{0} downloadTranslations <language>: §e下载翻译文件' - save: '§6/{0} save: §a手动保存数据.' - list: '§e/{0} list: §a查看任务列表 (部分版本无效)' - typeCancel: '§a输入 "cancel" 返回到上一条消息.' - editor: - blockAmount: '§e请输入所需方块数:' - blockName: '§a请输入方块名:' - blockData: '§a请输入方块数据 (可用的方块数据: {0}):' - blockTag: '§a请输入方块标签 (可用标签:§7{0}§a):' - typeBucketAmount: '§a请输入要装满桶的数量:' - typeDamageAmount: '输入玩家需要造成的伤害:' - goToLocation: '§a前往该任务阶段指定地点。' - typeLocationRadius: '§a请输入距离指定位置所需的距离:' - typeGameTicks: '§a请输入所需的刻数:' - already: '§c你已在编辑器中.' - stage: - location: - typeWorldPattern: '§a输入世界名称的正则表达式:' - enter: - title: '§6~ 进入编辑器模式 ~' - subtitle: '§e输入 "/quests exitEditor" 强制退出任务编辑器。' - list: '§c⚠ §7你已进入"list"编辑器。输入"add"添加一行。使用 "help" (无需斜杠) 查看帮助。§e§l输入"close"退出编辑器。' - chat: '§6你已进入编辑器模式。输入"/quests exitEditor" 强制退出编辑器。(不推荐使用,最好使用 "close" 或 "cancel" 回到上一个菜单)' - npc: - enter: '§a点击一个NPC,或输入"cancel"取消.' - choseStarter: '§a选择接受任务的NPC.' - notStarter: '§c这个NPC没有可以接受的任务...' - text: - argNotSupported: '§c不支持 {0} 参数.' - chooseLvlRequired: '§a输入所需等级:' - chooseJobRequired: '§a输入所需的工作名:' - choosePermissionRequired: '§a输入开始任务所需权限:' - choosePermissionMessage: '§e如果玩家没有所需权限则显示的拒绝消息. (输入 "null" 跳过这步)' - choosePlaceholderRequired: - identifier: '§e输入所需的占位符名 (§l不用加上 %%§r§e).' - value: '§a请输入所需的§e%§e{0}§e%§a占位符值:' - chooseSkillRequired: '§a输入技能名:' - chooseMoneyRequired: '§e输入所需金额:' - reward: - permissionName: '§a请输入权限名称。' - permissionWorld: '§a请输入可编辑权限的世界名,输入"null"则所有世界可编辑。' - money: '§e输入获得的钱数:' - wait: '§a输入所需等待游戏刻数(1秒=20刻)' - random: - min: '§a输入给予玩家的最低奖励数量 (包括全部)。' - max: '§a输入给予玩家的最高奖励数量 (包括全部)。' - chooseObjectiveRequired: '§a请输入目标名。' - chooseObjectiveTargetScore: '§a请输入完成任务目标所需目标数。' - chooseRegionRequired: '§a请输入所需区域名 (你必须与该区域在同一个世界中)。' - selectWantedBlock: '§a用木棍点击开始任务阶段的方块.' - itemCreator: - itemType: '§a输入物品类型名:' - itemAmount: '§e请输入所需物品数:' - itemName: '§a输入物品名:' - itemLore: '§e修改物品描述. 输入 "help" 查看帮助.' - unknownItemType: '§c未知的物品类型.' - invalidItemType: '§c无效的物品类型 (必须是物品而不能是方块).' - unknownBlockType: '§c未知方块类型。' - invalidBlockType: '§c无效的方块类型。' - dialog: - syntax: '§c正确用法 : {0}{1} <消息>' - syntaxRemove: '§c正确用法: remove <id>' - player: '§a已为玩家添加消息 "§7{0}§a"。' - npc: '§a已为NPC添加消息 "§7{0}§a"。' - noSender: '§a已添加无发送者的消息“{0}”。' - messageRemoved: '§a已删除消息 "§7{0}§a"。' - edited: '§a已编辑消息 "§7{0}§a"。' - soundAdded: '§a已为消息 "§7{1}§a"添加音效 "§7{0}§a"。' - cleared: '§a已删除{0}条消息.' - help: - header: '§e§lBeautyQuest - §6对话编辑器帮助' - npc: '§npc <message>: §b添加一条由NPC说出的消息。' - player: '§6player <message>: §b添加一条由玩家说出的消息。' - nothing: '§6noSender <消息>: §e添加一条没有发送者的消息.' - remove: '§6emove <id>: §e删除一条消息.' - list: '§elist: §b查看所有的消息.' - npcInsert: '§enpcinsert <id> <消息>: §b插入一条由NPC说出的话.' - playerInsert: '§eplayerinsert <id> <消息>: §b插入一条由玩家说出的话.' - nothingInsert: '§enothinginsert <id> <消息>: §b插入一条没有任何前缀的消息.' - edit: '§6edit <id> <message>:§e编辑消息。' - addSound: '§eaddsound <id> <音效名>: §b给一条消息添加音效.' - clear: '§eclear: §b删除所有消息.' - close: '§eclose: §b退出并保存所有消息.' - setTime: '§6setTime <id> <时间>: §e设置自动播放下一条消息的时间(单位为刻) 。' - npcName: '§6npcname [自定义NPC名称]: §eSet (或重置为默认) 自定义NPC名称' - skippable: '§6skippable [true|false]: §e设置是否可跳过对话' - timeSet: '§a已编辑消息 {0} 的时间: 现在是 {1} 刻。' - timeRemoved: '§a已删除消息{0}的时间。' - npcName: - set: '§a自定义NPC名称已设置为§7{1}§a (原为§7{0}§a)' - unset: '§a自定义NPC名称重置为默认值 (原为§7{0}§a)' - skippable: - set: '§a对话可跳过状态已设置为§7{1}§a (原为§7{0}§a)' - unset: '§a对话可跳过状态已重置为默认§7{1}§a (原为§7{0}§a)' - mythicmobs: - list: '§a所有的MythocMobs:' - isntMythicMob: '§c这个MythicMob不存在.' - disabled: '§cMythicMob已关闭.' - advancedSpawnersMob: '输入所需击杀的自定义刷怪笼怪物名称:' - textList: - syntax: '§c正确用法: ' - added: '§a已添加文本 "§7{0}§a"。' - removed: '§a已删除文本 "§7{0}§a"。' - help: - header: '§6§lBeautyQuests — 编辑器列表帮助' - add: '§6add [消息]: §e添加一条文本.' - remove: '§6remove [id]: §e删除一条文本.' - list: '§6list: §e查看所有已添加的文本.' - close: '6close: §e确认添加文本并退出编辑器.' - availableElements: '可用元素:§e{0}' - noSuchElement: '§c没有这样的元素。可用元素:§e{0}' - invalidPattern: '§c无效的正则表达式§4{0}§c。' - comparisonTypeDefault: '§a请选择你想要在{0}中使用的比较类型。默认比较类型为:§e§l{1}§r§a。输入§onull§r§a使用。' - scoreboardObjectiveNotFound: '§c未知的计分板目标。' - pool: - hologramText: '请输入该池的自定义全息显示文本(输入“null”使用默认值)。' - maxQuests: '输入在该池中可运行的最大任务数。' - questsPerLaunch: '输入点击NPC时给予玩家的任务数。' - timeMsg: '请输入玩家可接取新任务的等候时间。(默认单位:天)' - title: - title: '输入标题文本(输入“null”则不显示文本)。' - subtitle: '输入副标题文本(输入“null”则不显示文本)。' - fadeIn: '输入淡入持续时间,单位为刻(20刻=1秒)。' - stay: '输入停留持续时间,单位为刻(20刻=1秒)。' - fadeOut: '输入淡出持续时间,单位为刻(20刻=1秒)。' - colorNamed: '输入颜色名称。' - color: '可以输入十六位格式(#XXXXX)或RGB格式(RED GRE BLU)的颜色。' - invalidColor: '你输入的颜色无效,必须是十六位或RGB颜色。' - firework: - invalid: '这件物品不是有效的烟花。' - invalidHand: '你必须在主手手持烟花。' - edited: '已编辑任务烟花!' - removed: '已移除任务烟花!' - writeCommandDelay: '§a请输入指令延迟,单位为刻。' advancement: finished: Finished notStarted: Not started +description: + requirement: + class: '{class_name} 职业' + combatLevel: 战斗等级 {short_level} + faction: '{faction_name} 派系' + jobLevel: '{job_name} {short_level}级' + level: '{short_level}级' + quest: 完成任务 §e{quest_name} + skillLevel: '{skill_name} {short_level}级' + title: '§8§l要求:' + reward: + title: '§8§l奖励:' +indication: + cancelQuest: '§7您确定要取消任务 {quest_name}?' + closeInventory: '§7你确定要关闭该页面吗?' + removeQuest: '§7您确定要删除任务 {quest}?' + startQuest: '§7您是否想要接受任务 {quest_name}?' inv: - validate: '§b§l确认' - cancel: '§c§l取消' - search: '§e§l搜索' addObject: '§a添加一个目标' + block: + blockData: '§d方块数据(高级)' + blockName: '§b自定义方块名称' + blockTag: '§d标签 (高级)' + blockTagLore: 选择描述可能方块列表的标签。可使用数据包自定义标签。你可以在Minecraft Wiki查询标签列表。 + material: '§e材料: {block_type}' + materialNotItemLore: 所选方块无法显示为物品。它仍正确地存储为{block_material}。 + name: 选择方块 + blockAction: + location: '§e选择精确位置' + material: '§e选择方块材料' + name: 选择方块行动 + blocksList: + addBlock: '§a点击添加一个方块.' + name: 选择方块 + buckets: + name: 桶的类型 + cancel: '§c§l取消' + cancelActions: + name: 取消行动 + checkpointActions: + name: 记录点行动 + chooseAccount: + name: '§5选择哪一个帐号?' + chooseQuest: + menu: '§a任务菜单' + menuLore: 前往任务菜单。 + name: '§5选择哪一个任务?' + classesList.name: 职业列表 + classesRequired.name: 所需职业 + command: + console: 控制台 + delay: '§b延迟' + name: '§8指令' + parse: 解析占位符 + value: '§b指令' + commandsList: + console: '§e控制台: {command_console}' + name: 指令列表 + value: '§e指令: {command_label}' confirm: name: '§8你确认?' - 'yes': '§a确认' 'no': '§c让我再想想' + 'yes': '§a确认' create: - stageCreate: '§a创建新的阶段' - stageRemove: '§c删除这一阶段' - stageUp: 上移 - stageDown: 下移 - stageType: '§7阶段类型:§e{0}' - cantFinish: '§7你必须先创建至少一个任务阶段!' - findNPC: '§a寻找一个NPC' + NPCSelect: '§e选择或创建NPC' + NPCText: '§e编辑NPC的文本对话' + breedAnimals: '§a饲养动物' bringBack: '§a带回物品' - findRegion: '§a找到一片区域' - killMobs: '§a击杀怪物' - mineBlocks: '§a破坏方块' - placeBlocks: '§a放置方块' - talkChat: '§a在聊天框内输入' - interact: '§a点击方块' - fish: '§a钓鱼' - melt: '§熔炼物品' - enchant: '§附魔物品' - craft: '§a合成物品' bucket: '§a装满桶' - location: 前往指定位置 - playTime: '§e游戏时间' - breedAnimals: '§a饲养动物' - tameAnimals: '§a驯服动物' - death: '§c死亡' + cancelMessage: 取消发送 + cantFinish: '§7你必须先创建至少一个任务阶段!' + changeEntityType: '§e更改实体类型' + changeTicksRequired: '§e需要更改游玩刻' + craft: '§a合成物品' + currentRadius: '§e当前距离: §6{radius}' dealDamage: '§c对怪物造成伤害' + death: '§c死亡' eatDrink: '§a食用食物或饮用药水' - NPCText: '§e编辑NPC的文本对话' - dialogLines: '{0}行' - NPCSelect: '§e选择或创建NPC' - hideClues: 隐藏任务指示 (粒子效果和全息文字) - gps: 显示指向任务目标的指南针 - editMobsKill: '§e编辑要击杀的怪物' - mobsKillFromAFar: 需要远程击杀怪物 editBlocksMine: '§e编辑要破坏的方块' - preventBlockPlace: 防止玩家破坏方块 editBlocksPlace: '§e编辑要放置的方块' - editMessageType: '§e编辑要输入的消息' - cancelMessage: 取消发送 + editBucketAmount: '§e编辑要装满的桶数量' + editBucketType: '§e编辑要装满的桶类型' + editFishes: '§e编辑所需的鱼' + editItem: '§e编辑要合成的物品' + editItemsToEnchant: '§e编辑要附魔的物品' + editItemsToMelt: '§e编辑要熔炼的物品' + editLocation: '§e编辑位置' + editMessageType: '§e编辑要输入的消息' + editMobsKill: '§e编辑要击杀的怪物' + editRadius: '§e编辑离目的地的距离' + enchant: '§附魔物品' + findNPC: '§a寻找一个NPC' + findRegion: '§a找到一片区域' + fish: '§a钓鱼' + hideClues: 隐藏任务指示 (粒子效果和全息文字) ignoreCase: 忽略消息大小写 + interact: '§a点击方块' + killMobs: '§a击杀怪物' + leftClick: 必须左击 + location: 前往指定位置 + melt: '§熔炼物品' + mineBlocks: '§a破坏方块' + mobsKillFromAFar: 需要远程击杀怪物 + placeBlocks: '§a放置方块' + playTime: '§e游戏时间' + preventBlockPlace: 防止玩家破坏方块 replacePlaceholders: 使用PAPI替换{PLAYER}和占位符 + selectBlockLocation: '§6选择方块位置' + selectBlockMaterial: '§e选择方块材料' selectItems: '§b选择所需的物品' - selectItemsMessage: '§e编辑询问消息' selectItemsComparisons: '§e选择物品比较式(高级)' + selectItemsMessage: '§e编辑询问消息' selectRegion: '§7选择一片区域' - toggleRegionExit: 退出时 - stageStartMsg: '§e编辑阶段开始的消息' - selectBlockLocation: '§6选择方块位置' - selectBlockMaterial: '§e选择方块材料' - leftClick: 必须左击 - editFishes: '§e编辑所需的鱼' - editItemsToMelt: '§e编辑要熔炼的物品' - editItemsToEnchant: '§e编辑要附魔的物品' - editItem: '§e编辑要合成的物品' - editBucketType: '§e编辑要装满的桶类型' - editBucketAmount: '§e编辑要装满的桶数量' - editLocation: '§e编辑位置' - editRadius: '§e编辑离目的地的距离' - currentRadius: '§e当前距离: §6{0}' - changeTicksRequired: '§e需要更改游玩刻' - changeEntityType: '§e更改实体类型' stage: - location: - worldPattern: '§a设置世界名称模式 §d(高级选项)' - worldPatternLore: '如果你想要匹配特定模式的任意世界都能完成任务阶段,请在此输入正则表达式。' - death: - causes: '§a设置死因 §d(高级)' - anyCause: 任何死因 - setCauses: '{0} 死因' dealDamage: damage: '§e要造成的伤害' targetMobs: '§c要造成伤害的怪物对象' + death: + anyCause: 任何死因 + causes: '§a设置死因 §d(高级)' + setCauses: '{causes_amount} 死因' eatDrink: items: '§e编辑要食用或饮用的物品' - stages: - name: '§8创建任务阶段' - nextPage: '§e下一页' - laterPage: '§e上一页' - endingItem: '§e编辑阶段结束奖励' - descriptionTextItem: '§e编辑文本描述' - regularPage: '§a普通任务阶段' - branchesPage: '§d分支任务阶段' - previousBranch: '§e返回上一个分支' - newBranch: '§e前往新的任务分支' - validationRequirements: '§e验证需求' - validationRequirementsLore: 所有需求必须匹配尝试完成阶段的玩家。否则该阶段无法完成。 + location: + worldPattern: '§a设置世界名称模式 §d(高级选项)' + worldPatternLore: 如果你想要匹配特定模式的任意世界都能完成任务阶段,请在此输入正则表达式。 + stageCreate: '§a创建新的阶段' + stageDown: 下移 + stageRemove: '§c删除这一阶段' + stageStartMsg: '§e编辑阶段开始的消息' + stageType: '§7阶段类型:§e{stage_type}' + stageUp: 上移 + talkChat: '§a在聊天框内输入' + tameAnimals: '§a驯服动物' + toggleRegionExit: 退出时 + damageCause: + name: 造成伤害 + damageCausesList: + name: 造成伤害列表 details: - hologramLaunch: '§e编辑 “启动” 全息项' - hologramLaunchLore: 显示在接受任务的NPC头上的全息文字。 - hologramLaunchNo: '§e编辑 “启动不可用” 全息项' - hologramLaunchNoLore: 在玩家没有接受任务时显示在NPC头上的全息文字。 + actions: '{amount}行动' + auto: 登录时自动开始任务 + autoLore: 如果启用,则玩家首次加入服务器时将自动开始该任务。 + bypassLimit: 忽略任务上限 + bypassLimitLore: 如果启用,即使玩家已经达到任务上限也能接受任务。 + cancelRewards: '§c取消行动' + cancelRewardsLore: 玩家取消该任务时触发的行动。 + cancellable: 玩家可取消任务 + cancellableLore: 允许玩家在任务菜单中取消任务。 + createQuestLore: 你必须设定任务名。 + createQuestName: '§l创建任务' customConfirmMessage: '§e编辑确认接受任务的消息' customConfirmMessageLore: 显示在确认菜单中的消息。 customDescription: '§e编辑任务描述' customDescriptionLore: 在GUI中显示在任务名下方的描述。 - name: '§8最终任务详细设置' - multipleTime: - itemName: 切换是否可重复 - itemLore: 任务是否可以多次完成? - cancellable: 玩家可取消任务 - cancellableLore: 允许玩家在任务菜单中取消任务。 - startableFromGUI: 可从GUI菜单中开始任务 - startableFromGUILore: 允许玩家在任务菜单中开始任务。 - scoreboardItem: 启用计分版 - scoreboardItemLore: 如果禁用,则该任务目标不会显示在计分板上。 + customMaterial: '§a编辑任务物品材料名' + customMaterialLore: 在任务菜单中代表该任务的物品图标。 + defaultValue: '§8(默认值)' + editQuestName: '§l编辑任务' + editRequirements: '§e编辑需求' + editRequirementsLore: 接受任务所需前置。 + endMessage: '§a编辑任务结束消息' + endMessageLore: 将在任务结束时发送给玩家的消息。 + endSound: '§e编辑结束音效' + endSoundLore: 在任务结束时播放的音效。 + failOnDeath: 玩家死亡时任务失败 + failOnDeathLore: 当玩家死亡时是否取消任务? + firework: '§d任务结束烟花' + fireworkLore: 玩家完成任务时发射的烟花 + fireworkLoreDrop: 把你的自定义烟花放在这里 hideNoRequirementsItem: 未满足需求时隐藏 hideNoRequirementsItemLore: 如果启用,在未满足需求时任务将不会显示在任务菜单中。 - bypassLimit: 忽略任务上限 - bypassLimitLore: 如果启用,即使玩家已经达到任务上限也能接受任务。 - auto: 登录时自动开始任务 - autoLore: 如果启用,则玩家首次加入服务器时将自动开始该任务。 + hologramLaunch: '§e编辑 “启动” 全息项' + hologramLaunchLore: 显示在接受任务的NPC头上的全息文字。 + hologramLaunchNo: '§e编辑 “启动不可用” 全息项' + hologramLaunchNoLore: 在玩家没有接受任务时显示在NPC头上的全息文字。 + hologramText: '§e全息文字' + hologramTextLore: 显示在可接受任务的NPC的头上的全息文字。 + keepDatas: 保留玩家数据 + keepDatasLore: '强制插件保存玩家数据,即使是已编辑阶段也会保存。 §c§l警告§c- 启用此选项可能会损坏你的玩家数据。' + loreReset: '§e§l所有玩家的进度将被重置' + multipleTime: + itemLore: 任务是否可以多次完成? + itemName: 切换是否可重复 + name: '§8最终任务详细设置' + optionValue: '§8数值:§7{value}' questName: '§a§l编辑任务名' questNameLore: 必须设置一个名称来创建任务。 - setItemsRewards: '§7编辑获得的物品' + questPool: '§e任务池' + questPoolLore: 将该任务加到任务池中 removeItemsReward: 从物品栏中移除物品 - setXPRewards: '§e编辑获得的经验' + requiredParameter: '§7所需参数' + requirements: '{amount} 个任务需求' + rewards: '{amount} 个奖励' + rewardsLore: 任务接受时执行的行动。 + scoreboardItem: 启用计分版 + scoreboardItemLore: 如果禁用,则该任务目标不会显示在计分板上。 + selectStarterNPC: '§6§l选择接受任务的NPC' + selectStarterNPCLore: 点击选中的NPC将开始任务。 + selectStarterNPCPool: '§c:⚠ 已选择一个任务池' setCheckpointReward: '§e编辑记录点奖励' + setItemsRewards: '§7编辑获得的物品' + setMoneyReward: '§e编辑获得的金钱' + setPermReward: '§e编辑权限' setRewardStopQuest: '§c停止任务' - setRewardsWithRequirements: '§e需满足需求的奖励' setRewardsRandom: '§d随机奖励' - setPermReward: '§e编辑权限' - setMoneyReward: '§e编辑获得的金钱' - setWaitReward: '§e编辑“等待”奖励' + setRewardsWithRequirements: '§e需满足需求的奖励' setTitleReward: '§e编辑标题奖励' - selectStarterNPC: '§6§l选择接受任务的NPC' - selectStarterNPCLore: 点击选中的NPC将开始任务。 - selectStarterNPCPool: '§c:⚠ 已选择一个任务池' - createQuestName: '§l创建任务' - createQuestLore: 你必须设定任务名。 - editQuestName: '§l编辑任务' - endMessage: '§a编辑任务结束消息' - endMessageLore: 将在任务结束时发送给玩家的消息。 - endSound: '§e编辑结束音效' - endSoundLore: 在任务结束时播放的音效。 - startMessage: '§e编辑开始消息' - startMessageLore: 任务开始时发送给玩家的消息。 + setWaitReward: '§e编辑“等待”奖励' + setXPRewards: '§e编辑获得的经验' startDialog: '§e编辑任务开场白' startDialogLore: 当玩家点击任务NPC时,在任务开始之前播放的对话框。 - editRequirements: '§e编辑需求' - editRequirementsLore: 接受任务所需前置。 + startMessage: '§e编辑开始消息' + startMessageLore: 任务开始时发送给玩家的消息。 startRewards: '§6开始任务的奖励' startRewardsLore: 玩家接受任务时执行的行动。 - cancelRewards: '§c取消行动' - cancelRewardsLore: 玩家取消该任务时触发的行动。 - hologramText: '§e全息文字' - hologramTextLore: 显示在可接受任务的NPC的头上的全息文字。 + startableFromGUI: 可从GUI菜单中开始任务 + startableFromGUILore: 允许玩家在任务菜单中开始任务。 timer: '§b重启计时器' timerLore: 玩家可以再次开始任务的时间。 - requirements: '{0} 个任务需求' - rewards: '{0} 个奖励' - actions: '{0}行动' - rewardsLore: 任务接受时执行的行动。 - customMaterial: '§a编辑任务物品材料名' - customMaterialLore: 在任务菜单中代表该任务的物品图标。 - failOnDeath: 玩家死亡时任务失败 - failOnDeathLore: 当玩家死亡时是否取消任务? - questPool: '§e任务池' - questPoolLore: 将该任务加到任务池中 - firework: '§d任务结束烟花' - fireworkLore: 玩家完成任务时发射的烟花 - fireworkLoreDrop: 把你的自定义烟花放在这里 visibility: '§b任务可见度' visibilityLore: 选择在菜单栏何处显示任务,如果安装了卫星地图插件,则在地图上显示任务。 - keepDatas: 保留玩家数据 - keepDatasLore: |- - 强制插件保存玩家数据,即使是已编辑阶段也会保存。 - §c§l警告§c- 启用此选项可能会损坏你的玩家数据。 - loreReset: '§e§l所有玩家的进度将被重置' - optionValue: '§8数值:§7{0}' - defaultValue: '§8(默认值)' - requiredParameter: '§7所需参数' - itemsSelect: - name: 编辑物品 - none: |- - §a把物品放到这里或点击打开物品编辑器. - itemSelect: - name: 选择物品 - npcCreate: - name: 创建NPC - setName: '§a编辑NPC名称' - setSkin: '§e编辑NPC皮肤' - setType: '§a编辑NPC类型' - move: - itemName: '§6传送' - itemLore: '§a更改NPC位置.' - moveItem: '§a§l确认前往' - npcSelect: - name: 选择还是创建NPC? - selectStageNPC: '§6选择 NPC' - createStageNPC: '§e创建 NPC' + editTitle: + fadeIn: '§a淡入持续时间' + fadeOut: '§a淡出持续时间' + name: 编辑标题 + stay: '§b停留持续时间' + subtitle: '§e副标题' + title: '§6标题' entityType: name: '§5选择生物类型' - chooseQuest: - name: '§5选择哪一个任务?' - menu: '§a任务菜单' - menuLore: 前往任务菜单。 - mobs: - name: 选择怪物 - none: '§a点击添加怪物' - clickLore: |- - §a§l左击§a以编辑数量。 - §l§l§nShift§a§l+左击§a以编辑生物名称。 - §c§l右击§c以删除。 - setLevel: 设置最低等级 - mobSelect: - name: 选择怪物类型 - bukkitEntityType: '§e选择一个生物类型' - mythicMob: '§6选择一个MythicMob' - epicBoss: '§6选择一个Epic Boss' - boss: '§6选择一个Boss' - stageEnding: - locationTeleport: '§a编辑传送点' - command: '§a编辑执行的指令' - requirements: - name: 任务需求 - rewards: - name: 任务奖励 - commands: '指令: {0}' - teleportation: |- - §a已选取位置: - X: {0} - Y: {1} - Z: {2} - 世界: {3} - random: - rewards: 编辑奖励 - minMax: 编辑最小和最大值 - checkpointActions: - name: 记录点行动 - cancelActions: - name: 取消行动 - rewardsWithRequirements: - name: 需满足需求的奖励 - listAllQuests: - name: '§8任务' - listPlayerQuests: - name: '§8{0}的任务' - listQuests: - notStarted: 没有已开始的任务 - finished: 已完成的任务 - inProgress: 进行中的任务 - loreDialogsHistoryClick: '§7查看对话' - loreCancelClick: '§c取消任务' - loreStart: '§a§o点击开始任务。' - loreStartUnavailable: '§c§o你不满足任务需求,无法开始任务。' - timeToWaitRedo: '§3§o你可以在{0}后重启该任务。' - canRedo: '§3§o你可以再次接受这个任务!' - timesFinished: '§3该任务完成了{0}次。' + equipmentSlots: + name: 装备栏位 + factionsList.name: 派系列表 + factionsRequired.name: 所需派系 + itemComparisons: + bukkit: Bukkit原生比较 + bukkitLore: 使用Bukkit默认项目的比较系统。 比较材料、耐久度、NBT标签…… + customBukkit: Bukkit原生比较 - 无NBT + customBukkitLore: 使用Bukkit默认物品比较系统,但除去NBT标签。 兼容材料名、耐久度等 + enchants: 物品附魔 + enchantsLore: 比较物品附魔 + itemLore: 物品描述 + itemLoreLore: 比较物品描述 + itemName: 物品名称 + itemNameLore: 比较物品名称 + itemsAdder: ItemsAdder + itemsAdderLore: 比较ItemsAdder ID + material: 物品材料 + materialLore: 比较物品材料(比如石头|stone、铁剑|iron sword) + name: 物品比较式 + repairCost: 修复花费 + repairCostLore: 比较盔甲和武器的修复花费 itemCreator: - name: '§8物品编辑器' - itemType: '§b物品类型' + isQuestItem: '§b任务物品:' itemFlags: 开关物品标志显示 - itemName: '§b物品名' itemLore: '§b物品描述' - isQuestItem: '§b任务物品:' - command: - name: '§8指令' - value: '§b指令' - console: 控制台 - parse: 解析占位符 - delay: '§b延迟' - chooseAccount: - name: '§5选择哪一个帐号?' + itemName: '§b物品名' + itemType: '§b物品类型' + name: '§8物品编辑器' + itemSelect: + name: 选择物品 + itemsSelect: + name: 编辑物品 + none: '§a把物品放到这里或点击打开物品编辑器.' + listAllQuests: + name: '§8任务' listBook: + noQuests: 没有已创建的任务 + questMultiple: 可重复次数 questName: 任务名 - questStarter: 开始任务方式 questRewards: 任务奖励 - questMultiple: 可重复次数 - requirements: 任务需求 questStages: 任务阶段 - noQuests: 没有已创建的任务 - commandsList: - name: 指令列表 - value: '§e指令: {0}' - console: '§e控制台: {0}' - block: - name: 选择方块 - material: '§e材料: {0}' - materialNotItemLore: '所选方块无法显示为物品。它仍正确地存储为{0}。' - blockName: '§b自定义方块名称' - blockData: '§d方块数据(高级)' - blockTag: '§d标签 (高级)' - blockTagLore: '选择描述可能方块列表的标签。可使用数据包自定义标签。你可以在Minecraft Wiki查询标签列表。' - blocksList: - name: 选择方块 - addBlock: '§a点击添加一个方块.' - blockAction: - name: 选择方块行动 - location: '§e选择精确位置' - material: '§e选择方块材料' - buckets: - name: 桶的类型 + questStarter: 开始任务方式 + requirements: 任务需求 + listPlayerQuests: + name: '§8{player_name}的任务' + listQuests: + canRedo: '§3§o你可以再次接受这个任务!' + finished: 已完成的任务 + inProgress: 进行中的任务 + loreCancelClick: '§c取消任务' + loreDialogsHistoryClick: '§7查看对话' + loreStart: '§a§o点击开始任务。' + loreStartUnavailable: '§c§o你不满足任务需求,无法开始任务。' + notStarted: 没有已开始的任务 + timeToWaitRedo: '§3§o你可以在{time_left}后重启该任务。' + timesFinished: '§3该任务完成了{times_finished}次。' + mobSelect: + boss: '§6选择一个Boss' + bukkitEntityType: '§e选择一个生物类型' + epicBoss: '§6选择一个Epic Boss' + mythicMob: '§6选择一个MythicMob' + name: 选择怪物类型 + mobs: + name: 选择怪物 + none: '§a点击添加怪物' + setLevel: 设置最低等级 + npcCreate: + move: + itemLore: '§a更改NPC位置.' + itemName: '§6传送' + moveItem: '§a§l确认前往' + name: 创建NPC + setName: '§a编辑NPC名称' + setSkin: '§e编辑NPC皮肤' + setType: '§a编辑NPC类型' + npcSelect: + createStageNPC: '§e创建 NPC' + name: 选择还是创建NPC? + selectStageNPC: '§6选择 NPC' + particleEffect: + color: '§b粒子颜色' + name: 创建粒子特效 + shape: '§d粒子形状' + type: '§e粒子类型' + particleList: + colored: 彩色粒子 + name: 粒子列表 permission: name: 选择权限 perm: '§a权限' - world: '§a世界' - worldGlobal: '§b§l全局' remove: 删除权限 removeLore: '§7P将收回权限\n§7而非给予权限。' + world: '§a世界' + worldGlobal: '§b§l全局' permissionList: name: 权限列表 - removed: '§e已移除: §6{0}' - world: '§e世界:§6{0}' - classesRequired.name: 所需职业 - classesList.name: 职业列表 - factionsRequired.name: 所需派系 - factionsList.name: 派系列表 - poolsManage: - name: 任务池 - itemName: '§a池#{0}' - poolNPC: '§8NPC:§7{0}' - poolMaxQuests: '§8最大任务数:§7{0}' - poolQuestsPerLaunch: '§8每次给予的任务:§7{0}' - poolRedo: '§8可以重新接受已完成的任务:§7{0}' - poolTime: '§8任务之间的间隔:§7{0}' - poolHologram: '§8全息文本:§7{0}' - poolAvoidDuplicates: '§8避免重复:§7{0}' - poolQuestsList: '§7{0} §8任务:§7{1}' - create: '§a创建一个任务池' - edit: '§e> §6§o编辑任务池…… §e<' - choose: '§e> §6§o选择该任务池 §e<' + removed: '§e已移除: §6{permission_removed}' + world: '§e世界:§6{permission_world}' poolCreation: - name: 创建任务池 + avoidDuplicates: 避免重复 + avoidDuplicatesLore: '§8> §7尝试避免重复\n 同一任务' hologramText: '§e自定义任务池全息显示' maxQuests: '§a最大任务数' + name: 创建任务池 questsPerLaunch: 每次启动时开始的任务 - time: '§b设置任务之间的间隔' redoAllowed: 是否可重复完成 - avoidDuplicates: 避免重复 - avoidDuplicatesLore: '§8> §7尝试避免重复\n 同一任务' requirements: '§b开始任务所需前置' + time: '§b设置任务之间的间隔' poolsList.name: 任务池 - itemComparisons: - name: 物品比较式 - bukkit: Bukkit原生比较 - bukkitLore: "使用Bukkit默认项目的比较系统。\n比较材料、耐久度、NBT标签……" - customBukkit: Bukkit原生比较 - 无NBT - customBukkitLore: "使用Bukkit默认物品比较系统,但除去NBT标签。\n兼容材料名、耐久度等" - material: 物品材料 - materialLore: '比较物品材料(比如石头|stone、铁剑|iron sword)' - itemName: 物品名称 - itemNameLore: 比较物品名称 - itemLore: 物品描述 - itemLoreLore: 比较物品描述 - enchants: 物品附魔 - enchantsLore: 比较物品附魔 - repairCost: 修复花费 - repairCostLore: 比较盔甲和武器的修复花费 - editTitle: - name: 编辑标题 - title: '§6标题' - subtitle: '§e副标题' - fadeIn: '§a淡入持续时间' - stay: '§b停留持续时间' - fadeOut: '§a淡出持续时间' - particleEffect: - name: 创建粒子特效 - shape: '§d粒子形状' - type: '§e粒子类型' - color: '§b粒子颜色' - particleList: - name: 粒子列表 - colored: 彩色粒子 - damageCause: - name: 造成伤害 - damageCausesList: - name: 造成伤害列表 + poolsManage: + choose: '§e> §6§o选择该任务池 §e<' + create: '§a创建一个任务池' + edit: '§e> §6§o编辑任务池…… §e<' + itemName: '§a池#{pool}' + name: 任务池 + poolAvoidDuplicates: '§8避免重复:§7{pool_duplicates}' + poolHologram: '§8全息文本:§7{pool_hologram}' + poolMaxQuests: '§8最大任务数:§7{pool_max_quests}' + poolNPC: '§8NPC:§7{pool_npc_id}' + poolQuestsList: '§7{pool_quests_amount} §8任务:§7{pool_quests}' + poolQuestsPerLaunch: '§8每次给予的任务:§7{pool_quests_per_launch}' + poolRedo: '§8可以重新接受已完成的任务:§7{pool_redo}' + poolTime: '§8任务之间的间隔:§7{pool_time}' + requirements: + name: 任务需求 + rewards: + commands: '指令: {amount}' + name: 任务奖励 + random: + minMax: 编辑最小和最大值 + rewards: 编辑奖励 + rewardsWithRequirements: + name: 需满足需求的奖励 + search: '§e§l搜索' + stageEnding: + command: '§a编辑执行的指令' + locationTeleport: '§a编辑传送点' + stages: + branchesPage: '§d分支任务阶段' + descriptionTextItem: '§e编辑文本描述' + endingItem: '§e编辑阶段结束奖励' + laterPage: '§e上一页' + name: '§8创建任务阶段' + newBranch: '§e前往新的任务分支' + nextPage: '§e下一页' + previousBranch: '§e返回上一个分支' + regularPage: '§a普通任务阶段' + validationRequirements: '§e验证需求' + validationRequirementsLore: 所有需求必须匹配尝试完成阶段的玩家。否则该阶段无法完成。 + validate: '§b§l确认' visibility: + finished: '“已完成”菜单栏' + inProgress: '“进行中”菜单栏' + maps: 地图(比如Dynmap或BlueMap) name: 任务可见度 notStarted: '“未开始”菜单栏' - inProgress: '“进行中”菜单栏' - finished: '“已完成”菜单栏' - maps: '地图(比如Dynmap或BlueMap)' - equipmentSlots: - name: 装备栏位 -scoreboard: - name: '§6§l任务' - noLaunched: '§c你没有进行中的任务.' - noLaunchedName: '§c§l载入中' - noLaunchedDescription: '§c§o载入中' - textBetwteenBranch: '§e或' - asyncEnd: '§ex' - stage: - region: '§e找到区域 §6{0}' - npc: '§e和NPC谈话 §6{0}' - items: '§e将物品带给§6{0}§e:' - mobs: '§e击杀 §6{0}' - mine: '§e挖掘 {0}' - placeBlocks: '§e放置{0}' - chat: '§e输入 §6{0}' - interact: '§e点击在§6{0}的方块' - interactMaterial: '§e点击§6{0}§e方块' - fish: '§e钓鱼 §6{0}' - melt: '§e熔炼 §6{0}' - enchant: '§e附魔 §6{0}' - craft: '§e合成 §6{0}' - bucket: '§e装满 §6{0}' - location: '§e前往位于 §6{3}的坐标§6{0}§e, §6{1}§e, §6{2}§e ' - playTimeFormatted: '§e游玩 §6{0}' - breed: '§e饲养§6{0}' - tame: '§e驯服§6{0}' - die: '§c死亡' - dealDamage: - any: '§c造成{0}点伤害' - mobs: '§c对{1}造成{0}点伤害' - eatDrink: '§e消耗§6{0}' -indication: - startQuest: '§7您是否想要接受任务 {0}?' - closeInventory: '§7你确定要关闭该页面吗?' - cancelQuest: '§7您确定要取消任务 {0}?' - removeQuest: '§7您确定要删除任务 {0}?' -description: - requirement: - title: '§8§l要求:' - level: '{0}级' - jobLevel: '{1} {0}级' - combatLevel: '战斗等级 {0}' - skillLevel: '{1} {0}级' - class: '{0} 职业' - faction: '{0} 派系' - quest: '完成任务 §e{0}' - reward: - title: '§8§l奖励:' misc: - format: - prefix: '§6<§e§l任务§r§6> §r' - npcText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - selfText: '§6[{2}/{3}] §e§l{0}:§r§e {1}' - offText: '§r§e{0}' - time: - weeks: '{0}周' - days: '{0}天' - hours: '{0}小时' - minutes: '{0}分钟' - lessThanAMinute: '少于一分钟' - stageType: - region: 寻找区域 - npc: 寻找 NPC - items: 带回物品 - mobs: 击杀怪物 - mine: 破坏方块 - placeBlocks: 放置方块 - chat: 在聊天框内说话 - interact: 与方块交互 - Fish: 钓鱼 - Melt: 熔炼物品 - Enchant: 附魔物品 - Craft: 合成物品 - Bucket: 装满桶 - location: 寻找地点 - playTime: 游戏时间 - breedAnimals: 饲养动物 - tameAnimals: 驯服动物 - die: 死亡 - dealDamage: 造成伤害 - eatDrink: 食用或饮用 - comparison: - equals: 等于{0} - different: 不同于{0} - less: 精确小于 {0} - lessOrEquals: 小于{0} - greater: 精确大于{0} - greaterOrEquals: 大于{0} - requirement: - logicalOr: '§d逻辑 或 (前置)' - skillAPILevel: '§d所需SkillAPI等级' - class: '§b所需职业' - faction: '§b所需派系' - jobLevel: '§b所需工作等级' - combatLevel: '§b所需战斗等级' - experienceLevel: '§b所需经验等级' - permissions: '§3所需权限' - scoreboard: '§d所需分数' - region: '§d需要区域' - placeholder: '§b所需占位符数值' - quest: '§a所需前置任务' - mcMMOSkillLevel: '§d所需技能等级' - money: '§d所需金额' - equipment: '§e所需装备' + amount: '§e数量: {amount}' + amounts: + comparisons: '{comparisons_amount}个对比' + dialogLines: '{lines_amount}行' + items: '{items_amount}件物品' + mobs: '{mobs_amount}个怪物' + permissions: '{permissions_amount}个权限' + and: 和 bucket: - water: 水桶 lava: 岩浆桶 milk: 牛奶桶 snow: 雪桶 + water: 水桶 click: - right: 右击 left: 左击 - shift-right: Shift+右击 - shift-left: Shift+左击 middle: 中键点击 - amounts: - items: '{0}件物品' - comparisons: '{0}个对比' - dialogLines: '{0}行' - permissions: '{0}个权限' - mobs: '{0}个怪物' - ticks: '{0}刻' - questItemLore: '§e§o任务物品' - hologramText: '§8§l任务NPC' - poolHologramText: '§e有可接受的新任务!' - mobsProgression: '§6§l{0}: §r§e{1}/{2}' - entityType: '§e生物类型: {0}' - entityTypeAny: '§e任何实体' - enabled: 已启用 + right: 右击 + shift-left: Shift+左击 + shift-right: Shift+右击 + comparison: + different: 不同于{number} + equals: 等于{number} + greater: 精确大于{number} + greaterOrEquals: 大于{number} + less: 精确小于 {number} + lessOrEquals: 小于{number} disabled: 已关闭 - unknown: 未知 + enabled: 已启用 + entityType: '§e生物类型: {entity_type}' + entityTypeAny: '§e任何实体' + format: + prefix: '§6<§e§l任务§r§6> §r' + hologramText: '§8§l任务NPC' + 'no': '否' notSet: '§c未设置' - unused: '§e§l未设置' - used: '§6§l已设置' - remove: '§e§o点击鼠标中键删除' + or: 或 + poolHologramText: '§e有可接受的新任务!' + questItemLore: '§e§o任务物品' removeRaw: 移除 + requirement: + class: '§b所需职业' + combatLevel: '§b所需战斗等级' + equipment: '§e所需装备' + experienceLevel: '§b所需经验等级' + faction: '§b所需派系' + jobLevel: '§b所需工作等级' + logicalOr: '§d逻辑 或 (前置)' + mcMMOSkillLevel: '§d所需技能等级' + money: '§d所需金额' + permissions: '§3所需权限' + placeholder: '§b所需占位符数值' + quest: '§a所需前置任务' + region: '§d需要区域' + scoreboard: '§d所需分数' + skillAPILevel: '§d所需SkillAPI等级' reset: 重置 - or: 或 - amount: '§e数量: {0}' - items: 物品 - expPoints: 经验点数 + stageType: + Bucket: 装满桶 + Craft: 合成物品 + Enchant: 附魔物品 + Fish: 钓鱼 + Melt: 熔炼物品 + breedAnimals: 饲养动物 + chat: 在聊天框内说话 + dealDamage: 造成伤害 + die: 死亡 + eatDrink: 食用或饮用 + interact: 与方块交互 + items: 带回物品 + location: 寻找地点 + mine: 破坏方块 + mobs: 击杀怪物 + npc: 寻找 NPC + placeBlocks: 放置方块 + playTime: 游戏时间 + region: 寻找区域 + tameAnimals: 驯服动物 + ticks: '{ticks}刻' + time: + days: '{days_amount}天' + hours: '{hours_amount}小时' + lessThanAMinute: 少于一分钟 + minutes: '{minutes_amount}分钟' + weeks: '{weeks_amount}周' + unknown: 未知 'yes': '是' - 'no': '否' - and: 和 +msg: + bringBackObjects: 把 {items} 带回给我. + command: + adminModeEntered: '§a你已进入管理员模式.' + adminModeLeft: '§a你退出了管理员模式.' + backupCreated: '§6你成功地创建了任务和玩家数据的备份文件.' + backupPlayersFailed: '§c创建玩家数据备份失败.' + backupQuestsFailed: '§c创建任务数据备份失败.' + cancelQuest: '§6你放弃了任务 {quest}.' + cancelQuestUnavailable: '§c无法取消任务 {quest} .' + checkpoint: + noCheckpoint: '§c未找到任务{quest}的记录点。' + questNotStarted: '§c你没有接受这个任务。' + downloadTranslations: + downloaded: '§a已下载语言{lang}!§7你现在必须打开文件"/plugins/BeautyQuests/config.yml",更改§ominecraftTranslationsFile§7的值为{lang},然后重启服务器。' + exists: '§c文件 {file_name} 已存在。在你的指令后加上 "-overwrite" 覆盖文件。 (/quests downloadTranslations <lang> -overwrite)' + notFound: '§c找不到{version}版本的{lang}语言。' + syntax: '§c你必须指定要下载的语言。例如:"/quests downloadTranslations en_US"。' + help: + adminMode: '§6/{label} adminMode : §e切换管理员模式 (显示消息)' + create: '§6/{label} create: §a创建任务' + downloadTranslations: '§6/{label} downloadTranslations <language>: §e下载翻译文件' + edit: '§6/{label} edit: §a编辑任务' + finishAll: '§6/{label} finishAll <玩家名>: §a结束一名玩家所有进行中的任务。' + header: '§6§lBeautyQuests - §6帮助§r' + list: '§e/{label} list: §a查看任务列表 (部分版本无效)' + reload: '§e/{label} reload: §a保存并重载配置和插件数据 - §c§o不推荐使用' + remove: '§6/{label} remove [id]: §a删除ID为 [id] 的任务或点击任务NPC来删除' + resetPlayer: '§6/{label} resetPlayer <玩家名>: §e删除一名玩家的所有任务数据。' + resetPlayerQuest: '§6/{label} resetPlayerQuest <玩家名> [id]: §e删除一名玩家的一个任务数据' + save: '§6/{label} save: §a手动保存数据.' + seePlayer: '§6/{label} seePlayer <玩家名>: §a查看玩家的任务数据。' + setFirework: '§6/{label} setFirework: §e编辑默认结束烟花。' + setItem: '§6/{label} setItem <talk|launch> : §e保存全息物品到数据文件内.' + setStage: '§6/{label} setStage <玩家名> <id> [新任务分支] [新任务阶段]: §e跳过玩家当前的任务阶段/开始任务分支/s为任务分支设置任务阶段。' + start: '§6/{label} start <玩家名> [id] : §e强制玩家接受任务.' + startDialog: '§6/{label} startDialog <player> <quest id>: §e播放NPC任务阶段的待定对话或任务起始对话。' + version: '§6/{label} version: §e查看插件版本.' + invalidCommand: + simple: '§c指令不存在, 输入 §ehelp §c查看帮助(不需要 /)' + itemChanged: '§a已编辑物品. 更改会在重启后生效.' + itemRemoved: '§a已删除全息物品.' + leaveAll: '§e你强制结束了{success}个任务. §c出现{errors}个错误.' + removed: '§a成功删除任务 {quest_name}。' + resetPlayer: + player: '§6你的所有任务数据 ({quest_amount}) 被 {deleter_name} 删除了.' + remover: '§6已删除{player}的{quest_amount}任务信息(和{quest_pool}任务池)。' + resetPlayerPool: + full: '§a你重置了{pool}任务池的{player}数据。' + timer: '§a你已重置{pool}任务池计时器{player}。' + resetPlayerQuest: + player: '§6任务数据 {quest} 已被 {deleter_name} 删除.' + remover: '§6{quest} 的 {player} 条任务信息已被删除.' + resetQuest: '§6已移除{player_amount}的任务数据。' + scoreboard: + hidden: '§6已隐藏{player_name}的计分版.' + lineInexistant: '§c第 {line_id} 行不存在.' + lineRemoved: '§6你成功地删除了第 {line_id} 行.' + lineReset: '§6你成功地重置了第 {line_id} 行.' + lineSet: '§6你成功地编辑了第 {line_id} 行.' + own: + hidden: '§6已隐藏你的计分板。' + shown: '§6已显示你的计分板。' + resetAll: '§6你成功地清空了 {player_name} 的计分版.' + shown: '§6已重新显示{player_name}的计分版。' + setStage: + branchDoesntExist: '§cid为{branch_id}的任务分支不存在。' + doesntExist: '§cID为{stage_id}的任务阶段不存在.' + next: '§a已跳过该任务阶段.' + nextUnavailable: '§c"skip"选项在玩家到达任务分支结尾时无法使用。' + set: '§a已进入任务阶段 {stage_id} .' + startDialog: + alreadyIn: '§c已对玩家播放对话。' + impossible: '§c现在无法开始对话。' + noDialog: '§c玩家没有待定对话。' + success: '§a已为玩家{player}播放任务{quest}的对话!' + startPlayerPool: + error: 为{player}开始任务池{pool}失败。 + success: '已开始任务池{pool}为{player}。结果:{result}' + startQuest: '§6你接受了任务 {quest} (UUID: {player}).' + startQuestNoRequirements: '§c玩家不满足任务{quest}的需求……在指令结尾加上 "-overrideRequirements" 无视需求检测。' + dialogs: + skipped: '§8§o已跳过对话。' + tooFar: '§7§o你离{npc_name}太远了...' + editor: + advancedSpawnersMob: '输入所需击杀的自定义刷怪笼怪物名称:' + already: '§c你已在编辑器中.' + availableElements: '可用元素:§e{available_elements}' + blockAmount: '§e请输入所需方块数:' + blockData: '§a请输入方块数据 (可用的方块数据: {available_datas}):' + blockName: '§a请输入方块名:' + blockTag: '§a请输入方块标签 (可用标签:§7{available_tags}§a):' + chat: '§6你已进入编辑器模式。输入"/quests exitEditor" 强制退出编辑器。(不推荐使用,最好使用 "close" 或 "cancel" 回到上一个菜单)' + color: '可以输入十六位格式(#XXXXX)或RGB格式(RED GRE BLU)的颜色。' + colorNamed: 输入颜色名称。 + comparisonTypeDefault: '§a请选择你想要在{available}中使用的比较类型。默认比较类型为:§e§l{default}§r§a。输入§onull§r§a使用。' + dialog: + cleared: '§a已删除{amount}条消息.' + edited: '§a已编辑消息 "§7{msg}§a"。' + help: + addSound: '§eaddsound <id> <音效名>: §b给一条消息添加音效.' + clear: '§eclear: §b删除所有消息.' + close: '§eclose: §b退出并保存所有消息.' + edit: '§6edit <id> <message>:§e编辑消息。' + header: '§e§lBeautyQuest - §6对话编辑器帮助' + list: '§elist: §b查看所有的消息.' + nothing: '§6noSender <消息>: §e添加一条没有发送者的消息.' + nothingInsert: '§enothinginsert <id> <消息>: §b插入一条没有任何前缀的消息.' + npc: '§npc <message>: §b添加一条由NPC说出的消息。' + npcInsert: '§enpcinsert <id> <消息>: §b插入一条由NPC说出的话.' + npcName: '§6npcname [自定义NPC名称]: §eSet (或重置为默认) 自定义NPC名称' + player: '§6player <message>: §b添加一条由玩家说出的消息。' + playerInsert: '§eplayerinsert <id> <消息>: §b插入一条由玩家说出的话.' + remove: '§6emove <id>: §e删除一条消息.' + setTime: '§6setTime <id> <时间>: §e设置自动播放下一条消息的时间(单位为刻) 。' + skippable: '§6skippable [true|false]: §e设置是否可跳过对话' + messageRemoved: '§a已删除消息 "§7{msg}§a"。' + noSender: '§a已添加无发送者的消息“{msg}”。' + npc: '§a已为NPC添加消息 "§7{msg}§a"。' + npcName: + set: '§a自定义NPC名称已设置为§7{new_name}§a (原为§7{old_name}§a)' + unset: '§a自定义NPC名称重置为默认值 (原为§7{old_name}§a)' + player: '§a已为玩家添加消息 "§7{msg}§a"。' + skippable: + set: '§a对话可跳过状态已设置为§7{new_state}§a (原为§7{old_state}§a)' + unset: '§a对话可跳过状态已重置为默认§7{1}§a (原为§7{old_state}§a)' + soundAdded: '§a已为消息 "§7{msg}§a"添加音效 "§7{sound}§a"。' + syntaxRemove: '§c正确用法: remove <id>' + timeRemoved: '§a已删除消息{msg}的时间。' + timeSet: '§a已编辑消息 {msg} 的时间: 现在是 {time} 刻。' + enter: + list: '§c⚠ §7你已进入"list"编辑器。输入"add"添加一行。使用 "help" (无需斜杠) 查看帮助。§e§l输入"close"退出编辑器。' + subtitle: '§e输入 "/quests exitEditor" 强制退出任务编辑器。' + title: '§6~ 进入编辑器模式 ~' + firework: + edited: 已编辑任务烟花! + invalid: 这件物品不是有效的烟花。 + invalidHand: 你必须在主手手持烟花。 + removed: 已移除任务烟花! + goToLocation: '§a前往该任务阶段指定地点。' + invalidColor: 你输入的颜色无效,必须是十六位或RGB颜色。 + invalidPattern: '§c无效的正则表达式§4{input}§c。' + itemCreator: + invalidBlockType: '§c无效的方块类型。' + invalidItemType: '§c无效的物品类型 (必须是物品而不能是方块).' + itemAmount: '§e请输入所需物品数:' + itemLore: '§e修改物品描述. 输入 "help" 查看帮助.' + itemName: '§a输入物品名:' + itemType: '§a输入物品类型名:' + unknownBlockType: '§c未知方块类型。' + unknownItemType: '§c未知的物品类型.' + mythicmobs: + disabled: '§cMythicMob已关闭.' + isntMythicMob: '§c这个MythicMob不存在.' + list: '§a所有的MythocMobs:' + noSuchElement: '§c没有这样的元素。可用元素:§e{available_elements}' + npc: + choseStarter: '§a选择接受任务的NPC.' + enter: '§a点击一个NPC,或输入"cancel"取消.' + notStarter: '§c这个NPC没有可以接受的任务...' + pool: + hologramText: 请输入该池的自定义全息显示文本(输入“null”使用默认值)。 + maxQuests: 输入在该池中可运行的最大任务数。 + questsPerLaunch: 输入点击NPC时给予玩家的任务数。 + timeMsg: '请输入玩家可接取新任务的等候时间。(默认单位:天)' + scoreboardObjectiveNotFound: '§c未知的计分板目标。' + selectWantedBlock: '§a用木棍点击开始任务阶段的方块.' + stage: + location: + typeWorldPattern: '§a输入世界名称的正则表达式:' + text: + argNotSupported: '§c不支持 {arg} 参数.' + chooseJobRequired: '§a输入所需的工作名:' + chooseLvlRequired: '§a输入所需等级:' + chooseMoneyRequired: '§e输入所需金额:' + chooseObjectiveRequired: '§a请输入目标名。' + chooseObjectiveTargetScore: '§a请输入完成任务目标所需目标数。' + choosePermissionMessage: '§e如果玩家没有所需权限则显示的拒绝消息. (输入 "null" 跳过这步)' + choosePermissionRequired: '§a输入开始任务所需权限:' + choosePlaceholderRequired: + identifier: '§e输入所需的占位符名 (§l不用加上 %%§r§e).' + value: '§a请输入所需的§e%§e{placeholder}§e%§a占位符值:' + chooseRegionRequired: '§a请输入所需区域名 (你必须与该区域在同一个世界中)。' + chooseSkillRequired: '§a输入技能名:' + reward: + money: '§e输入获得的钱数:' + permissionName: '§a请输入权限名称。' + permissionWorld: '§a请输入可编辑权限的世界名,输入"null"则所有世界可编辑。' + random: + max: '§a输入给予玩家的最高奖励数量 (包括全部)。' + min: '§a输入给予玩家的最低奖励数量 (包括全部)。' + wait: '§a输入所需等待游戏刻数(1秒=20刻)' + textList: + added: '§a已添加文本 "§7{msg}§a"。' + help: + add: '§6add [消息]: §e添加一条文本.' + close: '6close: §e确认添加文本并退出编辑器.' + header: '§6§lBeautyQuests — 编辑器列表帮助' + list: '§6list: §e查看所有已添加的文本.' + remove: '§6remove [id]: §e删除一条文本.' + removed: '§a已删除文本 "§7{msg}§a"。' + syntax: '§c正确用法: ' + title: + fadeIn: 输入淡入持续时间,单位为刻(20刻=1秒)。 + fadeOut: 输入淡出持续时间,单位为刻(20刻=1秒)。 + stay: 输入停留持续时间,单位为刻(20刻=1秒)。 + subtitle: 输入副标题文本(输入“null”则不显示文本)。 + title: 输入标题文本(输入“null”则不显示文本)。 + typeBucketAmount: '§a请输入要装满桶的数量:' + typeDamageAmount: '输入玩家需要造成的伤害:' + typeGameTicks: '§a请输入所需的刻数:' + typeLocationRadius: '§a请输入距离指定位置所需的距离:' + errorOccurred: '§c插件发生错误,请联系管理员!错误代码为: {error}' + experience: + edited: '已编辑获得的经验: {old_xp_amount}pts. 改为 {xp_amount}pts.' + indexOutOfBounds: '§c数字 ({index}) 超过了区间 [{min}, {max}].' + invalidBlockData: '§c方块数据{block_data} 无效或者不兼容方块{block_material}。' + invalidBlockTag: '§c无法使用方块标签{block_tag}。' + inventoryFull: '§c你的背包已满, 任务奖励已掉落在地上.' + moveToTeleportPoint: 前往指定的传送点. + npcDoesntExist: '§cID为{npc_id}的NPC不存在.' + number: + invalid: '§c"{input}" 不是有效的数字.' + negative: '§c你必须输入正数!' + notInBounds: '§c你的数字必须介于{min}和{max}之间。' + zero: '§c你必须输入大于0的数!' + pools: + allCompleted: '§7你已完成所有任务!' + maxQuests: '§c你不能同时进行多于 {pool_max_quests}个任务……' + noAvailable: '§7没有更多可用的任务……' + noTime: '§c你必须先等待一会儿才能执行其它任务。' + quest: + alreadyStarted: '§c你已经接受了这个任务!' + cancelling: '§c已取消创建任务.' + createCancelled: '§c抱歉,任务创建/编辑已被其他插件取消...' + created: '§a你成功地创建了 "§e{quest}§a" 任务, 包含 {quest_branches} 个阶段!' + editCancelling: '§c已取消编辑任务.' + edited: '§a你成功地修改了 "§e{quest}§a", 包含 {quest_branches} 个阶段!' + finished: + base: '§a恭喜你完成了任务 §o§6{quest_name}§r§a!' + obtain: '§a你获得了 {rewards}!' + invalidID: '§cID为 {quest_id} 的任务不存在.' + invalidPoolID: '§c任务池{pool_id}不存在。' + notStarted: '§c你未执行这个任务。' + started: '§a你接受了任务 §r§e{quest_name}§o§6!' + questItem: + craft: '§c你不能用任务物品来合成物品!' + drop: '§c你不能丢弃任务物品!' + eat: '§c你不能吃下任务物品!' + quests: + checkpoint: '§7已到达任务记录点!' + failed: '§6任务{quest_name}失败……' + maxLaunched: '§c你不能同时进行多于{quests_max_amount}个任务……' + updated: '§7已更新任务 {quest_name} !' + regionDoesntExists: '§c这个区域不存在... (你必须在目标区域同一世界内)' + requirements: + combatLevel: '§c你的战力等级必须是{long_level}!' + job: '§c你的职业等级§e{job_name}§c必须是{long_level}!' + level: '§c你的等级必须是{long_level}!' + money: '§c你必须拥有{money}!' + quest: '§c你必须先完成任务§e "{quest_name}"§c!' + skill: '§c你的技能等级§e{skill_name}§c必须是{long_level}!' + waitTime: '§c你必须等待{time_left}才能重启该任务!' + restartServer: '§7重启服务器查看修改。' + selectNPCToKill: 选择要击杀的NPC. + stageMobs: + listMobs: '§a你需要杀死 {mobs}.' + typeCancel: '§a输入 "cancel" 返回到上一条消息.' + versionRequired: '需要版本:§l{version}' + writeChatMessage: '要玩家输入的消息 (在开头加上 {SLASH} 来让玩家输入指令).' + writeCommand: '§a输入指令. (开头无需加上斜杠/) 你可以用 {PLAYER}来代表玩家名.' + writeCommandDelay: '§a请输入指令延迟,单位为刻。' + writeConfirmMessage: '§a请输入玩家确认加入任务的消息: (输入 "null" 则显示默认消息)' + writeDescriptionText: '任务阶段目标描述.' + writeEndMsg: '§a输入任务结束时发送的消息,输入“null” 则发送默认消息,输入“none”则不发送。你可以使用 "{rewards}"显示获得的奖励。' + writeEndSound: '§a输入在任务结束时播放给玩家的音效名,输入“null”则使用默认音效,输入“none”则不播放音效:' + writeHologramText: '§a输入全息文字. (输入 "none" 则不显示, 输入 "null" 显示默认文本) ' + writeMessage: '§a输入发送给玩家的消息' + writeMobAmount: '输入要击杀的怪物数.' + writeMobName: '§a请输入要击杀的自定义怪物名称:' + writeNPCText: '输入玩家需要对NPC说的话. 输入 "help" 来获取帮助. (指令不需要输入 /)' + writeNpcName: '§a请输入NPC名称:' + writeNpcSkinName: '§a请输入NPC皮肤名:' + writeQuestDescription: '§a请输入显示在玩家任务菜单内的任务描述。' + writeQuestMaterial: '§a请输入任务物品材料名。' + writeQuestName: '§a输入任务名:' + writeQuestTimer: '§a输入重新开始任务的冷却时间 (单位为分钟)(输入 "null" 则使用默认值)' + writeRegionName: '输入任务阶段所需前往的区域名.' + writeStageText: '任务开始时发送的消息.' + writeStartMessage: '§a输入在开始任务时发送给玩家的消息,输入“null”则发送默认消息,输入“none”则不发送消息:' + writeXPGain: '输入玩家获得的经验点. 最终获得: §a{xp_amount}' +scoreboard: + asyncEnd: '§ex' + name: '§6§l任务' + noLaunched: '§c你没有进行中的任务.' + noLaunchedDescription: '§c§o载入中' + noLaunchedName: '§c§l载入中' + stage: + breed: '§e饲养§6{mobs}' + bucket: '§e装满 §6{buckets}' + chat: '§e输入 §6{text}' + craft: '§e合成 §6{items}' + dealDamage: + any: '§c造成{damage_remaining}点伤害' + mobs: '§c对{target_mobs}造成{damage_remaining}点伤害' + die: '§c死亡' + eatDrink: '§e消耗§6{items}' + enchant: '§e附魔 §6{items}' + fish: '§e钓鱼 §6{items}' + interact: '§e点击在§6{x}的方块' + interactMaterial: '§e点击§6{block}§e方块' + items: '§e将物品带给§6{dialog_npc_name}§e:' + location: '§e前往位于 §6{target_world}的坐标§6{target_x}§e, §6{target_y}§e, §6{target_z}§e ' + melt: '§e熔炼 §6{items}' + mine: '§e挖掘 {blocks}' + mobs: '§e击杀 §6{mobs}' + npc: '§e和NPC谈话 §6{dialog_npc_name}' + placeBlocks: '§e放置{blocks}' + playTimeFormatted: '§e游玩 §6{time_remaining_human}' + region: '§e找到区域 §6{region_id}' + tame: '§e驯服§6{mobs}' + textBetwteenBranch: '§e或' diff --git a/core/src/main/resources/locales/zh_HK.yml b/core/src/main/resources/locales/zh_HK.yml index 8aed156a..bddd5a17 100644 --- a/core/src/main/resources/locales/zh_HK.yml +++ b/core/src/main/resources/locales/zh_HK.yml @@ -1,656 +1,605 @@ --- -msg: - quest: - finished: - base: '§a恭喜你完成了任務 §o§6{0}§r§a!' - obtain: '§a你獲得了 {0}!' - started: '§a你接受了任務 §r§e{0}§o§6!' - created: '§a你成功地創建了 "§e{0}§a" 任務, 包含 {1} 個階段!' - edited: '§a你成功地修改了 "§e{0}§a", 包含 {1} 個階段!' - createCancelled: '§c抱歉,任務創建/編輯已被其他插件取消...' - cancelling: '§c已取消創建任務.' - editCancelling: '§c已取消編輯任務.' - invalidID: '§cID為 {0} 的任務不存在.' - alreadyStarted: '§c你已經接受了這個任務!' - quests: - maxLaunched: '§c你不可以同時接多過 {0} 個任務...' - nopStep: '§c這個任務沒有任何階段... :-)' - updated: '§7已更新任務 {0} !' - checkpoint: '§7已到達任務記錄點!' - failed: '§6任務{0}失敗……' - pools: - noTime: '§c你必須等待 {0} 才能做其他任務' - allCompleted: '§7你已經完成所有任務!' - noAvailable: '§7這裡沒有更多可以接的任務' - maxQuests: '§c你不可以同時接多過 {0} 個任務...' - questItem: - drop: '§c你不可以掉落一個任務道具' - craft: '§c你不可以用一個任務道具去合成' - stageMobs: - noMobs: '§c這個任務階段沒有要殺的怪物 :-)' - listMobs: '§a你需要殺死 {0}.' - writeNPCText: '輸入玩家需要對NPC說的話. 輸入 "help" 來獲取幫助. (指令不需要輸入 /)' - writeRegionName: '輸入任務階段所需前往的區域名.' - writeXPGain: '輸入玩家獲得的經驗點. 最終獲得: §a{0}' - writeMobAmount: '輸入要擊殺的怪物數.' - writeMobName: '§a填寫特殊怪物的名稱用作擊殺' - writeChatMessage: '要玩家輸入的消息 (在開頭加上 {SLASH} 來讓玩家輸入指令).' - writeEndMessage: '輸入在任務或任務階段結束後發送給玩家的消息' - writeDescriptionText: '任務階段目標描述.' - writeStageText: '任務開始時發送的消息.' - moveToTeleportPoint: 前往指定的傳送點. - writeNpcName: '輸入NPC名稱.' - writeNpcSkinName: '輸入NPC皮膚名.' - writeQuestName: '§a輸入任務名:' - writeCommand: '§a輸入指令. (開頭無需加上斜杠/) 你可以用 {PLAYER}來代表玩家名.' - writeHologramText: '§a輸入全息文字. (輸入 "none" 則不顯示, 輸入 "null" 顯示默認文本)' - writeQuestTimer: '§a輸入重新開始任務的冷卻時間 (單位為分鐘)(輸入 "null" 則使用默認值)' - writeConfirmMessage: '§a請輸入玩家確認加入任務的消息: (輸入 "null" 則顯示默認消息)' - writeQuestDescription: '§a請輸入顯示在玩家任務菜單內的任務描述。' - writeQuestMaterial: '§a請輸入任務物品材料名。' - requirements: - quest: '§c你必須先完成任務§e "{0}"§c!' - level: '§e你必須達到 {0} 級!' - job: '§e你必須達到 {0} 級才能應聘工作 {1}!' - skill: '§e你的{1}技能必須要達到{0}級!' - combatLevel: '§e你必須達到戰鬥等級 {0}!' - money: '§c你必須擁有{0}!' - waitTime: '§c你必須等待 {0} 分鐘才能再次接受這個任務!' - experience: - edited: '已編輯獲得的經驗: {0}pts. 改為 {1}pts.' - selectNPCToKill: 選擇要擊殺的NPC. - npc: - remove: '§a已刪除NPC.' - talk: '§a和§e{0}§a談話.' - regionDoesntExists: '§c這個區域不存在... (你必須在目標區域同一世界內)' - npcDoesntExist: '§cID為{0}的NPC不存在.' - objectDoesntExist: '§c特殊物品 (ID為{0}) 不存在.' - number: - negative: '§c你必須輸入正數!' - zero: '§c你必須輸入大於0的數!' - invalid: '§c"{0}" 不是有效的數字.' - errorOccurred: '§c插件發生錯誤,請聯系管理員!錯誤代碼為: {0}' - commandsDisabled: '§c你不能在這時輸入指令.' - indexOutOfBounds: '§c數字 ({0}) 超過了區間 [{1}, {2}].' - invalidBlockData: '§c此方塊 Data {0} 並不能用在 {1} 上' - bringBackObjects: 把 {0} 帶回給我. - inventoryFull: '§c你的背包已滿, 任務獎勵已掉落在地上.' - playerNeverConnected: '§c在玩家{0}身上找不到數據.' - playerNotOnline: '§c玩家 {0} 不在線.' - command: - checkpoint: - noCheckpoint: '§c未找到任務{0}的記錄點。' - questNotStarted: '§c你沒有接受這個任務。' - setStage: - branchDoesntExist: '§cid為{0}的任務分支不存在。' - doesntExist: '§cID為{0}的任務階段不存在.' - next: '§a已跳過該任務階段.' - nextUnavailable: '§c"skip"選項在玩家到達任務分支結尾時無法使用。' - set: '§a已進入任務階段 {0} .' - playerNeeded: '§c你必須是玩家才能使用這個指令.' - incorrectSyntax: '§c錯誤用法.' - noPermission: '§c你沒有足夠的權限以執行這個指令! (需要權限: {0})' - invalidCommand: - quests: '§c指令不存在, 輸入 §e/quests help 查看幫助§c.' - simple: '§c指令不存在, 輸入 §ehelp §c查看幫助(不需要 /)' - needItem: '§c你必須在主手手持該物品!' - itemChanged: '§a已編輯物品. 更改會在重啟後生效.' - itemRemoved: '§a已刪除全息物品.' - removed: '§a成功刪除任務 {0}。' - leaveAll: '§e你強制結束了{0}個任務. §c出現{1}個錯誤.' - resetPlayer: - player: '§6你的所有任務數據 ({0}) 被 {1} 刪除了.' - remover: '§6{0} 個任務資料 (包含 {2} 個池) 已經移除. 原本有 {1} 個.' - resetPlayerQuest: - player: '§6任務數據 {0} 已被 {1} 刪除.' - remover: '§6{1} 的 {0} 條任務信息已被刪除.' - resetQuest: '§6已移除{0}的任務數據。' - startQuest: '§6你接受了任務 {0} (UUID: {1}).' - cancelQuest: '§6你放棄了任務 {0}.' - cancelQuestUnavailable: '§c無法取消任務 {0} .' - backupCreated: '§6你成功地創建了任務和玩家數據的備份文件.' - backupPlayersFailed: '§c創建玩家數據備份失敗.' - backupQuestsFailed: '§c創建任務數據備份失敗.' - adminModeEntered: '§a你已進入管理員模式.' - adminModeLeft: '§a你退出了管理員模式.' - scoreboard: - lineSet: '§6你成功地編輯了第 {0} 行.' - lineReset: '§6你成功地重置了第 {0} 行.' - lineRemoved: '§6你成功地刪除了第 {0} 行.' - lineInexistant: '§c第 {0} 行不存在.' - resetAll: '§6你成功地清空了 {0} 的計分版.' - hidden: '§6已隱藏{0}的計分版.' - shown: '§6已重新顯示{0}的計分版。' - help: - header: '§6§lBeautyQuests - §6幫助§r' - create: '§6/{0} create: §a創建任務' - edit: '§6/{0} edit: §a編輯任務' - remove: '§6/{0} remove [id]: §a刪除ID為 [id] 的任務或點擊任務NPC來刪除' - finishAll: '§6/{0} finishAll <玩家名>: §a結束一名玩家所有進行中的任務。' - setStage: '§6/{0} setStage <玩家名> <id> [新任務分支] [新任務階段]: §e跳過玩家當前的任務階段/開始任務分支/s為任務分支設置任務階段。' - resetPlayer: '§6/{0} resetPlayer <玩家名>: §e刪除一名玩家的所有任務數據。' - resetPlayerQuest: '§6/{0} resetPlayerQuest <玩家名> [id]: §e刪除一名玩家的一個任務數據' - seePlayer: '§6/{0} seePlayer <玩家名>: §a查看玩家的任務數據。' - reload: '§e/{0} reload: §a保存並重載配置和插件數據 - §c§o不推薦使用' - start: '§6/{0} start <玩家名> [id] : §e強制玩家接受任務.' - setItem: '§6/{0} setItem <talk|launch> : §e保存全息物品到數據文件內.' - adminMode: '§6/{0} adminMode : §e切換管理員模式 (顯示消息)' - version: '§6/{0} version: §e查看插件版本.' - save: '§6/{0} save: §a手動保存數據.' - list: '§e/{0} list: §a查看任務列表 (部分版本無效)' - typeCancel: '§a輸入 "cancel" 返回到上一條消息.' - editor: - blockAmount: '§a請輸入所需的數量:' - blockName: '§a請輸入所需的方塊名稱:' - blockData: '§a請輸入所需的方塊 Data (可用的 Data: {0}):' - typeBucketAmount: '§a請輸入要裝滿桶的數量:' - goToLocation: '§a前往該任務階段指定地點。' - typeLocationRadius: '§a請輸入距離指定位置所需的距離:' - typeGameTicks: '§a請輸入所需的 Ticks:' - already: '§c你已在編輯器中.' - enter: - title: '§6~ 進入編輯器模式 ~' - subtitle: '§6使用指令 "/quests exitEditor" 強制離開編輯器' - chat: '§6你現在在編輯模式. 使用 "/quests exitEditor" 強制離開編輯器 (極度不推薦,請使用指令例如 "close" 或者 "cancel" 返回上一頁)' - npc: - enter: '§a點擊一個NPC,或輸入"cancel"取消.' - choseStarter: '§a選擇接受任務的NPC.' - notStarter: '§c這個NPC沒有可以接受的任務...' - text: - argNotSupported: '§c不支持 {0} 參數.' - chooseLvlRequired: '§a輸入所需等級:' - chooseJobRequired: '§a輸入所需的工作名:' - choosePermissionRequired: '§a輸入開始任務所需權限:' - choosePermissionMessage: '§e如果玩家沒有所需權限則顯示的拒絕消息. (輸入 "null" 跳過這步)' - choosePlaceholderRequired: - identifier: '§e輸入所需的占位符名 (§l不用加上 %%§r§e).' - value: '§a請為所需要的參數填寫適當資料 §e%§e{0}§e%§a:' - chooseSkillRequired: '§a輸入技能名:' - chooseMoneyRequired: '§e輸入所需金額:' - reward: - permissionName: '§a請輸入權限名稱。' - permissionWorld: '§a請輸入可編輯權限的世界名,輸入"null"則所有世界可編輯。' - money: '§e輸入獲得的錢數:' - wait: '§a填寫多少遊戲時間需要等待: (1 現實秒數 = 20 遊戲秒數)' - chooseObjectiveRequired: '§a請輸入目標名。' - chooseObjectiveTargetScore: '§a請輸入完成任務目標所需目標數。' - chooseRegionRequired: '§a請輸入所需區域名 (你必須與該區域在同一個世界中)。' - selectWantedBlock: '§a用木棍點擊開始任務階段的方塊.' - itemCreator: - itemType: '§a輸入物品類型名:' - itemAmount: '§e請輸入所需物品數:' - itemName: '§a輸入物品名:' - itemLore: '§e修改物品描述. 輸入 "help" 查看幫助.' - unknownItemType: '§c未知的物品類型.' - invalidItemType: '§c無效的物品類型 (必須是物品而不能是方塊).' - unknownBlockType: '§c未知方塊種類' - invalidBlockType: '§c未知方塊種類' - dialog: - syntax: '§c正確用法 : {0}{1} <消息>' - syntaxRemove: '§c正確用法: remove <id>' - player: '§a已為玩家增加消息“{0}”。' - npc: '§a已為NPC增加消息“{0}”。' - noSender: '§a已增加沒有發送者的消息“{0}”。' - messageRemoved: '§a已刪除消息 {0}.' - edited: '§a已更改訊息 {0}.' - soundAdded: '§a已為消息 {1} 增加音效 {0}.' - cleared: '§a已刪除{0}條消息.' - help: - header: '§e§lBeautyQuest - §6對話編輯器幫助' - npc: '§npc <message>: §b增加一條由NPC說出的消息。' - player: '§6player <message>: §b增加一條由玩家說出的消息。' - nothing: '§6noSender <消息>: §e增加一條沒有發送者的消息.' - remove: '§6emove <id>: §e刪除一條消息.' - list: '§elist: §b查看所有的消息.' - npcInsert: '§enpcinsert <id> <消息>: §b插入一條由NPC說出的話.' - playerInsert: '§eplayerinsert <id> <消息>: §b插入一條由玩家說出的話.' - nothingInsert: '§enothinginsert <id> <消息>: §b插入一條沒有任何前綴的消息.' - edit: '§6更改 <id> <message>: §e更改一個訊息' - addSound: '§eaddsound <id> <音效名>: §b給一條消息增加音效.' - clear: '§eclear: §b刪除所有消息.' - close: '§eclose: §b退出並保存所有消息.' - setTime: '§6setTime <id> <時間>: §e設置自動播放下一條消息的時間(單位為刻) 。' - timeSet: '§a已編輯消息 {0} 的時間: 現在是 {1} 刻。' - timeRemoved: '§a已刪除消息{0}的時間。' - mythicmobs: - list: '§a所有的MythocMobs:' - isntMythicMob: '§c這個MythicMob不存在.' - disabled: '§cMythicMob已關閉.' - epicBossDoesntExist: '§c這個EpicBoss 不存在.' - textList: - syntax: '§c正確用法: ' - added: '§a已增加 {0}.' - removed: '§a已刪除 {0} .' - help: - header: '§6§lBeautyQuests — 編輯器列表幫助' - add: '§6add [消息]: §e增加一條文本.' - remove: '§6remove [id]: §e刪除一條文本.' - list: '§6list: §e查看所有已增加的文本.' - close: '6close: §e確認增加文本並退出編輯器.' - noSuchElement: '§c沒有這樣的元素。可用元素:§e{0}' - comparisonType: '§a請選擇你想要在{0}中使用的比較類型。默認比較類型為:§e§lger或equals§r§a。輸入 §onull §r§a 來使用。' - scoreboardObjectiveNotFound: '§c未知的計分板目標。' - pool: - hologramText: '為這個池設定一個特定的浮空字 (如果你想用預設的請寫 "null")' - maxQuests: '填寫這個池最多可以開始的任務.' - time: '填寫多少日玩家才可以接新的任務' - title: - title: '填寫任務的標題 (填寫 "null" 代表沒有)' - subtitle: '填寫任務的副標題 (填寫 "null" 代表沒有)' - fadeIn: '填寫 "fade-in" 淡入時間, 單位是遊戲秒數 (20 遊戲妙數 = 1 秒).' - stay: '填寫 "stay" 逗留時間, 單位是遊戲秒數 (20 遊戲妙數 = 1 秒).' - fadeOut: '填寫 "fade-out" 淡出時間, 單位是遊戲秒數 (20 遊戲妙數 = 1 秒).' - writeCommandDelay: '§a請輸入指令延遲,單位為刻。' advancement: finished: 已完成 notStarted: 未完成 +indication: + cancelQuest: '§7您確定要取消任務 {quest_name}?' + closeInventory: '§7你確定要關閉該頁面嗎?' + removeQuest: '§7您確定要刪除任務 {quest}?' + startQuest: '§7您是否想要接受任務 {quest_name}?' inv: - validate: '§b§l確認' - cancel: '§c§l取消' - search: '§e§l搜索' addObject: '§a添加一個物件' + block: + blockData: '§d方塊Data' + material: '§e材料: {block_type}' + name: 選擇方塊 + blockAction: + location: '§6選擇準確位置' + material: '§e選擇方塊物料' + name: 選擇方塊行動 + blocksList: + addBlock: '§a點擊增加一個方塊.' + name: 選擇方塊 + buckets: + name: 桶的類型 + cancel: '§c§l取消' + checkpointActions: + name: 記錄點行動 + chooseAccount: + name: '§5選擇哪一個帳號?' + chooseQuest: + name: '§f괐괦광§8選擇哪一個任務?' + classesList.name: 職業列表 + classesRequired.name: 需要職業 + command: + console: 控制台 + delay: '§b延遲' + name: '§8指令' + value: '§b指令' + commandsList: + console: '§e控制台: {command_console}' + name: 指令列表 + value: '§e指令: {command_label}' confirm: name: '§8你確認?' - 'yes': '§a確認' 'no': '§c讓我再想想' + 'yes': '§a確認' create: - stageCreate: '§a創建新的階段' - stageRemove: '§c刪除這一階段' - findNPC: '§a尋找一個NPC' + NPCSelect: '§e選擇或者創建一個NPC' + NPCText: '§e編輯NPC的文本對話' + breedAnimals: '§a餵飼動物' bringBack: '§a帶回物品' + bucket: '§a裝滿桶' + cancelMessage: 取消發送 + changeEntityType: '§e更改一個生物類型' + changeTicksRequired: '§e需要更改遊玩刻' + craft: '§a合成物品' + currentRadius: '§e當前距離: §6{radius}' + editBlocksMine: '§e編輯要破壞的方塊' + editBlocksPlace: '§e編輯要放置的方塊' + editBucketAmount: '§e編輯要裝滿的桶數量' + editBucketType: '§e編輯要裝滿的桶類型' + editFishes: '§e編輯所需的魚' + editItem: '§e編輯要合成的物品' + editLocation: '§e編輯位置' + editMessageType: '§e編輯要輸入的消息' + editMobsKill: '§e編輯要擊殺的怪物' + editRadius: '§e編輯離目的地的距離' + findNPC: '§a尋找一個NPC' findRegion: '§a找到一片區域' + fish: '§a釣魚' + hideClues: 隱藏任務指示 (粒子效果和全息文字) + ignoreCase: 忽略消息大小寫 + interact: '§a點擊方塊' killMobs: '§a擊殺怪物' + leftClick: 必須左擊 + location: 前往指定位置 mineBlocks: '§a破壞方塊' + mobsKillFromAFar: 需要遠程擊殺怪物 placeBlocks: '§a放置方塊' - talkChat: '§a在聊天框內輸入' - interact: '§a點擊方塊' - fish: '§a釣魚' - craft: '§a合成物品' - bucket: '§a裝滿桶' - location: 前往指定位置 playTime: '§e遊戲時間' - breedAnimals: '§a餵飼動物' - tameAnimals: '§a領養動物' - NPCText: '§e編輯NPC的文本對話' - NPCSelect: '§e選擇或者創建一個NPC' - hideClues: 隱藏任務指示 (粒子效果和全息文字) - editMobsKill: '§e編輯要擊殺的怪物' - mobsKillFromAFar: 需要遠程擊殺怪物 - editBlocksMine: '§e編輯要破壞的方塊' preventBlockPlace: 防止玩家破壞方塊 - editBlocksPlace: '§e編輯要放置的方塊' - editMessageType: '§e編輯要輸入的消息' - cancelMessage: 取消發送 - ignoreCase: 忽略消息大小寫 replacePlaceholders: 替換 {PLAYER} 或者 PlaceholderAPI 的佔位符 + selectBlockLocation: '§6選擇方塊位置' + selectBlockMaterial: '§e選擇方塊物料' selectItems: '§b選擇所需的物品' - selectItemsMessage: '§e編輯發問訊息' selectItemsComparisons: '§e選取道具比較(複雜)' + selectItemsMessage: '§e編輯發問訊息' selectRegion: '§7選擇一片區域' - toggleRegionExit: 退出時 + stageCreate: '§a創建新的階段' + stageRemove: '§c刪除這一階段' stageStartMsg: '§e編輯階段開始的消息' - selectBlockLocation: '§6選擇方塊位置' - selectBlockMaterial: '§e選擇方塊物料' - leftClick: 必須左擊 - editFishes: '§e編輯所需的魚' - editItem: '§e編輯要合成的物品' - editBucketType: '§e編輯要裝滿的桶類型' - editBucketAmount: '§e編輯要裝滿的桶數量' - editLocation: '§e編輯位置' - editRadius: '§e編輯離目的地的距離' - currentRadius: '§e當前距離: §6{0}' - changeTicksRequired: '§e需要更改遊玩刻' - changeEntityType: '§e更改一個生物類型' - stages: - name: '§8創建任務階段' - nextPage: '§e下一頁' - laterPage: '§e上一頁' - endingItem: '§e編輯階段結束獎勵' - descriptionTextItem: '§e編輯文本描述' - regularPage: '§a普通任務階段' - branchesPage: '§d分支任務階段' - previousBranch: '§e返回上一個分支' - newBranch: '§e前往新的任務分支' - validationRequirements: '§e驗證需求' - validationRequirementsLore: 所有需求必須匹配嘗試完成階段的玩家。否則該階段無法完成。 + talkChat: '§a在聊天框內輸入' + tameAnimals: '§a領養動物' + toggleRegionExit: 退出時 details: - hologramLaunch: '§e編輯 “啟動” 全息項' - hologramLaunchLore: 顯示在接受任務的NPC頭上的全息文字。 - hologramLaunchNo: '§e編輯 “啟動不可用” 全息項' - hologramLaunchNoLore: 在玩家沒有接受任務時顯示在NPC頭上的全息文字。 + actions: '{amount}行動' + auto: 首次進入伺服器自動啟動 + autoLore: 如果開啟這個設定,玩家首次進入伺服器將會接這個任務 + bypassLimit: 忽略任務上限 + bypassLimitLore: 如果啟用,即使玩家已經達到任務上限也能接受任務。 + cancellable: 玩家可取消任務 + cancellableLore: 允許玩家在任務菜單中取消任務。 + createQuestLore: 你必須設定任務名。 + createQuestName: '§l創建任務' customConfirmMessage: '§e編輯確認接受任務的消息' customConfirmMessageLore: 顯示在確認菜單中的消息。 customDescription: '§e編輯任務描述' customDescriptionLore: 在GUI中顯示在任務名下方的描述。 - name: '§8最終任務詳細設置' - multipleTime: - itemName: 開關重覆任務 - itemLore: 任務是否可以多次完成? - cancellable: 玩家可取消任務 - cancellableLore: 允許玩家在任務菜單中取消任務。 - startableFromGUI: 介面開始任務 - startableFromGUILore: 允許玩家可於介面開始任務。 - scoreboardItem: 啟用計分版 - scoreboardItemLore: 如果禁用,則該任務目標不會顯示在計分板上。 - hideItem: 隱藏任務 (菜單和衛星地圖) - hideItemLore: 如果啟用,任務將不會在dynmap或任務菜單中顯示。 + customMaterial: '§a編輯任務物品材料名' + customMaterialLore: 在任務菜單中代表該任務的物品圖標。 + defaultValue: '§8(默認值)' + editQuestName: '§l編輯任務' + editRequirements: '§e編輯需求' + editRequirementsLore: 接受任務所需前置。 + endMessage: '§a編輯任務結束消息' + endMessageLore: 將在任務結束時發送給玩家的消息。 + failOnDeath: 玩家死亡時任務失敗 + failOnDeathLore: 當玩家死亡時是否取消任務? hideNoRequirementsItem: 當條件未滿足的時候隱藏 hideNoRequirementsItemLore: 如果開啟這個設定,任務列表GUI不會顯示未滿足任務接取條件的任務 - bypassLimit: 忽略任務上限 - bypassLimitLore: 如果啟用,即使玩家已經達到任務上限也能接受任務。 - auto: 首次進入伺服器自動啟動 - autoLore: 如果開啟這個設定,玩家首次進入伺服器將會接這個任務 + hologramLaunch: '§e編輯 “啟動” 全息項' + hologramLaunchLore: 顯示在接受任務的NPC頭上的全息文字。 + hologramLaunchNo: '§e編輯 “啟動不可用” 全息項' + hologramLaunchNoLore: 在玩家沒有接受任務時顯示在NPC頭上的全息文字。 + hologramText: '§e全息文字' + hologramTextLore: 顯示在可接受任務的NPC的頭上的全息文字。 + keepDatas: 保存玩家資料 + keepDatasLore: '強制任務插件記錄玩家資料,即使這個任務的內容已經更改。 §c§l警告 §c- 開啟這個設定可能會導致玩家資料毀壞' + loreReset: '§e§l所有玩家的進度將被重置' + multipleTime: + itemLore: 任務是否可以多次完成? + itemName: 開關重覆任務 + name: '§8最終任務詳細設置' + optionValue: '§8數值:§7{value}' questName: '§a§l編輯任務名' questNameLore: 必須設置一個名稱來創建任務。 - setItemsRewards: '§7編輯獲得的物品' - setXPRewards: '§e編輯獲得的經驗' + questPool: '§e任務池' + questPoolLore: 將這個任務加入任務池 + requiredParameter: '§7必需的參數' + requirements: '{amount} 個任務需求' + rewards: '{amount} 個獎勵' + rewardsLore: 任務接受時執行的行動。 + scoreboardItem: 啟用計分版 + scoreboardItemLore: 如果禁用,則該任務目標不會顯示在計分板上。 + selectStarterNPC: '§6§l選擇接受任務的NPC' + selectStarterNPCLore: 點擊選中的NPC將開始任務。 setCheckpointReward: '§e編輯記錄點獎勵' + setItemsRewards: '§7編輯獲得的物品' + setMoneyReward: '§e編輯獲得的金錢' + setPermReward: '§e編輯權限' setRewardStopQuest: '§c停止這個任務' setRewardsWithRequirements: '§e有條件發送獎勵' - setPermReward: '§e編輯權限' - setMoneyReward: '§e編輯獲得的金錢' - setWaitReward: '§e編輯"wait" 等待獎勵' setTitleReward: '§e編輯標題獎勵' - selectStarterNPC: '§6§l選擇接受任務的NPC' - selectStarterNPCLore: 點擊選中的NPC將開始任務。 - createQuestName: '§l創建任務' - createQuestLore: 你必須設定任務名。 - editQuestName: '§l編輯任務' - endMessage: '§a編輯任務結束消息' - endMessageLore: 將在任務結束時發送給玩家的消息。 + setWaitReward: '§e編輯"wait" 等待獎勵' + setXPRewards: '§e編輯獲得的經驗' startDialog: '§e編輯任務開場白' startDialogLore: 當玩家點擊任務NPC時,在任務開始之前播放的對話框。 - editRequirements: '§e編輯需求' - editRequirementsLore: 接受任務所需前置。 startRewards: '§6開始任務的獎勵' startRewardsLore: 玩家接受任務時執行的行動。 - hologramText: '§e全息文字' - hologramTextLore: 顯示在可接受任務的NPC的頭上的全息文字。 + startableFromGUI: 介面開始任務 + startableFromGUILore: 允許玩家可於介面開始任務。 timer: '§b任務冷卻時間' timerLore: 玩家可以再次開始任務的時間。 - requirements: '{0} 個任務需求' - rewards: '{0} 個獎勵' - actions: '{0}行動' - rewardsLore: 任務接受時執行的行動。 - customMaterial: '§a編輯任務物品材料名' - customMaterialLore: 在任務菜單中代表該任務的物品圖標。 - failOnDeath: 玩家死亡時任務失敗 - failOnDeathLore: 當玩家死亡時是否取消任務? - questPool: '§e任務池' - questPoolLore: 將這個任務加入任務池 - keepDatas: 保存玩家資料 - keepDatasLore: |- - 強制任務插件記錄玩家資料,即使這個任務的內容已經更改。 - §c§l警告 §c- 開啟這個設定可能會導致玩家資料毀壞 - loreReset: '§e§l所有玩家的進度將被重置' - optionValue: '§8數值:§7{0}' - defaultValue: '§8(默認值)' - requiredParameter: '§7必需的參數' - itemsSelect: - name: 編輯物品 - none: |- - §a把物品放到這里或點擊打開物品編輯器. - itemSelect: - name: 選擇物品 - npcCreate: - name: 創建NPC - setName: '§a編輯NPC名稱' - setSkin: '§e編輯NPC皮膚' - setType: '§a編輯NPC類型' - move: - itemName: '§6傳送' - itemLore: '§a更改NPC位置.' - moveItem: '§a§l確認前往' - npcSelect: - name: 選擇還是創建NPC? - selectStageNPC: '§6選擇 NPC' - createStageNPC: '§e創建 NPC' + editTitle: + fadeIn: '§a淡入時間' + fadeOut: '§a淡出時間' + name: 更改標題 + stay: '§b停留時間' + subtitle: '§e副標題' + title: '§6標題' entityType: name: '§5選擇生物類型' - chooseQuest: - name: '§f괐괦광§8選擇哪一個任務?' - mobs: - name: 選擇怪物 - none: '§a點擊增加怪物' - clickLore: |- - §a§l左鍵§a 更改數量 - §a§l§nShift§a§l + 左鍵§a 更改生物名稱. - §c§l右鍵§c移除 - mobSelect: - name: 選擇怪物 - bukkitEntityType: '§e選擇一個生物類型' - mythicMob: '§6選擇一個MythicMob' - epicBoss: '§6選擇一個Epic Boss' - boss: '§6選擇一個Boss' - stageEnding: - locationTeleport: '§a編輯傳送點' - command: '§a編輯執行的指令' - requirements: - name: 任務需求 - rewards: - name: 任務獎勵 - commands: '指令: {0}' - teleportation: |- - §a已選擇: - X: {0} - Y: {1} - Z: {2} - 世界: {3} - checkpointActions: - name: 記錄點行動 - rewardsWithRequirements: - name: 有條件發送獎勵 + factionsList.name: 派系/公會列表 + factionsRequired.name: 需要派系/公會 + itemComparisons: + bukkit: Bukkit原生比較 + bukkitLore: 使用Bukkit預設道具比較系統。 比較材料、耐久度、NBT標籤…… + customBukkit: Bukkit原生比較 -沒NBT + customBukkitLore: 使用Bukkit預設物品比較系統,但除去NBT標籤。 比較材料名、耐久度等 + enchants: 物品附魔 + enchantsLore: 比較物品附魔 + itemLore: 物品描述 + itemLoreLore: 比較物品描述 + itemName: 物品名 + itemNameLore: 比較物品名稱 + material: 物品材料 + materialLore: 比較物品材料(如石頭|stone、鐵劍|iron sword) + name: 比較物品 + repairCost: 修復花費 + repairCostLore: 比較盔甲和武器的修復花費 + itemCreator: + isQuestItem: '§b任務物品:' + itemFlags: 開關物品標志顯示 + itemLore: '§b物品描述' + itemName: '§b物品名' + itemType: '§b物品類型' + name: '§8物品編輯器' + itemSelect: + name: 選擇物品 + itemsSelect: + name: 編輯物品 + none: '§a把物品放到這里或點擊打開物品編輯器.' listAllQuests: name: '§8任務' + listBook: + noQuests: 沒有已創建的任務 + questMultiple: 可重覆次數 + questName: 任務名 + questRewards: 任務獎勵 + questStages: 任務階段 + questStarter: 開始任務方式 + requirements: 任務需求 listPlayerQuests: - name: '§f괐괦광§8{0} 的任務' + name: '§f괐괦광§8{player_name} 的任務' listQuests: - notStarted: 沒有已開始的任務 + canRedo: '§3§o你可以再次接受這個任務!' finished: 已完成的任務 inProgress: 進行中的任務 - loreCancel: '§c§o點擊取消任務' loreStart: '§a§o點擊開始任務。' loreStartUnavailable: '§c§o你不滿足任務需求,無法開始任務。' - timeToWaitRedo: '§3§o你可以在此時間之後再次接任務: {0} ' - canRedo: '§3§o你可以再次接受這個任務!' - timesFinished: '§3任務已經做過 {0} 次.' - itemCreator: - name: '§8物品編輯器' - itemType: '§b物品類型' - itemFlags: 開關物品標志顯示 - itemName: '§b物品名' - itemLore: '§b物品描述' - isQuestItem: '§b任務物品:' - command: - name: '§8指令' - value: '§b指令' - console: 控制台 - delay: '§b延遲' - chooseAccount: - name: '§5選擇哪一個帳號?' - listBook: - questName: 任務名 - questStarter: 開始任務方式 - questRewards: 任務獎勵 - questMultiple: 可重覆次數 - requirements: 任務需求 - questStages: 任務階段 - noQuests: 沒有已創建的任務 - commandsList: - name: 指令列表 - value: '§e指令: {0}' - console: '§e控制台: {0}' - block: - name: 選擇方塊 - material: '§e材料: {0}' - blockData: '§d方塊Data' - blocksList: - name: 選擇方塊 - addBlock: '§a點擊增加一個方塊.' - blockAction: - name: 選擇方塊行動 - location: '§6選擇準確位置' - material: '§e選擇方塊物料' - buckets: - name: 桶的類型 + notStarted: 沒有已開始的任務 + timeToWaitRedo: '§3§o你可以在此時間之後再次接任務: {time_left} ' + timesFinished: '§3任務已經做過 {times_finished} 次.' + mobSelect: + boss: '§6選擇一個Boss' + bukkitEntityType: '§e選擇一個生物類型' + epicBoss: '§6選擇一個Epic Boss' + mythicMob: '§6選擇一個MythicMob' + name: 選擇怪物 + mobs: + name: 選擇怪物 + none: '§a點擊增加怪物' + npcCreate: + move: + itemLore: '§a更改NPC位置.' + itemName: '§6傳送' + moveItem: '§a§l確認前往' + name: 創建NPC + setName: '§a編輯NPC名稱' + setSkin: '§e編輯NPC皮膚' + setType: '§a編輯NPC類型' + npcSelect: + createStageNPC: '§e創建 NPC' + name: 選擇還是創建NPC? + selectStageNPC: '§6選擇 NPC' permission: name: 選擇權限 perm: '§a權限' - world: '§a世界' - worldGlobal: '§b§l全局' remove: 刪除權限 removeLore: '§7P將收回權限\n§7而非給予權限。' + world: '§a世界' + worldGlobal: '§b§l全局' permissionList: name: 權限列表 - removed: '§e已移除: §6{0}' - world: '§e世界:§6{0}' - classesRequired.name: 需要職業 - classesList.name: 職業列表 - factionsRequired.name: 需要派系/公會 - factionsList.name: 派系/公會列表 - poolsManage: - name: 任務池 - itemName: '§a池#{0}' - poolNPC: '§8NPC:§7{0}' - poolMaxQuests: '§8最大任務數:§7{0}' - poolRedo: '§8可以重新接受已完成的任務:§7{0}' - poolTime: '§8任務之間的間隔:§7{0}' - poolHologram: '§8浮空字:§7{0}' - poolAvoidDuplicates: '§8避免重複:§7{0}' - poolQuestsList: '§7{0} §8任務:§7{1}' - create: '§a創建一個任務池' - edit: '§e> §6§o更改任務池... §e<' + removed: '§e已移除: §6{permission_removed}' + world: '§e世界:§6{permission_world}' poolCreation: - name: 創建任務池 + avoidDuplicates: 避免重複 + avoidDuplicatesLore: '§8> §7 嘗試避免重複\n相同任務' hologramText: '§e任務池特殊浮空字' maxQuests: '§a最大任務數' - time: '§b設置任務之間的間隔' + name: 創建任務池 redoAllowed: 是否可重複完成 - avoidDuplicates: 避免重複 - avoidDuplicatesLore: '§8> §7 嘗試避免重複\n相同任務' requirements: '§b接任務的需求' + time: '§b設置任務之間的間隔' poolsList.name: 任務池 - itemComparisons: - name: 比較物品 - bukkit: Bukkit原生比較 - bukkitLore: "使用Bukkit預設道具比較系統。\n比較材料、耐久度、NBT標籤……" - customBukkit: Bukkit原生比較 -沒NBT - customBukkitLore: "使用Bukkit預設物品比較系統,但除去NBT標籤。\n比較材料名、耐久度等" - material: 物品材料 - materialLore: '比較物品材料(如石頭|stone、鐵劍|iron sword)' - itemName: 物品名 - itemNameLore: 比較物品名稱 - itemLore: 物品描述 - itemLoreLore: 比較物品描述 - enchants: 物品附魔 - enchantsLore: 比較物品附魔 - repairCost: 修復花費 - repairCostLore: 比較盔甲和武器的修復花費 - editTitle: - name: 更改標題 - title: '§6標題' - subtitle: '§e副標題' - fadeIn: '§a淡入時間' - stay: '§b停留時間' - fadeOut: '§a淡出時間' -scoreboard: - name: '§6§l任務' - noLaunched: '§c你沒有進行中的任務.' - noLaunchedName: '§c§l載入中' - noLaunchedDescription: '§c§o載入中' - textBetwteenBranch: '§e或' - stage: - region: '§e找到區域 §6{0}' - npc: '§e和NPC談話 §6{0}' - items: '§e將物品帶給§6{0}§e:' - mobs: '§e擊殺 §6{0}' - mine: '§e挖掘 {0}' - placeBlocks: '§e放置 {0}' - chat: '§e輸入 §6{0}' - interact: '§e點擊在§6{0}的方塊' - interactMaterial: '§e點擊 §6{0}§e 方塊' - fish: '§e釣魚 §6{0}' - craft: '§e合成 §6{0}' - bucket: '§e裝滿 §6{0}' - location: '§e前往位於 §6{3}的坐標§6{0}§e, §6{1}§e, §6{2}§e ' - playTime: '§e遊玩遊戲§6{0}刻' - breed: '§e餵飼 §6{0}' - tame: '§e餵養 §6{0}' -indication: - startQuest: '§7您是否想要接受任務 {0}?' - closeInventory: '§7你確定要關閉該頁面嗎?' - cancelQuest: '§7您確定要取消任務 {0}?' - removeQuest: '§7您確定要刪除任務 {0}?' + poolsManage: + create: '§a創建一個任務池' + edit: '§e> §6§o更改任務池... §e<' + itemName: '§a池#{pool}' + name: 任務池 + poolAvoidDuplicates: '§8避免重複:§7{pool_duplicates}' + poolHologram: '§8浮空字:§7{pool_hologram}' + poolMaxQuests: '§8最大任務數:§7{pool_max_quests}' + poolNPC: '§8NPC:§7{pool_npc_id}' + poolQuestsList: '§7{pool_quests_amount} §8任務:§7{pool_quests}' + poolRedo: '§8可以重新接受已完成的任務:§7{pool_redo}' + poolTime: '§8任務之間的間隔:§7{pool_time}' + requirements: + name: 任務需求 + rewards: + commands: '指令: {amount}' + name: 任務獎勵 + rewardsWithRequirements: + name: 有條件發送獎勵 + search: '§e§l搜索' + stageEnding: + command: '§a編輯執行的指令' + locationTeleport: '§a編輯傳送點' + stages: + branchesPage: '§d分支任務階段' + descriptionTextItem: '§e編輯文本描述' + endingItem: '§e編輯階段結束獎勵' + laterPage: '§e上一頁' + name: '§8創建任務階段' + newBranch: '§e前往新的任務分支' + nextPage: '§e下一頁' + previousBranch: '§e返回上一個分支' + regularPage: '§a普通任務階段' + validationRequirements: '§e驗證需求' + validationRequirementsLore: 所有需求必須匹配嘗試完成階段的玩家。否則該階段無法完成。 + validate: '§b§l確認' misc: + amount: '§e數量: {amount}' + and: 和 + bucket: + lava: 巖漿桶 + milk: 牛奶桶 + water: 水桶 + comparison: + different: 不同於{number} + equals: 等於{number} + greater: 精確大於{number} + greaterOrEquals: 大於{number} + less: 精確小於 {number} + lessOrEquals: 小於{number} + disabled: 已關閉 + enabled: 已啟用 + entityType: '§e生物類型: {entity_type}' + entityTypeAny: '§e任何實體' format: + npcText: '§f<§e任務§f> §7[§f{message_id}§8/§7{message_count}] §f{npc_name_message} §8§l»§f {text}' prefix: '§f<§e任務§f> §r' - npcText: '§f<§e任務§f> §7[§f{2}§8/§7{3}] §f{0} §8§l»§f {1}' - selfText: '§f<§e任務§f> §7[§f{2}§8/§7{3}] §f{0} §8§l»§f {1}' - offText: '§r§e{0}' - time: - days: '{0} 日' - hours: '{0} 小時' - minutes: '{0} 分鐘' - lessThanAMinute: '少於一分鐘' - stageType: - region: 尋找區域 - npc: 尋找 NPC - items: 帶回物品 - mobs: 擊殺怪物 - mine: 破壞方塊 - placeBlocks: 放置方塊 - chat: 在聊天框內說話 - interact: 與方塊交互 - Fish: 釣魚 - Craft: 合成物品 - Bucket: 裝滿桶 - location: 尋找地點 - playTime: 遊戲時間 - breedAnimals: 餵飼動物 - tameAnimals: 領養動物 - comparison: - equals: 等於{0} - different: 不同於{0} - less: 精確小於 {0} - lessOrEquals: 小於{0} - greater: 精確大於{0} - greaterOrEquals: 大於{0} + selfText: '§f<§e任務§f> §7[§f{message_id}§8/§7{message_count}] §f{player_name} §8§l»§f {text}' + hologramText: '§8§l任務 NPC' + 'no': '否' + notSet: '§c未設置' + or: 或 + poolHologramText: '§e有新任務可接' + questItemLore: '§e§o任務物品' requirement: - skillAPILevel: '§d需要SkillAPI技能等級' class: '§b所需職業' - faction: '§b所需派系' - jobLevel: '§b所需工作等級' combatLevel: '§b所需戰鬥等級' experienceLevel: '§b所需經驗等級' + faction: '§b所需派系' + jobLevel: '§b所需工作等級' + mcMMOSkillLevel: '§d所需技能等級' + money: '§d所需金額' permissions: '§3所需權限' - scoreboard: '§d所需分數' - region: '§d需要區域' placeholder: '§b所需占位符數值' quest: '§a所需前置任務' - mcMMOSkillLevel: '§d所需技能等級' - money: '§d所需金額' - bucket: - water: 水桶 - lava: 巖漿桶 - milk: 牛奶桶 - ticks: '{0} 遊戲秒數' - questItemLore: '§e§o任務物品' - hologramText: '§8§l任務 NPC' - poolHologramText: '§e有新任務可接' - mobsProgression: '§f階段進度 §8§l» §f{1}§8/§7{2}' - entityType: '§e生物類型: {0}' - entityTypeAny: '§e任何實體' - enabled: 已啟用 - disabled: 已關閉 + region: '§d需要區域' + scoreboard: '§d所需分數' + skillAPILevel: '§d需要SkillAPI技能等級' + stageType: + Bucket: 裝滿桶 + Craft: 合成物品 + Fish: 釣魚 + breedAnimals: 餵飼動物 + chat: 在聊天框內說話 + interact: 與方塊交互 + items: 帶回物品 + location: 尋找地點 + mine: 破壞方塊 + mobs: 擊殺怪物 + npc: 尋找 NPC + placeBlocks: 放置方塊 + playTime: 遊戲時間 + region: 尋找區域 + tameAnimals: 領養動物 + ticks: '{ticks} 遊戲秒數' + time: + days: '{days_amount} 日' + hours: '{hours_amount} 小時' + lessThanAMinute: 少於一分鐘 + minutes: '{minutes_amount} 分鐘' unknown: 未知 - notSet: '§c未設置' - unused: '§e§l未設置' - used: '§6§l已設置' - remove: '§e§o點擊鼠標中鍵刪除' - or: 或 - amount: '§e數量: {0}' - items: 物品 - expPoints: 經驗點數 'yes': '是' - 'no': '否' - and: 和 +msg: + bringBackObjects: 把 {items} 帶回給我. + command: + adminModeEntered: '§a你已進入管理員模式.' + adminModeLeft: '§a你退出了管理員模式.' + backupCreated: '§6你成功地創建了任務和玩家數據的備份文件.' + backupPlayersFailed: '§c創建玩家數據備份失敗.' + backupQuestsFailed: '§c創建任務數據備份失敗.' + cancelQuest: '§6你放棄了任務 {quest}.' + cancelQuestUnavailable: '§c無法取消任務 {quest} .' + checkpoint: + noCheckpoint: '§c未找到任務{quest}的記錄點。' + questNotStarted: '§c你沒有接受這個任務。' + help: + adminMode: '§6/{label} adminMode : §e切換管理員模式 (顯示消息)' + create: '§6/{label} create: §a創建任務' + edit: '§6/{label} edit: §a編輯任務' + finishAll: '§6/{label} finishAll <玩家名>: §a結束一名玩家所有進行中的任務。' + header: '§6§lBeautyQuests - §6幫助§r' + list: '§e/{label} list: §a查看任務列表 (部分版本無效)' + reload: '§e/{label} reload: §a保存並重載配置和插件數據 - §c§o不推薦使用' + remove: '§6/{label} remove [id]: §a刪除ID為 [id] 的任務或點擊任務NPC來刪除' + resetPlayer: '§6/{label} resetPlayer <玩家名>: §e刪除一名玩家的所有任務數據。' + resetPlayerQuest: '§6/{label} resetPlayerQuest <玩家名> [id]: §e刪除一名玩家的一個任務數據' + save: '§6/{label} save: §a手動保存數據.' + seePlayer: '§6/{label} seePlayer <玩家名>: §a查看玩家的任務數據。' + setItem: '§6/{label} setItem <talk|launch> : §e保存全息物品到數據文件內.' + setStage: '§6/{label} setStage <玩家名> <id> [新任務分支] [新任務階段]: §e跳過玩家當前的任務階段/開始任務分支/s為任務分支設置任務階段。' + start: '§6/{label} start <玩家名> [id] : §e強制玩家接受任務.' + version: '§6/{label} version: §e查看插件版本.' + invalidCommand: + simple: '§c指令不存在, 輸入 §ehelp §c查看幫助(不需要 /)' + itemChanged: '§a已編輯物品. 更改會在重啟後生效.' + itemRemoved: '§a已刪除全息物品.' + leaveAll: '§e你強制結束了{success}個任務. §c出現{errors}個錯誤.' + removed: '§a成功刪除任務 {quest_name}。' + resetPlayer: + player: '§6你的所有任務數據 ({quest_amount}) 被 {deleter_name} 刪除了.' + remover: '§6{quest_amount} 個任務資料 (包含 {quest_pool} 個池) 已經移除. 原本有 {player} 個.' + resetPlayerQuest: + player: '§6任務數據 {quest} 已被 {deleter_name} 刪除.' + remover: '§6{quest} 的 {player} 條任務信息已被刪除.' + resetQuest: '§6已移除{player_amount}的任務數據。' + scoreboard: + hidden: '§6已隱藏{player_name}的計分版.' + lineInexistant: '§c第 {line_id} 行不存在.' + lineRemoved: '§6你成功地刪除了第 {line_id} 行.' + lineReset: '§6你成功地重置了第 {line_id} 行.' + lineSet: '§6你成功地編輯了第 {line_id} 行.' + resetAll: '§6你成功地清空了 {player_name} 的計分版.' + shown: '§6已重新顯示{player_name}的計分版。' + setStage: + branchDoesntExist: '§cid為{branch_id}的任務分支不存在。' + doesntExist: '§cID為{stage_id}的任務階段不存在.' + next: '§a已跳過該任務階段.' + nextUnavailable: '§c"skip"選項在玩家到達任務分支結尾時無法使用。' + set: '§a已進入任務階段 {stage_id} .' + startQuest: '§6你接受了任務 {quest} (UUID: {player}).' + editor: + already: '§c你已在編輯器中.' + blockAmount: '§a請輸入所需的數量:' + blockData: '§a請輸入所需的方塊 Data (可用的 Data: {available_datas}):' + blockName: '§a請輸入所需的方塊名稱:' + chat: '§6你現在在編輯模式. 使用 "/quests exitEditor" 強制離開編輯器 (極度不推薦,請使用指令例如 "close" 或者 "cancel" 返回上一頁)' + dialog: + cleared: '§a已刪除{amount}條消息.' + help: + addSound: '§eaddsound <id> <音效名>: §b給一條消息增加音效.' + clear: '§eclear: §b刪除所有消息.' + close: '§eclose: §b退出並保存所有消息.' + edit: '§6更改 <id> <message>: §e更改一個訊息' + header: '§e§lBeautyQuest - §6對話編輯器幫助' + list: '§elist: §b查看所有的消息.' + nothing: '§6noSender <消息>: §e增加一條沒有發送者的消息.' + nothingInsert: '§enothinginsert <id> <消息>: §b插入一條沒有任何前綴的消息.' + npc: '§npc <message>: §b增加一條由NPC說出的消息。' + npcInsert: '§enpcinsert <id> <消息>: §b插入一條由NPC說出的話.' + player: '§6player <message>: §b增加一條由玩家說出的消息。' + playerInsert: '§eplayerinsert <id> <消息>: §b插入一條由玩家說出的話.' + remove: '§6emove <id>: §e刪除一條消息.' + setTime: '§6setTime <id> <時間>: §e設置自動播放下一條消息的時間(單位為刻) 。' + syntaxRemove: '§c正確用法: remove <id>' + timeRemoved: '§a已刪除消息{msg}的時間。' + timeSet: '§a已編輯消息 {msg} 的時間: 現在是 {time} 刻。' + enter: + subtitle: '§6使用指令 "/quests exitEditor" 強制離開編輯器' + title: '§6~ 進入編輯器模式 ~' + goToLocation: '§a前往該任務階段指定地點。' + itemCreator: + invalidBlockType: '§c未知方塊種類' + invalidItemType: '§c無效的物品類型 (必須是物品而不能是方塊).' + itemAmount: '§e請輸入所需物品數:' + itemLore: '§e修改物品描述. 輸入 "help" 查看幫助.' + itemName: '§a輸入物品名:' + itemType: '§a輸入物品類型名:' + unknownBlockType: '§c未知方塊種類' + unknownItemType: '§c未知的物品類型.' + mythicmobs: + disabled: '§cMythicMob已關閉.' + isntMythicMob: '§c這個MythicMob不存在.' + list: '§a所有的MythocMobs:' + noSuchElement: '§c沒有這樣的元素。可用元素:§e{available_elements}' + npc: + choseStarter: '§a選擇接受任務的NPC.' + enter: '§a點擊一個NPC,或輸入"cancel"取消.' + notStarter: '§c這個NPC沒有可以接受的任務...' + pool: + hologramText: 為這個池設定一個特定的浮空字 (如果你想用預設的請寫 "null") + maxQuests: 填寫這個池最多可以開始的任務. + scoreboardObjectiveNotFound: '§c未知的計分板目標。' + selectWantedBlock: '§a用木棍點擊開始任務階段的方塊.' + text: + argNotSupported: '§c不支持 {arg} 參數.' + chooseJobRequired: '§a輸入所需的工作名:' + chooseLvlRequired: '§a輸入所需等級:' + chooseMoneyRequired: '§e輸入所需金額:' + chooseObjectiveRequired: '§a請輸入目標名。' + chooseObjectiveTargetScore: '§a請輸入完成任務目標所需目標數。' + choosePermissionMessage: '§e如果玩家沒有所需權限則顯示的拒絕消息. (輸入 "null" 跳過這步)' + choosePermissionRequired: '§a輸入開始任務所需權限:' + choosePlaceholderRequired: + identifier: '§e輸入所需的占位符名 (§l不用加上 %%§r§e).' + value: '§a請為所需要的參數填寫適當資料 §e%§e{placeholder}§e%§a:' + chooseRegionRequired: '§a請輸入所需區域名 (你必須與該區域在同一個世界中)。' + chooseSkillRequired: '§a輸入技能名:' + reward: + money: '§e輸入獲得的錢數:' + permissionName: '§a請輸入權限名稱。' + permissionWorld: '§a請輸入可編輯權限的世界名,輸入"null"則所有世界可編輯。' + wait: '§a填寫多少遊戲時間需要等待: (1 現實秒數 = 20 遊戲秒數)' + textList: + help: + add: '§6add [消息]: §e增加一條文本.' + close: '6close: §e確認增加文本並退出編輯器.' + header: '§6§lBeautyQuests — 編輯器列表幫助' + list: '§6list: §e查看所有已增加的文本.' + remove: '§6remove [id]: §e刪除一條文本.' + syntax: '§c正確用法: ' + title: + fadeIn: 填寫 "fade-in" 淡入時間, 單位是遊戲秒數 (20 遊戲妙數 = 1 秒). + fadeOut: 填寫 "fade-out" 淡出時間, 單位是遊戲秒數 (20 遊戲妙數 = 1 秒). + stay: 填寫 "stay" 逗留時間, 單位是遊戲秒數 (20 遊戲妙數 = 1 秒). + subtitle: 填寫任務的副標題 (填寫 "null" 代表沒有) + title: 填寫任務的標題 (填寫 "null" 代表沒有) + typeBucketAmount: '§a請輸入要裝滿桶的數量:' + typeGameTicks: '§a請輸入所需的 Ticks:' + typeLocationRadius: '§a請輸入距離指定位置所需的距離:' + errorOccurred: '§c插件發生錯誤,請聯系管理員!錯誤代碼為: {error}' + experience: + edited: '已編輯獲得的經驗: {old_xp_amount}pts. 改為 {xp_amount}pts.' + indexOutOfBounds: '§c數字 ({index}) 超過了區間 [{min}, {max}].' + invalidBlockData: '§c此方塊 Data {block_data} 並不能用在 {block_material} 上' + inventoryFull: '§c你的背包已滿, 任務獎勵已掉落在地上.' + moveToTeleportPoint: 前往指定的傳送點. + npcDoesntExist: '§cID為{npc_id}的NPC不存在.' + number: + invalid: '§c"{input}" 不是有效的數字.' + negative: '§c你必須輸入正數!' + zero: '§c你必須輸入大於0的數!' + pools: + allCompleted: '§7你已經完成所有任務!' + maxQuests: '§c你不可以同時接多過 {pool_max_quests} 個任務...' + noAvailable: '§7這裡沒有更多可以接的任務' + noTime: '§c你必須等待 {time_left} 才能做其他任務' + quest: + alreadyStarted: '§c你已經接受了這個任務!' + cancelling: '§c已取消創建任務.' + createCancelled: '§c抱歉,任務創建/編輯已被其他插件取消...' + created: '§a你成功地創建了 "§e{quest}§a" 任務, 包含 {quest_branches} 個階段!' + editCancelling: '§c已取消編輯任務.' + edited: '§a你成功地修改了 "§e{quest}§a", 包含 {quest_branches} 個階段!' + finished: + base: '§a恭喜你完成了任務 §o§6{quest_name}§r§a!' + obtain: '§a你獲得了 {rewards}!' + invalidID: '§cID為 {quest_id} 的任務不存在.' + started: '§a你接受了任務 §r§e{quest_name}§o§6!' + questItem: + craft: '§c你不可以用一個任務道具去合成' + drop: '§c你不可以掉落一個任務道具' + quests: + checkpoint: '§7已到達任務記錄點!' + failed: '§6任務{quest_name}失敗……' + maxLaunched: '§c你不可以同時接多過 {quests_max_amount} 個任務...' + updated: '§7已更新任務 {quest_name} !' + regionDoesntExists: '§c這個區域不存在... (你必須在目標區域同一世界內)' + requirements: + combatLevel: '§e你必須達到戰鬥等級 {long_level}!' + job: '§e你必須達到 {long_level} 級才能應聘工作 {job_name}!' + level: '§e你必須達到 {long_level} 級!' + money: '§c你必須擁有{money}!' + quest: '§c你必須先完成任務§e "{quest_name}"§c!' + skill: '§e你的{skill_name}技能必須要達到{long_level}級!' + waitTime: '§c你必須等待 {time_left} 分鐘才能再次接受這個任務!' + selectNPCToKill: 選擇要擊殺的NPC. + stageMobs: + listMobs: '§a你需要殺死 {mobs}.' + typeCancel: '§a輸入 "cancel" 返回到上一條消息.' + writeChatMessage: '要玩家輸入的消息 (在開頭加上 {SLASH} 來讓玩家輸入指令).' + writeCommand: '§a輸入指令. (開頭無需加上斜杠/) 你可以用 {PLAYER}來代表玩家名.' + writeCommandDelay: '§a請輸入指令延遲,單位為刻。' + writeConfirmMessage: '§a請輸入玩家確認加入任務的消息: (輸入 "null" 則顯示默認消息)' + writeDescriptionText: '任務階段目標描述.' + writeHologramText: '§a輸入全息文字. (輸入 "none" 則不顯示, 輸入 "null" 顯示默認文本)' + writeMobAmount: '輸入要擊殺的怪物數.' + writeMobName: '§a填寫特殊怪物的名稱用作擊殺' + writeNPCText: '輸入玩家需要對NPC說的話. 輸入 "help" 來獲取幫助. (指令不需要輸入 /)' + writeNpcName: '輸入NPC名稱.' + writeNpcSkinName: '輸入NPC皮膚名.' + writeQuestDescription: '§a請輸入顯示在玩家任務菜單內的任務描述。' + writeQuestMaterial: '§a請輸入任務物品材料名。' + writeQuestName: '§a輸入任務名:' + writeQuestTimer: '§a輸入重新開始任務的冷卻時間 (單位為分鐘)(輸入 "null" 則使用默認值)' + writeRegionName: '輸入任務階段所需前往的區域名.' + writeStageText: '任務開始時發送的消息.' + writeXPGain: '輸入玩家獲得的經驗點. 最終獲得: §a{xp_amount}' +scoreboard: + name: '§6§l任務' + noLaunched: '§c你沒有進行中的任務.' + noLaunchedDescription: '§c§o載入中' + noLaunchedName: '§c§l載入中' + stage: + breed: '§e餵飼 §6{mobs}' + bucket: '§e裝滿 §6{buckets}' + chat: '§e輸入 §6{text}' + craft: '§e合成 §6{items}' + fish: '§e釣魚 §6{items}' + interact: '§e點擊在§6{x}的方塊' + interactMaterial: '§e點擊 §6{block}§e 方塊' + items: '§e將物品帶給§6{dialog_npc_name}§e:' + location: '§e前往位於 §6{target_world}的坐標§6{target_x}§e, §6{target_y}§e, §6{target_z}§e ' + mine: '§e挖掘 {blocks}' + mobs: '§e擊殺 §6{mobs}' + npc: '§e和NPC談話 §6{dialog_npc_name}' + placeBlocks: '§e放置 {blocks}' + region: '§e找到區域 §6{region_id}' + tame: '§e餵養 §6{mobs}' + textBetwteenBranch: '§e或' From 67fc0b230b004cff55894d241ccc30cb4b7a3d67 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 18 Sep 2023 17:12:15 +0200 Subject: [PATCH 52/95] :bug: Fixed lot of small bugs --- .../quests/api/gui/GuiClickEvent.java | 5 +- .../quests/api/gui/layout/LayoutedGUI.java | 5 +- .../quests/api/options/QuestOptionString.java | 32 +- .../quests/gui/quests/DialogHistoryGUI.java | 6 +- .../skytasul/quests/rewards/ItemReward.java | 20 +- .../quests/stages/StageInteractBlock.java | 23 +- .../quests/stages/StageInteractLocation.java | 32 +- .../quests/utils/types/BQLocation.java | 58 +- core/src/main/resources/locales/en_US.yml | 1792 ++++++++--------- core/src/main/resources/locales/fr_FR.yml | 1521 +++++++------- 10 files changed, 1750 insertions(+), 1744 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java index 99fbf6fe..0871cdda 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiClickEvent.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.api.gui; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; @@ -30,7 +31,7 @@ public GuiClickEvent(@NotNull Player player, @NotNull Gui gui, @Nullable ItemSta public @NotNull Player getPlayer() { return player; } - + public @NotNull Gui getGui() { return gui; } @@ -44,7 +45,7 @@ public GuiClickEvent(@NotNull Player player, @NotNull Gui gui, @Nullable ItemSta } public boolean hasCursor() { - return cursor != null; + return cursor != null && cursor.getType() != Material.AIR; } public int getSlot() { diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java index 47ce3b2d..c1cf952d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/layout/LayoutedGUI.java @@ -30,7 +30,10 @@ protected LayoutedGUI(@Nullable String name, @NotNull Map<Integer, LayoutedButto @Override protected void populate(@NotNull Player player, @NotNull Inventory inventory) { - buttons.forEach((slot, button) -> button.place(inventory, slot)); + buttons.forEach((slot, button) -> { + if (button.isValid()) + button.place(inventory, slot); + }); } @Override diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java index b05558f1..5c3ec96f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOptionString.java @@ -14,43 +14,45 @@ import fr.skytasul.quests.api.quests.creation.QuestCreationGuiClickEvent; public abstract class QuestOptionString extends QuestOption<String> { - + public QuestOptionString(Class<? extends QuestOption<?>>... requiredQuestOptions) { super(requiredQuestOptions); } - + @Override public Object save() { return getValue(); } - + @Override public void load(ConfigurationSection config, String key) { setValue(config.getString(key)); } - + @Override public String cloneValue(String value) { return value; } - + private String[] getLore() { if (getItemDescription() == null) return new String[] { formatValue(getValue()) }; - + String description = formatDescription(getItemDescription()); return new String[] { description, "", formatValue((isMultiline() && getValue() != null ? "{nl}" : "") + getValue()) }; } - + @Override public ItemStack getItemStack(OptionSet options) { return ItemUtils.item(getItemMaterial(), getItemName(), getLore()); } - + @Override public void click(QuestCreationGuiClickEvent event) { sendIndication(event.getPlayer()); if (isMultiline()) { - List<String> splitText = getValue() == null ? new ArrayList<>() : new ArrayList<>(Arrays.asList(getValue().split("\\{nl\\}"))); + List<String> splitText = getValue() == null || getValue().isEmpty() + ? new ArrayList<>() + : new ArrayList<>(Arrays.asList(getValue().split("\\{nl\\}"))); new TextListEditor(event.getPlayer(), list -> { setValue(list.stream().collect(Collectors.joining("{nl}"))); ItemUtils.lore(event.getClicked(), getLore()); @@ -67,19 +69,19 @@ public void click(QuestCreationGuiClickEvent event) { }).passNullIntoEndConsumer().start(); } } - + public abstract void sendIndication(Player p); - + public abstract XMaterial getItemMaterial(); - + public abstract String getItemName(); - + public String getItemDescription() { return null; } - + public boolean isMultiline() { return false; } - + } 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 2bf2282b..d54ae36c 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 @@ -135,7 +135,7 @@ class WrappedDialogable { added = true; } page.header = "§7§l" + messagesAdded + "§8 / §7§l" - + Lang.AmountDialogLines.quickFormat("amount", messages.size()); + + Lang.AmountDialogLines.quickFormat("lines_amount", messages.size()); page.lines.addLast(" " + (pages.isEmpty() ? "§8" : "§7") + "◀ " + Lang.ClickLeft + " §8/ " + (last && !pageFull ? "§8" : "§7") + Lang.ClickRight + " ▶"); pages.add(page); @@ -150,8 +150,8 @@ class WrappedDialogable { } if (!page.lines.isEmpty()) { - page.header = - "§7§l" + messagesAdded + "§8 / §7§l" + Lang.AmountDialogLines.quickFormat("amount", messages.size()); + page.header = "§7§l" + messagesAdded + "§8 / §7§l" + + Lang.AmountDialogLines.quickFormat("lines_amount", messages.size()); page.lines.addLast( " " + (pages.isEmpty() ? "§8" : "§7") + "◀ " + Lang.ClickLeft + " §8/ " + Lang.ClickRight + " ▶"); pages.add(page); diff --git a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java index 637ebc10..f8863729 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/ItemReward.java @@ -19,11 +19,11 @@ public class ItemReward extends AbstractReward { public List<ItemStack> items; - + public ItemReward(){ this(null, new ArrayList<>()); } - + public ItemReward(String customDescription, List<ItemStack> items) { super(customDescription); this.items = items; @@ -41,22 +41,26 @@ public List<String> give(Player p) { public AbstractReward clone() { return new ItemReward(getCustomDescription(), items); } - + @Override public String getDefaultDescription(Player p) { - return getItemsSizeString(); + return Lang.AmountItems.toString(); } @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); - placeholders.register("items_amount", this::getItemsSizeString); + placeholders.register("items_amount", () -> Integer.toString(getItemsSize())); + } + + private int getItemsSize() { + return items.stream().mapToInt(ItemStack::getAmount).sum(); } private String getItemsSizeString() { - return Lang.AmountItems.quickFormat("amount", items.stream().mapToInt(ItemStack::getAmount).sum()); + return Lang.AmountItems.quickFormat("items_amount", getItemsSize()); } - + @Override protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); @@ -70,7 +74,7 @@ public void itemClick(QuestObjectClickEvent event) { event.reopenGUI(); }, items).open(event.getPlayer()); } - + @Override public void save(ConfigurationSection section) { super.save(section); diff --git a/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java index 69f36591..d2497c7b 100755 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractBlock.java @@ -1,6 +1,7 @@ package fr.skytasul.quests.stages; import java.util.Collections; +import java.util.Objects; import java.util.Spliterator; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -69,7 +70,7 @@ public void onInteract(PlayerInteractEvent e){ Player p = e.getPlayer(); if (hasStarted(p) && canUpdate(p)) { - if (left) e.setCancelled(true); + e.setCancelled(true); finishStage(p); } } @@ -116,6 +117,12 @@ public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); + line.setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), event -> { + new SelectBlockGUI(false, (newBlock, __) -> { + setMaterial(newBlock); + event.reopen(); + }).open(event.getPlayer()); + }); } public void setLeftClick(boolean leftClick) { @@ -125,17 +132,9 @@ public void setLeftClick(boolean leftClick) { } } - public void setMaterial(BQBlock block) { - if (this.block == null) { - getLine().setItem(7, ItemUtils.item(XMaterial.STICK, Lang.blockMaterial.toString()), event -> { - new SelectBlockGUI(false, (newBlock, __) -> { - setMaterial(newBlock); - event.reopen(); - }).open(event.getPlayer()); - }); - } - getLine().refreshItem(7, item -> ItemUtils.loreOptionValue(item, block.getName())); - this.block = block; + public void setMaterial(@NotNull BQBlock block) { + this.block = Objects.requireNonNull(block); + getLine().refreshItemLoreOptionValue(7, block.getName()); } @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 3215bda6..926e8e04 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StageInteractLocation.java @@ -1,5 +1,6 @@ package fr.skytasul.quests.stages; +import java.util.Objects; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.configuration.ConfigurationSection; @@ -31,17 +32,17 @@ public class StageInteractLocation extends AbstractStage implements Locatable.PreciseLocatable, Listener { private final boolean left; - private final BQLocation lc; + private final @NotNull BQLocation lc; private Located.LocatedBlock locatedBlock; - public StageInteractLocation(StageController controller, boolean leftClick, BQLocation location) { + public StageInteractLocation(@NotNull StageController controller, boolean leftClick, @NotNull BQLocation location) { super(controller); this.left = leftClick; this.lc = new BQLocation(location.getWorldName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); } - public BQLocation getLocation() { + public @NotNull BQLocation getLocation() { return lc; } @@ -75,7 +76,7 @@ public void onInteract(PlayerInteractEvent e){ Player p = e.getPlayer(); if (hasStarted(p) && canUpdate(p)) { - if (left) e.setCancelled(true); + e.setCancelled(true); finishStage(p); } } @@ -119,6 +120,13 @@ public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); line.setItem(6, ItemUtils.itemSwitch(Lang.leftClick.toString(), leftClick), event -> setLeftClick(!leftClick)); + line.setItem(7, ItemUtils.item(XMaterial.COMPASS, Lang.blockLocation.toString()), event -> { + Lang.CLICK_BLOCK.send(event.getPlayer()); + new WaitBlockClick(event.getPlayer(), event::reopen, obj -> { + setLocation(obj); + event.reopen(); + }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); + }); } public void setLeftClick(boolean leftClick) { @@ -128,19 +136,9 @@ public void setLeftClick(boolean leftClick) { } } - public void setLocation(Location location) { - if (this.location == null) { - getLine().setItem(7, ItemUtils.item(XMaterial.COMPASS, Lang.blockLocation.toString()), event -> { - Lang.CLICK_BLOCK.send(event.getPlayer()); - new WaitBlockClick(event.getPlayer(), event::reopen, obj -> { - setLocation(obj); - event.reopen(); - }, ItemUtils.item(XMaterial.STICK, Lang.blockLocation.toString())).start(); - }); - } - getLine().refreshItem(7, - item -> ItemUtils.loreOptionValue(item, Lang.Location.format(getBQLocation()))); - this.location = location; + public void setLocation(@NotNull Location location) { + this.location = Objects.requireNonNull(location); + getLine().refreshItemLoreOptionValue(7, Lang.Location.format(getBQLocation())); } @Override 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 f5d7d32e..dc5741dd 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 @@ -18,64 +18,64 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; public class BQLocation extends Location implements Locatable.Located, HasPlaceholders { - + private @Nullable Pattern worldPattern; private @Nullable PlaceholderRegistry placeholders; - - public BQLocation(Location bukkit) { + + 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); } - + public BQLocation(World world, double x, double y, double z, float yaw, float pitch) { super(world, x, y, z, yaw, pitch); if (world == null) worldPattern = Pattern.compile(".*"); } - + public BQLocation(String worldPattern, double x, double y, double z) { this(worldPattern, x, y, z, 0, 0); } - + public BQLocation(String worldPattern, double x, double y, double z, float yaw, float pitch) { super(null, x, y, z, yaw, pitch); this.worldPattern = Pattern.compile(worldPattern); } - + public Pattern getWorldPattern() { return worldPattern; } - + public BQLocation setWorldPattern(Pattern worldPattern) { this.worldPattern = worldPattern; if (worldPattern != null) super.setWorld(null); return this; } - + @Override public void setWorld(World world) { throw new UnsupportedOperationException(); } - + @Override public Location getLocation() { return new Location(getWorld(), getX(), getY(), getZ()); } - + @Override public LocatedType getType() { return LocatedType.OTHER; } - + public boolean isWorld(World world) { Validate.notNull(world); if (super.getWorld() != null) return super.getWorld().equals(world); return worldPattern.matcher(world.getName()).matches(); } - + public String getWorldName() { return getWorld() == null ? worldPattern.pattern() : getWorld().getName(); } @@ -91,7 +91,7 @@ public Block getMatchingBlock() { .map(world -> world.getBlockAt(getBlockX(), getBlockY(), getBlockZ())) .orElse(null); } - + @Override public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { if (placeholders == null) @@ -112,45 +112,45 @@ public double distanceSquared(Location o) { + NumberConversions.square(getY() - o.getY()) + NumberConversions.square(getZ() - o.getZ()); } - + @Override public boolean equals(Object obj) { if (!(obj instanceof Location)) return false; Location other = (Location) obj; - + if (Double.doubleToLongBits(this.getX()) != Double.doubleToLongBits(other.getX())) return false; if (Double.doubleToLongBits(this.getY()) != Double.doubleToLongBits(other.getY())) return false; if (Double.doubleToLongBits(this.getZ()) != Double.doubleToLongBits(other.getZ())) return false; if (Float.floatToIntBits(this.getPitch()) != Float.floatToIntBits(other.getPitch())) return false; if (Float.floatToIntBits(this.getYaw()) != Float.floatToIntBits(other.getYaw())) return false; - + if (obj instanceof BQLocation) { BQLocation otherBQ = (BQLocation) obj; if (worldPattern == null) return otherBQ.worldPattern == null; if (otherBQ.worldPattern == null) return false; return worldPattern.pattern().equals(otherBQ.worldPattern.pattern()); } - + if (!Objects.equals(other.getWorld(), getWorld())) { if (other.getWorld() == null) return false; if (worldPattern == null) return false; return worldPattern.matcher(other.getWorld().getName()).matches(); } - + return true; } - + @Override public int hashCode() { int hash = super.hashCode(); hash = 19 * hash + (worldPattern == null ? 0 : worldPattern.pattern().hashCode()); return hash; } - + @Override public Map<String, Object> serialize() { Map<String, Object> map = new HashMap<>(); - + if (getWorld() == null) { map.put("pattern", worldPattern.pattern()); } else { @@ -166,10 +166,10 @@ public Map<String, Object> serialize() { map.put("yaw", getYaw()); map.put("pitch", getPitch()); - + return map; } - + @NotNull public static BQLocation deserialize(@NotNull Map<String, Object> args) { double x = NumberConversions.toDouble(args.get("x")); @@ -177,10 +177,10 @@ public static BQLocation deserialize(@NotNull Map<String, Object> args) { double z = NumberConversions.toDouble(args.get("z")); float yaw = NumberConversions.toFloat(args.get("yaw")); float pitch = NumberConversions.toFloat(args.get("pitch")); - + World world = null; String worldPattern = null; - + if (args.containsKey("world")) { String worldName = (String) args.get("world"); world = Bukkit.getWorld(worldName); @@ -188,9 +188,9 @@ public static BQLocation deserialize(@NotNull Map<String, Object> args) { }else if (args.containsKey("pattern")) { worldPattern = (String) args.get("pattern"); } - + if (worldPattern != null) return new BQLocation(worldPattern, x, y, z, yaw, pitch); return new BQLocation(world, x, y, z, yaw, pitch); } - + } diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 53701a95..3fbbe398 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -1,915 +1,877 @@ -advancement: - finished: Finished - notStarted: Not started -description: - requirement: - class: Class {class_name} - combatLevel: Combat level {short_level} - faction: Faction {faction_name} - jobLevel: Level {short_level} for {job_name} - level: Level {short_level} - quest: Finish quest §e{quest_name} - skillLevel: Level {short_level} for {skill_name} - title: '§8§lRequirements:' - reward: - title: '§8§lRewards:' -indication: - cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? - closeInventory: §7Are you sure you want to close the GUI? - removePool: §7Are you sure you want to remove the pool {quest}? - removeQuest: §7Are you sure you want to remove the quest {quest}? - startQuest: §7Do you want to start the quest {quest_name}? -inv: - addObject: §aAdd an object - block: - blockData: §dBlockdata (advanced) - blockName: §bCustom block name - blockTag: §dTag (advanced) - blockTagLore: Choose a tag which describes a list of possible blocks. Tags can - be customized using datapacks. You can find list of tags on the Minecraft wiki. - material: '§eMaterial: {block_type}' - materialNotItemLore: The block chosen cannot be displayed as an item. It is still - correctly stored as {block_material}. - name: Choose block - blockAction: - location: §eSelect a precise location - material: §eSelect a block material - name: Select block action - blocksList: - addBlock: §aClick to add a block. - name: Select blocks - buckets: - name: Bucket type - cancel: §c§lCancel - cancelActions: - name: Cancel actions - checkpointActions: - name: Checkpoint actions - chooseAccount: - name: What account? - chooseQuest: - menu: §aQuests Menu - menuLore: Gets you to your Quests Menu. - name: Which quest? - classesList.name: Classes list - classesRequired.name: Classes required - command: - console: Console - delay: §bDelay - name: Command - parse: Parse placeholders - value: §eCommand - commandsList: - console: '§eConsole: {command_console}' - name: Command list - value: '§eCommand: {command_label}' - confirm: - name: Are you sure? - 'no': §cCancel - 'yes': §aConfirm - create: - NPCSelect: §eChoose or create NPC - NPCText: §eEdit dialog - breedAnimals: §aBreed animals - bringBack: §aBring back items - bucket: §aFill buckets - cancelMessage: Cancel sending - cantFinish: §7You must create at least one stage before finishing quest creation! - changeEntityType: §eChange entity type - changeTicksRequired: §eChange played ticks required - craft: §aCraft item - currentRadius: '§eCurrent distance: §6{radius}' - dealDamage: §cDeal damage to mobs - death: §cDie - eatDrink: §aEat or drink food or potions - editBlocksMine: §eEdit blocks to break - editBlocksPlace: §eEdit blocks to place - editBucketAmount: §eEdit amount of buckets to fill - editBucketType: §eEdit type of bucket to fill - editFishes: §eEdit fishes to catch - editItem: §eEdit item to craft - editItemsToEnchant: §eEdit items to enchant - editItemsToMelt: §eEdit items to melt - editLocation: §eEdit location - editMessageType: §eEdit message to write - editMobsKill: §eEdit mobs to kill - editRadius: §eEdit distance from location - enchant: §dEnchant items - findNPC: §aFind NPC - findRegion: §aFind region - fish: §aCatch fishes - hideClues: Hide particles and holograms - ignoreCase: Ignore the case of the message - interact: §aInteract with a type of block - interactLocation: §aInteract with block at location - killMobs: §aKill mobs - leftClick: Click must be left-click - location: §aGo to location - melt: §6Melt items - mineBlocks: §aBreak blocks - mobsKillFromAFar: Needs to be killed with projectile - placeBlocks: §aPlace blocks - playTime: §ePlay time - preventBlockPlace: Prevent players to break their own blocks - replacePlaceholders: Replace {PLAYER} and placeholders from PAPI - selectBlockLocation: §eSelect block location - selectBlockMaterial: §eSelect block material - selectItems: §eEdit required items - selectItemsComparisons: §eSelect items comparisons (ADVANCED) - selectItemsMessage: §eEdit asking message - selectRegion: §7Choose region - stage: - dealDamage: - damage: §eDamage to deal - targetMobs: §cMobs to damage - death: - anyCause: Any death cause - causes: §aSet death causes §d(ADVANCED) - setCauses: '{causes_amount} death cause(s)' - eatDrink: - items: §eEdit items to eat or drink - location: - worldPattern: §aSet world name pattern §d(ADVANCED) - worldPatternLore: If you want the stage to be completed for any world matching - a specific pattern, enter a regex (regular expression) here. - stageCreate: §aCreate new step - stageDown: Move down - stageRemove: §cDelete this step - stageStartMsg: §eEdit starting message - stageType: '§7Stage type: §e{stage_type}' - stageUp: Move up - talkChat: §aWrite in chat - tameAnimals: §aTame animals - toggleRegionExit: On exit - damageCause: - name: Damage cause - damageCausesList: - name: Damage causes list - details: - actions: '{amount} action(s)' - auto: Start automatically on first join - autoLore: If enabled, the quest will be started automatically when the player - joins the server for the first time. - bypassLimit: Don't count quest limit - bypassLimitLore: If enabled, the quest will be startable even if the player has - reached its maximum amount of started quests. - cancelRewards: §cCancel actions - cancelRewardsLore: Actions performed when players cancel this quest. - cancellable: Cancellable by player - cancellableLore: Allows the player to cancel the quest through its Quests Menu. - createQuestLore: You must define a quest name. - createQuestName: §lCreate quest - customConfirmMessage: §eEdit quest confirmation message - customConfirmMessageLore: Message displayed in the Confirmation GUI when a player - is about to start the quest. - customDescription: §eEdit quest description - customDescriptionLore: Description shown below the name of the quest in GUIs. - customMaterial: §eEdit quest item material - customMaterialLore: Item representative of this quest in the Quests Menu. - defaultValue: §8(default value) - editQuestName: §lEdit quest - editRequirements: §eEdit requirements - editRequirementsLore: Every requirements must apply to the player before it can - start the quest. - endMessage: §eEdit end message - endMessageLore: Message which will be sent to the player at the end of the quest. - endSound: §eEdit end sound - endSoundLore: Sound which will be played at the end of the quest. - failOnDeath: Fail on death - failOnDeathLore: Will the quest be cancelled when the player dies? - firework: §dEnding Firework - fireworkLore: Firework launched when the player finishes the quest - fireworkLoreDrop: Drop your custom firework here - hideNoRequirementsItem: Hide when requirements not met - hideNoRequirementsItemLore: If enabled, the quest will not be displayed in the - Quests Menu when the requirements are not met. - hologramLaunch: §eEdit "launch" hologram item - hologramLaunchLore: Hologram displayed above Starter NPC's head when the player - can start the quest. - hologramLaunchNo: §eEdit "launch unavailable" hologram item - hologramLaunchNoLore: Hologram displayed above Starter NPC's head when the player - can NOT start the quest. - hologramText: §eHologram text - hologramTextLore: Text displayed on the hologram above the Starter NPC's head. - keepDatas: Preserve players datas - keepDatasLore: 'Force the plugin to preserve players datas, even though stages - have been edited. - - §c§lWARNING §c- enabling this option may break your players datas.' - loreReset: §e§lAll players' advancement will be reset - multipleTime: - itemLore: Can the quest be done several times? - itemName: Toggle repeatable - name: Last quest details - optionValue: '§8Value: §7{value}' - questName: §a§lEdit quest name - questNameLore: A name must be set to complete quest creation. - questPool: §eQuest Pool - questPoolLore: Attach this quest to a quest pool - removeItemsReward: §eRemove items from inventory - requiredParameter: §7Required parameter - requirements: '{amount} requirement(s)' - rewards: '{amount} reward(s)' - rewardsLore: Actions performed when the quest ends. - scoreboardItem: Enable scoreboard - scoreboardItemLore: If disabled, the quest will not be tracked through the scoreboard. - selectStarterNPC: §e§lSelect NPC starter - selectStarterNPCLore: Clicking on the selected NPC will start the quest. - selectStarterNPCPool: §c⚠ A quest pool is selected - setCheckpointReward: §eEdit checkpoint rewards - setItemsRewards: §eEdit reward items - setMoneyReward: §eEdit money reward - setPermReward: §eEdit permissions - setRewardStopQuest: §cStop the quest - setRewardsRandom: §dRandom rewards - setRewardsWithRequirements: §eRewards with requirements - setTitleReward: §eEdit title reward - setWaitReward: §eEdit "wait" reward - setXPRewards: §eEdit reward experience - startDialog: §eEdit start dialog - startDialogLore: Dialog which will be played before the quests start when players - click on the Starter NPC. - startMessage: §eEdit start message - startMessageLore: Message which will be sent to the player at the beginning of - the quest. - startRewards: §6Start rewards - startRewardsLore: Actions performed when the quest starts. - startableFromGUI: Startable from GUI - startableFromGUILore: Allows the player to start the quest from the Quests Menu. - timer: §bRestart timer - timerLore: Time before the player can start the quest again. - visibility: §bQuest visibility - visibilityLore: Choose in which tabs of the menu will the quest be shown, and - if the quest is visible on dynamic maps. - editTitle: - fadeIn: §aFade-in duration - fadeOut: §aFade-out duration - name: Edit Title - stay: §bStay duration - subtitle: §eSubtitle - title: §6Title - entityType: - name: Choose entity type - equipmentSlots: - name: Equipment slots - factionsList.name: Factions list - factionsRequired.name: Factions required - itemComparisons: - bukkit: Bukkit native comparison - bukkitLore: Uses Bukkit default item comparison system.\nCompares material, durability, - nbt tags... - customBukkit: Bukkit native comparison - NO NBT - customBukkitLore: Uses Bukkit default item comparison system, but wipes out NBT - tags.\nCompares material, durability... - enchants: Items enchants - enchantsLore: Compares items enchants - itemLore: Item lore - itemLoreLore: Compares items lores - itemName: Item name - itemNameLore: Compares items names - itemsAdder: ItemsAdder - itemsAdderLore: Compares ItemsAdder IDs - material: Item material - materialLore: Compares item material (i. e. stone, iron sword...) - mmoItems: MMOItems item - mmoItemsLore: Compares MMOItems types and IDs - name: Item Comparisons - repairCost: Repair cost - repairCostLore: Compares repair cost for armors and swords - itemCreator: - isQuestItem: '§bQuest item:' - itemFlags: Toggle item flags - itemLore: §bItem lore - itemName: §bItem name - itemType: §bItem type - name: Item creator - itemSelect: - name: Choose item - itemsSelect: - name: Edit items - none: '§aMove an item to here or - - click to open the item editor.' - listAllQuests: - name: Quests - listBook: - noQuests: No quests have previously been created. - questMultiple: Several times - questName: Name - questRewards: Rewards - questStages: Stages - questStarter: Starter - requirements: Requirements - listPlayerQuests: - name: '{player_name}''s quests' - listQuests: - canRedo: §e§oYou can restart this quest! - finished: Finished quests - format: - normal: §6§l§o{quest_name} - withId: §6§l§o{quest_name}§r §e#{quest_id} - inProgress: Quests in progress - loreCancelClick: §cCancel the quest - loreDialogsHistoryClick: §7View the dialogs - loreStart: §a§oClick to start the quest. - loreStartUnavailable: §c§oYou do not meet requirements to start the quest. - notStarted: Not started quests - timeToWaitRedo: §7§oYou can restart this quest in {time_left}... - timesFinished: §eCompleted §6{times_finished} x§e. - mobSelect: - advancedSpawners: §6Select an AdvancedSpawners mob - boss: §6Select a Boss - bukkitEntityType: §eSelect entity type - epicBoss: §6Select Epic Boss - mythicMob: §6Select Mythic Mob - name: Select mob type - mobs: - editAmount: Edit amount - editMobName: Edit mob name - name: Select mobs - none: §aClick to add a mob. - setLevel: Set minimum level - npcCreate: - move: - itemLore: §aChange the NPC location. - itemName: §eMove - moveItem: §a§lValidate place - name: Create NPC - setName: §eEdit NPC name - setSkin: §eEdit NPC skin - setType: §eEdit NPC type - npcSelect: - createStageNPC: §eCreate NPC - name: Select or create? - selectStageNPC: §eSelect existing NPC - particleEffect: - color: §bParticle color - name: Create particle effect - shape: §dParticle shape - type: §eParticle type - particleList: - colored: Colored particle - name: Particles list - permission: - name: Choose permission - perm: §aPermission - remove: Remove permission - removeLore: §7Permission will be taken off\n§7instead of given. - world: §aWorld - worldGlobal: §b§lGlobal - permissionList: - name: Permissions list - removed: '§eTaken off: §6{permission_removed}' - world: '§eWorld: §6{permission_world}' - poolCreation: - avoidDuplicates: Avoid duplicates - avoidDuplicatesLore: §8> §7Try to avoid doing\n the same quest over and over - hologramText: §ePool custom hologram - maxQuests: §aMax quests - name: Quest pool creation - questsPerLaunch: §aQuests started per launch - redoAllowed: Is redo allowed - requirements: §bRequirements to start a quest - time: §bSet time between quests - poolsList.name: Quest pools - poolsManage: - choose: §e> §6§oChoose this pool §e< - create: §aCreate a quest pool - edit: §e> §6§oEdit the pool... §e< - itemName: §aPool {pool} - name: Quest Pools - poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' - poolHologram: '§8Hologram text: §7{pool_hologram}' - poolMaxQuests: '§8Max quests: §7{pool_max_quests}' - poolNPC: '§8NPC: §7{pool_npc_id}' - poolQuestsList: '§7{pool_quests_amount} §8quest(s): §7{pool_quests}' - poolQuestsPerLaunch: '§8Quests given per launch: §7{pool_quests_per_launch}' - poolRedo: '§8Can redo completed quests: §7{pool_redo}' - poolTime: '§8Time between quests: §7{pool_time}' - questObjects: - description: '§8Description: §7{description}' - setCustomDescription: Set custom description - requirements: - name: Requirements - reason: '§8Custom reason: §7{reason}' - setReason: Set custom reason - rewards: - commands: 'Commands: {amount}' - name: Rewards - random: - minMax: Edit min and max - rewards: Edit rewards - rewardsWithRequirements: - name: Rewards with requirements - search: §e§lSearch - stageEnding: - command: §eEdit executed command - locationTeleport: §eEdit teleport location - stages: - branchesPage: §dBranch stages - descriptionTextItem: §eEdit description - endingItem: §eEdit end rewards - laterPage: §ePrevious page - name: Create stages - newBranch: §eGo to new branch - nextPage: §eNext page - previousBranch: §eBack to previous branch - regularPage: §aRegular stages - validationRequirements: §eValidation requirements - validationRequirementsLore: All the requirements must match the player that tries - to complete the stage. If not, the stage can not be completed. - validate: §b§lValidate - visibility: - finished: '"Finished" menu tab' - inProgress: '"In progress" menu tab' - maps: Maps (such as dynmap or BlueMap) - name: Quest visibility - notStarted: '"Not started" menu tab' -misc: - amount: '§eAmount: {amount}' - amounts: - comparisons: '{comparisons_amount} comparison(s)' - dialogLines: '{lines_amount} line(s)' - items: '{items_amount} item(s)' - mobs: '{mobs_amount} mob(s)' - permissions: '{permissions_amount} permission(s)' - xp: '{xp_amount} experience point(s)' - and: and - bucket: - lava: Lava bucket - milk: Milk bucket - snow: Snow bucket - water: Water bucket - click: - left: Left click - middle: Middle click - right: Right click - shift-left: Shift-left click - shift-right: Shift-right click - comparison: - different: different to {number} - equals: equal to {number} - greater: strictly greater than {number} - greaterOrEquals: greater than {number} - less: strictly less than {number} - lessOrEquals: less than {number} - disabled: Disabled - enabled: Enabled - entityType: '§eEntity type: {entity_type}' - entityTypeAny: §eAny entity - format: - editorPrefix: §a - errorPrefix: §4✖ §c - npcText: §6[{message_id}/{message_count}] §e§l{npc_name_message}:§r§e {text} - offText: §r§e{message} - prefix: §6<§e§lQuests§r§6> §r - requirementNotMetPrefix: §c - selfText: §6[{message_id}/{message_count}] §e§l{player_name}:§r§e {text} - successPrefix: §2✔ §a - hologramText: §8§lQuest NPC - location: 'Location: {x} {y} {z} - - World: {world}' - 'no': 'No' - notSet: §cnot set - or: or - poolHologramText: §eNew quest available! - questItemLore: §e§oQuest Item - removeRaw: Remove - requirement: - class: §bClass(es) required - combatLevel: §bCombat level required - equipment: §eEquipment required - experienceLevel: §bExperience levels required - faction: §bFaction(s) required - jobLevel: §bJob level required - logicalOr: §dLogical OR (requirements) - mcMMOSkillLevel: §dSkill level required - money: §dMoney required - permissions: §3Permission(s) required - placeholder: §bPlaceholder value required - quest: §aQuest required - region: §dRegion required - scoreboard: §dScore required - skillAPILevel: §bSkillAPI level required - reset: Reset - reward: - skillApiXp: SkillAPI XP reward - stageType: - Bucket: Fill bucket - Craft: Craft item - Enchant: Enchant items - Fish: Catch fishes - Melt: Melt items - breedAnimals: Breed animals - chat: Write in chat - dealDamage: Deal damage - die: Die - eatDrink: Eat or drink - interact: Interact with block - interactLocation: Interact with block at location - items: Bring back items - location: Find location - mine: Break blocks - mobs: Kill mobs - npc: Find NPC - placeBlocks: Place blocks - playTime: Play time - region: Find region - tameAnimals: Tame animals - ticks: '{ticks} ticks' - time: - days: '{days_amount} days' - hours: '{hours_amount} hours' - lessThanAMinute: a few seconds - minutes: '{minutes_amount} minutes' - weeks: '{weeks_amount} weeks' - unknown: unknown - 'yes': 'Yes' -msg: - bringBackObjects: Bring me back {items}. - command: - adminModeEntered: §aYou have entered the Admin Mode. - adminModeLeft: §aYou have left the Admin Mode. - backupCreated: §6You have successfully created backups of all quests and player - informations. - backupPlayersFailed: §cCreating a backup for all the player informations has failed. - backupQuestsFailed: §cCreating a backup for all the quests has failed. - cancelQuest: §6You have cancelled the quest {quest}. - cancelQuestUnavailable: §cThe quest {quest} can't be cancelled. - checkpoint: - noCheckpoint: §cNo checkpoint found for the quest {quest}. - questNotStarted: §cYou are not doing this quest. - downloadTranslations: - downloaded: §aLanguage {lang} has been downloaded! §7You must now edit the file - "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 - with {lang}, then restart the server. - exists: §cThe file {file_name} already exists. Append "-overwrite" to your command - to overwrite it. (/quests downloadTranslations <lang> -overwrite) - notFound: §cLanguage {lang} not found for version {version}. - syntax: '§cYou must specify a language to download. Example: "/quests downloadTranslations - en_US".' - help: - adminMode: '§6/{label} adminMode: §eToggle the Admin Mode. (Useful for displaying - little log messages.)' - create: '§6/{label} create: §eCreate a quest.' - downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownloads - a vanilla translation file' - edit: '§6/{label} edit: §eEdit a quest.' - finishAll: '§6/{label} finishAll <player>: §eFinish all quests of a player.' - header: §6§lBeautyQuests — Help - list: '§6/{label} list: §eSee the quest list. (Only for supported versions.)' - reload: '§6/{label} reload: §eSave and reload all configurations and files. - (§cdeprecated§e)' - remove: '§6/{label} remove <id>: §eDelete a quest with a specified id or click - on the NPC when not defined.' - resetPlayer: '§6/{label} resetPlayer <player>: §eRemove all informations about - a player.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete informations - of a quest for a player.' - save: '§6/{label} save: §eMake a manual plugin save.' - seePlayer: '§6/{label} seePlayer <player>: §eView informations about a player.' - setFirework: '§6/{label} setFirework: §eEdit the default ending firework.' - setItem: '§6/{label} setItem <talk|launch>: §eSave the hologram item.' - setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eSkip - the current stage/start the branch/set a stage for a branch.' - start: '§6/{label} start <player> [id]: §eForce the starting of a quest.' - startDialog: '§6/{label} startDialog <player> <quest id>: §eStarts the pending - dialog for a NPC stage or the starting dialog for a quest.' - version: '§6/{label} version: §eSee the current plugin version.' - invalidCommand: - simple: §cThis command doesn't exist, write §ehelp§c. - itemChanged: §aThe item has been edited. The changes will affect after a restart. - itemRemoved: §aThe hologram item has been removed. - leaveAll: '§aYou have forced the end of {success} quest(s). Errors: {errors}' - removed: §aThe quest {quest_name} has successfully been removed. - resetPlayer: - player: §6All informations of your {quest_amount} quest(s) has/have been deleted - by {deleter_name}. - remover: §6{quest_amount} quest information(s) (and {quest_pool} pools) of {player} - has/have been deleted. - resetPlayerPool: - full: §aYou have reset the {pool} pool datas of {player}. - timer: §aYou have reset the {pool} pool timer of {player}. - resetPlayerQuest: - player: §6All informations about the quest {quest} have been deleted by {deleter_name}. - remover: §6{player} informations of quest {quest} has/have been deleted. - resetQuest: §6Removed datas of the quest for {player_amount} players. - scoreboard: - hidden: §6The scoreboard of the player {player_name} has been hidden. - lineInexistant: §cThe line {line_id} doesn't exist. - lineRemoved: §6You have successfully removed the line {line_id}. - lineReset: §6You have successfully reset the line {line_id}. - lineSet: §6You have successfully edited the line {line_id}. - own: - hidden: §6Your scoreboard is now hidden. - shown: §6Your scoreboard is shown again. - resetAll: §6You have successfully reset the scoreboard of the player {player_name}. - shown: §6The scoreboard of the player {player_name} has been shown. - setStage: - branchDoesntExist: §cThe branch with the id {branch_id} doesn't exist. - doesntExist: §cThe stage with the id {stage_id} doesn't exist. - next: §aThe stage has been skipped. - nextUnavailable: §cThe "skip" option is not available when the player is at - the end of a branch. - set: §aStage {stage_id} launched. - startDialog: - alreadyIn: §cThe player is already playing a dialog. - impossible: §cImpossible to start the dialog now. - noDialog: §cThe player has no pending dialog. - success: §aStarted dialog for player {player} in quest {quest}! - startPlayerPool: - error: Failed to start the pool {pool} for {player}. - success: 'Started pool {pool} to {player}. Result: {result}' - startQuest: §6You have forced starting of quest {quest} for {player}. - startQuestNoRequirements: §cThe player does not meet the requirements for the - quest {quest}... Append "-overrideRequirements" at the end of your command to - bypass the requirements check. - dialogs: - skipped: §8§o Dialog skipped. - tooFar: §7§oYou are too far away from {npc_name}... - editor: - advancedSpawnersMob: 'Write the name of the custom spawner mob to kill:' - already: §cYou are already in the editor. - availableElements: 'Available elements: §e{available_elements}' - blockAmount: '§aWrite the amount of blocks:' - blockData: '§aWrite the blockdata (available blockdatas: §7{available_datas}§a):' - blockName: '§aWrite the name of the block:' - blockTag: '§aWrite the block tag (available tags: §7{available_tags}§a):' - chat: §6You are currently in the Editor Mode. Write "/quests exitEditor" to force - leaving the editor. (Highly not recommended, consider using commands such as - "close" or "cancel" to come back to the previous inventory.) - color: Enter a color in the hexadecimal format (#XXXXX) or RGB format (RED GRE - BLU). - colorNamed: Enter the name of a color. - comparisonTypeDefault: '§aChoose the comparison type you want among {available}. - Default comparison is: §e§l{default}§r§a. Type §onull§r§a to use it.' - dialog: - cleared: §aRemoved §2§l{amount}§a message(s). - edited: §aMessage "§7{msg}§a" edited. - help: - addSound: '§6addSound <id> <sound>: §eAdd a sound to a message.' - clear: '§6clear: §eRemove all messages.' - close: '§6close: §eValidate all messages.' - edit: '§6edit <id> <message>: §eEdit a message.' - header: §6§lBeautyQuests — Dialog editor help - list: '§6list: §eView all messages.' - nothing: '§6noSender <message>: §eAdd a message without a sender.' - nothingInsert: '§6nothingInsert <id> <message>: §eInsert a message without - any prefix.' - npc: '§6npc <message>: §eAdd a message said by the NPC.' - npcInsert: '§6npcInsert <id> <message>: §eInsert a message said by the NPC.' - npcName: '§6npcName [custom NPC name]: §eSet (or reset to default) custom - name of the NPC in the dialog' - player: '§6player <message>: §eAdd a message said by the player.' - playerInsert: '§6playerInsert <id> <message>: §eInsert a message said by player.' - remove: '§6remove <id>: §eRemove a message.' - setTime: '§6setTime <id> <time>: §eSet the time (in ticks) before the next - msg plays automatically.' - skippable: '§6skippable [true|false]: §eSet if the dialog can be skipped or - not' - messageRemoved: §aMessage "§7{msg}§a" removed. - noSender: §aMessage "§7{msg}§a" added without a sender. - npc: §aMessage "§7{msg}§a" added for the NPC. - npcName: - set: §aCustom NPC name set to §7{new_name}§a (was §7{old_name}§a) - unset: §aCustom NPC name reset to default (was §7{old_name}§a) - player: §aMessage "§7{msg}§a" added for the player. - skippable: - set: §aThe dialog skippable status is now set to §7{new_state}§a (was §7{old_state}§a) - unset: §aThe dialog skippable status is reset to default (was §7{old_state}§a) - soundAdded: §aSound "§7{sound}§a" added for the message "§7{msg}§a". - syntaxMessage: '§cCorrect syntax: {command} <message>' - syntaxRemove: '§cCorrect sytax: remove <id>' - timeRemoved: §aTime has been removed for message {msg}. - timeSet: '§aTime has been edited for message {msg}: now {time} ticks.' - enter: - list: §c⚠ §7You have entered a "list" editor. Use "add" to add lines. Refer - to "help" (without slash) for help. §e§lType "close" to exit editor. - subtitle: §6Write "/quests exitEditor" to force quit the editor. - title: §6~ Editor Mode ~ - firework: - edited: Edited the quest firework! - invalid: This item is not a valid firework. - invalidHand: You must hold a firework in your main hand. - removed: Removed the quest firework! - goToLocation: §aGo to the wanted location for the stage. - invalidColor: The color you entered is invalid. It must be either hexadecimal - or RGB. - invalidPattern: §cInvalid regex pattern §4{input}§c. - itemCreator: - invalidBlockType: §cInvalid block type. - invalidItemType: §cInvalid item type. (The item can't be a block.) - itemAmount: '§aWrite the amount of item(s):' - itemLore: '§aModify the item lore: (Write "help" for help.)' - itemName: '§aWrite the item name:' - itemType: '§aWrite the name of the wanted item type:' - unknownBlockType: §cUnknown block type. - unknownItemType: §cUnknown item type. - mythicmobs: - disabled: §cMythicMob is disabled. - isntMythicMob: §cThis Mythic Mob doesn't exist. - list: '§aA list of all Mythic Mobs:' - noSuchElement: '§cThere is no such element. Allowed elements are: §e{available_elements}' - npc: - choseStarter: §aChoose the NPC which starts the quest. - enter: §aClick on a NPC, or write "cancel". - notStarter: §cThis NPC isn't a quest starter. - pool: - hologramText: Write the custom hologram text for this pool (or "null" if you - want the default one). - maxQuests: Write the maximum amount of quests launcheable from this pool. - questsPerLaunch: Write the amount of quests given when players click on the - NPC. - timeMsg: 'Write the time before players can take a new quest. (default unit: - days)' - scoreboardObjectiveNotFound: §cUnknown scoreboard objective. - selectWantedBlock: §aClick with the stick on the wanted block for the stage. - stage: - location: - typeWorldPattern: '§aWrite a regex for world names:' - text: - argNotSupported: §cThe argument {arg} not supported. - chooseJobRequired: '§aWrite name of the wanted job:' - chooseLvlRequired: '§aWrite the required amount of levels:' - chooseMoneyRequired: '§aWrite the amount of required money:' - chooseObjectiveRequired: §aWrite the objective name. - chooseObjectiveTargetScore: §aWrite the target score for the objective. - choosePermissionMessage: §aYou can choose a rejection message if the player - doesn't have the required permission. (To skip this step, write "null".) - choosePermissionRequired: '§aWrite the required permission to start the quest:' - choosePlaceholderRequired: - identifier: '§aWrite the name of the required placeholder without the percent - characters:' - value: '§aWrite the required value for the placeholder §e%§e{placeholder}§e%§a:' - chooseRegionRequired: §aWrite the name of the required region (you must be in - the same world). - chooseRequirementCustomDescription: Write the custom description for this requirement. - It will appear in the description of the quest in the menu. - chooseRequirementCustomReason: Write the custom reason for this requirement. - If the player does not meet the requirement but tries to start the quest anyway, - this message will appear in the chat. - chooseRewardCustomDescription: Write the custom description for this reward. - It will appear in the description of the quest in the menu. - chooseSkillRequired: '§aWrite the name of the required skill:' - reward: - money: '§aWrite the amount of the received money:' - permissionName: §aWrite the permission name. - permissionWorld: §aWrite the world in which the permission will be edited, - or "null" if you want to be global. - random: - max: §aWrite the maximum amount of rewards given to the player (inclusive). - min: §aWrite the minimum amount of rewards given to the player (inclusive). - wait: '§aWrite the amount of game ticks to wait: (1 second = 20 game ticks)' - textList: - added: §aText "§7{msg}§a" added. - help: - add: '§6add <message>: §eAdd a text.' - close: '§6close: §eValidate the added texts.' - header: §6§lBeautyQuests — List editor help - list: '§6list: §eView all added texts.' - remove: '§6remove <id>: §eRemove a text.' - removed: §aText "§7{msg}§a" removed. - syntax: '§cCorrect syntax: {command}' - title: - fadeIn: Write the "fade-in" duration, in ticks (20 ticks = 1 second). - fadeOut: Write the "fade-out" duration, in ticks (20 ticks = 1 second). - stay: Write the "stay" duration, in ticks (20 ticks = 1 second). - subtitle: Write the subtitle text (or "null" if you want none). - title: Write the title text (or "null" if you want none). - typeBucketAmount: '§aWrite the amount of buckets to fill:' - typeDamageAmount: 'Write the amount of damage player have to deal:' - typeGameTicks: '§aWrite the required game ticks:' - typeLocationRadius: '§aWrite the required distance from the location:' - errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: - {error}' - experience: - edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} - points. - indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} - and {max}. - invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the - block {block_material}. - invalidBlockTag: §cUnavailable block tag {block_tag}. - inventoryFull: §cYour inventory is full, the item has been dropped on the floor. - moveToTeleportPoint: §aGo to the wanted teleport location. - npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. - number: - invalid: §c{input} isn't a valid number. - negative: §cYou must enter a positive number! - notInBounds: §cYour number must be between {min} and {max}. - zero: §cYou must enter a number other than 0! - pools: - allCompleted: §7You have completed all the quests! - maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same - time... - noAvailable: §7There is no more quest available... - noTime: §cYou must wait {time_left} before doing another quest. - quest: - alreadyStarted: §cYou have already started the quest! - cancelling: §cProcess of quest creation cancelled. - createCancelled: §cThe creation or edition has been cancelled by another plugin! - created: §aCongratulations! You have created the quest §e{quest}§a which includes - {quest_branches} branch(es)! - editCancelling: §cProcess of quest edition cancelled. - edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes - {quest_branches} branch(es)! - finished: - base: §aCongratulations! You have finished the quest §e{quest_name}§a! - obtain: §aYou obtain {rewards}! - invalidID: §cThe quest with the id {quest_id} doesn't exist. - invalidPoolID: §cThe pool {pool_id} does not exist. - notStarted: §cYou are not currently doing this quest. - started: §aYou have started the quest §r§e{quest_name}§o§6! - questItem: - craft: §cYou can't use a quest item to craft! - drop: §cYou can't drop a quest item! - eat: §cYou cannot eat a quest item! - quests: - checkpoint: §7Quest checkpoint reached! - failed: §cYou have failed the quest {quest_name}... - maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same - time... - updated: §7Quest §e{quest_name}§7 updated. - regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) - requirements: - combatLevel: §cYour combat level must be {long_level}! - job: §cYour level for the job §e{job_name}§c must be {long_level}! - level: §cYour level must be {long_level}! - money: §cYou must have {money}! - quest: §cYou must have finished the quest §e{quest_name}§c! - skill: §cYour level for the skill §e{skill_name}§c must be {long_level}! - waitTime: §cYou must wait {time_left} before you can restart this quest! - restartServer: §7Restart your server to see the modifications. - selectNPCToKill: §aSelect the NPC to kill. - stageMobs: - listMobs: §aYou must kill {mobs}. - typeCancel: §aWrite "cancel" to come back to the last text. - versionRequired: 'Version required: §l{version}' - writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if - you want a command.)' - writeCommand: '§aWrite the wanted command: (The command is without the "/" and the - placeholder "{PLAYER}" is supported. It will be replaced with the name of the - executor.)' - writeCommandDelay: §aWrite the desired command delay, in ticks. - writeConfirmMessage: '§aWrite the confirmation message shown when a player is about - to start the quest: (Write "null" if you want the default message.)' - writeDescriptionText: '§aWrite the text which describes the goal of the stage:' - writeEndMsg: §aWrite the message that will be sent at the end of the quest, "null" - if you want the default one or "none" if you want none. You can use "{rewards}" - which will be replaced with the rewards obtained. - writeEndSound: '§aWrite the sound name that will be played to the player at the - end of the quest, "null" if you want the default one or "none" if you want none:' - writeHologramText: '§aWrite text of the hologram: (Write "none" if you don''t want - a hologram and "null" if you want the default text.)' - writeMessage: §aWrite the message that will be sent to the player - writeMobAmount: '§aWrite the amount of mobs to kill:' - writeMobName: '§aWrite the custom name of the mob to kill:' - writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write - "help" to receive help.)' - writeNpcName: '§aWrite the name of the NPC:' - writeNpcSkinName: '§aWrite the name of the skin of the NPC:' - writeQuestDescription: §aWrite the description of the quest, shown in the player's - quest GUI. - writeQuestMaterial: §aWrite the material of the quest item. - writeQuestName: '§aWrite the name of your quest:' - writeQuestTimer: '§aWrite the required time (in minutes) before you can restart - the quest: (Write "null" if you want the default timer.)' - writeRegionName: '§aWrite the name of the region required for the step:' - writeStageText: '§aWrite the text that will be sent to the player at the beginning - of the step:' - writeStartMessage: '§aWrite the message that will be sent at the beginning of the - quest, "null" if you want the default one or "none" if you want none:' - writeXPGain: '§aWrite the amount of experience points the player will obtain: (Last - value: {xp_amount})' -scoreboard: - asyncEnd: §ex - name: §6§lQuests - noLaunched: §cNo quests in progress. - noLaunchedDescription: §c§oLoading - noLaunchedName: §c§lLoading - stage: - breed: §eBreed §6{mobs} - bucket: §eFill §6{buckets} - chat: §eWrite §6{text} - craft: §eCraft §6{items} - dealDamage: - any: §cDeal {damage_remaining} damage - mobs: §cDeal {damage_remaining} damage to {target_mobs} - die: §cDie - eatDrink: §eConsume §6{items} - enchant: §eEnchant §6{items} - fish: §eFish §6{items} - interact: §eClick on the block at §6{x} {y} {z} - interactMaterial: §eClick on a §6{block}§e block - items: '§eBring items to §6{dialog_npc_name}§e: {items}' - location: §eGo to §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world} - melt: §eMelt §6{items} - mine: §eMine {blocks} - mobs: §eKill §6{mobs} - npc: §eTalk with NPC §6{dialog_npc_name} - placeBlocks: §ePlace {blocks} - playTimeFormatted: §ePlay §6{time_remaining_human} - region: §eFind region §6{region_id} - tame: §eTame §6{mobs} - textBetwteenBranch: §e or +msg: + quest: + finished: + base: §aCongratulations! You have finished the quest §e{quest_name}§a! + obtain: §aYou obtain {rewards}! + started: §aYou have started the quest §r§e{quest_name}§o§6! + created: §aCongratulations! You have created the quest §e{quest}§a which includes + {quest_branches} branch(es)! + edited: §aCongratulations! You have edited the quest §e{quest}§a which now includes + {quest_branches} branch(es)! + createCancelled: §cThe creation or edition has been cancelled by another plugin! + cancelling: §cProcess of quest creation cancelled. + editCancelling: §cProcess of quest edition cancelled. + invalidID: §cThe quest with the id {quest_id} doesn't exist. + invalidPoolID: §cThe pool {pool_id} does not exist. + alreadyStarted: §cYou have already started the quest! + notStarted: §cYou are not currently doing this quest. + quests: + maxLaunched: §cYou cannot have more than {quests_max_amount} quest(s) at the same time... + updated: §7Quest §e{quest_name}§7 updated. + checkpoint: §7Quest checkpoint reached! + failed: §cYou have failed the quest {quest_name}... + pools: + noTime: §cYou must wait {time_left} before doing another quest. + allCompleted: §7You have completed all the quests! + noAvailable: §7There is no more quest available... + maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same time... + questItem: + drop: §cYou can't drop a quest item! + craft: §cYou can't use a quest item to craft! + eat: §cYou cannot eat a quest item! + stageMobs: + listMobs: §aYou must kill {mobs}. + writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write + "help" to receive help.)' + writeRegionName: '§aWrite the name of the region required for the step:' + writeXPGain: '§aWrite the amount of experience points the player will obtain: (Last + value: {xp_amount})' + writeMobAmount: '§aWrite the amount of mobs to kill:' + writeMobName: '§aWrite the custom name of the mob to kill:' + writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if + you want a command.)' + writeMessage: '§aWrite the message that will be sent to the player' + writeStartMessage: '§aWrite the message that will be sent at the beginning of the quest, + "null" if you want the default one or "none" if you want none:' + writeEndMsg: '§aWrite the message that will be sent at the end of the quest, + "null" if you want the default one or "none" if you want none. You can use "{rewards}" which + will be replaced with the rewards obtained.' + writeEndSound: '§aWrite the sound name that will be played to the player at the end of + the quest, "null" if you want the default one or "none" if you want none:' + writeDescriptionText: '§aWrite the text which describes the goal of the stage:' + writeStageText: '§aWrite the text that will be sent to the player at the beginning + of the step:' + moveToTeleportPoint: §aGo to the wanted teleport location. + writeNpcName: '§aWrite the name of the NPC:' + writeNpcSkinName: '§aWrite the name of the skin of the NPC:' + writeQuestName: '§aWrite the name of your quest:' + writeCommand: '§aWrite the wanted command: (The command is without the "/" and the + placeholder "{PLAYER}" is supported. It will be replaced with the name of the + executor.)' + writeHologramText: '§aWrite text of the hologram: (Write "none" if you don''t want + a hologram and "null" if you want the default text.)' + writeQuestTimer: '§aWrite the required time (in minutes) before you can restart + the quest: (Write "null" if you want the default timer.)' + writeConfirmMessage: '§aWrite the confirmation message shown when a player is about + to start the quest: (Write "null" if you want the default message.)' + writeQuestDescription: '§aWrite the description of the quest, shown in the player''s quest GUI.' + writeQuestMaterial: '§aWrite the material of the quest item.' + requirements: + quest: §cYou must have finished the quest §e{quest_name}§c! + level: §cYour level must be {long_level}! + job: §cYour level for the job §e{job_name}§c must be {long_level}! + skill: §cYour level for the skill §e{skill_name}§c must be {long_level}! + combatLevel: §cYour combat level must be {long_level}! + money: §cYou must have {money}! + waitTime: §cYou must wait {time_left} before you can restart this quest! + experience: + edited: §aYou have changed the experience gain from {old_xp_amount} to {xp_amount} points. + selectNPCToKill: §aSelect the NPC to kill. + regionDoesntExists: §cThis region doesn't exist. (You have to be in the same world.) + npcDoesntExist: §cThe NPC with the id {npc_id} doesn't exist. + number: + negative: §cYou must enter a positive number! + zero: §cYou must enter a number other than 0! + invalid: §c{input} isn't a valid number. + notInBounds: §cYour number must be between {min} and {max}. + errorOccurred: '§cAn error occurred, please contact an adminstrator! §4§lError code: {error}' + indexOutOfBounds: §cThe number {index} is out of bounds! It has to be between {min} and + {max}. + invalidBlockData: §cThe blockdata {block_data} is invalid or incompatible with the block {block_material}. + invalidBlockTag: §cUnavailable block tag {block_tag}. + bringBackObjects: Bring me back {items}. + inventoryFull: §cYour inventory is full, the item has been dropped on the floor. + versionRequired: 'Version required: §l{version}' + restartServer: '§7Restart your server to see the modifications.' + dialogs: + skipped: '§8§o Dialog skipped.' + tooFar: '§7§oYou are too far away from {npc_name}...' + command: + downloadTranslations: + syntax: '§cYou must specify a language to download. Example: "/quests downloadTranslations en_US".' + notFound: '§cLanguage {lang} not found for version {version}.' + exists: '§cThe file {file_name} already exists. Append "-overwrite" to your command to overwrite it. (/quests downloadTranslations <lang> -overwrite)' + downloaded: '§aLanguage {lang} has been downloaded! §7You must now edit the + file "/plugins/BeautyQuests/config.yml" to change the value of §ominecraftTranslationsFile§7 with {lang}, then restart the server.' + checkpoint: + noCheckpoint: §cNo checkpoint found for the quest {quest}. + questNotStarted: §cYou are not doing this quest. + setStage: + branchDoesntExist: §cThe branch with the id {branch_id} doesn't exist. + doesntExist: §cThe stage with the id {stage_id} doesn't exist. + next: §aThe stage has been skipped. + nextUnavailable: §cThe "skip" option is not available when the player is at + the end of a branch. + set: §aStage {stage_id} launched. + startDialog: + impossible: §cImpossible to start the dialog now. + noDialog: §cThe player has no pending dialog. + alreadyIn: §cThe player is already playing a dialog. + success: §aStarted dialog for player {player} in quest {quest}! + invalidCommand: + simple: §cThis command doesn't exist, write §ehelp§c. + itemChanged: §aThe item has been edited. The changes will affect after a restart. + itemRemoved: §aThe hologram item has been removed. + removed: §aThe quest {quest_name} has successfully been removed. + leaveAll: '§aYou have forced the end of {success} quest(s). Errors: {errors}' + resetPlayer: + player: §6All informations of your {quest_amount} quest(s) has/have been deleted by {deleter_name}. + remover: §6{quest_amount} quest information(s) (and {quest_pool} pools) of {player} has/have been deleted. + resetPlayerQuest: + player: §6All informations about the quest {quest} have been deleted by {deleter_name}. + remover: §6{player} informations of quest {quest} has/have been deleted. + resetQuest: §6Removed datas of the quest for {player_amount} players. + startQuest: '§6You have forced starting of quest {quest} for {player}.' + startQuestNoRequirements: '§cThe player does not meet the requirements for the quest {quest}... + Append "-overrideRequirements" at the end of your command to bypass the requirements check.' + cancelQuest: §6You have cancelled the quest {quest}. + cancelQuestUnavailable: §cThe quest {quest} can't be cancelled. + backupCreated: §6You have successfully created backups of all quests and player + informations. + backupPlayersFailed: §cCreating a backup for all the player informations has failed. + backupQuestsFailed: §cCreating a backup for all the quests has failed. + adminModeEntered: §aYou have entered the Admin Mode. + adminModeLeft: §aYou have left the Admin Mode. + resetPlayerPool: + timer: §aYou have reset the {pool} pool timer of {player}. + full: §aYou have reset the {pool} pool datas of {player}. + startPlayerPool: + error: 'Failed to start the pool {pool} for {player}.' + success: 'Started pool {pool} to {player}. Result: {result}' + scoreboard: + lineSet: §6You have successfully edited the line {line_id}. + lineReset: §6You have successfully reset the line {line_id}. + lineRemoved: §6You have successfully removed the line {line_id}. + lineInexistant: §cThe line {line_id} doesn't exist. + resetAll: §6You have successfully reset the scoreboard of the player {player_name}. + hidden: §6The scoreboard of the player {player_name} has been hidden. + shown: §6The scoreboard of the player {player_name} has been shown. + own: + hidden: §6Your scoreboard is now hidden. + shown: §6Your scoreboard is shown again. + help: + header: §6§lBeautyQuests — Help + create: '§6/{label} create: §eCreate a quest.' + edit: '§6/{label} edit: §eEdit a quest.' + remove: '§6/{label} remove <id>: §eDelete a quest with a specified id or click on + the NPC when not defined.' + finishAll: '§6/{label} finishAll <player>: §eFinish all quests of a player.' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eSkip the + current stage/start the branch/set a stage for a branch.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eStarts the pending dialog + for a NPC stage or the starting dialog for a quest.' + resetPlayer: '§6/{label} resetPlayer <player>: §eRemove all informations about a + player.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete informations + of a quest for a player.' + seePlayer: '§6/{label} seePlayer <player>: §eView informations about a player.' + reload: '§6/{label} reload: §eSave and reload all configurations and files. (§cdeprecated§e)' + start: '§6/{label} start <player> [id]: §eForce the starting of a quest.' + setItem: '§6/{label} setItem <talk|launch>: §eSave the hologram item.' + setFirework: '§6/{label} setFirework: §eEdit the default ending firework.' + adminMode: '§6/{label} adminMode: §eToggle the Admin Mode. (Useful for displaying + little log messages.)' + version: '§6/{label} version: §eSee the current plugin version.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownloads a vanilla translation file' + save: '§6/{label} save: §eMake a manual plugin save.' + list: '§6/{label} list: §eSee the quest list. (Only for supported versions.)' + typeCancel: §aWrite "cancel" to come back to the last text. + editor: + blockAmount: '§aWrite the amount of blocks:' + blockName: '§aWrite the name of the block:' + blockData: '§aWrite the blockdata (available blockdatas: §7{available_datas}§a):' + blockTag: '§aWrite the block tag (available tags: §7{available_tags}§a):' + typeBucketAmount: '§aWrite the amount of buckets to fill:' + typeDamageAmount: 'Write the amount of damage player have to deal:' + goToLocation: §aGo to the wanted location for the stage. + typeLocationRadius: '§aWrite the required distance from the location:' + typeGameTicks: '§aWrite the required game ticks:' + already: §cYou are already in the editor. + stage: + location: + typeWorldPattern: '§aWrite a regex for world names:' + enter: + title: §6~ Editor Mode ~ + subtitle: §6Write "/quests exitEditor" to force quit the editor. + list: '§c⚠ §7You have entered a "list" editor. Use "add" to add lines. Refer to "help" (without slash) for help. §e§lType "close" to exit editor.' + chat: §6You are currently in the Editor Mode. Write "/quests exitEditor" to force + leaving the editor. (Highly not recommended, consider using commands such as + "close" or "cancel" to come back to the previous inventory.) + npc: + enter: §aClick on a NPC, or write "cancel". + choseStarter: §aChoose the NPC which starts the quest. + notStarter: §cThis NPC isn't a quest starter. + text: + argNotSupported: §cThe argument {arg} not supported. + chooseLvlRequired: '§aWrite the required amount of levels:' + chooseJobRequired: '§aWrite name of the wanted job:' + choosePermissionRequired: '§aWrite the required permission to start the quest:' + choosePermissionMessage: §aYou can choose a rejection message if the player + doesn't have the required permission. (To skip this step, write "null".) + choosePlaceholderRequired: + identifier: '§aWrite the name of the required placeholder without the percent + characters:' + value: '§aWrite the required value for the placeholder §e%§e{placeholder}§e%§a:' + chooseSkillRequired: '§aWrite the name of the required skill:' + chooseMoneyRequired: '§aWrite the amount of required money:' + reward: + permissionName: §aWrite the permission name. + permissionWorld: §aWrite the world in which the permission will be edited, + or "null" if you want to be global. + money: '§aWrite the amount of the received money:' + wait: '§aWrite the amount of game ticks to wait: (1 second = 20 game ticks)' + random: + min: '§aWrite the minimum amount of rewards given to the player (inclusive).' + max: '§aWrite the maximum amount of rewards given to the player (inclusive).' + chooseObjectiveRequired: §aWrite the objective name. + chooseObjectiveTargetScore: §aWrite the target score for the objective. + chooseRegionRequired: §aWrite the name of the required region (you must be in the same world). + chooseRequirementCustomReason: 'Write the custom reason for this requirement. If the player does + not meet the requirement but tries to start the quest anyway, this message will appear in the chat.' + chooseRequirementCustomDescription: 'Write the custom description for this requirement. It will appear + in the description of the quest in the menu.' + chooseRewardCustomDescription: 'Write the custom description for this reward. It will appear + in the description of the quest in the menu.' + selectWantedBlock: §aClick with the stick on the wanted block for the stage. + itemCreator: + itemType: '§aWrite the name of the wanted item type:' + itemAmount: '§aWrite the amount of item(s):' + itemName: '§aWrite the item name:' + itemLore: '§aModify the item lore: (Write "help" for help.)' + unknownItemType: §cUnknown item type. + invalidItemType: §cInvalid item type. (The item can't be a block.) + unknownBlockType: §cUnknown block type. + invalidBlockType: §cInvalid block type. + dialog: + syntaxMessage: '§cCorrect syntax: {command} <message>' + syntaxRemove: '§cCorrect sytax: remove <id>' + player: §aMessage "§7{msg}§a" added for the player. + npc: §aMessage "§7{msg}§a" added for the NPC. + noSender: §aMessage "§7{msg}§a" added without a sender. + messageRemoved: §aMessage "§7{msg}§a" removed. + edited: §aMessage "§7{msg}§a" edited. + soundAdded: §aSound "§7{sound}§a" added for the message "§7{msg}§a". + cleared: §aRemoved §2§l{amount}§a message(s). + help: + header: §6§lBeautyQuests — Dialog editor help + npc: '§6npc <message>: §eAdd a message said by the NPC.' + player: '§6player <message>: §eAdd a message said by the player.' + nothing: '§6noSender <message>: §eAdd a message without a sender.' + remove: '§6remove <id>: §eRemove a message.' + list: '§6list: §eView all messages.' + npcInsert: '§6npcInsert <id> <message>: §eInsert a message said by the NPC.' + playerInsert: '§6playerInsert <id> <message>: §eInsert a message said by player.' + nothingInsert: '§6nothingInsert <id> <message>: §eInsert a message without + any prefix.' + edit: '§6edit <id> <message>: §eEdit a message.' + addSound: '§6addSound <id> <sound>: §eAdd a sound to a message.' + clear: '§6clear: §eRemove all messages.' + close: '§6close: §eValidate all messages.' + setTime: '§6setTime <id> <time>: §eSet the time (in ticks) before the next msg plays automatically.' + npcName: '§6npcName [custom NPC name]: §eSet (or reset to default) custom name of the NPC in the dialog' + skippable: '§6skippable [true|false]: §eSet if the dialog can be skipped or not' + timeSet: '§aTime has been edited for message {msg}: now {time} ticks.' + timeRemoved: '§aTime has been removed for message {msg}.' + npcName: + set: '§aCustom NPC name set to §7{new_name}§a (was §7{old_name}§a)' + unset: '§aCustom NPC name reset to default (was §7{old_name}§a)' + skippable: + set: '§aThe dialog skippable status is now set to §7{new_state}§a (was §7{old_state}§a)' + unset: '§aThe dialog skippable status is reset to default (was §7{old_state}§a)' + mythicmobs: + list: '§aA list of all Mythic Mobs:' + isntMythicMob: §cThis Mythic Mob doesn't exist. + disabled: §cMythicMob is disabled. + advancedSpawnersMob: 'Write the name of the custom spawner mob to kill:' + textList: + syntax: '§cCorrect syntax: {command}' + added: §aText "§7{msg}§a" added. + removed: §aText "§7{msg}§a" removed. + help: + header: §6§lBeautyQuests — List editor help + add: '§6add <message>: §eAdd a text.' + remove: '§6remove <id>: §eRemove a text.' + list: '§6list: §eView all added texts.' + close: '§6close: §eValidate the added texts.' + availableElements: 'Available elements: §e{available_elements}' + noSuchElement: '§cThere is no such element. Allowed elements are: §e{available_elements}' + invalidPattern: '§cInvalid regex pattern §4{input}§c.' + comparisonTypeDefault: '§aChoose the comparison type you want among {available}. Default comparison is: §e§l{default}§r§a. Type §onull§r§a to use it.' + scoreboardObjectiveNotFound: '§cUnknown scoreboard objective.' + pool: + hologramText: 'Write the custom hologram text for this pool (or "null" if you want the default one).' + maxQuests: 'Write the maximum amount of quests launcheable from this pool.' + questsPerLaunch: 'Write the amount of quests given when players click on the NPC.' + timeMsg: 'Write the time before players can take a new quest. (default unit: days)' + title: + title: 'Write the title text (or "null" if you want none).' + subtitle: 'Write the subtitle text (or "null" if you want none).' + fadeIn: 'Write the "fade-in" duration, in ticks (20 ticks = 1 second).' + stay: 'Write the "stay" duration, in ticks (20 ticks = 1 second).' + fadeOut: 'Write the "fade-out" duration, in ticks (20 ticks = 1 second).' + colorNamed: 'Enter the name of a color.' + color: 'Enter a color in the hexadecimal format (#XXXXX) or RGB format (RED GRE BLU).' + invalidColor: 'The color you entered is invalid. It must be either hexadecimal or RGB.' + firework: + invalid: 'This item is not a valid firework.' + invalidHand: 'You must hold a firework in your main hand.' + edited: 'Edited the quest firework!' + removed: 'Removed the quest firework!' + writeCommandDelay: '§aWrite the desired command delay, in ticks.' +advancement: + finished: Finished + notStarted: Not started +inv: + validate: §b§lValidate + cancel: §c§lCancel + search: §e§lSearch + addObject: §aAdd an object + confirm: + name: Are you sure? + 'yes': §aConfirm + 'no': §cCancel + create: + stageCreate: §aCreate new step + stageRemove: §cDelete this step + stageUp: Move up + stageDown: Move down + stageType: '§7Stage type: §e{stage_type}' + cantFinish: §7You must create at least one stage before finishing quest creation! + findNPC: §aFind NPC + bringBack: §aBring back items + findRegion: §aFind region + killMobs: §aKill mobs + mineBlocks: §aBreak blocks + placeBlocks: §aPlace blocks + talkChat: §aWrite in chat + interact: §aInteract with a type of block + interactLocation: §aInteract with block at location + fish: §aCatch fishes + melt: §6Melt items + enchant: §dEnchant items + craft: §aCraft item + bucket: §aFill buckets + location: §aGo to location + playTime: §ePlay time + breedAnimals: §aBreed animals + tameAnimals: §aTame animals + death: §cDie + dealDamage: §cDeal damage to mobs + eatDrink: §aEat or drink food or potions + NPCText: §eEdit dialog + NPCSelect: §eChoose or create NPC + hideClues: Hide particles and holograms + editMobsKill: §eEdit mobs to kill + mobsKillFromAFar: Needs to be killed with projectile + editBlocksMine: §eEdit blocks to break + preventBlockPlace: Prevent players to break their own blocks + editBlocksPlace: §eEdit blocks to place + editMessageType: §eEdit message to write + cancelMessage: Cancel sending + ignoreCase: Ignore the case of the message + replacePlaceholders: Replace {PLAYER} and placeholders from PAPI + selectItems: §eEdit required items + selectItemsMessage: §eEdit asking message + selectItemsComparisons: §eSelect items comparisons (ADVANCED) + selectRegion: §7Choose region + toggleRegionExit: On exit + stageStartMsg: §eEdit starting message + selectBlockLocation: §eSelect block location + selectBlockMaterial: §eSelect block material + leftClick: Click must be left-click + editFishes: §eEdit fishes to catch + editItemsToMelt: §eEdit items to melt + editItemsToEnchant: §eEdit items to enchant + editItem: §eEdit item to craft + editBucketType: §eEdit type of bucket to fill + editBucketAmount: §eEdit amount of buckets to fill + editLocation: §eEdit location + editRadius: §eEdit distance from location + currentRadius: '§eCurrent distance: §6{radius}' + changeTicksRequired: '§eChange played ticks required' + changeEntityType: '§eChange entity type' + stage: + location: + worldPattern: '§aSet world name pattern §d(ADVANCED)' + worldPatternLore: 'If you want the stage to be completed for any world matching a specific pattern, enter a regex (regular expression) here.' + death: + causes: '§aSet death causes §d(ADVANCED)' + anyCause: Any death cause + setCauses: '{causes_amount} death cause(s)' + dealDamage: + damage: '§eDamage to deal' + targetMobs: '§cMobs to damage' + eatDrink: + items: '§eEdit items to eat or drink' + stages: + name: Create stages + nextPage: §eNext page + laterPage: §ePrevious page + endingItem: §eEdit end rewards + descriptionTextItem: §eEdit description + regularPage: §aRegular stages + branchesPage: §dBranch stages + previousBranch: §eBack to previous branch + newBranch: §eGo to new branch + validationRequirements: §eValidation requirements + validationRequirementsLore: All the requirements must match the player that tries to complete the stage. If not, the stage can not be completed. + details: + hologramLaunch: §eEdit "launch" hologram item + hologramLaunchLore: Hologram displayed above Starter NPC's head when the player can start the quest. + hologramLaunchNo: §eEdit "launch unavailable" hologram item + hologramLaunchNoLore: Hologram displayed above Starter NPC's head when the player can NOT start the quest. + customConfirmMessage: §eEdit quest confirmation message + customConfirmMessageLore: Message displayed in the Confirmation GUI when a player is about to start the quest. + customDescription: §eEdit quest description + customDescriptionLore: Description shown below the name of the quest in GUIs. + name: Last quest details + multipleTime: + itemName: Toggle repeatable + itemLore: Can the quest be done several times? + cancellable: Cancellable by player + cancellableLore: Allows the player to cancel the quest through its Quests Menu. + startableFromGUI: Startable from GUI + startableFromGUILore: Allows the player to start the quest from the Quests Menu. + scoreboardItem: Enable scoreboard + scoreboardItemLore: If disabled, the quest will not be tracked through the scoreboard. + hideNoRequirementsItem: Hide when requirements not met + hideNoRequirementsItemLore: If enabled, the quest will not be displayed in the Quests Menu when the requirements are not met. + bypassLimit: Don't count quest limit + bypassLimitLore: If enabled, the quest will be startable even if the player has reached its maximum amount of started quests. + auto: Start automatically on first join + autoLore: If enabled, the quest will be started automatically when the player joins the server for the first time. + questName: §a§lEdit quest name + questNameLore: A name must be set to complete quest creation. + setItemsRewards: §eEdit reward items + removeItemsReward: §eRemove items from inventory + setXPRewards: §eEdit reward experience + setCheckpointReward: §eEdit checkpoint rewards + setRewardStopQuest: §cStop the quest + setRewardsWithRequirements: §eRewards with requirements + setRewardsRandom: §dRandom rewards + setPermReward: §eEdit permissions + setMoneyReward: §eEdit money reward + setWaitReward: '§eEdit "wait" reward' + setTitleReward: '§eEdit title reward' + selectStarterNPC: §e§lSelect NPC starter + selectStarterNPCLore: Clicking on the selected NPC will start the quest. + selectStarterNPCPool: §c⚠ A quest pool is selected + createQuestName: §lCreate quest + createQuestLore: You must define a quest name. + editQuestName: §lEdit quest + endMessage: §eEdit end message + endMessageLore: Message which will be sent to the player at the end of the quest. + endSound: §eEdit end sound + endSoundLore: Sound which will be played at the end of the quest. + startMessage: §eEdit start message + startMessageLore: Message which will be sent to the player at the beginning of the quest. + startDialog: §eEdit start dialog + startDialogLore: Dialog which will be played before the quests start when players click on the Starter NPC. + editRequirements: §eEdit requirements + editRequirementsLore: Every requirements must apply to the player before it can start the quest. + startRewards: §6Start rewards + startRewardsLore: Actions performed when the quest starts. + cancelRewards: §cCancel actions + cancelRewardsLore: Actions performed when players cancel this quest. + hologramText: §eHologram text + hologramTextLore: Text displayed on the hologram above the Starter NPC's head. + timer: §bRestart timer + timerLore: Time before the player can start the quest again. + requirements: '{amount} requirement(s)' + rewards: '{amount} reward(s)' + actions: '{amount} action(s)' + rewardsLore: Actions performed when the quest ends. + customMaterial: '§eEdit quest item material' + customMaterialLore: Item representative of this quest in the Quests Menu. + failOnDeath: Fail on death + failOnDeathLore: Will the quest be cancelled when the player dies? + questPool: §eQuest Pool + questPoolLore: Attach this quest to a quest pool + firework: §dEnding Firework + fireworkLore: Firework launched when the player finishes the quest + fireworkLoreDrop: Drop your custom firework here + visibility: §bQuest visibility + visibilityLore: Choose in which tabs of the menu will the quest be shown, and if + the quest is visible on dynamic maps. + keepDatas: Preserve players datas + keepDatasLore: |- + Force the plugin to preserve players datas, even though stages have been edited. + §c§lWARNING §c- enabling this option may break your players datas. + loreReset: '§e§lAll players'' advancement will be reset' + optionValue: '§8Value: §7{value}' + defaultValue: '§8(default value)' + requiredParameter: '§7Required parameter' + itemsSelect: + name: Edit items + none: |- + §aMove an item to here or + click to open the item editor. + itemSelect: + name: Choose item + npcCreate: + name: Create NPC + setName: §eEdit NPC name + setSkin: §eEdit NPC skin + setType: §eEdit NPC type + move: + itemName: §eMove + itemLore: §aChange the NPC location. + moveItem: §a§lValidate place + npcSelect: + name: Select or create? + selectStageNPC: §eSelect existing NPC + createStageNPC: §eCreate NPC + entityType: + name: Choose entity type + chooseQuest: + name: Which quest? + menu: §aQuests Menu + menuLore: Gets you to your Quests Menu. + mobs: + name: Select mobs + none: §aClick to add a mob. + editAmount: Edit amount + editMobName: Edit mob name + setLevel: Set minimum level + mobSelect: + name: Select mob type + bukkitEntityType: §eSelect entity type + mythicMob: §6Select Mythic Mob + epicBoss: §6Select Epic Boss + boss: §6Select a Boss + advancedSpawners: §6Select an AdvancedSpawners mob + stageEnding: + locationTeleport: §eEdit teleport location + command: §eEdit executed command + requirements: + name: Requirements + setReason: Set custom reason + reason: '§8Custom reason: §7{reason}' + rewards: + name: Rewards + commands: 'Commands: {amount}' + random: + rewards: Edit rewards + minMax: Edit min and max + checkpointActions: + name: Checkpoint actions + cancelActions: + name: Cancel actions + rewardsWithRequirements: + name: Rewards with requirements + listAllQuests: + name: Quests + listPlayerQuests: + name: '{player_name}''s quests' + listQuests: + notStarted: Not started quests + finished: Finished quests + inProgress: Quests in progress + loreDialogsHistoryClick: §7View the dialogs + loreCancelClick: §cCancel the quest + loreStart: §a§oClick to start the quest. + loreStartUnavailable: §c§oYou do not meet requirements to start the quest. + timeToWaitRedo: §7§oYou can restart this quest in {time_left}... + canRedo: §e§oYou can restart this quest! + timesFinished: §eCompleted §6{times_finished} x§e. + format: + normal: §6§l§o{quest_name} + withId: §6§l§o{quest_name}§r §e#{quest_id} + itemCreator: + name: Item creator + itemType: §bItem type + itemFlags: Toggle item flags + itemName: §bItem name + itemLore: §bItem lore + isQuestItem: '§bQuest item:' + command: + name: Command + value: §eCommand + console: Console + parse: Parse placeholders + delay: §bDelay + chooseAccount: + name: What account? + listBook: + questName: Name + questStarter: Starter + questRewards: Rewards + questMultiple: Several times + requirements: Requirements + questStages: Stages + noQuests: No quests have previously been created. + commandsList: + name: Command list + value: '§eCommand: {command_label}' + console: '§eConsole: {command_console}' + block: + name: Choose block + material: '§eMaterial: {block_type}' + materialNotItemLore: 'The block chosen cannot be displayed as an item. It is still correctly stored as {block_material}.' + blockName: '§bCustom block name' + blockData: '§dBlockdata (advanced)' + blockTag: '§dTag (advanced)' + blockTagLore: 'Choose a tag which describes a list of possible blocks. + Tags can be customized using datapacks. + You can find list of tags on the Minecraft wiki.' + blocksList: + name: Select blocks + addBlock: §aClick to add a block. + blockAction: + name: Select block action + location: §eSelect a precise location + material: §eSelect a block material + buckets: + name: Bucket type + permission: + name: Choose permission + perm: §aPermission + world: §aWorld + worldGlobal: §b§lGlobal + remove: Remove permission + removeLore: §7Permission will be taken off\n§7instead of given. + permissionList: + name: Permissions list + removed: '§eTaken off: §6{permission_removed}' + world: '§eWorld: §6{permission_world}' + classesRequired.name: Classes required + classesList.name: Classes list + factionsRequired.name: Factions required + factionsList.name: Factions list + poolsManage: + name: Quest Pools + itemName: '§aPool {pool}' + poolNPC: '§8NPC: §7{pool_npc_id}' + poolMaxQuests: '§8Max quests: §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Quests given per launch: §7{pool_quests_per_launch}' + poolRedo: '§8Can redo completed quests: §7{pool_redo}' + poolTime: '§8Time between quests: §7{pool_time}' + poolHologram: '§8Hologram text: §7{pool_hologram}' + poolAvoidDuplicates: '§8Avoid duplicates: §7{pool_duplicates}' + poolQuestsList: '§7{pool_quests_amount} §8quest(s): §7{pool_quests}' + create: §aCreate a quest pool + edit: §e> §6§oEdit the pool... §e< + choose: §e> §6§oChoose this pool §e< + poolCreation: + name: Quest pool creation + hologramText: §ePool custom hologram + maxQuests: §aMax quests + questsPerLaunch: §aQuests started per launch + time: §bSet time between quests + redoAllowed: Is redo allowed + avoidDuplicates: Avoid duplicates + avoidDuplicatesLore: §8> §7Try to avoid doing\n the same quest over and over + requirements: §bRequirements to start a quest + poolsList.name: Quest pools + itemComparisons: + name: Item Comparisons + bukkit: Bukkit native comparison + bukkitLore: 'Uses Bukkit default item comparison system.\nCompares material, durability, nbt tags...' + customBukkit: Bukkit native comparison - NO NBT + customBukkitLore: 'Uses Bukkit default item comparison system, but wipes out NBT tags.\nCompares material, durability...' + material: Item material + materialLore: 'Compares item material (i. e. stone, iron sword...)' + itemName: Item name + itemNameLore: Compares items names + itemLore: Item lore + itemLoreLore: Compares items lores + enchants: Items enchants + enchantsLore: Compares items enchants + repairCost: Repair cost + repairCostLore: Compares repair cost for armors and swords + itemsAdder: ItemsAdder + itemsAdderLore: Compares ItemsAdder IDs + mmoItems: MMOItems item + mmoItemsLore: Compares MMOItems types and IDs + editTitle: + name: Edit Title + title: §6Title + subtitle: §eSubtitle + fadeIn: §aFade-in duration + stay: §bStay duration + fadeOut: §aFade-out duration + particleEffect: + name: Create particle effect + shape: §dParticle shape + type: §eParticle type + color: §bParticle color + particleList: + name: Particles list + colored: Colored particle + damageCause: + name: Damage cause + damageCausesList: + name: Damage causes list + visibility: + name: Quest visibility + notStarted: '"Not started" menu tab' + inProgress: '"In progress" menu tab' + finished: '"Finished" menu tab' + maps: 'Maps (such as dynmap or BlueMap)' + equipmentSlots: + name: Equipment slots + questObjects: + setCustomDescription: 'Set custom description' + description: '§8Description: §7{description}' + +scoreboard: + name: §6§lQuests + noLaunched: §cNo quests in progress. + noLaunchedName: §c§lLoading + noLaunchedDescription: §c§oLoading + textBetwteenBranch: §e or + asyncEnd: §ex + stage: + region: §eFind region §6{region_id} + npc: §eTalk with NPC §6{dialog_npc_name} + items: '§eBring items to §6{dialog_npc_name}§e: {items}' + mobs: §eKill §6{mobs} + mine: §eMine {blocks} + placeBlocks: §ePlace {blocks} + chat: §eWrite §6{text} + interact: §eClick on the block at §6{x} {y} {z} + interactMaterial: §eClick on a §6{block}§e block + fish: §eFish §6{items} + melt: §eMelt §6{items} + enchant: §eEnchant §6{items} + craft: §eCraft §6{items} + bucket: §eFill §6{buckets} + location: §eGo to §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world} + playTimeFormatted: §ePlay §6{time_remaining_human} + breed: §eBreed §6{mobs} + tame: §eTame §6{mobs} + die: §cDie + dealDamage: + any: §cDeal {damage_remaining} damage + mobs: §cDeal {damage_remaining} damage to {target_mobs} + eatDrink: §eConsume §6{items} +indication: + startQuest: §7Do you want to start the quest {quest_name}? + closeInventory: §7Are you sure you want to close the GUI? + cancelQuest: §7Are you sure you want to cancel the quest {quest_name}? + removeQuest: §7Are you sure you want to remove the quest {quest}? + removePool: §7Are you sure you want to remove the pool {pool}? +description: + requirement: + title: '§8§lRequirements:' + level: 'Level {short_level}' + jobLevel: 'Level {short_level} for {job_name}' + combatLevel: 'Combat level {short_level}' + skillLevel: 'Level {short_level} for {skill_name}' + class: 'Class {class_name}' + faction: 'Faction {faction_name}' + quest: 'Finish quest §e{quest_name}' + reward: + title: '§8§lRewards:' + +misc: + format: + prefix: §6<§e§lQuests§r§6> §r + npcText: §6[{message_id}/{message_count}] §e§l{npc_name_message}:§r§e {text} + selfText: §6[{message_id}/{message_count}] §e§l{player_name}:§r§e {text} + offText: §r§e{message} + editorPrefix: §a + errorPrefix: §4✖ §c + successPrefix: §2✔ §a + requirementNotMetPrefix: §c + time: + weeks: '{weeks_amount} weeks' + days: '{days_amount} days' + hours: '{hours_amount} hours' + minutes: '{minutes_amount} minutes' + lessThanAMinute: 'a few seconds' + stageType: + region: Find region + npc: Find NPC + items: Bring back items + mobs: Kill mobs + mine: Break blocks + placeBlocks: Place blocks + chat: Write in chat + interact: Interact with block + interactLocation: Interact with block at location + Fish: Catch fishes + Melt: Melt items + Enchant: Enchant items + Craft: Craft item + Bucket: Fill bucket + location: Find location + playTime: Play time + breedAnimals: Breed animals + tameAnimals: Tame animals + die: Die + dealDamage: Deal damage + eatDrink: Eat or drink + comparison: + equals: equal to {number} + different: different to {number} + less: strictly less than {number} + lessOrEquals: less than {number} + greater: strictly greater than {number} + greaterOrEquals: greater than {number} + requirement: + logicalOr: §dLogical OR (requirements) + skillAPILevel: §bSkillAPI level required + class: §bClass(es) required + faction: §bFaction(s) required + jobLevel: §bJob level required + combatLevel: §bCombat level required + experienceLevel: §bExperience levels required + permissions: §3Permission(s) required + scoreboard: §dScore required + region: §dRegion required + placeholder: §bPlaceholder value required + quest: §aQuest required + mcMMOSkillLevel: §dSkill level required + money: §dMoney required + equipment: §eEquipment required + reward: + skillApiXp: SkillAPI XP reward + bucket: + water: Water bucket + lava: Lava bucket + milk: Milk bucket + snow: Snow bucket + click: + right: Right click + left: Left click + shift-right: Shift-right click + shift-left: Shift-left click + middle: Middle click + amounts: + items: '{items_amount} item(s)' + comparisons: '{comparisons_amount} comparison(s)' + dialogLines: '{lines_amount} line(s)' + permissions: '{permissions_amount} permission(s)' + mobs: '{mobs_amount} mob(s)' + xp: '{xp_amount} experience point(s)' + ticks: '{ticks} ticks' + location: |- + Location: {x} {y} {z} + World: {world} + questItemLore: §e§oQuest Item + hologramText: §8§lQuest NPC + poolHologramText: §eNew quest available! + entityType: '§eEntity type: {entity_type}' + entityTypeAny: §eAny entity + enabled: Enabled + disabled: Disabled + unknown: unknown + notSet: §cnot set + removeRaw: Remove + reset: Reset + or: or + amount: '§eAmount: {amount}' + 'yes': 'Yes' + 'no': 'No' + and: and diff --git a/core/src/main/resources/locales/fr_FR.yml b/core/src/main/resources/locales/fr_FR.yml index d440797b..95081747 100644 --- a/core/src/main/resources/locales/fr_FR.yml +++ b/core/src/main/resources/locales/fr_FR.yml @@ -1,795 +1,832 @@ --- -advancement: - finished: Terminée - notStarted: Pas commencée -description: - requirement: - class: Classe {class_name} - combatLevel: Niveau de combat {short_level} - jobLevel: Niveau {short_level} pour {job_name} - level: Niveau {short_level} - quest: Terminer la quête §e{quest_name} - skillLevel: Niveau {short_level} pour {skill_name} - title: '§8§lConditions :' - reward: - title: '§8§lRécompenses :' -indication: - cancelQuest: '§7Êtes-vous sûr de vouloir annuler la quête {quest_name} ?' - closeInventory: '§7Êtes-vous sûr de vouloir fermer l''interface graphique ?' - removeQuest: '§7Êtes-vous sûr de vouloir supprimer la quête {quest} ?' - startQuest: '§7Voulez-vous commencer la quête {quest_name} ?' -inv: - addObject: '§aAjouter un objet' - block: - blockData: '§dBlockdata (avancé)' - blockName: '§bNom de bloc personnalisé' - blockTag: '§dTag (avancé)' - blockTagLore: Choisissez un tag qui décrit une liste de blocs possibles. Les tags peuvent être personnalisés en utilisant des datapacks. Vous pouvez trouver une liste des tags sur le Minecraft Wiki. - material: '§eType de bloc : {block_type}' - materialNotItemLore: Le bloc choisi ne peut pas être affiché comme un item. Il est toujours correctement sauvegardé comme {block_material}. - name: Choisir un bloc - blockAction: - location: '§eSélectionner un emplacement précis' - material: '§eSélectionner un type de bloc' - name: Sélectionner l'action - blocksList: - addBlock: '§aCliquez pour ajouter un block.' - name: Sélectionner des blocs - buckets: - name: Type de seau - cancel: '§c§lAnnuler' - cancelActions: - name: Actions d'annulation - checkpointActions: - name: Actions du checkpoint - chooseAccount: - name: Quel compte ? - chooseQuest: - menu: '§aMenu des Quêtes' - menuLore: Vous ouvre votre menu de Quêtes. - name: Quelle quête ? - classesList.name: Liste des classes - classesRequired.name: Classes requises - command: - console: Console - delay: '§bDélai' - name: Commande - parse: Remplacer les placeholders - value: '§eCommande' - commandsList: - console: '§eConsole : {command_console}' - name: Liste des commandes - value: '§eCommande : {command_label}' - confirm: - name: Êtes-vous sûr ? - 'no': '§cAnnuler' - 'yes': '§aConfirmer' - create: - NPCSelect: '§eChoisir ou créer un NPC' - NPCText: '§eModifier le dialogue' - breedAnimals: '§aFaire reproduire des animaux' - bringBack: '§aRapporter des objets' - bucket: '§aRemplir des seaux' - cancelMessage: Annuler l'envoi - cantFinish: '§7Vous devez créer au moins une étape avant de terminer la création de la quête !' - changeEntityType: '§eSélectionner un type d''entité' - changeTicksRequired: '§eChanger la quantité de ticks requis' - craft: '§aFabriquer un objet' - currentRadius: '§eDistance actuelle : §6{radius}' - dealDamage: '§cInfliger des dégâts à des mobs' - death: '§cMourir' - eatDrink: '§aManger ou boire de la nourriture ou des potions' - editBlocksMine: '§eModifier les blocs à casser' - editBlocksPlace: '§eModifier les blocs à poser' - editBucketAmount: '§eModifier la quantité de seaux à remplir' - editBucketType: '§eModifier le type de seau à remplir' - editFishes: '§eModifier les poissons nécessaires' - editItem: '§eEditer l''objet à fabriquer' - editItemsToEnchant: '§eModifier les items à enchanter' - editItemsToMelt: '§eModifier les items à cuire' - editLocation: '§eModifier l''endroit' - editMessageType: '§eModifier le message à écrire' - editMobsKill: '§eModifier les mobs à tuer' - editRadius: '§eModifier la distance à partir de l''endroit' - enchant: '§dEnchanter des items' - findNPC: '§aTrouver un NPC' - findRegion: '§aTrouver une région' - fish: '§aPêcher' - hideClues: Cacher les particules et les hologrammes - ignoreCase: Ignorer la casse du message - interact: '§aCliquez sur un bloc' - killMobs: '§aTuer des mobs' - leftClick: Clic gauche nécessaire - location: '§aAller à un endroit' - melt: '§6Cuire des items' - mineBlocks: '§aCasser des blocs' - mobsKillFromAFar: Doit être tué de loin - placeBlocks: '§aPoser des blocs' - playTime: '§eTemps de jeu' - preventBlockPlace: Empêcher les joueurs de casser leurs propres blocs - replacePlaceholders: Remplacer {PLAYER} et les placeholders de PAPI - selectBlockLocation: '§eSélectionner la position du bloc' - selectBlockMaterial: '§eSélectionner le type de block' - selectItems: '§eChoisir les items nécessaires' - selectItemsComparisons: '§eSélectionnez les comparaisons d''items (AVANCÉ)' - selectItemsMessage: '§eModifier le message de demande' - selectRegion: '§7Choisir la région' - stage: - dealDamage: - damage: '§eDégâts à infliger' - targetMobs: '§cMobs à heurter' - death: - anyCause: Toute cause de mort - causes: '§aDéfinir les causes de la mort §d(AVANCED)' - setCauses: '{causes_amount} cause(s) de mort' - eatDrink: - items: '§eModifier les objets à manger ou à boire' - location: - worldPattern: '§aModifier le motif de nom de monde §d(AVANCÉ)' - worldPatternLore: Si vous voulez que l'étape soit terminée pour un monde correspondant à un motif spécifique, entrez ici une regex (expression régulière). - stageCreate: '§aCréer une nouvelle étape' - stageDown: Descendre - stageRemove: '§cSupprimer cette étape' - stageStartMsg: '§eModifier le message de départ' - stageType: '§7Type d''étape: §e{stage_type}' - stageUp: Monter - talkChat: '§aEcrire dans le chat' - tameAnimals: '§aApprivoiser des animaux' - toggleRegionExit: À la sortie - damageCause: - name: Cause de dégât - damageCausesList: - name: Liste des causes de dégât - details: - auto: Démarrer automatiquement à la première connexion - autoLore: Si activé, la quête sera lancée automatiquement lorsque le joueur rejoindra le serveur pour la première fois. - bypassLimit: Ne pas compter la limite de quêtes - bypassLimitLore: Si activé, la quête sera démarrée même si le joueur a atteint son nombre maximum de quêtes en cours. - cancelRewards: '§cActions d''annulation' - cancelRewardsLore: Actions effectuées lorsque les joueurs annulent cette quête. - cancellable: Annulable par le joueur - cancellableLore: Permet au joueur d'annuler la quête par l'intermédiaire de son menu de Quêtes. - createQuestLore: Vous devez définir le nom de la quête. - createQuestName: '§lCréer la quête' - customConfirmMessage: '§eModifier le message de confirmation de quête' - customConfirmMessageLore: Message affiché dans l'interface de confirmation lorsqu'un joueur est sur le point de commencer la quête. - customDescription: '§eModifier la description de la quête' - customDescriptionLore: Description affichée sous le nom de la quête dans les interfaces graphiques. - customMaterial: '§eModifiez l''item de la quête' - customMaterialLore: Item représentant cette quête dans le menu de Quêtes. - defaultValue: '§8(valeur par défaut)' - editQuestName: '§lModifier la quête' - editRequirements: '§eModifier les nécessités' - editRequirementsLore: Toutes les conditions doivent s’appliquer au joueur avant de pouvoir commencer la quête. - endMessage: '§eModifier le message de fin' - endMessageLore: Message qui sera envoyé au joueur à la fin de la quête. - endSound: '§eModifier le son de fin' - endSoundLore: Son qui sera joué à la fin de la quête. - failOnDeath: Échec lors de la mort - failOnDeathLore: La quête sera-t-elle annulée à la mort du joueur ? - firework: '§dFeu d''artifice de fin' - fireworkLore: Feu d'artifice lancé lorsque le joueur termine la quête - fireworkLoreDrop: Déposez votre feu d'artifice personnalisé ici - hideNoRequirementsItem: Masquer lorsque les conditions ne sont pas remplies - hideNoRequirementsItemLore: Si activé, la quête ne sera pas affichée dans le menu des quêtes lorsque les conditions ne sont pas remplies. - hologramLaunch: '§eModifier l''item de l''hologramme "lancement"' - hologramLaunchLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur peut commencer la quête. - hologramLaunchNo: '§eModifier l''item de l''hologramme "lancement impossible"' - hologramLaunchNoLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur ne peut PAS démarrer la quête. - hologramText: '§eTexte de l''hologramme' - hologramTextLore: Texte affiché sur l'hologramme au-dessus de la tête du NPC de démarrage. - keepDatas: Conserver les données des joueurs - keepDatasLore: 'Forcer le plugin à préserver les données des joueurs, même si les étapes ont été modifiées. §c§lAVERTISSEMENT §c- activer cette option peut endommager les données de vos joueurs.' - loreReset: '§e§lL''avancement de tous les joueurs sera réinitialisé' - multipleTime: - itemLore: La quête peut-elle être faite plusieurs fois ? - itemName: Activer/désactiver la répétition - name: Derniers détails de la quête - optionValue: '§8Valeur : §7{value}' - questName: '§a§lModifier le nom de la quête' - questNameLore: Un nom doit être défini pour terminer la création de quête. - questPool: '§eGroupe de quêtes' - questPoolLore: Attacher cette quête à un groupe de quêtes - removeItemsReward: '§eRetirer des objets de l''inventaire' - requiredParameter: '§7Paramètre requis' - requirements: '{amount} exigence(s)' - rewards: '{amount} récompense(s)' - rewardsLore: Actions effectuées à la fin de la quête. - scoreboardItem: Activer le scoreboard - scoreboardItemLore: Si désactivée, la quête ne sera pas affichée dans le scoreboard. - selectStarterNPC: '§e§lSélectionner le NPC de départ' - selectStarterNPCLore: Cliquer sur le PNJ sélectionné commencera la quête. - selectStarterNPCPool: '§c⚠ Un groupe de quêtes est sélectionné' - setCheckpointReward: '§eModifier les récompenses du checkpoints' - setItemsRewards: '§eModifier les gains d''item' - setMoneyReward: '§eModifier le gain de monnaie' - setPermReward: '§eModifier les permissions' - setRewardStopQuest: '§cArrêter la quête' - setRewardsRandom: '§dRécompenses aléatoires' - setRewardsWithRequirements: '§eRécompenses avec requirements' - setTitleReward: '§eModifier la récompense /title' - setWaitReward: '§eModifier l''attente' - setXPRewards: '§eModifier les gains d''expérience' - startDialog: '§eModifier le dialogue de début' - startDialogLore: Dialogue qui sera joué avant le début de la quête lorsque les joueurs cliquent sur le NPC de démarrage. - startMessage: '§eModifier le message de départ' - startMessageLore: Message qui sera envoyé au joueur au début de la quête. - startRewards: '§6Récompenses de début' - startRewardsLore: Actions effectuées au démarrage de la quête. - startableFromGUI: Démarrable depuis le GUI - startableFromGUILore: Permet au joueur de commencer la quête depuis son menu de Quêtes. - timer: '§bTimer de redémarrage' - timerLore: Temps avant que le joueur puisse recommencer la quête. - visibility: '§bVisibilité de la quête' - visibilityLore: Choisir dans quels onglets du menu seront affichés la quête et si la quête est visible sur les cartes dynamiques. - editTitle: - fadeIn: '§aDurée du fondu d''entrée' - fadeOut: '§aDurée du fondu de sortie' - name: Modifier le titre - stay: '§bDurée statique' - subtitle: '§eSous-titre' - title: '§6Titre' - entityType: - name: Choisir le type d'entité - equipmentSlots: - name: Emplacements d'équipement - factionsList.name: Liste des factions - factionsRequired.name: Factions requises - itemComparisons: - bukkit: Comparaison native de Bukkit - bukkitLore: Utilise le système de comparaison d'items par défaut de Bukkit. Compare le type d'item, la durabilité, les tags nbt... - customBukkit: Comparaison native de Bukkit - SANS NBT - customBukkitLore: Utilise le système de comparaison d'items par défaut de Bukkit, mais efface les balises NBT. Compare le type d'item, la durabilité... - enchants: Enchantements des items - enchantsLore: Compare les enchantements des items - itemLore: Description de l'item - itemLoreLore: Compare les descriptions des items - itemName: Nom de l’objet - itemNameLore: Compare les noms des items - itemsAdder: ItemsAdder - itemsAdderLore: Compare les IDs d'ItemsAdder - material: Type d'item - materialLore: Compare le type d'item (ex. pierre, épée de fer...) - name: Comparaisons d'item - repairCost: Coût de réparation - repairCostLore: Compare les coûts de réparation des armures et des épées - itemCreator: - isQuestItem: '§bItem de quête :' - itemFlags: Flags d'item - itemLore: '§bDescription de l''item' - itemName: '§bNom de l''item' - itemType: '§bType d''item' - name: Créateur d'item - itemSelect: - name: Choisissez un objet - itemsSelect: - name: Modifier les items - none: "§aDéplacez un item ici ou \n §acliquez pour ouvrir l'éditeur d'item" - listAllQuests: - name: Quêtes - listBook: - noQuests: Aucune quête n'a été préalablement créée. - questMultiple: Plusieurs fois - questName: Nom - questRewards: Récompenses - questStages: Etapes - questStarter: NPC - requirements: Exigences - listPlayerQuests: - name: 'Quêtes de {player_name}' - listQuests: - canRedo: '§3§oVous pouvez refaire cette quête !' - finished: Quêtes terminées - inProgress: Quêtes en cours - loreCancelClick: '§cAnnuler la quête' - loreDialogsHistoryClick: '§7Voir les dialogues' - loreStart: '§a§oCliquez pour commencer la quête.' - loreStartUnavailable: '§c§oVous ne remplissez pas les conditions pour commencer la quête.' - notStarted: Quêtes non commencées - timeToWaitRedo: '§3§oVous pouvez refaire cette quête dans {time_left}.' - timesFinished: '§3Quête accomplie {times_finished} fois.' - mobSelect: - boss: '§6Choisir un Boss' - bukkitEntityType: '§eSélectionner un type de mob' - epicBoss: '§6Sélectionner un Epic Boss' - mythicMob: '§6Sélectionner un Mythic Mob' - name: Choisir le type de monstre - mobs: - name: Choisir les mobs - none: '§aCliquer pour ajouter un mob.' - setLevel: Modifier le niveau minimum - npcCreate: - move: - itemLore: '§aModifier la position du NPC.' - itemName: '§eSe déplacer' - moveItem: '§a§lValider l''endroit' - name: Créer le NPC - setName: '§eModifier le nom du NPC' - setSkin: '§eModifier le skin du NPC' - setType: '§eModifier le type du NPC' - npcSelect: - createStageNPC: '§eCréer le NPC' - name: Sélectionner ou créer ? - selectStageNPC: '§eSélectionner un NPC existant' - particleEffect: - color: '§bCouleur des particules' - name: Créer un effet de particules - shape: '§dForme de l''effet' - type: '§eType de particules' - particleList: - colored: Particule colorée - name: Liste des particules - permission: - name: Choisir la permission - perm: '§aPermission' - remove: Supprimer la permission - removeLore: '§7La permission sera retirée\n§7au lieu d''être donnée.' - world: '§aMonde' - worldGlobal: '§b§lGlobal' - permissionList: - name: Liste des permissions - removed: '§eRetiré : §6{permission_removed}' - world: '§eMonde : §6{permission_world}' - poolCreation: - avoidDuplicates: Éviter les doublons - avoidDuplicatesLore: '§8> §7Essaye d''éviter de faire\n la même quête encore et encore' - hologramText: '§eHologramme personnalisé du groupe' - maxQuests: '§aNombre maximum de quêtes' - name: Création du groupe de quêtes - questsPerLaunch: '§aQuêtes commencées par lancement' - redoAllowed: Est-il recommençable ? - requirements: '§bExigences pour démarrer une quête' - time: '§bDéfinir le temps entre les quêtes' - poolsList.name: Groupe de quêtes - poolsManage: - choose: '§e> §6§oChoisir ce groupe §e<' - create: '§aCréer un groupe de quêtes' - edit: '§e> §6§oModifier le groupe de quêtes... §e<' - itemName: '§aGroupe #{pool}' - name: Groupe de quêtes - poolAvoidDuplicates: '§8Éviter les doublons : §7{pool_duplicates}' - poolHologram: '§8Hologramme : §7{pool_hologram}' - poolMaxQuests: '§8Nombre maximum de quêtes : §7{pool_max_quests}' - poolNPC: '§8NPC : §7{pool_npc_id}' - poolQuestsList: '§7{pool_quests_amount} §8quête(s) : §7{pool_quests}' - poolQuestsPerLaunch: '§8Quêtes données par lancement : §7{pool_quests_per_launch}' - poolRedo: '§8Peut refaire les quêtes : §7{pool_redo}' - poolTime: '§8Temps entre les quêtes : §7{pool_time}' - requirements: - name: Nécessités - rewards: - commands: 'Commandes : {amount}' - name: Récompenses - random: - minMax: Modifier les quantités min/max - rewards: Modifier les récompenses - rewardsWithRequirements: - name: Récompenses avec requirements - search: '§e§lRechercher' - stageEnding: - command: '§eModifier la commande exécutée' - locationTeleport: '§eModifier le point de téléportation' - stages: - branchesPage: '§dÉtapes d''embranchement' - descriptionTextItem: '§eModifier le texte de description' - endingItem: '§eRécompenses de fin' - laterPage: '§ePage précédente' - name: Créer les étapes - newBranch: '§eAller à la nouvelle branche' - nextPage: '§ePage suivante' - previousBranch: '§eRetourner à la branche précédente' - regularPage: '§aÉtapes simples' - validationRequirements: '§eConditions de validation' - validationRequirementsLore: Toutes les conditions doivent s'appliquer au joueur qui tente de terminer l'étape. Sinon, l'étape ne peut pas être terminée. - validate: '§b§lValider' - visibility: - finished: 'Onglet du menu "Terminées"' - inProgress: 'Onglet du menu "En cours"' - maps: Cartes (dynmap, BlueMap...) - name: Visibilité de la quête - notStarted: 'Onglet du menu "Non commencées"' -misc: - amount: '§eQuantité : {amount}' - amounts: - comparisons: '{comparisons_amount} comparaison(s)' - dialogLines: '{lines_amount} ligne(s)' - and: et - bucket: - lava: Seau de lave - milk: Seau de lait - snow: Seau de neige - water: Seau d'eau - click: - left: Clic gauche - middle: Clic central - right: Clic droit - shift-left: Maj + clic-gauche - shift-right: Maj + clic-droit - comparison: - different: différent de {number} - equals: égal à {number} - greater: strictement supérieur à {number} - greaterOrEquals: supérieur à {number} - less: strictement inférieur à {number} - lessOrEquals: inférieur à {number} - disabled: Désactivé - enabled: Activé - entityType: '§eType d''entité : {entity_type}' - entityTypeAny: '§eN''importe quelle entité' - format: - npcText: '§6[{message_id}/{message_count}] §e§l{npc_name_message} :§r§e {text}' - prefix: '§6<§e§lQuêtes§r§6> §r' - selfText: '§6[{message_id}/{message_count}] §e§l{player_name} :§r§e {text}' - hologramText: '§8§lNPC de Quête' - 'no': 'Non' - notSet: '§cnon défini' - or: ou - poolHologramText: '§eNouvelle quête disponible !' - questItemLore: '§e§oItem de Quête' - removeRaw: Supprimer - requirement: - class: '§bClasse(s) requise(s)' - combatLevel: '§bNiveau de combat requis' - equipment: '§eÉquipement requis' - experienceLevel: '§bNiveau d''expérience requis' - faction: '§bFaction(s) requise(s)' - jobLevel: '§bNiveau de job requis' - logicalOr: '§dOU logique (requirements)' - mcMMOSkillLevel: '§dNiveau de compétence requis' - money: '§dMonnaie requise' - permissions: '§3Permission(s) requise(s)' - placeholder: '§bPlaceholder requis' - quest: '§aQuête requise' - region: '§dRégion requise' - scoreboard: '§dScore requis' - skillAPILevel: '§bNiveau SkillAPI requis' - reset: Réinitialiser - stageType: - Bucket: Remplir un seau - Craft: Fabriquer un objet - Enchant: Enchanter des items - Fish: Pêcher - Melt: Cuire des items - breedAnimals: Faire reproduire des animaux - chat: Parler dans le chat - dealDamage: Infliger des dégâts - die: Mourir - eatDrink: Manger ou boire - interact: Intéragir avec un bloc - items: Rapporter des items - location: Trouver un endroit - mine: Casser des blocs - mobs: Tuer des mobs - npc: Trouver un NPC - placeBlocks: Poser des blocs - playTime: Temps de jeu - region: Trouver une region - tameAnimals: Apprivoiser des animaux - time: - days: '{days_amount} jours' - hours: '{hours_amount} heures' - lessThanAMinute: moins d'une minute - weeks: '{weeks_amount} semaines' - unknown: inconnu - 'yes': 'Oui' msg: + quest: + finished: + base: '§aFélicitations ! Vous avez complété la quête §e{quest_name}§r§a !' + obtain: '§aVous remportez {rewards} !' + started: '§aVous commencez la quête §r§e{quest_name}§o§6 !' + created: '§aFélicitations ! Vous avez créé la quête §e{quest}§a, qui comporte {quest_branches} branche(s) !' + edited: '§aFélicitations ! Vous avez modifié la quête §e{quest}§a, qui comporte désormais {quest_branches} branche(s) !' + createCancelled: '§cLa création (ou l''édition) de votre quête a été annulée par un plugin tiers.' + cancelling: '§cAnnulation du processus de création de quête.' + editCancelling: '§cAnnulation du processus d''édition de la quête.' + invalidID: '§cLa quête avec l''id {quest_id} n''existe pas.' + invalidPoolID: '§cLe groupe {pool_id} n''existe pas.' + alreadyStarted: '§cVous avez déjà commencé cette quête !' + notStarted: '§cVous ne faites pas cette quête en ce moment.' + quests: + maxLaunched: '§cVous ne pouvez pas avoir plus de {quests_max_amount} quête(s) simultanément...' + updated: '§7Quête §e{quest_name}§7 actualisée.' + checkpoint: '§7Checkpoint de quête atteint !' + failed: '§cVous avez échoué à la quête {quest_name}...' + pools: + noTime: '§cVous devez attendre {time_left} avant de faire une autre quête.' + allCompleted: '§7Vous avez terminé toutes les quêtes !' + noAvailable: '§7Il n''y a plus de quête disponible...' + maxQuests: '§cVous ne pouvez pas avoir plus de {pool_max_quests} quête(s) simultanément...' + questItem: + drop: '§cVous ne pouvez pas jeter un objet de quête !' + craft: '§cVous ne pouvez pas utiliser un objet de quête pour crafter !' + eat: '§cVous ne pouvez pas manger un objet de quête !' + stageMobs: + listMobs: '§aIl faut que vous tuiez {mobs}.' + writeNPCText: '§aÉcrivez le dialogue qui sera dit au joueur par le NPC : (Tapez "help" pour recevoir de l''aide.)' + writeRegionName: '§aEcrivez le nom de la région voulue pour l''étape :' + writeXPGain: '§aÉcrivez le nombre de points d’expérience que le joueur va remporter. (Ancien gain : {xp_amount})' + writeMobAmount: '§aEcrivez le nombre de mobs à tuer :' + writeMobName: '§aÉcrivez le nom personnalisé du mob à tuer :' + writeChatMessage: '§aÉcrivez le message requis (rajoutez "{SLASH}" au début pour en faire une commande.)' + writeMessage: '§aÉcrivez le message qui sera envoyé au joueur' + writeStartMessage: '§aÉcrivez le message qui sera envoyé au début de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas :' + writeEndMsg: '§aÉcrivez le message qui sera envoyé à la fin de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas. Vous pouvez utiliser "{rewards}" qui sera remplacé par les récompenses obtenues.' + writeEndSound: '§aÉcrivez le nom du son qui sera joué au joueur à la fin de la quête, "null" si vous voulez le son par défaut ou "none" si vous n''en voulez pas :' + writeDescriptionText: '§aEcrivez le texte qui décrira le but de l''étape :' + writeStageText: '§aEcrivez le texte qui sera transmis au joueur au début de l''étape :' + moveToTeleportPoint: '§aAllez au lieu de téléportation désiré.' + writeNpcName: '§aEcrivez le nom du NPC :' + writeNpcSkinName: '§aEcrivez le nom du skin du NPC :' + writeQuestName: '§aEcrivez le nom de votre quête :' + writeCommand: '§aÉcrivez la commande : (n''écrivez pas le "/" ; le placeholder "{PLAYER}" est pris en charge. Il sera remplacée par le nom du joueur exécuteur.)' + writeHologramText: '§aEcrivez le texte de l''hologramme. (tapez "none" si vous ne voulez pas d''hologramme, et "null" si vous voulez le texte par défaut.)' + writeQuestTimer: '§aRenseignez le temps nécessaire (en minutes) avant de pouvoir refaire la quête. (Tapez "null" si vous voulez le temps par défaut)' + writeConfirmMessage: '§aÉcrivez le message de confirmation affiché lorsqu''un joueur est sur le point de démarrer la quête : (Tapez "null" si vous voulez le message par défaut).' + writeQuestDescription: '§aÉcrivez la description de la quête, affichée dans l''interface des quêtes du joueur.' + writeQuestMaterial: '§aIndiquez le type d''item pour la quête.' + requirements: + quest: '§cVous devez avoir terminé la quête §e{quest_name}§c !' + level: '§cVotre niveau doit être {long_level}!' + job: '§cVotre niveau pour le métier §e{job_name}§c doit être {long_level}!' + skill: '§cVotre niveau pour la compétence §e{skill_name}§c doit être {long_level}!' + combatLevel: '§cVotre niveau de combat doit être {long_level}!' + money: '§cVous devez avoir {money} !' + waitTime: '§cVous devez encore attendre {time_left} avant de pouvoir recommencer cette quête !' + experience: + edited: '§aVous avez changé le gain d''expérience de {old_xp_amount} à {xp_amount} points.' + selectNPCToKill: '§aSélectionnez le NPC à tuer.' + regionDoesntExists: '§cCette région n''existe pas. (Vous devez être dans le même monde.)' + npcDoesntExist: '§cLa quête avec l''id {npc_id} n''existe pas.' + number: + negative: '§cTu dois entrer un nombre positif !' + zero: '§cTu dois entrer un nombre autre que 0 !' + invalid: '§c{input} n''est pas un nombre valide.' + notInBounds: '§cLa valeur doit être comprise entre {min} et {max}.' + errorOccurred: '§cUne erreur est survenue, prévenez un administrateur ! §4§lCode d''erreur : {error}' + indexOutOfBounds: '§cLe numéro {index} est hors des limites ! Il doit se trouver entre {min} et {max}.' + invalidBlockData: '§cLa blockdata {block_data} est invalide ou incompatible avec le bloc {block_material}.' + invalidBlockTag: '§cTag de bloc {block_tag} indisponible.' bringBackObjects: Rapporte-moi {items}. + inventoryFull: '§cVotre inventaire est plein, l''item a été jeté au sol.' + versionRequired: 'Version requise : §l{version}' + restartServer: '§7Redémarrez votre serveur pour voir les modifications.' + dialogs: + skipped: '§8§o Le dialogue a été passé.' + tooFar: '§7§oVous êtes trop loin de {npc_name}...' command: - adminModeEntered: '§aVous entrez dans le mode Administrateur.' - adminModeLeft: '§aVous sortez du mode Administrateur.' - backupCreated: '§6Vous avez créé une sauvegarde des quêtes et des données joueurs avec succès.' - backupPlayersFailed: '§cLa création d''une sauvegarde des données joueur a échoué.' - backupQuestsFailed: '§cLa création d''une sauvegarde des quêtes a échoué.' - cancelQuest: '§6Vous avez annulé la quête {quest}.' - cancelQuestUnavailable: '§cLa quête {quest} ne peut être annulée.' + downloadTranslations: + syntax: '§cVous devez spécifier une langue à télécharger. Exemple: "/quests downloadTranslations fr_FR".' + notFound: '§cLangue {lang} introuvable pour la version {version}.' + exists: '§cLe fichier {file_name} existe déjà. Ajoutez "-overwrite" à votre commande pour l''écraser. (/quests downloadTranslations <lang> -overwrite)' + downloaded: '§aLa langue {lang} a été téléchargée ! §7Vous devez maintenant modifier le fichier "/plugins/BeautyQuests/config.yml" pour changer la valeur de §ominecraftTranslationsFile§7 avec {lang}, puis redémarrer le serveur.' checkpoint: noCheckpoint: '§cAucun checkpoint trouvé pour la quête {quest}.' questNotStarted: '§cVous ne faites pas cette quête.' - downloadTranslations: - downloaded: '§aLa langue {lang} a été téléchargée ! §7Vous devez maintenant modifier le fichier "/plugins/BeautyQuests/config.yml" pour changer la valeur de §ominecraftTranslationsFile§7 avec {lang}, puis redémarrer le serveur.' - exists: '§cLe fichier {file_name} existe déjà. Ajoutez "-overwrite" à votre commande pour l''écraser. (/quests downloadTranslations <lang> -overwrite)' - notFound: '§cLangue {lang} introuvable pour la version {version}.' - syntax: '§cVous devez spécifier une langue à télécharger. Exemple: "/quests downloadTranslations fr_FR".' - help: - adminMode: '§6/{label} adminMode : §eMode administrateur (réception d''informations journal)' - create: '§6/{label} create : §eCréer une quête.' - downloadTranslations: '§6/{label} downloadTranslations <langage>: §eTélécharge un fichier de traductions vanilla' - edit: '§6/{label} edit : §eModifier une quête.' - finishAll: '§6/{label} finishAll <joueur> : §eFinir toutes les quêtes d''un joueur.' - header: '§6§lBeautyQuests — Aide' - list: '§6/{label} list : §eVoir la liste des quêtes (seulement pour les versions supportées).' - reload: '§6/{label} reload : §eSauvegarder et recharger les fichiers de configuration/sauvegarde. (§cdéconseillé§e)' - remove: '§6/{label} remove <id> : §eSupprimer une quête avec un ID spécifié ou en cliquant sur son NPC.' - resetPlayer: '§6/{label} resetPlayer <joueur> : §eSupprimer les données d''un joueur.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <joueur> [id] : §eSupprimer les données d''une seule quête pour un joueur.' - save: '§6/{label} save: §eFaire une sauvegarde manuelles des données.' - seePlayer: '§6/{label} seePlayer <joueur> : §eVoir les données d''un joueur.' - setFirework: '§6/{label} setFirework : §eModifie le feu d''artifice de fin par défaut.' - setItem: '§6/{label} setItem <talk|launch> : §eSauvegarder l''item de l''hologramme dans le fichier de données.' - setStage: '§6/{label} setStage <joueur> <id> [nouvelle branche] [nouvelle étape]: §ePasser l''étape en cours/lancer une branche/lancer une étape pour une branche.' - start: '§6/{label} start <joueur> [id] : §eForcer le lancement d''une quête.' - startDialog: '§6/{label} startDialog <joueur> <id de quête>: §eDémarre le dialogue en attente pour une étape "NPC" ou le dialogue de début d''une quête.' - version: '§6/{label} version : §eVoir la version du plugin.' + setStage: + branchDoesntExist: '§cLa branche avec l''id {branch_id} n''existe pas.' + doesntExist: '§cL''étape avec l''id {stage_id} n''existe pas.' + next: '§aL''étape a été passée.' + nextUnavailable: '§cL''option "passer l''étape" n''est pas disponible quand le joueur est à la fin d''une branche.' + set: '§aL''étape {stage_id} a été lancée.' + startDialog: + impossible: '§cImpossible de démarrer le dialogue maintenant.' + noDialog: '§cLe joueur n''a aucun dialogue en attente.' + alreadyIn: '§cLe joueur est déjà dans un dialogue.' + success: '§aDébut du dialogue pour le joueur {player} dans la quête {quest}!' invalidCommand: simple: '§cCette commande n''existe pas, tapez §ehelp§c.' itemChanged: '§aL''item a été modifié. Le changement prendra effet après redémarrage.' itemRemoved: '§aL''item de l''hologramme a été supprimé.' - leaveAll: '§aVous avez forcé la fin de {success} quête(s). §c{errors} erreur(s).' removed: '§aLa quête {quest_name} a bien été supprimée.' + leaveAll: '§aVous avez forcé la fin de {success} quête(s). §c{errors} erreur(s).' resetPlayer: player: '§6Les données de vos {quest_amount} quêtes ont été supprimées par {deleter_name}.' remover: '§6Les données de {quest_amount} quête(s) (et {quest_pool} pools) pour le joueur {player} ont bien été supprimées.' - resetPlayerPool: - full: '§aVous avez réinitialisé les données de {player} pour le groupe {pool}.' - timer: '§aVous avez réinitialisé le minuteur de {player} pour le groupe {pool}.' resetPlayerQuest: player: '§6Les données de la quête {quest} ont été supprimées par {deleter_name}.' remover: '§6Les données de la quête {quest} du joueur {player} ont bien été supprimées.' resetQuest: '§6Les données de la quête ont été supprimées pour {player_amount} joueurs.' - scoreboard: - hidden: '§6Le scoreboard du joueur {player_name} a été masqué.' - lineInexistant: '§cLa ligne {line_id} n''existe pas.' - lineRemoved: '§6Vous avez supprimé la ligne {line_id}.' - lineReset: '§6Vous avez réinitialisé la ligne {line_id}.' - lineSet: '§6Vous avez modifié la ligne {line_id}.' - own: - hidden: '§6Votre scoreboard est désormais caché.' - shown: '§6Votre scoreboard est de nouveau visible.' - resetAll: '§6Vous avez réinitialisé le scoreboard du joueur {player_name}.' - shown: '§6Le scoreboard du joueur {player_name} est maintenant affiché.' - setStage: - branchDoesntExist: '§cLa branche avec l''id {branch_id} n''existe pas.' - doesntExist: '§cL''étape avec l''id {stage_id} n''existe pas.' - next: '§aL''étape a été passée.' - nextUnavailable: '§cL''option "passer l''étape" n''est pas disponible quand le joueur est à la fin d''une branche.' - set: '§aL''étape {stage_id} a été lancée.' - startDialog: - alreadyIn: '§cLe joueur est déjà dans un dialogue.' - impossible: '§cImpossible de démarrer le dialogue maintenant.' - noDialog: '§cLe joueur n''a aucun dialogue en attente.' - success: '§aDébut du dialogue pour le joueur {player} dans la quête {quest}!' - startPlayerPool: - error: Impossible de démarrer le groupe {pool} pour {player}. - success: 'Groupe {pool} démarré pour {player}. Résultat: {result}' - startQuest: '§6Vous avez forcé le début de la quête {quest} (UUID du joueur : {player}).' + startQuest: '§eVous avez forcé le début de la quête {quest} pour {player}.' startQuestNoRequirements: '§cLe joueur ne remplit pas les conditions pour la quête {quest}... Ajoutez "-overrideRequirements" à la fin de votre commande pour ne pas effectuer la vérification des conditions.' - dialogs: - skipped: '§8§o Le dialogue a été passé.' - tooFar: '§7§oVous êtes trop loin de {npc_name}...' + cancelQuest: '§6Vous avez annulé la quête {quest}.' + cancelQuestUnavailable: '§cLa quête {quest} ne peut être annulée.' + backupCreated: '§6Vous avez créé une sauvegarde des quêtes et des données joueurs avec succès.' + backupPlayersFailed: '§cLa création d''une sauvegarde des données joueur a échoué.' + backupQuestsFailed: '§cLa création d''une sauvegarde des quêtes a échoué.' + adminModeEntered: '§aVous entrez dans le mode Administrateur.' + adminModeLeft: '§aVous sortez du mode Administrateur.' + resetPlayerPool: + timer: '§aVous avez réinitialisé le minuteur de {player} pour le groupe {pool}.' + full: '§aVous avez réinitialisé les données de {player} pour le groupe {pool}.' + startPlayerPool: + error: 'Impossible de démarrer le groupe {pool} pour {player}.' + success: 'Groupe {pool} démarré pour {player}. Résultat: {result}' + scoreboard: + lineSet: '§6Vous avez modifié la ligne {line_id}.' + lineReset: '§6Vous avez réinitialisé la ligne {line_id}.' + lineRemoved: '§6Vous avez supprimé la ligne {line_id}.' + lineInexistant: '§cLa ligne {line_id} n''existe pas.' + resetAll: '§6Vous avez réinitialisé le scoreboard du joueur {player_name}.' + hidden: '§6Le scoreboard du joueur {player_name} a été masqué.' + shown: '§6Le scoreboard du joueur {player_name} est maintenant affiché.' + own: + hidden: '§6Votre scoreboard est désormais caché.' + shown: '§6Votre scoreboard est de nouveau visible.' + help: + header: '§6§lBeautyQuests — Aide' + create: '§6/{label} create : §eCréer une quête.' + edit: '§6/{label} edit : §eModifier une quête.' + remove: '§6/{label} remove <id> : §eSupprimer une quête avec un ID spécifié ou en cliquant sur son NPC.' + finishAll: '§6/{label} finishAll <joueur> : §eFinir toutes les quêtes d''un joueur.' + setStage: '§6/{label} setStage <joueur> <id> [nouvelle branche] [nouvelle étape]: §ePasser l''étape en cours/lancer une branche/lancer une étape pour une branche.' + startDialog: '§6/{label} startDialog <joueur> <id de quête>: §eDémarre le dialogue en attente pour une étape "NPC" ou le dialogue de début d''une quête.' + resetPlayer: '§6/{label} resetPlayer <joueur> : §eSupprimer les données d''un joueur.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <joueur> [id] : §eSupprimer les données d''une seule quête pour un joueur.' + seePlayer: '§6/{label} seePlayer <joueur> : §eVoir les données d''un joueur.' + reload: '§6/{label} reload : §eSauvegarder et recharger les fichiers de configuration/sauvegarde. (§cdéconseillé§e)' + start: '§6/{label} start <joueur> [id] : §eForcer le lancement d''une quête.' + setItem: '§6/{label} setItem <talk|launch> : §eSauvegarder l''item de l''hologramme dans le fichier de données.' + setFirework: '§6/{label} setFirework : §eModifie le feu d''artifice de fin par défaut.' + adminMode: '§6/{label} adminMode : §eMode administrateur (réception d''informations journal)' + version: '§6/{label} version : §eVoir la version du plugin.' + downloadTranslations: '§6/{label} downloadTranslations <langage>: §eTélécharge un fichier de traductions vanilla' + save: '§6/{label} save: §eFaire une sauvegarde manuelles des données.' + list: '§6/{label} list : §eVoir la liste des quêtes (seulement pour les versions supportées).' + typeCancel: '§aTapez "cancel" pour revenir à l''ancien texte.' editor: - advancedSpawnersMob: 'Écrivez le nom du mob de AdvancedSpawners à tuer :' - already: '§cVous êtes déjà dans un éditeur.' - availableElements: 'Éléments disponibles : §e{available_elements}' blockAmount: '§aÉcrivez le nombre de blocs :' - blockData: '§aÉcrivez la blockdata (blockdatas disponibles : {available_datas}) :' blockName: '§aÉcrivez le nom du bloc :' + blockData: '§aÉcrivez la blockdata (blockdatas disponibles : {available_datas}) :' blockTag: '§aÉcrivez le tag de bloc (tagsdisponibles: §7{available_tags}§a):' - chat: '§6Vous êtes actuellement dans le mode éditeur. Entrez "/quests exitEditor" pour forcer la sortie de ce mode (peu recommandé, préférez l''usage de mots-clés tels que "close" ou "cancel" pour revenir à l''inventaire précédent).' - color: 'Entrez une couleur au format hexadécimal (#XXXXX) ou RVB (ROUGE VERT BLEU).' - colorNamed: 'Saisissez le nom de la couleur :' - comparisonTypeDefault: '§aChoissez le type de comparaison que vous voulez parmi {available}. La comparaison par défaut est: §e§l{default}§r§a. Tapez §onull§r§a pour l''utiliser.' - dialog: - cleared: '§a{amount} messages supprimés.' - edited: '§aMessage "§7{msg}§a" modifié.' - help: - addSound: '§6addSound <id> <son> : §eAjouter un son sur un message.' - clear: '§6clear: §eSupprimer tous les messages.' - close: '§6close: §eValider les messages.' - edit: '§6edit <id> <message>: §eModifier un message.' - header: '§e§lBeautyQuests — §6Aide de l''éditeur de dialogues' - list: '§6list: §eVoir une liste des messages.' - nothing: '§6noSender <message> : §eAjouter un message exempt d''entité parlante.' - nothingInsert: '§6nothingInsert <id> <message> : §eInsérer un message sans préfixe.' - npc: '§6npc <message> : §aAjouter un message dit par le NPC.' - npcInsert: '§6npcInsert <id> <message> : §eInsérer un message dit par le NPC.' - npcName: '§6npcName [nom du NPC] : §eModifie (ou remet au nom par défaut) le nom personnalisé du NPC dans le dialogue' - player: '§6player <message> : §eAjouter un message dit par le joueur.' - playerInsert: '§6playerInsert <id> <message> : §eInsérer un message dit par le joueur.' - remove: '§6remove <id> : §eSupprimer un message.' - setTime: '§6setTime <id> <time>: §eModifie le temps (en ticks) avant que le message suivant ne se lance.' - skippable: '§6skippable [true|false] : §eDéfinir si le dialogue peut être ignoré ou non' - messageRemoved: '§aMessage "§7{msg}§a" supprimé.' - noSender: '§aMessage "§7{msg}§a" ajouté pour aucune entité parlante.' - npc: '§aMessage "§7{msg}§a" ajouté pour le NPC.' - npcName: - set: '§aNom du NPC personnalisé modifié pour §7{new_name}§a (avant: §7{old_name}§a)' - unset: '§aNom du NPC personnalisé réinitialisé à la valeur par défaut (était §7{old_name}§a)' - player: '§aMessage "§7{msg}§a" ajouté pour le joueur.' - skippable: - set: '§aStatut "ignorable" du dialogue modifié pour §7{new_state}§a (avant: §7{old_state}§a)' - unset: '§aStatut "ignorable" du dialogue remis à la valeur par défaut (était §7{old_state}§a)' - soundAdded: '§aSon "§7{sound}§a" ajouté pour le message "§7{msg}§a".' - syntaxRemove: '§cSyntaxe correcte : remove <id>' - timeRemoved: '§aLe temps a été supprimé du message {msg}.' - timeSet: '§aLe temps a été modifié pour le message {msg}: il est maintenant de {time} tick(s).' + typeBucketAmount: '§aÉcrivez la quantité de seaux à remplir :' + typeDamageAmount: 'Écrivez le nombre de dégâts que le joueur doit infliger :' + goToLocation: '§aAllez à l''emplacement souhaité pour l''étape.' + typeLocationRadius: '§aÉcrivez la distance requise à partir de cet endroit :' + typeGameTicks: '§aEcrivez la quantité de ticks requis :' + already: '§cVous êtes déjà dans un éditeur.' + stage: + location: + typeWorldPattern: '§aÉcrivez une expression régulière (regex) pour les noms de monde :' enter: - list: '§c⚠ §7Vous êtes entré dans un éditeur "liste". Utilisez "add" pour ajouter des lignes. Tapez "help" (sans slash) pour obtenir de l''aide. §e§lTapez "close" pour quitter l''éditeur.' - subtitle: '§6Entrez "/quests exitEditor" pour forcer la sortie.' title: '§6~ mode éditeur ~' - firework: - edited: Feu d'artifice de quête modifié ! - invalid: Cet objet n'est pas un feu d'artifice valide. - invalidHand: Vous devez tenir un feu d'artifice dans votre main principale. - removed: Feu d'artifice de quête supprimé ! - goToLocation: '§aAllez à l''emplacement souhaité pour l''étape.' - invalidColor: La couleur que vous avez saisie n'est pas valide. Elle doit être hexadécimale ou RVB. - invalidPattern: '§cRegex invalide: §4{input}§c.' - itemCreator: - invalidBlockType: '§cType de bloc invalide.' - invalidItemType: '§cType d''item invalide (il doit être un item et non un bloc).' - itemAmount: '§aÉcrivez le nombre d''item(s) :' - itemLore: '§aModifiez la description de l''item. (Tapez "help" pour obtenir de l''aide.)' - itemName: '§aEntrez le nom de l''item :' - itemType: '§aEntrez le nom du type d''item voulu :' - unknownBlockType: '§cType de bloc inconnu.' - unknownItemType: '§cType d''item inconnu.' - mythicmobs: - disabled: '§cMythicMob est désactivé.' - isntMythicMob: '§cCe Mythic Mob n''existe pas.' - list: '§aListe de tous les MythicMobs :' - noSuchElement: '§cIl n''y a pas d’élément correspondant. Les éléments permis sont : §e{available_elements}' + subtitle: '§6Entrez "/quests exitEditor" pour forcer la sortie.' + list: '§c⚠ §7Vous êtes entré dans un éditeur "liste". Utilisez "add" pour ajouter des lignes. Tapez "help" (sans slash) pour obtenir de l''aide. §e§lTapez "close" pour quitter l''éditeur.' + chat: '§6Vous êtes actuellement dans le mode éditeur. Entrez "/quests exitEditor" pour forcer la sortie de ce mode (peu recommandé, préférez l''usage de mots-clés tels que "close" ou "cancel" pour revenir à l''inventaire précédent).' npc: - choseStarter: '§aSélectionnez le NPC qui commence la quête.' enter: '§aCliquez sur un NPC, ou tapez "cancel" pour annuler.' + choseStarter: '§aSélectionnez le NPC qui commence la quête.' notStarter: '§cCe NPC n''est pas lanceur de quête.' - pool: - hologramText: Écrivez le texte personnalisé de l'hologramme pour ce groupe (ou "null" si vous voulez le texte par défaut). - maxQuests: Écrivez le nombre maximum de quêtes lancées dans ce groupe. - questsPerLaunch: Écrivez le nombre de quêtes données lorsque les joueurs cliquent sur le NPC. - timeMsg: 'Écrivez le temps avant que les joueurs puissent prendre une nouvelle quête. (Unité par défaut: jours)' - scoreboardObjectiveNotFound: '§cObjectif de scoreboard inconnu.' - selectWantedBlock: '§aCliquez avec le bâton sur le bloc voulu pour l''étape.' - stage: - location: - typeWorldPattern: '§aÉcrivez une expression régulière (regex) pour les noms de monde :' text: argNotSupported: '§cArgument {arg} non supporté.' - chooseJobRequired: '§aEntrez le nom du le métier voulu :' chooseLvlRequired: '§aEntrez la quantité de niveaux requise :' - chooseMoneyRequired: '§aEntrez la quantité de monnaie nécessaire :' - chooseObjectiveRequired: '§aÉcrivez le nom de l''objectif.' - chooseObjectiveTargetScore: '§aIndiquez le score visé pour cet objectif.' - choosePermissionMessage: '§aVous pouvez choisir un message de refus si le joueur n''a pas la permission requise. (pour passer cette étape, entrez "null" et aucun message ne sera envoyé)' + chooseJobRequired: '§aEntrez le nom du le métier voulu :' choosePermissionRequired: '§aEntrez les permissions requises pour commencer la quête :' + choosePermissionMessage: '§aVous pouvez choisir un message de refus si le joueur n''a pas la permission requise. (pour passer cette étape, entrez "null" et aucun message ne sera envoyé)' choosePlaceholderRequired: identifier: '§aEntrez le nom du placeholder requis, sans les pourcentages de début et de fin :' value: '§aEntrez la valeur requise pour le placeholder §e%§e{placeholder}§e%§a :' - chooseRegionRequired: '§aÉcrivez le nom de la région requise (vous devez être dans le même monde).' chooseSkillRequired: '§aEntrez le nom de la compétence requise :' + chooseMoneyRequired: '§aEntrez la quantité de monnaie nécessaire :' reward: - money: '§aEntrez la quantité de monnaie gagnée :' permissionName: '§aIndiquez le nom de la permission.' permissionWorld: '§aIndiquez le monde dans lequel la permission sera mise à jour, ou "null" si vous voulez que ça le soit partout.' + money: '§aEntrez la quantité de monnaie gagnée :' + wait: '§aÉcrivez le nombre de ticks à attendre : (1 seconde = 20 ticks)' random: - max: '§aÉcrivez le nombre maximum de récompenses données au joueur (inclus).' min: '§aÉcrivez le nombre minimum de récompenses données au joueur (inclus).' - wait: '§aÉcrivez le nombre de ticks à attendre : (1 seconde = 20 ticks)' - textList: - added: '§aTexte "§7{msg}§a" ajouté.' + max: '§aÉcrivez le nombre maximum de récompenses données au joueur (inclus).' + chooseObjectiveRequired: '§aÉcrivez le nom de l''objectif.' + chooseObjectiveTargetScore: '§aIndiquez le score visé pour cet objectif.' + chooseRegionRequired: '§aÉcrivez le nom de la région requise (vous devez être dans le même monde).' + chooseRequirementCustomReason: 'Écrivez la raison personnalisée de cette condition. Si le joueur ne remplit pas les conditions requises mais essaye de commencer la quête quand même, ce message apparaîtra dans le chat.' + chooseRequirementCustomDescription: 'Écrivez la description personnalisée pour cette condition. Elle apparaîtra dans la description de la quête dans le menu.' + chooseRewardCustomDescription: 'Écrivez la description personnalisée de cette récompense. Elle apparaîtra dans la description de la quête dans le menu.' + selectWantedBlock: '§aCliquez avec le bâton sur le bloc voulu pour l''étape.' + itemCreator: + itemType: '§aEntrez le nom du type d''item voulu :' + itemAmount: '§aÉcrivez le nombre d''item(s) :' + itemName: '§aEntrez le nom de l''item :' + itemLore: '§aModifiez la description de l''item. (Tapez "help" pour obtenir de l''aide.)' + unknownItemType: '§cType d''item inconnu.' + invalidItemType: '§cType d''item invalide (il doit être un item et non un bloc).' + unknownBlockType: '§cType de bloc inconnu.' + invalidBlockType: '§cType de bloc invalide.' + dialog: + syntaxMessage: '§cSyntaxe correcte : {command} <message>' + syntaxRemove: '§cSyntaxe correcte : remove <id>' + player: '§aMessage "§7{msg}§a" ajouté pour le joueur.' + npc: '§aMessage "§7{msg}§a" ajouté pour le NPC.' + noSender: '§aMessage "§7{msg}§a" ajouté pour aucune entité parlante.' + messageRemoved: '§aMessage "§7{msg}§a" supprimé.' + edited: '§aMessage "§7{msg}§a" modifié.' + soundAdded: '§aSon "§7{sound}§a" ajouté pour le message "§7{msg}§a".' + cleared: '§a{amount} messages supprimés.' help: - add: '§6add <message> : §eAjouter un texte.' - close: '§6close: §eValider les textes.' - header: '§6§lBeautyQuests — Aide de l''éditeur de liste' - list: '§6list: §eVoir tout les textes.' - remove: '§6remove <id> : §eSupprimer un texte.' - removed: '§aTexte "§7{msg}§a" supprimé.' - syntax: '§cSyntaxe correcte : ' - title: - fadeIn: Écrivez la durée du fondu d'entrée, en ticks (20 ticks = 1 seconde). - fadeOut: Écrivez la durée du fondu de sortie, en ticks (20 ticks = 1 seconde). - stay: Écrivez la durée où le titre reste affiché, en ticks (20 ticks = 1 seconde). - subtitle: Écrivez le sous-titre (ou "null" si vous n'en voulez pas). - title: Écrivez le titre (ou "null" si vous n'en voulez pas). - typeBucketAmount: '§aÉcrivez la quantité de seaux à remplir :' - typeDamageAmount: 'Écrivez le nombre de dégâts que le joueur doit infliger :' - typeGameTicks: '§aEcrivez la quantité de ticks requis :' - typeLocationRadius: '§aÉcrivez la distance requise à partir de cet endroit :' - errorOccurred: '§cUne erreur est survenue, prévenez un administrateur ! §4§lCode d''erreur : {error}' - experience: - edited: '§aVous avez changé le gain d''expérience de {old_xp_amount} à {xp_amount} points.' - indexOutOfBounds: '§cLe numéro {index} est hors des limites ! Il doit se trouver entre {min} et {max}.' - invalidBlockData: '§cLa blockdata {block_data} est invalide ou incompatible avec le bloc {block_material}.' - invalidBlockTag: '§cTag de bloc {block_tag} indisponible.' - inventoryFull: '§cVotre inventaire est plein, l''item a été jeté au sol.' - moveToTeleportPoint: '§aAllez au lieu de téléportation désiré.' - npcDoesntExist: '§cLa quête avec l''id {npc_id} n''existe pas.' - number: - invalid: '§c{input} n''est pas un nombre valide.' - negative: '§cTu dois entrer un nombre positif !' - notInBounds: '§cLa valeur doit être comprise entre {min} et {max}.' - zero: '§cTu dois entrer un nombre autre que 0 !' - pools: - allCompleted: '§7Vous avez terminé toutes les quêtes !' - maxQuests: '§cVous ne pouvez pas avoir plus de {pool_max_quests} quête(s) simultanément...' - noAvailable: '§7Il n''y a plus de quête disponible...' - noTime: '§cVous devez attendre {time_left} avant de faire une autre quête.' - quest: - alreadyStarted: '§cVous avez déjà commencé cette quête !' - cancelling: '§cAnnulation du processus de création de quête.' - createCancelled: '§cLa création (ou l''édition) de votre quête a été annulée par un plugin tiers.' - created: '§aFélicitations ! Vous avez créé la quête §e{quest}§a, qui comporte {quest_branches} branche(s) !' - editCancelling: '§cAnnulation du processus d''édition de la quête.' - edited: '§aFélicitations ! Vous avez modifié la quête §e{quest}§a, qui comporte désormais {quest_branches} branche(s) !' - finished: - base: '§aFélicitations ! Vous avez complété la quête §e{quest_name}§r§a !' - obtain: '§aVous remportez {rewards} !' - invalidID: '§cLa quête avec l''id {quest_id} n''existe pas.' - invalidPoolID: '§cLe groupe {pool_id} n''existe pas.' - notStarted: '§cVous ne faites pas cette quête en ce moment.' - started: '§aVous commencez la quête §r§e{quest_name}§o§6 !' - questItem: - craft: '§cVous ne pouvez pas utiliser un objet de quête pour crafter !' - drop: '§cVous ne pouvez pas jeter un objet de quête !' - eat: '§cVous ne pouvez pas manger un objet de quête !' - quests: - checkpoint: '§7Checkpoint de quête atteint !' - failed: '§cVous avez échoué à la quête {quest_name}...' - maxLaunched: '§cVous ne pouvez pas avoir plus de {quests_max_amount} quête(s) simultanément...' - updated: '§7Quête §e{quest_name}§7 actualisée.' - regionDoesntExists: '§cCette région n''existe pas. (Vous devez être dans le même monde.)' - requirements: - combatLevel: '§cVotre niveau de combat doit être {long_level}!' - job: '§cVotre niveau pour le métier §e{job_name}§c doit être {long_level}!' - level: '§cVotre niveau doit être {long_level}!' - money: '§cVous devez avoir {money} !' - quest: '§cVous devez avoir terminé la quête §e{quest_name}§c !' - skill: '§cVotre niveau pour la compétence §e{skill_name}§c doit être {long_level}!' - waitTime: '§cVous devez encore attendre {time_left} avant de pouvoir recommencer cette quête !' - restartServer: '§7Redémarrez votre serveur pour voir les modifications.' - selectNPCToKill: '§aSélectionnez le NPC à tuer.' - stageMobs: - listMobs: '§aIl faut que vous tuiez {mobs}.' - typeCancel: '§aTapez "cancel" pour revenir à l''ancien texte.' - versionRequired: 'Version requise : §l{version}' - writeChatMessage: '§aÉcrivez le message requis (rajoutez "{SLASH}" au début pour en faire une commande.)' - writeCommand: '§aÉcrivez la commande : (n''écrivez pas le "/" ; le placeholder "{PLAYER}" est pris en charge. Il sera remplacée par le nom du joueur exécuteur.)' + header: '§e§lBeautyQuests — §6Aide de l''éditeur de dialogues' + npc: '§6npc <message> : §aAjouter un message dit par le NPC.' + player: '§6player <message> : §eAjouter un message dit par le joueur.' + nothing: '§6noSender <message> : §eAjouter un message exempt d''entité parlante.' + remove: '§6remove <id> : §eSupprimer un message.' + list: '§6list: §eVoir une liste des messages.' + npcInsert: '§6npcInsert <id> <message> : §eInsérer un message dit par le NPC.' + playerInsert: '§6playerInsert <id> <message> : §eInsérer un message dit par le joueur.' + nothingInsert: '§6nothingInsert <id> <message> : §eInsérer un message sans préfixe.' + edit: '§6edit <id> <message>: §eModifier un message.' + addSound: '§6addSound <id> <son> : §eAjouter un son sur un message.' + clear: '§6clear: §eSupprimer tous les messages.' + close: '§6close: §eValider les messages.' + setTime: '§6setTime <id> <time>: §eModifie le temps (en ticks) avant que le message suivant ne se lance.' + npcName: '§6npcName [nom du NPC] : §eModifie (ou remet au nom par défaut) le nom personnalisé du NPC dans le dialogue' + skippable: '§6skippable [true|false] : §eDéfinir si le dialogue peut être ignoré ou non' + timeSet: '§aLe temps a été modifié pour le message {msg}: il est maintenant de {time} tick(s).' + timeRemoved: '§aLe temps a été supprimé du message {msg}.' + npcName: + set: '§aNom du NPC personnalisé modifié pour §7{new_name}§a (avant: §7{old_name}§a)' + unset: '§aNom du NPC personnalisé réinitialisé à la valeur par défaut (était §7{old_name}§a)' + skippable: + set: '§aStatut "ignorable" du dialogue modifié pour §7{new_state}§a (avant: §7{old_state}§a)' + unset: '§aStatut "ignorable" du dialogue remis à la valeur par défaut (était §7{old_state}§a)' + mythicmobs: + list: '§aListe de tous les MythicMobs :' + isntMythicMob: '§cCe Mythic Mob n''existe pas.' + disabled: '§cMythicMob est désactivé.' + advancedSpawnersMob: 'Écrivez le nom du mob de AdvancedSpawners à tuer :' + textList: + syntax: '§cSyntaxe correcte : ' + added: '§aTexte "§7{msg}§a" ajouté.' + removed: '§aTexte "§7{msg}§a" supprimé.' + help: + header: '§6§lBeautyQuests — Aide de l''éditeur de liste' + add: '§6add <message> : §eAjouter un texte.' + remove: '§6remove <id> : §eSupprimer un texte.' + list: '§6list: §eVoir tout les textes.' + close: '§6close: §eValider les textes.' + availableElements: 'Éléments disponibles : §e{available_elements}' + noSuchElement: '§cIl n''y a pas d’élément correspondant. Les éléments permis sont : §e{available_elements}' + invalidPattern: '§cRegex invalide: §4{input}§c.' + comparisonTypeDefault: '§aChoissez le type de comparaison que vous voulez parmi {available}. La comparaison par défaut est: §e§l{default}§r§a. Tapez §onull§r§a pour l''utiliser.' + scoreboardObjectiveNotFound: '§cObjectif de scoreboard inconnu.' + pool: + hologramText: 'Écrivez le texte personnalisé de l''hologramme pour ce groupe (ou "null" si vous voulez le texte par défaut).' + maxQuests: 'Écrivez le nombre maximum de quêtes lancées dans ce groupe.' + questsPerLaunch: 'Écrivez le nombre de quêtes données lorsque les joueurs cliquent sur le NPC.' + timeMsg: 'Écrivez le temps avant que les joueurs puissent prendre une nouvelle quête. (Unité par défaut: jours)' + title: + title: 'Écrivez le titre (ou "null" si vous n''en voulez pas).' + subtitle: 'Écrivez le sous-titre (ou "null" si vous n''en voulez pas).' + fadeIn: 'Écrivez la durée du fondu d''entrée, en ticks (20 ticks = 1 seconde).' + stay: 'Écrivez la durée où le titre reste affiché, en ticks (20 ticks = 1 seconde).' + fadeOut: 'Écrivez la durée du fondu de sortie, en ticks (20 ticks = 1 seconde).' + colorNamed: 'Saisissez le nom de la couleur :' + color: 'Entrez une couleur au format hexadécimal (#XXXXX) ou RVB (ROUGE VERT BLEU).' + invalidColor: 'La couleur que vous avez saisie n''est pas valide. Elle doit être hexadécimale ou RVB.' + firework: + invalid: 'Cet objet n''est pas un feu d''artifice valide.' + invalidHand: 'Vous devez tenir un feu d''artifice dans votre main principale.' + edited: 'Feu d''artifice de quête modifié !' + removed: 'Feu d''artifice de quête supprimé !' writeCommandDelay: '§aIndiquez le délai de commande désiré, en ticks.' - writeConfirmMessage: '§aÉcrivez le message de confirmation affiché lorsqu''un joueur est sur le point de démarrer la quête : (Tapez "null" si vous voulez le message par défaut).' - writeDescriptionText: '§aEcrivez le texte qui décrira le but de l''étape :' - writeEndMsg: '§aÉcrivez le message qui sera envoyé à la fin de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas. Vous pouvez utiliser "{rewards}" qui sera remplacé par les récompenses obtenues.' - writeEndSound: '§aÉcrivez le nom du son qui sera joué au joueur à la fin de la quête, "null" si vous voulez le son par défaut ou "none" si vous n''en voulez pas :' - writeHologramText: '§aEcrivez le texte de l''hologramme. (tapez "none" si vous ne voulez pas d''hologramme, et "null" si vous voulez le texte par défaut.)' - writeMessage: '§aÉcrivez le message qui sera envoyé au joueur' - writeMobAmount: '§aEcrivez le nombre de mobs à tuer :' - writeMobName: '§aÉcrivez le nom personnalisé du mob à tuer :' - writeNPCText: '§aÉcrivez le dialogue qui sera dit au joueur par le NPC : (Tapez "help" pour recevoir de l''aide.)' - writeNpcName: '§aEcrivez le nom du NPC :' - writeNpcSkinName: '§aEcrivez le nom du skin du NPC :' - writeQuestDescription: '§aÉcrivez la description de la quête, affichée dans l''interface des quêtes du joueur.' - writeQuestMaterial: '§aIndiquez le type d''item pour la quête.' - writeQuestName: '§aEcrivez le nom de votre quête :' - writeQuestTimer: '§aRenseignez le temps nécessaire (en minutes) avant de pouvoir refaire la quête. (Tapez "null" si vous voulez le temps par défaut)' - writeRegionName: '§aEcrivez le nom de la région voulue pour l''étape :' - writeStageText: '§aEcrivez le texte qui sera transmis au joueur au début de l''étape :' - writeStartMessage: '§aÉcrivez le message qui sera envoyé au début de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas :' - writeXPGain: '§aÉcrivez le nombre de points d’expérience que le joueur va remporter. (Ancien gain : {xp_amount})' +advancement: + finished: Terminée + notStarted: Pas commencée +inv: + validate: '§b§lValider' + cancel: '§c§lAnnuler' + search: '§e§lRechercher' + addObject: '§aAjouter un objet' + confirm: + name: Êtes-vous sûr ? + 'yes': '§aConfirmer' + 'no': '§cAnnuler' + create: + stageCreate: '§aCréer une nouvelle étape' + stageRemove: '§cSupprimer cette étape' + stageUp: Monter + stageDown: Descendre + stageType: '§7Type d''étape: §e{stage_type}' + cantFinish: '§7Vous devez créer au moins une étape avant de terminer la création de la quête !' + findNPC: '§aTrouver un NPC' + bringBack: '§aRapporter des objets' + findRegion: '§aTrouver une région' + killMobs: '§aTuer des mobs' + mineBlocks: '§aCasser des blocs' + placeBlocks: '§aPoser des blocs' + talkChat: '§aÉcrire dans le chat' + interact: '§aCliquer sur un certain type de bloc' + interactLocation: '§aCliquer sur le bloc à un emplacement' + fish: '§aPêcher' + melt: '§6Cuire des items' + enchant: '§dEnchanter des items' + craft: '§aFabriquer un objet' + bucket: '§aRemplir des seaux' + location: '§aAller à un endroit' + playTime: '§eTemps de jeu' + breedAnimals: '§aFaire reproduire des animaux' + tameAnimals: '§aApprivoiser des animaux' + death: '§cMourir' + dealDamage: '§cInfliger des dégâts à des mobs' + eatDrink: '§aManger ou boire de la nourriture ou des potions' + NPCText: '§eModifier le dialogue' + NPCSelect: '§eChoisir ou créer un NPC' + hideClues: Cacher les particules et les hologrammes + editMobsKill: '§eModifier les mobs à tuer' + mobsKillFromAFar: Doit être tué de loin + editBlocksMine: '§eModifier les blocs à casser' + preventBlockPlace: Empêcher les joueurs de casser leurs propres blocs + editBlocksPlace: '§eModifier les blocs à poser' + editMessageType: '§eModifier le message à écrire' + cancelMessage: Annuler l'envoi + ignoreCase: Ignorer la casse du message + replacePlaceholders: Remplacer {PLAYER} et les placeholders de PAPI + selectItems: '§eChoisir les items nécessaires' + selectItemsMessage: '§eModifier le message de demande' + selectItemsComparisons: '§eSélectionnez les comparaisons d''items (AVANCÉ)' + selectRegion: '§7Choisir la région' + toggleRegionExit: À la sortie + stageStartMsg: '§eModifier le message de départ' + selectBlockLocation: '§eSélectionner la position du bloc' + selectBlockMaterial: '§eSélectionner le type de block' + leftClick: Clic gauche nécessaire + editFishes: '§eModifier les poissons nécessaires' + editItemsToMelt: '§eModifier les items à cuire' + editItemsToEnchant: '§eModifier les items à enchanter' + editItem: '§eEditer l''objet à fabriquer' + editBucketType: '§eModifier le type de seau à remplir' + editBucketAmount: '§eModifier la quantité de seaux à remplir' + editLocation: '§eModifier l''endroit' + editRadius: '§eModifier la distance à partir de l''endroit' + currentRadius: '§eDistance actuelle : §6{radius}' + changeTicksRequired: '§eChanger la quantité de ticks requis' + changeEntityType: '§eSélectionner un type d''entité' + stage: + location: + worldPattern: '§aModifier le motif de nom de monde §d(AVANCÉ)' + worldPatternLore: 'Si vous voulez que l''étape soit terminée pour un monde correspondant à un motif spécifique, entrez ici une regex (expression régulière).' + death: + causes: '§aDéfinir les causes de la mort §d(AVANCED)' + anyCause: Toute cause de mort + setCauses: '{causes_amount} cause(s) de mort' + dealDamage: + damage: '§eDégâts à infliger' + targetMobs: '§cMobs à heurter' + eatDrink: + items: '§eModifier les objets à manger ou à boire' + stages: + name: Créer les étapes + nextPage: '§ePage suivante' + laterPage: '§ePage précédente' + endingItem: '§eRécompenses de fin' + descriptionTextItem: '§eModifier le texte de description' + regularPage: '§aÉtapes simples' + branchesPage: '§dÉtapes d''embranchement' + previousBranch: '§eRetourner à la branche précédente' + newBranch: '§eAller à la nouvelle branche' + validationRequirements: '§eConditions de validation' + validationRequirementsLore: Toutes les conditions doivent s'appliquer au joueur qui tente de terminer l'étape. Sinon, l'étape ne peut pas être terminée. + details: + hologramLaunch: '§eModifier l''item de l''hologramme "lancement"' + hologramLaunchLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur peut commencer la quête. + hologramLaunchNo: '§eModifier l''item de l''hologramme "lancement impossible"' + hologramLaunchNoLore: Hologramme affiché au-dessus de la tête du NPC de démarrage lorsque le joueur ne peut PAS démarrer la quête. + customConfirmMessage: '§eModifier le message de confirmation de quête' + customConfirmMessageLore: Message affiché dans l'interface de confirmation lorsqu'un joueur est sur le point de commencer la quête. + customDescription: '§eModifier la description de la quête' + customDescriptionLore: Description affichée sous le nom de la quête dans les interfaces graphiques. + name: Derniers détails de la quête + multipleTime: + itemName: Activer/désactiver la répétition + itemLore: La quête peut-elle être faite plusieurs fois ? + cancellable: Annulable par le joueur + cancellableLore: Permet au joueur d'annuler la quête par l'intermédiaire de son menu de Quêtes. + startableFromGUI: Démarrable depuis le GUI + startableFromGUILore: Permet au joueur de commencer la quête depuis son menu de Quêtes. + scoreboardItem: Activer le scoreboard + scoreboardItemLore: Si désactivée, la quête ne sera pas affichée dans le scoreboard. + hideNoRequirementsItem: Masquer lorsque les conditions ne sont pas remplies + hideNoRequirementsItemLore: Si activé, la quête ne sera pas affichée dans le menu des quêtes lorsque les conditions ne sont pas remplies. + bypassLimit: Ne pas compter la limite de quêtes + bypassLimitLore: Si activé, la quête sera démarrée même si le joueur a atteint son nombre maximum de quêtes en cours. + auto: Démarrer automatiquement à la première connexion + autoLore: Si activé, la quête sera lancée automatiquement lorsque le joueur rejoindra le serveur pour la première fois. + questName: '§a§lModifier le nom de la quête' + questNameLore: Un nom doit être défini pour terminer la création de quête. + setItemsRewards: '§eModifier les gains d''item' + removeItemsReward: '§eRetirer des objets de l''inventaire' + setXPRewards: '§eModifier les gains d''expérience' + setCheckpointReward: '§eModifier les récompenses du checkpoints' + setRewardStopQuest: '§cArrêter la quête' + setRewardsWithRequirements: '§eRécompenses avec requirements' + setRewardsRandom: '§dRécompenses aléatoires' + setPermReward: '§eModifier les permissions' + setMoneyReward: '§eModifier le gain de monnaie' + setWaitReward: '§eModifier l''attente' + setTitleReward: '§eModifier la récompense /title' + selectStarterNPC: '§e§lSélectionner le NPC de départ' + selectStarterNPCLore: Cliquer sur le PNJ sélectionné commencera la quête. + selectStarterNPCPool: '§c⚠ Un groupe de quêtes est sélectionné' + createQuestName: '§lCréer la quête' + createQuestLore: Vous devez définir le nom de la quête. + editQuestName: '§lModifier la quête' + endMessage: '§eModifier le message de fin' + endMessageLore: Message qui sera envoyé au joueur à la fin de la quête. + endSound: '§eModifier le son de fin' + endSoundLore: Son qui sera joué à la fin de la quête. + startMessage: '§eModifier le message de départ' + startMessageLore: Message qui sera envoyé au joueur au début de la quête. + startDialog: '§eModifier le dialogue de début' + startDialogLore: Dialogue qui sera joué avant le début de la quête lorsque les joueurs cliquent sur le NPC de démarrage. + editRequirements: '§eModifier les nécessités' + editRequirementsLore: Toutes les conditions doivent s’appliquer au joueur avant de pouvoir commencer la quête. + startRewards: '§6Récompenses de début' + startRewardsLore: Actions effectuées au démarrage de la quête. + cancelRewards: '§cActions d''annulation' + cancelRewardsLore: Actions effectuées lorsque les joueurs annulent cette quête. + hologramText: '§eTexte de l''hologramme' + hologramTextLore: Texte affiché sur l'hologramme au-dessus de la tête du NPC de démarrage. + timer: '§bTimer de redémarrage' + timerLore: Temps avant que le joueur puisse recommencer la quête. + requirements: '{amount} exigence(s)' + rewards: '{amount} récompense(s)' + actions: '{amount} action(s)' + rewardsLore: Actions effectuées à la fin de la quête. + customMaterial: '§eModifiez l''item de la quête' + customMaterialLore: Item représentant cette quête dans le menu de Quêtes. + failOnDeath: Échec lors de la mort + failOnDeathLore: La quête sera-t-elle annulée à la mort du joueur ? + questPool: '§eGroupe de quêtes' + questPoolLore: Attacher cette quête à un groupe de quêtes + firework: '§dFeu d''artifice de fin' + fireworkLore: Feu d'artifice lancé lorsque le joueur termine la quête + fireworkLoreDrop: Déposez votre feu d'artifice personnalisé ici + visibility: '§bVisibilité de la quête' + visibilityLore: Choisir dans quels onglets du menu seront affichés la quête et si la quête est visible sur les cartes dynamiques. + keepDatas: Conserver les données des joueurs + keepDatasLore: |- + Forcer le plugin à préserver les données des joueurs, même si les étapes ont été modifiées. §c§lAVERTISSEMENT §c- activer cette option peut endommager les données de vos joueurs. + loreReset: '§e§lL''avancement de tous les joueurs sera réinitialisé' + optionValue: '§8Valeur : §7{value}' + defaultValue: '§8(valeur par défaut)' + requiredParameter: '§7Paramètre requis' + itemsSelect: + name: Modifier les items + none: |- + §aDéplacez un item ici ou + §acliquez pour ouvrir l'éditeur d'item + itemSelect: + name: Choisissez un objet + npcCreate: + name: Créer le NPC + setName: '§eModifier le nom du NPC' + setSkin: '§eModifier le skin du NPC' + setType: '§eModifier le type du NPC' + move: + itemName: '§eSe déplacer' + itemLore: '§aModifier la position du NPC.' + moveItem: '§a§lValider l''endroit' + npcSelect: + name: Sélectionner ou créer ? + selectStageNPC: '§eSélectionner un NPC existant' + createStageNPC: '§eCréer le NPC' + entityType: + name: Choisir le type d'entité + chooseQuest: + name: Quelle quête ? + menu: '§aMenu des Quêtes' + menuLore: Vous ouvre votre menu de Quêtes. + mobs: + name: Choisir les mobs + none: '§aCliquer pour ajouter un mob.' + editAmount: Modifier la quantité + editMobName: Modifier le nom du mob + setLevel: Modifier le niveau minimum + mobSelect: + name: Choisir le type de monstre + bukkitEntityType: '§eSélectionner un type de mob' + mythicMob: '§6Sélectionner un Mythic Mob' + epicBoss: '§6Sélectionner un Epic Boss' + boss: '§6Choisir un Boss' + advancedSpawners: '§6Sélectionnez un mob d''AdvancedSpawners' + stageEnding: + locationTeleport: '§eModifier le point de téléportation' + command: '§eModifier la commande exécutée' + requirements: + name: Nécessités + setReason: Définir une raison personnalisée + reason: '§8Raison personnalisée : §7{reason}' + rewards: + name: Récompenses + commands: 'Commandes : {amount}' + random: + rewards: Modifier les récompenses + minMax: Modifier les quantités min/max + checkpointActions: + name: Actions du checkpoint + cancelActions: + name: Actions d'annulation + rewardsWithRequirements: + name: Récompenses avec requirements + listAllQuests: + name: Quêtes + listPlayerQuests: + name: 'Quêtes de {player_name}' + listQuests: + notStarted: Quêtes non commencées + finished: Quêtes terminées + inProgress: Quêtes en cours + loreDialogsHistoryClick: '§7Voir les dialogues' + loreCancelClick: '§cAnnuler la quête' + loreStart: '§a§oCliquez pour commencer la quête.' + loreStartUnavailable: '§c§oVous ne remplissez pas les conditions pour commencer la quête.' + timeToWaitRedo: '§7§oVous pouvez refaire cette quête dans {time_left}...' + canRedo: '§e§oVous pouvez refaire cette quête !' + timesFinished: '§eTerminé §6{times_finished} x§e.' + format: + normal: '§6§l§o{quest_name}' + withId: '§6§l§o{quest_name}§r §e#{quest_id}' + itemCreator: + name: Créateur d'item + itemType: '§bType d''item' + itemFlags: Flags d'item + itemName: '§bNom de l''item' + itemLore: '§bDescription de l''item' + isQuestItem: '§bItem de quête :' + command: + name: Commande + value: '§eCommande' + console: Console + parse: Remplacer les placeholders + delay: '§bDélai' + chooseAccount: + name: Quel compte ? + listBook: + questName: Nom + questStarter: NPC + questRewards: Récompenses + questMultiple: Plusieurs fois + requirements: Exigences + questStages: Etapes + noQuests: Aucune quête n'a été préalablement créée. + commandsList: + name: Liste des commandes + value: '§eCommande : {command_label}' + console: '§eConsole : {command_console}' + block: + name: Choisir un bloc + material: '§eType de bloc : {block_type}' + materialNotItemLore: 'Le bloc choisi ne peut pas être affiché comme un item. Il est toujours correctement sauvegardé comme {block_material}.' + blockName: '§bNom de bloc personnalisé' + blockData: '§dBlockdata (avancé)' + blockTag: '§dTag (avancé)' + blockTagLore: 'Choisissez un tag qui décrit une liste de blocs possibles. Les tags peuvent être personnalisés en utilisant des datapacks. Vous pouvez trouver une liste des tags sur le Minecraft Wiki.' + blocksList: + name: Sélectionner des blocs + addBlock: '§aCliquez pour ajouter un block.' + blockAction: + name: Sélectionner l'action + location: '§eSélectionner un emplacement précis' + material: '§eSélectionner un type de bloc' + buckets: + name: Type de seau + permission: + name: Choisir la permission + perm: '§aPermission' + world: '§aMonde' + worldGlobal: '§b§lGlobal' + remove: Supprimer la permission + removeLore: '§7La permission sera retirée\n§7au lieu d''être donnée.' + permissionList: + name: Liste des permissions + removed: '§eRetiré : §6{permission_removed}' + world: '§eMonde : §6{permission_world}' + classesRequired.name: Classes requises + classesList.name: Liste des classes + factionsRequired.name: Factions requises + factionsList.name: Liste des factions + poolsManage: + name: Groupe de quêtes + itemName: '§aGroupe {pool}' + poolNPC: '§8NPC : §7{pool_npc_id}' + poolMaxQuests: '§8Nombre maximum de quêtes : §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Quêtes données par lancement : §7{pool_quests_per_launch}' + poolRedo: '§8Peut refaire les quêtes : §7{pool_redo}' + poolTime: '§8Temps entre les quêtes : §7{pool_time}' + poolHologram: '§8Hologramme : §7{pool_hologram}' + poolAvoidDuplicates: '§8Éviter les doublons : §7{pool_duplicates}' + poolQuestsList: '§7{pool_quests_amount} §8quête(s) : §7{pool_quests}' + create: '§aCréer un groupe de quêtes' + edit: '§e> §6§oModifier le groupe de quêtes... §e<' + choose: '§e> §6§oChoisir ce groupe §e<' + poolCreation: + name: Création du groupe de quêtes + hologramText: '§eHologramme personnalisé du groupe' + maxQuests: '§aNombre maximum de quêtes' + questsPerLaunch: '§aQuêtes commencées par lancement' + time: '§bDéfinir le temps entre les quêtes' + redoAllowed: Est-il recommençable ? + avoidDuplicates: Éviter les doublons + avoidDuplicatesLore: '§8> §7Essaye d''éviter de faire\n la même quête encore et encore' + requirements: '§bExigences pour démarrer une quête' + poolsList.name: Groupe de quêtes + itemComparisons: + name: Comparaisons d'item + bukkit: Comparaison native de Bukkit + bukkitLore: "Utilise le système de comparaison d'items par défaut de Bukkit.\nCompare le type d'item, la durabilité, les tags nbt..." + customBukkit: Comparaison native de Bukkit - SANS NBT + customBukkitLore: "Utilise le système de comparaison d'items par défaut de Bukkit, mais efface les balises NBT.\nCompare le type d'item, la durabilité..." + material: Type d'item + materialLore: 'Compare le type d''item (ex. pierre, épée de fer...)' + itemName: Nom de l’objet + itemNameLore: Compare les noms des items + itemLore: Description de l'item + itemLoreLore: Compare les descriptions des items + enchants: Enchantements des items + enchantsLore: Compare les enchantements des items + repairCost: Coût de réparation + repairCostLore: Compare les coûts de réparation des armures et des épées + itemsAdder: ItemsAdder + itemsAdderLore: Compare les IDs d'ItemsAdder + mmoItems: Objet de MMOItems + mmoItemsLore: Compare les types et IDs des MMOItems + editTitle: + name: Modifier le titre + title: '§6Titre' + subtitle: '§eSous-titre' + fadeIn: '§aDurée du fondu d''entrée' + stay: '§bDurée statique' + fadeOut: '§aDurée du fondu de sortie' + particleEffect: + name: Créer un effet de particules + shape: '§dForme de l''effet' + type: '§eType de particules' + color: '§bCouleur des particules' + particleList: + name: Liste des particules + colored: Particule colorée + damageCause: + name: Cause de dégât + damageCausesList: + name: Liste des causes de dégât + visibility: + name: Visibilité de la quête + notStarted: 'Onglet du menu "Non commencées"' + inProgress: 'Onglet du menu "En cours"' + finished: 'Onglet du menu "Terminées"' + maps: 'Cartes (dynmap, BlueMap...)' + equipmentSlots: + name: Emplacements d'équipement + questObjects: + setCustomDescription: 'Définir une description personnalisée' + description: '§8Description: §7{description}' scoreboard: - asyncEnd: '§ex' name: '§6§lQuêtes' noLaunched: '§cAucune quête en cours.' - noLaunchedDescription: '§c§oChargement' noLaunchedName: '§c§lChargement' + noLaunchedDescription: '§c§oChargement' + textBetwteenBranch: '§e ou' + asyncEnd: '§ex' stage: - breed: '§eFaites se reproduire §6{mobs}' - bucket: '§eRemplissez §6{buckets}' - chat: '§eEcrivez §6{text}' - craft: '§eFabriquez §6{items}' + region: '§eTrouve la région §6{region_id}' + npc: '§eParle au NPC §6{dialog_npc_name}' + items: '§eApporte des items à §6{dialog_npc_name} §e: {items}' + mobs: '§eTue {mobs}' + mine: '§eMine {blocks}' + placeBlocks: '§ePose {blocks}' + chat: '§eÉcris §6{text}§e dans le chat' + interact: '§eClique sur le bloc en §6{x} {y} {z}' + interactMaterial: '§eClique sur un bloc §6{block}' + fish: '§ePêche §6{items}' + melt: '§eCuis §6{items}' + enchant: '§eEnchante §6{items}' + craft: '§eFabrique §6{items}' + bucket: '§eRemplis §6{buckets}' + location: '§eVa en §6{target_x}§e, §6{target_y}§e, §6{target_z}§e dans §6{target_world}' + playTimeFormatted: '§eJoue §6{time_remaining_human}' + breed: '§eFais se reproduire §6{mobs}' + tame: '§eApprivoise §6{mobs}' + die: '§cMeurs' dealDamage: any: '§cInflige {damage_remaining} dégâts' mobs: '§cInflige {damage_remaining} dégâts à {target_mobs}' - die: '§cMourez' eatDrink: '§eConsomme §6{items}' - enchant: '§eEnchante §6{items}' - fish: '§ePêchez §6{items}' - interact: '§eCliquez sur le bloc à §6{x}' - interactMaterial: '§eCliquez sur un bloc §6{block}§e' - items: '§eRapporte des items à §6{dialog_npc_name} §e:' - location: '§eAllez à §6{target_x}§e, §6{target_y}§e, §6{target_z}§e dans §6{target_world}' - melt: '§eCuis §6{items}' - mobs: '§eTue {mobs}' - npc: '§eParle au NPC §6{dialog_npc_name}' - placeBlocks: '§ePose {blocks}' - playTimeFormatted: '§eJoue §6{time_remaining_human}' - region: '§eTrouve la région §6{region_id}' - tame: '§eApprivoisez §6{mobs}' - textBetwteenBranch: '§e ou' +indication: + startQuest: '§7Voulez-vous commencer la quête {quest_name} ?' + closeInventory: '§7Êtes-vous sûr de vouloir fermer l''interface graphique ?' + cancelQuest: '§7Êtes-vous sûr de vouloir annuler la quête {quest_name} ?' + removeQuest: '§7Êtes-vous sûr de vouloir supprimer la quête {quest} ?' + removePool: '§7Êtes-vous sûr de vouloir supprimer le groupe de quêtes {pool} ?' +description: + requirement: + title: '§8§lConditions :' + level: 'Niveau {short_level}' + jobLevel: 'Niveau {short_level} pour {job_name}' + combatLevel: 'Niveau de combat {short_level}' + skillLevel: 'Niveau {short_level} pour {skill_name}' + class: 'Classe {class_name}' + faction: 'Faction {faction_name}' + quest: 'Terminer la quête §e{quest_name}' + reward: + title: '§8§lRécompenses :' +misc: + format: + prefix: '§6<§e§lQuêtes§r§6> §r' + npcText: '§6[{message_id}/{message_count}] §e§l{npc_name_message} :§r§e {text}' + selfText: '§6[{message_id}/{message_count}] §e§l{player_name} :§r§e {text}' + time: + weeks: '{weeks_amount} semaines' + days: '{days_amount} jours' + hours: '{hours_amount} heures' + minutes: '{minutes_amount} minutes' + lessThanAMinute: 'moins d''une minute' + stageType: + region: Trouver une region + npc: Trouver un NPC + items: Rapporter des items + mobs: Tuer des mobs + mine: Casser des blocs + placeBlocks: Poser des blocs + chat: Parler dans le chat + interact: Intéragir avec un bloc + interactLocation: Interagir avec le bloc à un emplacement + Fish: Pêcher + Melt: Cuire des items + Enchant: Enchanter des items + Craft: Fabriquer un objet + Bucket: Remplir un seau + location: Trouver un endroit + playTime: Temps de jeu + breedAnimals: Faire reproduire des animaux + tameAnimals: Apprivoiser des animaux + die: Mourir + dealDamage: Infliger des dégâts + eatDrink: Manger ou boire + comparison: + equals: égal à {number} + different: différent de {number} + less: strictement inférieur à {number} + lessOrEquals: inférieur à {number} + greater: strictement supérieur à {number} + greaterOrEquals: supérieur à {number} + requirement: + logicalOr: '§dOU logique (requirements)' + skillAPILevel: '§bNiveau SkillAPI requis' + class: '§bClasse(s) requise(s)' + faction: '§bFaction(s) requise(s)' + jobLevel: '§bNiveau de job requis' + combatLevel: '§bNiveau de combat requis' + experienceLevel: '§bNiveau d''expérience requis' + permissions: '§3Permission(s) requise(s)' + scoreboard: '§dScore requis' + region: '§dRégion requise' + placeholder: '§bPlaceholder requis' + quest: '§aQuête requise' + mcMMOSkillLevel: '§dNiveau de compétence requis' + money: '§dMonnaie requise' + equipment: '§eÉquipement requis' + reward: + skillApiXp: Récompense d'XP SkillAPI + bucket: + water: Seau d'eau + lava: Seau de lave + milk: Seau de lait + snow: Seau de neige + click: + right: Clic droit + left: Clic gauche + shift-right: Maj + clic-droit + shift-left: Maj + clic-gauche + middle: Clic central + amounts: + items: '{items_amount} item(s)' + comparisons: '{comparisons_amount} comparaison(s)' + dialogLines: '{lines_amount} ligne(s)' + permissions: '{permissions_amount} permission(s)' + mobs: '{mobs_amount} mob(s)' + xp: '{xp_amount} point(s) d''expérience' + ticks: '{ticks} ticks' + location: |- + Position : {x} {y} {z} + Monde : {world} + questItemLore: '§e§oItem de Quête' + hologramText: '§8§lNPC de Quête' + poolHologramText: '§eNouvelle quête disponible !' + entityType: '§eType d''entité : {entity_type}' + entityTypeAny: '§eN''importe quelle entité' + enabled: Activé + disabled: Désactivé + unknown: inconnu + notSet: '§cnon défini' + removeRaw: Supprimer + reset: Réinitialiser + or: ou + amount: '§eQuantité : {amount}' + 'yes': 'Oui' + 'no': 'Non' + and: et From f2c249b6888a79457a926c5fa311f8b3aefdc32c Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 20 Sep 2023 15:56:42 +0200 Subject: [PATCH 53/95] :coffin: Clean old option code --- .../java/fr/skytasul/quests/api/options/QuestOption.java | 2 +- .../java/fr/skytasul/quests/options/OptionStarterNPC.java | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java index 9d9ec801..09aa9970 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/QuestOption.java @@ -119,7 +119,7 @@ public boolean shouldDisplay(@NotNull OptionSet options) { return true; } - public void onDependenciesUpdated(@NotNull OptionSet options/* , @NotNull ItemStack item TODO wtf */) {} + public void onDependenciesUpdated(@NotNull OptionSet options) {} public abstract @NotNull ItemStack getItemStack(@NotNull OptionSet options); diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java index 3fef152f..91444e30 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionStarterNPC.java @@ -57,12 +57,5 @@ public void click(QuestCreationGuiClickEvent event) { event.reopen(); }, true).open(event.getPlayer()); } - - @Override - public void onDependenciesUpdated(OptionSet options) { - super.onDependenciesUpdated(options); - // ItemUtils.lore(item, getLore(options)); - // TODO wtf ? - } } From d2d8015813b49c101f79dccca57e0606b05eaeb7 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 26 Sep 2023 11:34:21 +0200 Subject: [PATCH 54/95] :bug: Fixed some bugs related to branches --- .../stages/types/AbstractCountableStage.java | 35 ++++++++----------- .../quests/gui/creation/stages/StagesGUI.java | 2 +- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index 60663a18..3461285d 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -1,12 +1,7 @@ package fr.skytasul.quests.api.stages.types; -import java.util.AbstractMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Optional; -import java.util.UUID; import java.util.stream.Collectors; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -58,15 +53,16 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { return map; } - @SuppressWarnings("rawtypes") - public @UnknownNullability Map<@NotNull UUID, @NotNull Integer> getPlayerRemainings(@NotNull PlayerAccount acc, - boolean warnNull) { + public @NotNull Map<@NotNull UUID, @NotNull Integer> getPlayerRemainings(@NotNull PlayerAccount acc, boolean warnNull) { Map<?, Integer> remaining = getData(acc, "remaining"); - if (warnNull && remaining == null) - QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot retrieve stage datas for " + acc.getNameAndID() + " on " + super.toString()); + if (warnNull && remaining == null) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning( + "Cannot retrieve stage datas for " + acc.getNameAndID() + " on " + super.toString(), + "datas" + acc.getNameAndID() + controller.toString(), 10); + } if (remaining == null || remaining.isEmpty()) - return (Map) remaining; + return Map.of(); Object object = remaining.keySet().iterator().next(); if (object instanceof Integer) { @@ -95,11 +91,8 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { @Override public @NotNull Map<CountableObject<T>, Integer> getPlayerAmounts(@NotNull PlayerAccount account) { - Map<@NotNull UUID, @NotNull Integer> remainings = getPlayerRemainings(account, false); - if (remainings == null || remainings.isEmpty()) - return (Map) remainings; - - return remainings.entrySet().stream() + return getPlayerRemainings(account, true) + .entrySet().stream() .map(entry -> Map.entry(getObject(entry.getKey()).orElse(null), entry.getValue())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } @@ -153,7 +146,7 @@ public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull St /** * When called, this will test the player datas for the passed object. If found, the remaining * amount will be lowered. If no remaining items are found, the stage will complete. - * + * * @param acc player account * @param p player * @param object object of the event @@ -178,7 +171,7 @@ public boolean event(@NotNull Player p, @UnknownNullability Object object, int a playerAmounts.put(countableObject.getUUID(), playerAmount - amount); } else continue; - + if (playerAmounts.isEmpty()) { finishStage(p); return true; @@ -194,7 +187,7 @@ public boolean event(@NotNull Player p, @UnknownNullability Object object, int a protected boolean objectApplies(@NotNull T object, @UnknownNullability Object other) { return object.equals(other); } - + protected @NotNull T cloneObject(@NotNull T object) { return object; } @@ -206,7 +199,7 @@ protected boolean objectApplies(@NotNull T object, @UnknownNullability Object ot protected abstract @NotNull Object serialize(@NotNull T object); protected abstract @NotNull T deserialize(@NotNull Object object); - + @Override protected void serialize(@NotNull ConfigurationSection section) { ConfigurationSection objectsSection = section.createSection("objects"); diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index e781bb9f..7d235ad8 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -190,7 +190,7 @@ private void editBranch(QuestBranchImplementation branch){ } for (EndingStage stage : branch.getEndingStages()) { - getLine(branch.getEndingStageId(stage.getStage())).setStageEdition(stage.getStage(), stage.getBranch()); + getLine(15 + branch.getEndingStageId(stage.getStage())).setStageEdition(stage.getStage(), stage.getBranch()); } } From fc8de46ca237d5afc6ee6e8f9614b5e2e97f49ba Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 27 Sep 2023 21:33:50 +0200 Subject: [PATCH 55/95] :construction_worker: Deploy javadocs and sources for API --- api/dependency-reduced-pom.xml | 17 ++++++++++++++++ api/pom.xml | 17 ++++++++++++++++ pom.xml | 36 +++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml index eea86111..eeca2f22 100755 --- a/api/dependency-reduced-pom.xml +++ b/api/dependency-reduced-pom.xml @@ -44,11 +44,28 @@ <shadeSourcesContent>true</shadeSourcesContent> </configuration> </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.0</version> + <configuration> + <parameters>true</parameters> + </configuration> + </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> <version>3.4.1</version> + <executions> + <execution> + <id>attach-javadocs</id> + <phase>verify</phase> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> <configuration> <skip>false</skip> + <doclint>none</doclint> </configuration> </plugin> <plugin> diff --git a/api/pom.xml b/api/pom.xml index 249c67e8..85d178b1 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -50,12 +50,29 @@ </execution> </executions> </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.0</version> + <configuration> + <parameters>true</parameters> + </configuration> + </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> <version>3.4.1</version> <configuration> <skip>false</skip> + <doclint>none</doclint> </configuration> + <executions> + <execution> + <id>attach-javadocs</id> + <phase>verify</phase> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> diff --git a/pom.xml b/pom.xml index 76b3c372..cb425a1c 100644 --- a/pom.xml +++ b/pom.xml @@ -9,9 +9,32 @@ <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> - <name>beautyquests</name> + <name>BeautyQuests</name> + <description>A Spigot quests plugin based on a simple-to-use graphical + interface.</description> <url>https://github.com/SkytAsul/BeautyQuests/</url> + <licenses> + <license> + <name>MIT License</name> + <url>http://www.opensource.org/licenses/mit-license.php</url> + </license> + </licenses> + + <developers> + <developer> + <name>SkytAsul</name> + <email>skytasul@gmail.com</email> + <url>https://github.com/SkytAsul</url> + </developer> + </developers> + + <scm> + <connection>scm:git:git://github.com/SkytAsul/BeautyQuests.git</connection> + <developerConnection>scm:git:ssh://github.com:SkytAsul/BeautyQuests.git</developerConnection> + <url>http://github.com/SkytAsul/BeautyQuests/tree/master</url> + </scm> + <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> @@ -28,6 +51,17 @@ </repository> </repositories> + <distributionManagement> + <repository> + <id>codemc-releases</id> + <url>https://repo.codemc.org/repository/maven-releases/</url> + </repository> + <snapshotRepository> + <id>codemc-snapshots</id> + <url>https://repo.codemc.io/repository/maven-snapshots/</url> + </snapshotRepository> + </distributionManagement> + <modules> <module>api</module> <module>core</module> From 7ebaeb8fd0c2f88f5c76781e58f2546d776ebcf9 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 29 Sep 2023 12:10:20 +0200 Subject: [PATCH 56/95] :memo: Updated README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b09a554b..ec4d09b8 100644 --- a/README.md +++ b/README.md @@ -52,11 +52,11 @@ In *pom.xml*, add this to the `repositories` section: <url>https://repo.codemc.org/repository/maven-public</url> </repository> ``` -And add this to the `dependencies` section: (replace VERSION by whatever version you want, i.e. `0.19.7`, `0.20-SNAPSHOT`...) +And add this to the `dependencies` section: (replace VERSION by whatever version you want, i.e. `1.0-SNAPSHOT`) ```xml <dependency> <groupId>fr.skytasul</groupId> - <artifactId>beautyquests-core</artifactId> + <artifactId>beautyquests-api</artifactId> <version>VERSION</version> <scope>provided</scope> </dependency> From b6adf6b171771e9ed29afd1eed5c08ec35d76d41 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 29 Sep 2023 15:25:31 +0200 Subject: [PATCH 57/95] :bug: Fixed player datas not being saved at server stop --- .../quests/players/PlayersManagerYAML.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) 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 2b2b9c2e..ad85b8ba 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerYAML.java @@ -27,20 +27,21 @@ public class PlayersManagerYAML extends AbstractPlayersManager { private static final int ACCOUNTS_THRESHOLD = 1000; - + private final Cache<Integer, PlayerAccountImplementation> unloadedAccounts = CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build(); - + private final Map<Integer, PlayerAccountImplementation> pendingSaveAccounts = new ConcurrentHashMap<>(); + protected final Map<Integer, PlayerAccountImplementation> loadedAccounts = new HashMap<>(); private final Map<Integer, String> identifiersIndex = new ConcurrentHashMap<>(); - + private final File directory = new File(BeautyQuests.getInstance().getDataFolder(), "players"); - + private int lastAccountID = 0; - + public File getDirectory() { return directory; } - + @Override public void load(AccountFetchRequest request) { String identifier = super.getIdentifier(request.getOfflinePlayer()); @@ -94,7 +95,7 @@ public void load(AccountFetchRequest request) { request.notLoaded(); } } - + @Override protected CompletableFuture<Void> removeAccount(PlayerAccountImplementation acc) { loadedAccounts.remove(acc.index); @@ -106,12 +107,12 @@ protected CompletableFuture<Void> removeAccount(PlayerAccountImplementation acc) public PlayerQuestDatasImplementation createPlayerQuestDatas(PlayerAccountImplementation acc, Quest quest) { return new PlayerQuestDatasImplementation(acc, quest.getId()); } - + @Override public PlayerPoolDatasImplementation createPlayerPoolDatas(PlayerAccountImplementation acc, QuestPool pool) { return new PlayerPoolDatasImplementation(acc, pool.getId()); } - + @Override public CompletableFuture<Integer> removeQuestDatas(Quest quest) { return CompletableFuture.supplyAsync(() -> { @@ -306,7 +307,7 @@ public void load() { } } QuestsPlugin.getPlugin().getLoggerExpanded().debug(loadedAccounts.size() + " accounts loaded and " + identifiersIndex.size() + " identifiers."); - + if (identifiersIndex.size() >= ACCOUNTS_THRESHOLD) { QuestsPlugin.getPlugin().getLoggerExpanded().warning( "⚠ WARNING - " + identifiersIndex.size() + " players are registered on this server." @@ -325,8 +326,9 @@ public synchronized void save() { // as the save can take a few seconds and MAY be done asynchronously, // it is possible that the "loadedAccounts" map is being edited concurrently. // therefore, we create a new list to avoid this issue. - ArrayList<PlayerAccountImplementation> accountToSave = new ArrayList<>(loadedAccounts.values()); - for (PlayerAccountImplementation acc : accountToSave) { + Set<PlayerAccountImplementation> accountsToSave = new HashSet<>(loadedAccounts.values()); + accountsToSave.addAll(pendingSaveAccounts.values()); + for (PlayerAccountImplementation acc : accountsToSave) { try { savePlayerFile(acc); }catch (Exception e) { @@ -334,12 +336,14 @@ public synchronized void save() { } } } - + @Override public void unloadAccount(PlayerAccountImplementation acc) { loadedAccounts.remove(acc.index); unloadedAccounts.put(acc.index, acc); + pendingSaveAccounts.put(acc.index, acc); QuestUtils.runAsync(() -> { + pendingSaveAccounts.remove(acc.index); try { savePlayerFile(acc); }catch (IOException e) { From 29cf0996742914ccc18759d5df16d6880359262d Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 29 Sep 2023 15:46:21 +0200 Subject: [PATCH 58/95] :sparkles: Added quest_restartable_ID placeholder --- core/src/main/resources/locales/en_US.yml | 2 +- .../placeholders/QuestsPlaceholders.java | 90 ++++++++++--------- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 3fbbe398..657a5916 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -329,7 +329,7 @@ msg: removed: 'Removed the quest firework!' writeCommandDelay: '§aWrite the desired command delay, in ticks.' advancement: - finished: Finished + finished: Finished {times_finished} x notStarted: Not started inv: validate: §b§lValidate diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/QuestsPlaceholders.java b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/QuestsPlaceholders.java index 2ce413db..43721706 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/QuestsPlaceholders.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/placeholders/QuestsPlaceholders.java @@ -1,15 +1,7 @@ package fr.skytasul.quests.integrations.placeholders; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -33,72 +25,87 @@ import me.clip.placeholderapi.expansion.PlaceholderExpansion; public class QuestsPlaceholders extends PlaceholderExpansion implements Listener { - + private static QuestsPlaceholders placeholders; - + private final int lineLength; private final int changeTime; private final String splitFormat; private final String inlineFormat; - + private BukkitTask task; private Map<Player, PlayerPlaceholderData> players = new HashMap<>(); private ReentrantLock playersLock = new ReentrantLock(); - + private List<Entry<String, Consumer<PlaceholderExpansion>>> waitingExpansions = new ArrayList<>(); - + private QuestsPlaceholders(ConfigurationSection placeholderConfig) { lineLength = placeholderConfig.getInt("lineLength"); changeTime = placeholderConfig.getInt("changeTime"); splitFormat = placeholderConfig.getString("splitPlaceholderFormat"); inlineFormat = placeholderConfig.getString("inlinePlaceholderFormat"); } - + public static void registerPlaceholders(ConfigurationSection placeholderConfig) { placeholders = new QuestsPlaceholders(placeholderConfig); placeholders.register(); Bukkit.getPluginManager().registerEvents(placeholders, QuestsPlugin.getPlugin()); QuestsPlugin.getPlugin().getLoggerExpanded().info("Placeholders registered !"); } - + public static void waitForExpansion(String identifier, Consumer<PlaceholderExpansion> callback) { placeholders.waitingExpansions.add(new AbstractMap.SimpleEntry<>(identifier, callback)); } - + @Override public String getAuthor() { return QuestsPlugin.getPlugin().getDescription().getAuthors().toString(); } - + @Override public String getIdentifier() { return "beautyquests"; } - + @Override public String getVersion() { return QuestsPlugin.getPlugin().getDescription().getVersion(); } - + @Override public boolean persist() { return true; } - + @Override public boolean canRegister() { return true; } - + @Override public List<String> getPlaceholders() { - return Arrays.asList("total_amount", "player_inprogress_amount", "player_finished_amount", "player_finished_total_amount", "started", "started_ordered", "started_ordered_X", "advancement_ID", "advancement_ID_raw", "player_quest_finished_ID", "started_id_list"); + return Arrays.asList("total_amount", "quest_restartable_ID", "player_inprogress_amount", "player_finished_amount", + "player_finished_total_amount", "started", "started_ordered", "started_ordered_X", "advancement_ID", + "advancement_ID_raw", "player_quest_finished_ID", "started_id_list"); } - + @Override public String onRequest(OfflinePlayer off, String identifier) { if (identifier.equals("total_amount")) return "" + QuestsAPI.getAPI().getQuestsManager().getQuests().size(); + + if (identifier.startsWith("quest_restartable_")) { + String sid = identifier.substring(18); + try { + Quest qu = QuestsAPI.getAPI().getQuestsManager().getQuest(Integer.parseInt(sid)); + if (qu == null) + return "§c§lError: unknown quest §o" + sid; + return Boolean.toString(qu.isRepeatable()); + } catch (NumberFormatException ex) { + return "§c§lError: §o" + sid; + } + } + if (!off.isOnline()) return "§cerror: offline"; Player p = off.getPlayer(); PlayerAccount acc = PlayersManager.getPlayerAccount(p); @@ -112,7 +119,7 @@ public String onRequest(OfflinePlayer off, String identifier) { if (identifier.equals("started_id_list")) return acc.getQuestsDatas().stream().filter(PlayerQuestDatas::hasStarted) .map(x -> Integer.toString(x.getQuestID())).collect(Collectors.joining(";")); - + if (identifier.equals("started")) { return acc.getQuestsDatas() .stream() @@ -128,24 +135,24 @@ public String onRequest(OfflinePlayer off, String identifier) { }) .collect(Collectors.joining("\n")); } - + if (identifier.startsWith("started_ordered")) { String after = identifier.substring(15); if (task == null) launchTask(); - + playersLock.lock(); try { PlayerPlaceholderData data = players.get(p); - + if (data == null) { data = new PlayerPlaceholderData(acc); players.put(p, data); } - + if (data.left.isEmpty()) { data.left = QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(data.acc, false, true); }else QuestsAPI.getAPI().getQuestsManager().updateQuestsStarted(acc, true, data.left); - + try { int i = -1; boolean noSplit = after.isEmpty(); @@ -157,16 +164,16 @@ public String onRequest(OfflinePlayer off, String identifier) { } if (i < 0) return "§cindex must be a positive integer"; } - + if (data.left.isEmpty()) return i == -1 || i == 0 ? Lang.SCOREBOARD_NONE.toString() : ""; - + Quest quest = data.left.get(0); String desc = quest.getDescriptionLine(acc, DescriptionSource.PLACEHOLDER); String format = noSplit ? inlineFormat : splitFormat; format = format.replace("{questName}", quest.getName()).replace("{questDescription}", desc); - + if (noSplit) return format; - + try { List<String> lines = ChatColorUtils.wordWrap(format, lineLength); if (i >= lines.size()) return ""; @@ -183,7 +190,7 @@ public String onRequest(OfflinePlayer off, String identifier) { playersLock.unlock(); } } - + if (identifier.startsWith("advancement_")) { int rawId = identifier.indexOf("_raw"); String sid = rawId == -1 ? identifier.substring(12) : identifier.substring(12, rawId); @@ -194,7 +201,8 @@ public String onRequest(OfflinePlayer off, String identifier) { if (qu.hasStarted(acc)) { return qu.getDescriptionLine(acc, DescriptionSource.PLACEHOLDER); } - if (qu.hasFinished(acc)) return Lang.Finished.toString(); + if (qu.hasFinished(acc)) + return Lang.Finished.quickFormat("times_finished", acc.getQuestDatas(qu).getTimesFinished()); return Lang.Not_Started.toString(); }else { if (!acc.hasQuestDatas(qu)) return "-1"; @@ -219,7 +227,7 @@ public String onRequest(OfflinePlayer off, String identifier) { } return null; } - + private void launchTask() { task = Bukkit.getScheduler().runTaskTimerAsynchronously(QuestsPlugin.getPlugin(), () -> { playersLock.lock(); @@ -238,7 +246,7 @@ private void launchTask() { } }, 0, changeTime * 20); } - + @EventHandler public void onExpansionRegister(ExpansionRegisterEvent e) { for (Iterator<Entry<String, Consumer<PlaceholderExpansion>>> iterator = waitingExpansions.iterator(); iterator.hasNext();) { @@ -249,14 +257,14 @@ public void onExpansionRegister(ExpansionRegisterEvent e) { } } } - + class PlayerPlaceholderData { private List<Quest> left = Collections.emptyList(); private PlayerAccount acc; - + public PlayerPlaceholderData(PlayerAccount acc) { this.acc = acc; } } - + } From ca3690039b19e78970a8c467c8f3b99c5835e6ca Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 30 Sep 2023 15:57:32 +0200 Subject: [PATCH 59/95] :bug: Fixed ending stage with no linked branch deserialization --- .../fr/skytasul/quests/structure/EndingStageImplementation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java index 4f9ec058..66632e72 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/EndingStageImplementation.java @@ -13,7 +13,7 @@ public class EndingStageImplementation implements EndingStage { public EndingStageImplementation(@NotNull StageControllerImplementation<?> stage, @Nullable QuestBranchImplementation branch) { this.stage = Objects.requireNonNull(stage); - this.branch = Objects.requireNonNull(branch); + this.branch = branch; } @Override From 2ad40105d3810fd54ad25ff50b456554b9d4eef7 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 2 Oct 2023 22:51:03 +0200 Subject: [PATCH 60/95] :bug: Fixed multiple bugs --- .../java/fr/skytasul/quests/BeautyQuests.java | 35 ++++++++++--------- .../quests/QuestsAPIImplementation.java | 12 ++++--- .../QuestsConfigurationImplementation.java | 8 ++--- .../quests/gui/creation/stages/StagesGUI.java | 10 +++--- .../quests/rewards/TeleportationReward.java | 15 ++++---- 5 files changed, 44 insertions(+), 36 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 64d988f0..95388748 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -142,10 +142,6 @@ public void onEnable(){ checkPaper(); - loadDefaultIntegrations(); - integrations.testCompatibilities(); - Bukkit.getPluginManager().registerEvents(integrations, this); - saveDefaultConfig(); NMS.isValid(); // to force initialization @@ -158,6 +154,10 @@ public void onEnable(){ registerCommands(); try { + loadDefaultIntegrations(); + integrations.testCompatibilities(); + Bukkit.getPluginManager().registerEvents(integrations, this); + integrations.initializeCompatibilities(); }catch (Exception ex) { logger.severe("An error occurred while initializing compatibilities. Consider restarting.", ex); @@ -181,7 +181,7 @@ public void run() { launchSaveCycle(); if (!lastVersion.equals(pluginVersion)) { // maybe change in data structure : update of all quest files - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Migrating from " + lastVersion + " to " + pluginVersion); + logger.debug("Migrating from " + lastVersion + " to " + pluginVersion); int updated = quests.updateAll(); if (updated > 0) logger.info("Updated " + updated + " quests during migration."); pools.updateAll(); @@ -260,7 +260,7 @@ private void initApi() throws ReflectiveOperationException { private void checkPaper() { try { isPaper = Class.forName("com.destroystokyo.paper.ParticleBuilder") != null; - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Paper detected."); + logger.debug("Paper detected."); }catch (ClassNotFoundException ex) { isPaper = false; logger.warning("You are not running the Paper software.\n" @@ -336,11 +336,11 @@ private void launchMetrics(String pluginVersion) { .distinct() .collect(Collectors.toMap(Function.identity(), __ -> 1)); })); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Started bStats metrics"); + logger.debug("Started bStats metrics"); } private void launchUpdateChecker(String pluginVersion) { - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Starting Spigot updater"); + logger.debug("Starting Spigot updater"); UpdateChecker checker; if (pluginVersion.contains("_")) { Matcher matcher = Pattern.compile("_BUILD(\\d+)").matcher(pluginVersion); @@ -397,19 +397,20 @@ private void loadConfigParameters(boolean init) throws LoadingException { /* static initialization */ if (init) { - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default stage types."); + getAPI().setup(); + logger.debug("Initializing default stage types."); DefaultQuestFeatures.registerStages(); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default quest options."); + logger.debug("Initializing default quest options."); DefaultQuestFeatures.registerQuestOptions(); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default item comparisons."); + logger.debug("Initializing default item comparisons."); DefaultQuestFeatures.registerItemComparisons(); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default rewards."); + logger.debug("Initializing default rewards."); DefaultQuestFeatures.registerRewards(); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default requirements."); + logger.debug("Initializing default requirements."); DefaultQuestFeatures.registerRequirements(); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default stage options."); + logger.debug("Initializing default stage options."); DefaultQuestFeatures.registerStageOptions(); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Initializing default miscellenaeous."); + logger.debug("Initializing default miscellenaeous."); DefaultQuestFeatures.registerMisc(); DefaultQuestFeatures.registerMessageProcessors(); getServer().getPluginManager().registerEvents(guiManager = new GuiManagerImplementation(), this); @@ -454,7 +455,7 @@ private void loadDataFile() throws LoadingException { throw new LoadingException("Couldn't create data file.", e); } } - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Loading data file, last time edited : " + new Date(dataFile.lastModified()).toString()); + logger.debug("Loading data file, last time edited : " + new Date(dataFile.lastModified()).toString()); data = YamlConfiguration.loadConfiguration(dataFile); data.options().header("Do not edit ANYTHING here."); data.options().copyHeader(true); @@ -556,7 +557,7 @@ public void saveAllConfig(boolean unload) throws Exception { logger.severe("Error when saving player datas.", ex); } data.save(dataFile); - QuestsPlugin.getPlugin().getLoggerExpanded().debug("Saved datas (" + (((double) System.currentTimeMillis() - time) / 1000D) + "s)!"); + logger.debug("Saved datas (" + (((double) System.currentTimeMillis() - time) / 1000D) + "s)!"); } if (unload){ diff --git a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java index 012f738f..bf4bea4a 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsAPIImplementation.java @@ -29,14 +29,13 @@ public class QuestsAPIImplementation implements QuestsAPI { static final QuestsAPIImplementation INSTANCE = new QuestsAPIImplementation(); - private final QuestObjectsRegistry<AbstractRequirement, RequirementCreator> requirements = - new QuestObjectsRegistry<>("requirements", Lang.INVENTORY_REQUIREMENTS.toString()); - private final QuestObjectsRegistry<AbstractReward, RewardCreator> rewards = - new QuestObjectsRegistry<>("rewards", Lang.INVENTORY_REWARDS.toString()); private final StageTypeRegistry stages = new StageTypeRegistry(); private final List<ItemComparison> itemComparisons = new LinkedList<>(); private final List<MobStacker> mobStackers = new ArrayList<>(); + private QuestObjectsRegistry<AbstractRequirement, RequirementCreator> requirements; + private QuestObjectsRegistry<AbstractReward, RewardCreator> rewards; + private AbstractHolograms<?> hologramsManager = null; private BossBarManager bossBarManager = null; private BQBlocksManagerImplementation blocksManager = new BQBlocksManagerImplementation(); @@ -47,6 +46,11 @@ public class QuestsAPIImplementation implements QuestsAPI { private QuestsAPIImplementation() {} + void setup() { + requirements = new QuestObjectsRegistry<>("requirements", Lang.INVENTORY_REQUIREMENTS.toString()); + rewards = new QuestObjectsRegistry<>("rewards", Lang.INVENTORY_REWARDS.toString()); + } + @Override public @NotNull StageTypeRegistry getStages() { return stages; diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index 37ed6acd..d4e177d7 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -320,6 +320,10 @@ private void init() { questConfirmGUI = config.getBoolean("questConfirmGUI"); sounds = config.getBoolean("sounds"); fireworks = config.getBoolean("fireworks"); + if (config.contains("pageItem")) + pageItem = XMaterial.matchXMaterial(config.getString("pageItem")).orElse(XMaterial.ARROW); + if (pageItem == null) + pageItem = XMaterial.ARROW; if (config.isItemStack("item")) { defaultQuestItem = config.getItemStack("item"); } else if (config.isString("item")) { @@ -327,10 +331,6 @@ private void init() { } else defaultQuestItem = XMaterial.BOOK.parseItem(); defaultQuestItem = ItemUtils.clearVisibleAttributes(defaultQuestItem); - if (config.contains("pageItem")) - pageItem = XMaterial.matchXMaterial(config.getString("pageItem")).orElse(XMaterial.ARROW); - if (pageItem == null) - pageItem = XMaterial.ARROW; startParticleDistance = config.getInt("startParticleDistance"); requirementUpdateTime = config.getInt("requirementUpdateTime"); finishSound = loadSound("finishSound"); diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 7d235ad8..89c3f37d 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -196,13 +196,14 @@ private void editBranch(QuestBranchImplementation branch){ class Line { - StageLineImplementation lineObj; int lineId; + final boolean ending; + StageLineImplementation lineObj; StageCreationContextImplementation<?> context; - boolean ending; Line(int lineId, boolean ending) { this.lineId = lineId; + this.ending = ending; this.lineObj = new StageLineImplementation(this); } @@ -290,7 +291,8 @@ void setStageEdition(StageController stage, @Nullable QuestBranch branch) { } void updateLineManageLore() { - lineObj.refreshItemLore(0, getLineManageLore(lineId)); + if (isActive()) + lineObj.refreshItemLore(0, getLineManageLore(lineId)); } boolean isFirst() { @@ -312,7 +314,7 @@ void remove() { for (int i = lineId + 1; i < maxStages; i++) { Line nextLine = getLine(i); nextLine.exchangeLines(lastLine); - lastLine = nextLine; + // lastLine = nextLine; if (!nextLine.isActive()) { if (nextLine.lineObj.isEmpty()) nextLine.setCreationState(); 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 fb02b4d2..d6663bf8 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/TeleportationReward.java @@ -18,7 +18,7 @@ public class TeleportationReward extends AbstractReward { public Location teleportation; public TeleportationReward() {} - + public TeleportationReward(String customDescription, Location teleportation) { super(customDescription); this.teleportation = teleportation; @@ -34,13 +34,14 @@ public List<String> give(Player player) { public AbstractReward clone() { return new TeleportationReward(getCustomDescription(), teleportation.clone()); } - + @Override protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); - loreBuilder.addDescriptionAsValue(Lang.Location.format(new BQLocation(teleportation))); + loreBuilder + .addDescriptionAsValue(Lang.Location.format(teleportation == null ? null : new BQLocation(teleportation))); } - + @Override public void itemClick(QuestObjectClickEvent event) { Lang.MOVE_TELEPORT_POINT.send(event.getPlayer()); @@ -49,17 +50,17 @@ public void itemClick(QuestObjectClickEvent event) { event.reopenGUI(); }).start(); } - + @Override public void save(ConfigurationSection section) { super.save(section); section.set("tp", teleportation.serialize()); } - + @Override public void load(ConfigurationSection section) { super.load(section); teleportation = Location.deserialize(section.getConfigurationSection("tp").getValues(false)); } - + } From e07594fe926fce2a25a75e9aa327bd93b50d8304 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 4 Oct 2023 18:22:33 +0200 Subject: [PATCH 61/95] :arrow_up: Added 1.20.2 support --- .../quests/gui/creation/stages/StagesGUI.java | 1 - v1_20_R2/pom.xml | 81 +++++++++++++++++++ .../skytasul/quests/utils/nms/v1_20_R2.java | 49 +++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100755 v1_20_R2/pom.xml create mode 100755 v1_20_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R2.java diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 89c3f37d..3c452cff 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -314,7 +314,6 @@ void remove() { for (int i = lineId + 1; i < maxStages; i++) { Line nextLine = getLine(i); nextLine.exchangeLines(lastLine); - // lastLine = nextLine; if (!nextLine.isActive()) { if (nextLine.lineObj.isEmpty()) nextLine.setCreationState(); diff --git a/v1_20_R2/pom.xml b/v1_20_R2/pom.xml new file mode 100755 index 00000000..6aa50859 --- /dev/null +++ b/v1_20_R2/pom.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <packaging>jar</packaging> + <artifactId>beautyquests-v1_20_R2</artifactId> + <parent> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-parent</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + + <properties> + <maven.deploy.skip>true</maven.deploy.skip> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + <spigot.version>1.20.2-R0.1-SNAPSHOT</spigot.version> + </properties> + + <repositories> + <repository> + <id>jitpack.io</id> + <url>https://jitpack.io</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-core</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.spigotmc</groupId> + <artifactId>spigot</artifactId> + <version>${spigot.version}</version> + <classifier>remapped-mojang</classifier> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>net.md-5</groupId> + <artifactId>specialsource-maven-plugin</artifactId> + <version>1.2.4</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>remap</goal> + </goals> + <id>remap-obf</id> + <configuration> + <srgIn>org.spigotmc:minecraft-server:${spigot.version}:txt:maps-mojang</srgIn> + <reverse>true</reverse> + <remappedDependencies>org.spigotmc:spigot:${spigot.version}:jar:remapped-mojang</remappedDependencies> + <remappedArtifactAttached>true</remappedArtifactAttached> + <remappedClassifierName>remapped-obf</remappedClassifierName> + </configuration> + </execution> + <execution> + <phase>package</phase> + <goals> + <goal>remap</goal> + </goals> + <id>remap-spigot</id> + <configuration> + <inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile> + <srgIn>org.spigotmc:minecraft-server:${spigot.version}:csrg:maps-spigot</srgIn> + <remappedDependencies>org.spigotmc:spigot:${spigot.version}:jar:remapped-obf</remappedDependencies> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/v1_20_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R2.java b/v1_20_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R2.java new file mode 100755 index 00000000..58e07eda --- /dev/null +++ b/v1_20_R2/src/main/java/fr/skytasul/quests/utils/nms/v1_20_R2.java @@ -0,0 +1,49 @@ +package fr.skytasul.quests.utils.nms; + +import java.util.List; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +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; + +public class v1_20_R2 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<String> getAvailableBlockProperties(Material material) { + RegistryLookup<Block> blockRegistry = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK); + Reference<Block> block = blockRegistry + .getOrThrow(ResourceKey.create(Registries.BLOCK, new ResourceLocation(material.getKey().getKey()))); + StateDefinition<Block, BlockState> stateList = block.value().getStateDefinition(); + return stateList.getProperties().stream().map(Property::getName).toList(); + } + + @Override + public List<String> getAvailableBlockTags() { + return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK).listTags() + .map(x -> x.key().location().toString()).toList(); + } + +} \ No newline at end of file From e50005c7b1d1a0a410e89b9bfa88ed89db2489e1 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 14 Oct 2023 15:46:43 +0200 Subject: [PATCH 62/95] :sparkles: Reworked quest selection GUI and added more configuration --- .../quests/api/QuestsConfiguration.java | 13 +++- .../skytasul/quests/api/gui/GuiFactory.java | 9 +++ .../fr/skytasul/quests/api/quests/Quest.java | 2 + .../QuestsConfigurationImplementation.java | 53 +++++++++++++-- .../fr/skytasul/quests/QuestsListener.java | 29 ++++----- .../quests/commands/CommandsAdmin.java | 9 ++- .../quests/gui/DefaultGuiFactory.java | 15 +++++ .../gui/quests/ChoosePlayerQuestGUI.java | 64 +++++++++++++++++++ .../quests/gui/quests/ChooseQuestGUI.java | 41 +++--------- .../quests/requirements/QuestRequirement.java | 26 ++++---- .../quests/structure/QuestImplementation.java | 3 +- core/src/main/resources/config.yml | 10 ++- 12 files changed, 196 insertions(+), 78 deletions(-) create mode 100755 core/src/main/java/fr/skytasul/quests/gui/quests/ChoosePlayerQuestGUI.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java index f08b1c84..d251d9ec 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -23,6 +23,9 @@ public interface QuestsConfiguration { @NotNull Dialogs getDialogsConfig(); + @NotNull + QuestsSelection getQuestsSelectionConfig(); + @NotNull QuestsMenu getQuestsMenuConfig(); @@ -56,8 +59,6 @@ interface Quests { Collection<NpcClickType> getNpcClicks(); - boolean skipNpcGuiIfOnlyOneQuest(); - ItemStack getDefaultQuestItem(); XMaterial getPageMaterial(); @@ -96,6 +97,14 @@ interface Dialogs { } + interface QuestsSelection { + + boolean skipGuiIfOnlyOneQuest(); + + boolean hideNoRequirements(); + + } + interface QuestsMenu { boolean isNotStartedTabOpenedWhenEmpty(); diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java index 096b6b70..a0a9fd87 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiFactory.java @@ -6,6 +6,7 @@ import java.util.function.Consumer; import java.util.function.Predicate; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,6 +14,7 @@ import fr.skytasul.quests.api.comparison.ItemComparisonMap; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; public interface GuiFactory { @@ -63,4 +65,11 @@ Gui createConfirmation(@Nullable Runnable yes, @Nullable Runnable no, @NotNull S @NotNull Gui createEntityTypeSelection(@NotNull Consumer<EntityType> callback, @Nullable Predicate<@NotNull EntityType> filter); + @NotNull + Gui createQuestSelection(@NotNull Consumer<Quest> callback, @Nullable Runnable cancel, + @NotNull Collection<Quest> quests); + + @NotNull + Gui createPlayerQuestSelection(@NotNull Player player, @NotNull Collection<Quest> quests); + } diff --git a/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java index cdcdafbb..dc02b749 100644 --- a/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java +++ b/api/src/main/java/fr/skytasul/quests/api/quests/Quest.java @@ -67,6 +67,8 @@ public interface Quest extends OptionSet, Comparable<Quest>, HasPlaceholders { public @NotNull CompletableFuture<Boolean> attemptStart(@NotNull Player player); + public void doNpcClick(@NotNull Player player); + public default void start(@NotNull Player player) { start(player, false); } diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index d4e177d7..a5b5d2ac 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -53,6 +53,7 @@ public static QuestsConfigurationImplementation getConfiguration() { private final FileConfiguration config; private QuestsConfig quests; private DialogsConfig dialogs; + private QuestsSelectionConfig selection; private QuestsMenuConfig menu; private StageDescriptionConfig stageDescription; private QuestDescriptionConfig questDescription; @@ -62,6 +63,7 @@ public static QuestsConfigurationImplementation getConfiguration() { quests = new QuestsConfig(); dialogs = new DialogsConfig(config.getConfigurationSection("dialogs")); + selection = new QuestsSelectionConfig(config.getConfigurationSection("questsSelection")); menu = new QuestsMenuConfig(config.getConfigurationSection("questsMenu")); stageDescription = new StageDescriptionConfig(config.getConfigurationSection("stage description")); questDescription = new QuestDescriptionConfig(config.getConfigurationSection("questDescription")); @@ -70,6 +72,7 @@ public static QuestsConfigurationImplementation getConfiguration() { boolean update() { boolean result = false; result |= dialogs.update(); + result |= selection.update(); result |= menu.update(); result |= stageDescription.update(); return result; @@ -84,6 +87,7 @@ void init() { initializeTranslations(); quests.init(); dialogs.init(); + selection.init(); menu.init(); stageDescription.init(); questDescription.init(); @@ -203,6 +207,11 @@ public FileConfiguration getConfig() { return dialogs; } + @Override + public @NotNull QuestsSelectionConfig getQuestsSelectionConfig() { + return selection; + } + @Override public @NotNull QuestsMenuConfig getQuestsMenuConfig() { return menu; @@ -307,7 +316,6 @@ public class QuestsConfig implements QuestsConfiguration.Quests { private boolean stageStart = true; private boolean questConfirmGUI = false; private Collection<NpcClickType> npcClicks = Arrays.asList(NpcClickType.RIGHT, NpcClickType.SHIFT_RIGHT); - private boolean skipNpcGuiIfOnlyOneQuest = true; private boolean requirementReasonOnMultipleQuests = true; private boolean stageEndRewardsMessage = true; @@ -351,7 +359,6 @@ private void init() { QuestsPlugin.getPlugin().getLoggerExpanded() .warning("Unknown click type " + config.get("npcClick") + " for config entry \"npcClick\""); } - skipNpcGuiIfOnlyOneQuest = config.getBoolean("skip npc gui if only one quest"); requirementReasonOnMultipleQuests = config.getBoolean("requirementReasonOnMultipleQuests"); stageEndRewardsMessage = config.getBoolean("stageEndRewardsMessage"); } @@ -411,11 +418,6 @@ public Collection<NpcClickType> getNpcClicks() { return npcClicks; } - @Override - public boolean skipNpcGuiIfOnlyOneQuest() { - return skipNpcGuiIfOnlyOneQuest; - } - @Override public ItemStack getDefaultQuestItem() { return defaultQuestItem; @@ -544,6 +546,43 @@ public String getDefaultNPCSound() { } + public class QuestsSelectionConfig implements QuestsConfiguration.QuestsSelection { + + private boolean skipGuiIfOnlyOneQuest = true; + private boolean hideNoRequirements = true; + + private final ConfigurationSection config; + + private QuestsSelectionConfig(ConfigurationSection config) { + this.config = config; + } + + private boolean update() { + boolean result = false; + if (config.getParent() != null) { + result |= migrateEntry(config.getParent(), "skip npc gui if only one quest", config, + "skip gui if only one quest"); + } + return result; + } + + private void init() { + skipGuiIfOnlyOneQuest = config.getBoolean("skip gui if only one quest"); + hideNoRequirements = config.getBoolean("hide quests without requirement"); + } + + @Override + public boolean skipGuiIfOnlyOneQuest() { + return skipGuiIfOnlyOneQuest; + } + + @Override + public boolean hideNoRequirements() { + return hideNoRequirements; + } + + } + public class QuestsMenuConfig implements QuestsConfiguration.QuestsMenu { private Set<PlayerListCategory> tabs; diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 592685e5..944baf79 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -1,9 +1,6 @@ package fr.skytasul.quests; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -28,18 +25,14 @@ import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; import fr.skytasul.quests.api.events.internal.BQBlockBreakEvent; import fr.skytasul.quests.api.events.internal.BQCraftEvent; -import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.npcs.BqNpc; -import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.MessageType; import fr.skytasul.quests.api.utils.messaging.MessageUtils; -import fr.skytasul.quests.gui.quests.ChooseQuestGUI; -import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.npcs.BQNPCClickEvent; import fr.skytasul.quests.options.OptionAutoQuest; import fr.skytasul.quests.players.PlayerAccountImplementation; @@ -101,18 +94,20 @@ public void onNPCClick(BQNPCClickEvent e) { if (!launcheable.isEmpty()) { for (QuestImplementation quest : launcheable) { if (quest.isInDialog(p)) { - quest.clickNPC(p); + quest.doNpcClick(p); return; } } - ChooseQuestGUI.choose(p, quests, quest -> { - ((QuestImplementation) quest).clickNPC(p); - }, null, true, gui -> { - gui.setValidate(__ -> { - new PlayerListGUI(acc).open(p); - }, ItemUtils.item(XMaterial.BOOKSHELF, Lang.questMenu.toString(), - QuestOption.formatDescription(Lang.questMenuLore.toString()))); - }); + + Collection<? extends Quest> guiQuests = + QuestsConfiguration.getConfig().getQuestsSelectionConfig().hideNoRequirements() ? launcheable : quests; + if (guiQuests.size() == 1 + && QuestsConfiguration.getConfig().getQuestsSelectionConfig().skipGuiIfOnlyOneQuest()) { + guiQuests.iterator().next().doNpcClick(p); + } else if (!guiQuests.isEmpty()) { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createPlayerQuestSelection(p, (Collection) guiQuests) + .open(p); + } }else if (!startablePools.isEmpty()) { QuestPool pool = startablePools.iterator().next(); QuestsPlugin.getPlugin().getLoggerExpanded() diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index a5a0ec56..98043839 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -32,7 +32,6 @@ import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; import fr.skytasul.quests.gui.creation.QuestCreationSession; import fr.skytasul.quests.gui.misc.ListBook; -import fr.skytasul.quests.gui.quests.ChooseQuestGUI; import fr.skytasul.quests.npcs.BqNpcImplementation; import fr.skytasul.quests.players.AdminMode; import fr.skytasul.quests.players.PlayersManagerDB; @@ -73,11 +72,11 @@ public void edit(Player player, @Optional Quest quest) { }, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { - ChooseQuestGUI.choose(player, npc.getQuests(), clickedQuest -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createQuestSelection(clickedQuest -> { QuestCreationSession session = new QuestCreationSession(player); session.setQuestEdited((QuestImplementation) quest); session.openStagesGUI(player); - }, null, false); + }, null, npc.getQuests()).open(player); }else { Lang.NPC_NOT_QUEST.send(player); } @@ -97,9 +96,9 @@ public void remove(BukkitCommandActor actor, @Optional Quest quest) { }, npc -> { if (npc == null) return; if (!npc.getQuests().isEmpty()) { - ChooseQuestGUI.choose(actor.getAsPlayer(), npc.getQuests(), clickedQuest -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createQuestSelection(clickedQuest -> { doRemove(actor, clickedQuest); - }, null, false); + }, null, npc.getQuests()).open(actor.getAsPlayer()); }else { Lang.NPC_NOT_QUEST.send(actor.getAsPlayer()); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java index 3569d14c..c141c320 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultGuiFactory.java @@ -5,6 +5,7 @@ import java.util.function.Consumer; import java.util.function.Predicate; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,6 +16,7 @@ import fr.skytasul.quests.api.gui.templates.ConfirmGUI; import fr.skytasul.quests.api.npcs.BqNpc; import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.utils.CountableObject.MutableCountableObject; import fr.skytasul.quests.gui.blocks.BlocksGUI; import fr.skytasul.quests.gui.items.ItemComparisonGUI; @@ -23,6 +25,8 @@ import fr.skytasul.quests.gui.items.ItemsGUI; import fr.skytasul.quests.gui.mobs.EntityTypeGUI; import fr.skytasul.quests.gui.npc.NpcSelectGUI; +import fr.skytasul.quests.gui.quests.ChoosePlayerQuestGUI; +import fr.skytasul.quests.gui.quests.ChooseQuestGUI; import fr.skytasul.quests.gui.quests.PlayerListGUI; import fr.skytasul.quests.players.PlayerAccountImplementation; @@ -78,4 +82,15 @@ public class DefaultGuiFactory implements GuiFactory { return new EntityTypeGUI(callback, filter); } + @Override + public @NotNull Gui createQuestSelection(@NotNull Consumer<Quest> callback, @Nullable Runnable cancel, + @NotNull Collection<Quest> quests) { + return new ChooseQuestGUI(quests, callback, cancel); + } + + @Override + public @NotNull Gui createPlayerQuestSelection(@NotNull Player player, @NotNull Collection<Quest> quests) { + return new ChoosePlayerQuestGUI(quests, player); + } + } diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/ChoosePlayerQuestGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/ChoosePlayerQuestGUI.java new file mode 100755 index 00000000..e11b144c --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/ChoosePlayerQuestGUI.java @@ -0,0 +1,64 @@ +package fr.skytasul.quests.gui.quests; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.bukkit.DyeColor; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.QuestOption; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.options.description.QuestDescriptionContext; +import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.XMaterial; +import fr.skytasul.quests.players.PlayerAccountImplementation; + +public class ChoosePlayerQuestGUI extends PagedGUI<Quest> { + + private final @NotNull Player targetPlayer; + private final @NotNull PlayerAccount acc; + + public ChoosePlayerQuestGUI(@NotNull Collection<Quest> quests, @NotNull Player player) { + super(Lang.INVENTORY_CHOOSE.toString(), DyeColor.MAGENTA, quests); + + this.targetPlayer = player; + this.acc = PlayersManager.getPlayerAccount(player); + + Collections.sort(super.objects); + + setValidate(__ -> { + new PlayerListGUI((PlayerAccountImplementation) acc).open(player); + }, ItemUtils.item(XMaterial.BOOKSHELF, Lang.questMenu.toString(), + QuestOption.formatDescription(Lang.questMenuLore.toString()))); + } + + @Override + public @NotNull ItemStack getItemStack(@NotNull Quest quest) { + List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), quest, + acc, PlayerListCategory.NOT_STARTED, DescriptionSource.MENU).formatDescription(); + return ItemUtils.nameAndLore(quest.getQuestItem(), Lang.formatNormal.format(quest), lore); + } + + @Override + public void click(@NotNull Quest existing, @NotNull ItemStack item, @NotNull ClickType clickType) { + close(); + existing.doNpcClick(targetPlayer); + } + + @Override + public @NotNull CloseBehavior onClose(@NotNull Player player) { + return StandardCloseBehavior.REMOVE; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java index 0dec444b..33d9fa65 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/ChooseQuestGUI.java @@ -1,17 +1,15 @@ package fr.skytasul.quests.gui.quests; import java.util.Collection; -import java.util.Comparator; +import java.util.Collections; import java.util.Objects; import java.util.function.Consumer; -import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; @@ -19,30 +17,33 @@ import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.utils.QuestUtils; public class ChooseQuestGUI extends PagedGUI<Quest> { - + private @NotNull Consumer<Quest> run; private @Nullable Runnable cancel; - private ChooseQuestGUI(@NotNull Collection<@NotNull Quest> quests, @NotNull Consumer<@NotNull Quest> run, + public ChooseQuestGUI(@NotNull Collection<@NotNull Quest> quests, @NotNull Consumer<@NotNull Quest> run, @Nullable Runnable cancel) { super(Lang.INVENTORY_CHOOSE.toString(), DyeColor.MAGENTA, quests); - super.objects.sort(Comparator.naturalOrder()); - + this.run = Objects.requireNonNull(run); this.cancel = cancel; + + Collections.sort(objects); // to have quests in ID ordering } @Override public ItemStack getItemStack(Quest object) { - return ItemUtils.nameAndLore(object.getQuestItem().clone(), ChatColor.YELLOW + object.getName(), object.getDescription()); + return ItemUtils.nameAndLore(object.getQuestItem().clone(), Lang.formatId.format(object), + "§7" + object.getDescription()); } @Override public void click(Quest existing, ItemStack item, ClickType clickType) { close(player); - run.accept(existing); + QuestUtils.runSync(() -> run.accept(existing)); } @Override @@ -52,26 +53,4 @@ public void click(Quest existing, ItemStack item, ClickType clickType) { return StandardCloseBehavior.REMOVE; } - public static void choose(@NotNull Player player, @NotNull Collection<@NotNull Quest> quests, - @NotNull Consumer<@Nullable Quest> run, @Nullable Runnable cancel, boolean canSkip) { - choose(player, quests, run, cancel, canSkip, null); - } - - public static void choose(@NotNull Player player, @NotNull Collection<@NotNull Quest> quests, - @NotNull Consumer<@Nullable Quest> run, @Nullable Runnable cancel, boolean canSkip, - @Nullable Consumer<@NotNull ChooseQuestGUI> guiConsumer) { - if (quests.isEmpty()) { - if (cancel != null) - cancel.run(); - } else if (quests.size() == 1 && canSkip - && QuestsConfiguration.getConfig().getQuestsConfig().skipNpcGuiIfOnlyOneQuest()) { - run.accept(quests.iterator().next()); - } else { - ChooseQuestGUI gui = new ChooseQuestGUI(quests, run, cancel); - if (guiConsumer != null) - guiConsumer.accept(gui); - gui.open(player); - } - } - } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java index 159dfe86..6f28a2cc 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/QuestRequirement.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.objects.QuestObjectClickEvent; @@ -12,28 +13,27 @@ import fr.skytasul.quests.api.quests.Quest; import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; -import fr.skytasul.quests.gui.quests.ChooseQuestGUI; public class QuestRequirement extends AbstractRequirement { private int questId; private Quest cached; - + public QuestRequirement() { this(null, null, -1); } - + public QuestRequirement(String customDescription, String customReason, int questId) { super(customDescription, customReason); this.questId = questId; } - + @Override public boolean test(Player p) { if (exists()) return cached.hasFinished(PlayersManager.getPlayerAccount(p)); return true; } - + @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); @@ -45,7 +45,7 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol protected String getDefaultReason(Player player) { return exists() ? Lang.REQUIREMENT_QUEST.format(cached) : null; } - + @Override public String getDefaultDescription(Player p) { return Lang.RDQuest.format(exists() ? cached : this); @@ -55,7 +55,7 @@ private boolean exists(){ cached = QuestsAPI.getAPI().getQuestsManager().getQuest(questId); return cached != null; } - + @Override protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); @@ -64,27 +64,27 @@ protected void addLore(LoreBuilder loreBuilder) { @Override public void itemClick(QuestObjectClickEvent event) { - ChooseQuestGUI.choose(event.getPlayer(), QuestsAPI.getAPI().getQuestsManager().getQuests(), quest -> { + QuestsPlugin.getPlugin().getGuiManager().getFactory().createQuestSelection(quest -> { this.questId = quest.getId(); event.reopenGUI(); - }, event::remove, false); + }, event::remove, QuestsAPI.getAPI().getQuestsManager().getQuests()).open(event.getPlayer()); } - + @Override public AbstractRequirement clone() { return new QuestRequirement(getCustomDescription(), getCustomReason(), questId); } - + @Override public void save(ConfigurationSection section) { super.save(section); section.set("questID", questId); } - + @Override public void load(ConfigurationSection section) { super.load(section); questId = section.getInt("questID"); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index 266b5a7b..5a15d359 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -338,7 +338,8 @@ public boolean isInDialog(@NotNull Player p) { return hasOption(OptionStartDialog.class) && getOption(OptionStartDialog.class).getDialogRunner().isPlayerInDialog(p); } - public void clickNPC(@NotNull Player p) { + @Override + public void doNpcClick(@NotNull Player p) { if (hasOption(OptionStartDialog.class)) { getOption(OptionStartDialog.class).getDialogRunner().onClick(p); } else diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 55040357..5832c9dd 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -52,8 +52,6 @@ fireworks: true # Which clicks are acceptable for a player to do on the NPC in order to start a quest, follow a dialog... # (can be: RIGHT, LEFT, SHIFT_RIGHT, SHIFT_LEFT) npcClick: [RIGHT, SHIFT_RIGHT] -# If enabled, the "choose a quest from this NPC" GUI will not open if there is only 1 quest attached to the NPC -skip npc gui if only one quest: true # Default item shown for a quest in the menus item: BOOK # Page item material @@ -90,6 +88,14 @@ dialogs: # Default dialog sound when NPCs are speaking defaultNPCSound: 'none' +# - Quest selection - +# Options related to the behavior when a player click on an NPC which has associated quests +questsSelection: + # If enabled, the "choose a quest from this NPC" GUI will not open if there is only 1 quest attached to the NPC + skip gui if only one quest: true + # Hide quests from the GUI if the requirements are not met + hide quests without requirement: true + # - Quests Menu - # Options related to the "/quests" menu questsMenu: From 58d97680ed7af347ec0ed00ebf97f449bb7b635c Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 14 Oct 2023 15:51:50 +0200 Subject: [PATCH 63/95] :green_heart: Fixed some pom.xml issues --- dist/pom.xml | 7 +++++++ integrations/pom.xml | 2 +- pom.xml | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dist/pom.xml b/dist/pom.xml index 0f178dd7..f31f79bc 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -156,5 +156,12 @@ <type>jar</type> <scope>compile</scope> </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>beautyquests-v1_20_R2</artifactId> + <version>${project.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> </dependencies> </project> \ No newline at end of file diff --git a/integrations/pom.xml b/integrations/pom.xml index 78053860..c3ee4f8c 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -52,7 +52,7 @@ </repository> <repository> <id>citizens</id> - <url>http://repo.citizensnpcs.co/</url> <!-- really slow repo --> + <url>https://maven.citizensnpcs.co/repo</url> <!-- really slow repo --> <releases> <updatePolicy>interval:10080</updatePolicy> </releases> diff --git a/pom.xml b/pom.xml index cb425a1c..76e6bd88 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,7 @@ <module>v1_19_R2</module> <module>v1_19_R3</module> <module>v1_20_R1</module> + <module>v1_20_R2</module> <module>dist</module> </modules> From a2a8078f5f2de8be23348e03d737217baae9e8af Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 14 Oct 2023 17:37:10 +0200 Subject: [PATCH 64/95] :bug: Added escaping for placeholders that should not be parsed --- .../api/utils/messaging/MessageUtils.java | 23 +++++++++++++------ core/pom.xml | 2 +- core/src/main/resources/locales/en_US.yml | 8 +++---- core/src/main/resources/locales/fr_FR.yml | 10 ++++---- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java index fcac0bcd..64be8354 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/MessageUtils.java @@ -24,7 +24,7 @@ public static void sendMessage(@NotNull CommandSender sender, @Nullable String m public static void sendMessage(@NotNull CommandSender sender, @Nullable String message, @NotNull MessageType type, @Nullable PlaceholderRegistry placeholders) { - sendRawMessage(sender, message, placeholders, PlaceholdersContext.of(sender, false, type)); + sendRawMessage(sender, message, placeholders, PlaceholdersContext.of(sender, true, type)); } public static void sendRawMessage(@NotNull CommandSender sender, @Nullable String text, @@ -82,14 +82,23 @@ public static String itemsToFormattedString(String[] items, String separator) { if (output == null) output = new StringBuilder(msg.length()); - String key = matcher.group(1); - String replacement = placeholders.resolve(key, context); String substring = msg.substring(lastAppend, matcher.start()); - colors = ChatColorUtils.getLastColors(colors, substring); output.append(substring); - if (replacement != null) - output.append(RESET_PATTERN.matcher(replacement).replaceAll("§r" + colors)); - lastAppend = matcher.end(); + colors = ChatColorUtils.getLastColors(colors, substring); + + if (matcher.start() != 0 && msg.charAt(matcher.start() - 1) == '\\') { + // means the placeholder has been escaped => we delete the \ character and we continue + // (the unchanged placeholder will get pasted next time the parser encounters + // another placeholder, or at the end) + output.deleteCharAt(output.length() - 1); + } else { + String key = matcher.group(1); + String replacement = placeholders.resolve(key, context); + if (replacement != null) + output.append(RESET_PATTERN.matcher(replacement).replaceAll("§r" + colors)); + + lastAppend = matcher.end(); + } } if (output != null) { diff --git a/core/pom.xml b/core/pom.xml index dce0a225..81ed84ad 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -157,7 +157,7 @@ <dependency> <groupId>fr.mrmicky</groupId> <artifactId>fastboard</artifactId> - <version>2.0.0</version> + <version>2.0.1</version> <scope>compile</scope> </dependency> <dependency> diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 657a5916..22016ff1 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -38,13 +38,13 @@ msg: value: {xp_amount})' writeMobAmount: '§aWrite the amount of mobs to kill:' writeMobName: '§aWrite the custom name of the mob to kill:' - writeChatMessage: '§aWrite required message: (Add "{SLASH}" to the beginning if + writeChatMessage: '§aWrite required message: (Add "\{SLASH}" to the beginning if you want a command.)' writeMessage: '§aWrite the message that will be sent to the player' writeStartMessage: '§aWrite the message that will be sent at the beginning of the quest, "null" if you want the default one or "none" if you want none:' writeEndMsg: '§aWrite the message that will be sent at the end of the quest, - "null" if you want the default one or "none" if you want none. You can use "{rewards}" which + "null" if you want the default one or "none" if you want none. You can use "\{rewards}" which will be replaced with the rewards obtained.' writeEndSound: '§aWrite the sound name that will be played to the player at the end of the quest, "null" if you want the default one or "none" if you want none:' @@ -56,7 +56,7 @@ msg: writeNpcSkinName: '§aWrite the name of the skin of the NPC:' writeQuestName: '§aWrite the name of your quest:' writeCommand: '§aWrite the wanted command: (The command is without the "/" and the - placeholder "{PLAYER}" is supported. It will be replaced with the name of the + placeholder "\{player}" is supported. It will be replaced with the name of the executor.)' writeHologramText: '§aWrite text of the hologram: (Write "none" if you don''t want a hologram and "null" if you want the default text.)' @@ -379,7 +379,7 @@ inv: editMessageType: §eEdit message to write cancelMessage: Cancel sending ignoreCase: Ignore the case of the message - replacePlaceholders: Replace {PLAYER} and placeholders from PAPI + replacePlaceholders: 'Replaces \{PLAYER} and placeholders from PAPI' selectItems: §eEdit required items selectItemsMessage: §eEdit asking message selectItemsComparisons: §eSelect items comparisons (ADVANCED) diff --git a/core/src/main/resources/locales/fr_FR.yml b/core/src/main/resources/locales/fr_FR.yml index 95081747..1d951a1e 100644 --- a/core/src/main/resources/locales/fr_FR.yml +++ b/core/src/main/resources/locales/fr_FR.yml @@ -35,10 +35,10 @@ msg: writeXPGain: '§aÉcrivez le nombre de points d’expérience que le joueur va remporter. (Ancien gain : {xp_amount})' writeMobAmount: '§aEcrivez le nombre de mobs à tuer :' writeMobName: '§aÉcrivez le nom personnalisé du mob à tuer :' - writeChatMessage: '§aÉcrivez le message requis (rajoutez "{SLASH}" au début pour en faire une commande.)' + writeChatMessage: '§aÉcrivez le message requis (rajoutez "\{SLASH}" au début pour en faire une commande.)' writeMessage: '§aÉcrivez le message qui sera envoyé au joueur' writeStartMessage: '§aÉcrivez le message qui sera envoyé au début de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas :' - writeEndMsg: '§aÉcrivez le message qui sera envoyé à la fin de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas. Vous pouvez utiliser "{rewards}" qui sera remplacé par les récompenses obtenues.' + writeEndMsg: '§aÉcrivez le message qui sera envoyé à la fin de la quête, "null" si vous voulez la valeur par défaut ou "none" si vous n''en voulez pas. Vous pouvez utiliser "\{rewards}" qui sera remplacé par les récompenses obtenues.' writeEndSound: '§aÉcrivez le nom du son qui sera joué au joueur à la fin de la quête, "null" si vous voulez le son par défaut ou "none" si vous n''en voulez pas :' writeDescriptionText: '§aEcrivez le texte qui décrira le but de l''étape :' writeStageText: '§aEcrivez le texte qui sera transmis au joueur au début de l''étape :' @@ -46,7 +46,7 @@ msg: writeNpcName: '§aEcrivez le nom du NPC :' writeNpcSkinName: '§aEcrivez le nom du skin du NPC :' writeQuestName: '§aEcrivez le nom de votre quête :' - writeCommand: '§aÉcrivez la commande : (n''écrivez pas le "/" ; le placeholder "{PLAYER}" est pris en charge. Il sera remplacée par le nom du joueur exécuteur.)' + writeCommand: '§aÉcrivez la commande : (n''écrivez pas le "/" ; le placeholder "\{player}" est pris en charge. Il sera remplacée par le nom du joueur exécuteur.)' writeHologramText: '§aEcrivez le texte de l''hologramme. (tapez "none" si vous ne voulez pas d''hologramme, et "null" si vous voulez le texte par défaut.)' writeQuestTimer: '§aRenseignez le temps nécessaire (en minutes) avant de pouvoir refaire la quête. (Tapez "null" si vous voulez le temps par défaut)' writeConfirmMessage: '§aÉcrivez le message de confirmation affiché lorsqu''un joueur est sur le point de démarrer la quête : (Tapez "null" si vous voulez le message par défaut).' @@ -295,7 +295,7 @@ msg: removed: 'Feu d''artifice de quête supprimé !' writeCommandDelay: '§aIndiquez le délai de commande désiré, en ticks.' advancement: - finished: Terminée + finished: Terminé {times_finished} x notStarted: Pas commencée inv: validate: '§b§lValider' @@ -345,7 +345,7 @@ inv: editMessageType: '§eModifier le message à écrire' cancelMessage: Annuler l'envoi ignoreCase: Ignorer la casse du message - replacePlaceholders: Remplacer {PLAYER} et les placeholders de PAPI + replacePlaceholders: 'Remplacer \{PLAYER} et les placeholders de PAPI' selectItems: '§eChoisir les items nécessaires' selectItemsMessage: '§eModifier le message de demande' selectItemsComparisons: '§eSélectionnez les comparaisons d''items (AVANCÉ)' From 5f3470a7a15883c8689f209774b55cfe08e101f3 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 24 Oct 2023 14:47:26 +0200 Subject: [PATCH 65/95] :bug: Fixed blockdatas editor not working --- .../quests/blocks/BQBlocksManagerImplementation.java | 6 ++++-- .../fr/skytasul/quests/gui/blocks/SelectBlockGUI.java | 3 ++- .../skytasul/quests/utils/compatibility/Post1_13.java | 11 +---------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java index 9ce4339a..e9cfec2d 100644 --- a/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/blocks/BQBlocksManagerImplementation.java @@ -1,7 +1,9 @@ package fr.skytasul.quests.blocks; import java.util.*; +import org.bukkit.Bukkit; import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.google.common.collect.BiMap; @@ -35,7 +37,7 @@ private void registerDefaultTypes() { registerBlockType("", materialType); if (MinecraftVersion.MAJOR >= 13) { - blockdataType = (string, options) -> new Post1_13.BQBlockData(options, string); + blockdataType = (string, options) -> new Post1_13.BQBlockData(options, Bukkit.createBlockData(string)); registerBlockType("blockdata", blockdataType); tagType = (string, options) -> new Post1_13.BQBlockTag(options, string); @@ -155,7 +157,7 @@ public Located next() { return new BQBlockMaterial(new BQBlockOptions(materialType, customName), material); } - public @NotNull BQBlock createBlockdata(@NotNull String blockData, @Nullable String customName) { + public @NotNull BQBlock createBlockdata(@NotNull BlockData blockData, @Nullable String customName) { return new Post1_13.BQBlockData(new BQBlockOptions(blockdataType, customName), blockData); } 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 6e02ae98..330ef1c7 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 @@ -165,7 +165,8 @@ private void doneClick(LayoutedClickEvent event) { event.close(); BQBlock block; if (blockData != null) { - block = BeautyQuests.getInstance().getAPI().getBlocksManager().createBlockdata(blockData, customName); + block = BeautyQuests.getInstance().getAPI().getBlocksManager() + .createBlockdata(Bukkit.createBlockData(type.parseMaterial(), blockData), customName); } else if (tag != null) { block = BeautyQuests.getInstance().getAPI().getBlocksManager().createTag(tag, customName); } else { diff --git a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java index e8504286..891be529 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java +++ b/core/src/main/java/fr/skytasul/quests/utils/compatibility/Post1_13.java @@ -1,12 +1,7 @@ package fr.skytasul.quests.utils.compatibility; import java.util.Set; -import org.bukkit.Bukkit; -import org.bukkit.Color; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Particle; -import org.bukkit.Tag; +import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import fr.skytasul.quests.api.blocks.BQBlock; @@ -39,10 +34,6 @@ public static class BQBlockData extends BQBlock { private final BlockData data; - public BQBlockData(BQBlockOptions options, String stringData) { - this(options, Bukkit.createBlockData(stringData)); - } - public BQBlockData(BQBlockOptions options, BlockData data) { super(options); this.data = data; From e06b09052d4fee59744622e24148a61baa371ae8 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 25 Oct 2023 20:49:51 +0200 Subject: [PATCH 66/95] :arrow_up: Added support for ZNPCsPlus 2.0 * and changed numeric ids to string ids for NPCs --- .../quests/api/npcs/BqInternalNpc.java | 7 +- .../quests/api/npcs/BqInternalNpcFactory.java | 8 +- .../quests/api/npcs/BqNpcManager.java | 6 +- .../quests/api/stages/types/Locatable.java | 152 +++++++++--------- .../quests/npcs/BqNpcImplementation.java | 116 ++++++------- .../npcs/BqNpcManagerImplementation.java | 51 +++--- .../fr/skytasul/quests/utils/QuestUtils.java | 30 +++- integrations/pom.xml | 32 ++-- .../integrations/IntegrationsLoader.java | 20 ++- .../quests/integrations/npcs/BQCitizens.java | 20 +-- .../integrations/npcs/BQServerNPCs.java | 16 +- .../quests/integrations/npcs/BQZNPCsPlus.java | 90 +++++------ .../integrations/npcs/BQZNPCsPlusOld.java | 132 +++++++++++++++ 13 files changed, 421 insertions(+), 259 deletions(-) create mode 100755 integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlusOld.java diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java index a3a0081c..425d7ce4 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpc.java @@ -3,22 +3,23 @@ import org.bukkit.Location; import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface BqInternalNpc { - public int getInternalId(); + public String getInternalId(); public abstract @NotNull String getName(); public abstract boolean isSpawned(); - public abstract @NotNull Entity getEntity(); + public abstract @Nullable Entity getEntity(); public abstract @NotNull Location getLocation(); /** * Sets the "paused" state of the NPC navigation - * + * * @param paused should the navigation be paused * @return <code>true</code> if the navigation was paused before this call, <code>false</code> * otherwise diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java index 815c099c..83fbfe7b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqInternalNpcFactory.java @@ -19,16 +19,16 @@ public interface BqInternalNpcFactory { boolean isNPC(@NotNull Entity entity); @NotNull - Collection<@NotNull Integer> getIDs(); + Collection<@NotNull String> getIDs(); @Nullable - BqInternalNpc fetchNPC(int id); + BqInternalNpc fetchNPC(String id); - default void npcClicked(@Nullable Cancellable event, int npcID, @NotNull Player p, @NotNull NpcClickType click) { + default void npcClicked(@Nullable Cancellable event, String npcID, @NotNull Player p, @NotNull NpcClickType click) { QuestsPlugin.getPlugin().getNpcManager().npcClicked(this, event, npcID, p, click); } - default void npcRemoved(int id) { + default void npcRemoved(String id) { QuestsPlugin.getPlugin().getNpcManager().npcRemoved(this, id); } diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java index 6900dc63..7e8fc5b1 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/BqNpcManager.java @@ -34,10 +34,10 @@ BqNpc createNPC(@NotNull BqInternalNpcFactoryCreatable internalFactory, @NotNull @Nullable BqNpc getById(String id); - void npcRemoved(@NotNull BqInternalNpcFactory internalFactory, int id); + void npcRemoved(@NotNull BqInternalNpcFactory internalFactory, String internalId); - void npcClicked(@NotNull BqInternalNpcFactory internalFactory, @Nullable Cancellable event, int npcID, @NotNull Player p, - @NotNull NpcClickType click); + void npcClicked(@NotNull BqInternalNpcFactory internalFactory, @Nullable Cancellable event, String internalId, + @NotNull Player p, @NotNull NpcClickType click); void reload(@NotNull BqInternalNpcFactory internalFactory); diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java index a76d5a31..a78fb585 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java @@ -4,10 +4,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.Spliterator; +import java.util.*; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Entity; @@ -28,11 +25,11 @@ * located objects can be retrieved. */ public interface Locatable { - + /** * If no indication should be displayed to the <code>player</code>, * then this method should return <code>false</code>. - * + * * @param player Player to test for indications * @return <code>true</code> if location indications should be displayed * to the player, <code>false</code> otherwise. @@ -40,25 +37,25 @@ public interface Locatable { default boolean isShown(@NotNull Player player) { return true; } - + /** * Indicates if the Located instances gotten from {@link PreciseLocatable#getLocated()} * and {@link MultipleLocatable#getNearbyLocated(MultipleLocatable.NearbyFetcher)} * can be safely retrieved from an asynchronous thread. - * + * * @return <code>true</code> <b>only if</b> the Located fetch operations can * be done asynchronously, <code>false</code> otherwise. */ default boolean canBeFetchedAsynchronously() { return true; } - + /** * This interface indicates that an object can provide a unique and precise location, * no matter the player. */ interface PreciseLocatable extends Locatable { - + /** * Gets the uniquely located object. * <p> @@ -68,15 +65,15 @@ interface PreciseLocatable extends Locatable { */ @Nullable Located getLocated(); - + } - + /** * This interface indicates that an object can provide multiple locations depending on * factors such as a center and a maximum distance, detailed in {@link NearbyFetcher}. */ interface MultipleLocatable extends Locatable { - + /** * Gets a {@link Spliterator} of all targets in the region specified by * the {@link NearbyFetcher} parameter. @@ -85,67 +82,67 @@ interface MultipleLocatable extends Locatable { */ @Nullable Spliterator<@NotNull Located> getNearbyLocated(@NotNull NearbyFetcher fetcher); - + /** * This POJO contains informations on the region from where * the {@link MultipleLocatable} object has to find its targets. */ interface NearbyFetcher { - + @NotNull Location getCenter(); - + double getMaxDistance(); - + default double getMaxDistanceSquared() { return getMaxDistance() * getMaxDistance(); } - + default boolean isTargeting(@NotNull LocatedType type) { return true; } - + static @NotNull NearbyFetcher create(@NotNull Location location, double maxDistance) { return new NearbyFetcherImpl(location, maxDistance, null); } - + static @NotNull NearbyFetcher create(@NotNull Location location, double maxDistance, @Nullable LocatedType targetType) { return new NearbyFetcherImpl(location, maxDistance, targetType); } - + class NearbyFetcherImpl implements NearbyFetcher { private final Location center; private final double maxDistance; private final LocatedType targetType; - + public NearbyFetcherImpl(Location center, double maxDistance, LocatedType targetType) { this.center = center; this.maxDistance = maxDistance; this.targetType = targetType; } - + @Override public Location getCenter() { return center; } - + @Override public double getMaxDistance() { return maxDistance; } - + @Override public boolean isTargeting(LocatedType type) { return targetType == null || targetType == type; } - + } - + } - + } - + /** * This annotation indicates which types of {@link Located} objects can be retrieved from the attached class. * <p> @@ -161,107 +158,106 @@ public boolean isTargeting(LocatedType type) { @NotNull LocatedType @NotNull [] types() default {LocatedType.ENTITY, LocatedType.BLOCK, LocatedType.OTHER}; } - + /** * Represents something that is locatable on a world. */ interface Located { - + @NotNull Location getLocation(); - + @NotNull LocatedType getType(); - + static @NotNull Located create(@NotNull Location location) { return new LocatedImpl(location); } - + class LocatedImpl implements Located { protected Location location; - + public LocatedImpl(Location location) { this.location = location; } - + @Override public Location getLocation() { return location.clone(); } - + @Override public LocatedType getType() { return LocatedType.OTHER; } - + @Override public int hashCode() { return location.hashCode(); } - + @Override public boolean equals(Object obj) { if (!(obj instanceof LocatedImpl)) return false; LocatedImpl other = (LocatedImpl) obj; return other.location.equals(location); } - + } - + interface LocatedEntity extends Located { - - @NotNull + + @Nullable Entity getEntity(); - - @Override - default @NotNull Location getLocation() { - Entity entity = getEntity(); - return entity == null ? null : entity.getLocation(); - } - + @Override default @NotNull LocatedType getType() { return LocatedType.ENTITY; } - + static @NotNull LocatedEntity create(Entity entity) { return new LocatedEntityImpl(entity); } - + class LocatedEntityImpl implements LocatedEntity { private Entity entity; - - public LocatedEntityImpl(Entity entity) { - this.entity = entity; + + public LocatedEntityImpl(@NotNull Entity entity) { + this.entity = Objects.requireNonNull(entity); } - + @Override public Entity getEntity() { return entity; } - + + @Override + public @NotNull Location getLocation() { + return entity.getLocation(); + } + @Override public int hashCode() { return entity.hashCode(); } - + @Override public boolean equals(Object obj) { if (!(obj instanceof LocatedEntityImpl)) return false; LocatedEntityImpl other = (LocatedEntityImpl) obj; return other.entity.equals(entity); } - + } - + } - + interface LocatedBlock extends Located { - + default @NotNull Block getBlock() { return getLocation().getBlock(); } - + default @Nullable Block getBlockNullable() { Location location = getLocation(); if (location == null || location.getWorld() == null) @@ -273,25 +269,25 @@ interface LocatedBlock extends Located { default @NotNull LocatedType getType() { return LocatedType.BLOCK; } - + static @NotNull LocatedBlock create(@NotNull Block block) { return new LocatedBlockImpl(block); } - + static @NotNull LocatedBlock create(@NotNull Location location) { return new LocatedBlockLocationImpl(location); } - + class LocatedBlockLocationImpl extends LocatedImpl implements LocatedBlock { public LocatedBlockLocationImpl(Location location) { super(location); } - + @Override public Block getBlock() { return location.getBlock(); } - + @Override public LocatedType getType() { // As LocatedBlockImpl inherits getType() @@ -299,9 +295,9 @@ public LocatedType getType() { // we redefine the method correctly. return LocatedType.BLOCK; } - + } - + class LocatedBlockImpl implements LocatedBlock { private Block block; @@ -328,20 +324,20 @@ public Block getBlockNullable() { } } - + } - + enum LocatedType { BLOCK, ENTITY, OTHER; } - + /** * Allows to check if some {@link LocatedType}s can be retrieved from a {@link Locatable} class. * <p> * If the Class <code>clazz</code> does not have a {@link LocatableType} annotation attached, * then this will return <code>true</code> as it is assumed that it can retrieve all kinds of * located types. - * + * * @param clazz Class implementing the {@link Locatable} interface for which the <code>types</code> * will get tested. * @param types Array of {@link LocatedType}s that must be checked they can be retrieved from @@ -353,7 +349,7 @@ enum LocatedType { static boolean hasLocatedTypes(@NotNull Class<? extends Locatable> clazz, @NotNull LocatedType @NotNull... types) { Set<LocatedType> toTest = new HashSet<>(Arrays.asList(types)); boolean foundAnnotation = false; - + Class<?> superclass = clazz; do { LocatableType annotation = superclass.getDeclaredAnnotation(Locatable.LocatableType.class); @@ -365,13 +361,13 @@ static boolean hasLocatedTypes(@NotNull Class<? extends Locatable> clazz, @NotNu } } }while ((superclass = superclass.getSuperclass()) != null); - + if (!foundAnnotation) { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Class " + clazz.getName() + " does not have the @LocatableType annotation."); return true; } - + return false; } - + } 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 76d12ae2..45062a1d 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcImplementation.java @@ -1,17 +1,7 @@ package fr.skytasul.quests.npcs; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; import java.util.function.Predicate; import org.apache.commons.lang.StringUtils; import org.bukkit.Location; @@ -47,15 +37,15 @@ import fr.skytasul.quests.utils.QuestUtils; public class BqNpcImplementation implements Located.LocatedEntity, BqNpc { - + private Map<Quest, List<Player>> quests = new TreeMap<>(); private Set<QuestPool> pools = new TreeSet<>(); - + private List<Entry<Player, Object>> hiddenTickets = new ArrayList<>(); private Map<Object, Predicate<Player>> startable = new HashMap<>(); - + private BukkitTask launcheableTask; - + /* Holograms */ private boolean debug = false; private BukkitTask hologramsTask; @@ -92,7 +82,7 @@ public BqNpcImplementation(@NotNull WrappedInternalNpc wrappedNpc) { holograms = hologramText.enabled || hologramLaunch.enabled || hologramLaunchNo.enabled || hologramPool.enabled; launcheableTask = startLauncheableTasks(); } - + public @NotNull WrappedInternalNpc getWrappedNpc() { return wrappedNpc; } @@ -108,7 +98,7 @@ public BqInternalNpc getNpc() { } @Override - public @NotNull Entity getEntity() { + public @Nullable Entity getEntity() { return getNpc().getEntity(); } @@ -130,21 +120,21 @@ public BqInternalNpc getNpc() { private BukkitTask startLauncheableTasks() { return new BukkitRunnable() { private int timer = 0; - + @Override public void run() { if (!getNpc().isSpawned()) return; if (!(getEntity() instanceof LivingEntity)) return; LivingEntity en = (LivingEntity) getEntity(); - + if (timer-- == 0) { timer = QuestsConfiguration.getConfig().getQuestsConfig().requirementUpdateTime(); return; } - + quests.values().forEach(List::clear); - + Set<Player> playersInRadius = new HashSet<>(); Location lc = en.getLocation(); for (Player p : lc.getWorld().getPlayers()) { @@ -161,12 +151,12 @@ public void run() { } } } - + if (QuestsConfigurationImplementation.getConfiguration().showStartParticles()) { quests.forEach((quest, players) -> QuestsConfigurationImplementation.getConfiguration() .getParticleStart().send(en, players)); } - + if (hologramPool.canAppear) { for (Player p : playersInRadius) { boolean visible = false; @@ -213,11 +203,11 @@ public void run() { hologramLaunch.setVisible(launcheable); hologramLaunchNo.setVisible(unlauncheable); } - + } }.runTaskTimer(BeautyQuests.getInstance(), 20L, 20L); } - + private BukkitTask startHologramsTask() { return new BukkitRunnable() { @Override @@ -230,7 +220,7 @@ public void run() { return; } hologramsRemoved = false; - + if (hologramText.canAppear && hologramText.visible) hologramText.refresh(en); if (hologramLaunch.canAppear) hologramLaunch.refresh(en); if (hologramLaunchNo.canAppear) hologramLaunchNo.refresh(en); @@ -238,24 +228,24 @@ public void run() { } }.runTaskTimer(BeautyQuests.getInstance(), 20L, 1L); } - + @Override public Set<Quest> getQuests() { return quests.keySet(); } - + public Hologram getHologramText() { return hologramText; } - + public Hologram getHologramLaunch() { return hologramLaunch; } - + public Hologram getHologramLaunchNo() { return hologramLaunchNo; } - + public void addQuest(Quest quest) { if (quests.containsKey(quest)) return; quests.put(quest, new ArrayList<>()); @@ -266,7 +256,7 @@ public void addQuest(Quest quest) { addStartablePredicate(p -> quest.canStart(p, false), quest); updatedObjects(); } - + public boolean removeQuest(Quest quest) { boolean b = quests.remove(quest) == null; removeStartablePredicate(quest); @@ -277,25 +267,25 @@ public boolean removeQuest(Quest quest) { } return b; } - + @Override public boolean hasQuestStarted(Player p) { PlayerAccount acc = PlayersManager.getPlayerAccount(p); return quests.keySet().stream().anyMatch(quest -> quest.hasStarted(acc)); } - + @Override public Set<QuestPool> getPools() { return pools; } - + public void addPool(QuestPool pool) { if (!pools.add(pool)) return; if (hologramPool.enabled && (pool.getHologram() != null)) hologramPool.setText(pool.getHologram()); addStartablePredicate(pool::canGive, pool); updatedObjects(); } - + public boolean removePool(QuestPool pool) { boolean b = pools.remove(pool); removeStartablePredicate(pool); @@ -303,22 +293,22 @@ public boolean removePool(QuestPool pool) { if (pools.isEmpty()) hologramPool.delete(); return b; } - + @Override public void addStartablePredicate(Predicate<Player> predicate, Object holder) { startable.put(holder, predicate); } - + @Override public void removeStartablePredicate(Object holder) { startable.remove(holder); } - + @Override public void hideForPlayer(Player p, Object holder) { hiddenTickets.add(new AbstractMap.SimpleEntry<>(p, holder)); } - + @Override public void removeHiddenForPlayer(Player p, Object holder) { for (Iterator<Entry<Player, Object>> iterator = hiddenTickets.iterator(); iterator.hasNext();) { @@ -329,12 +319,12 @@ public void removeHiddenForPlayer(Player p, Object holder) { } } } - + @Override public boolean canGiveSomething(Player p) { return startable.values().stream().anyMatch(predicate -> predicate.test(p)); } - + private void removeHolograms(boolean cancelRefresh) { hologramText.delete(); hologramLaunch.delete(); @@ -346,11 +336,11 @@ private void removeHolograms(boolean cancelRefresh) { hologramsTask = null; } } - + private boolean isEmpty() { return quests.isEmpty() && pools.isEmpty(); } - + private void updatedObjects() { if (isEmpty()) { removeHolograms(true); @@ -358,7 +348,7 @@ private void updatedObjects() { hologramsTask = startHologramsTask(); } } - + public void unload() { removeHolograms(true); if (launcheableTask != null) { @@ -366,7 +356,7 @@ public void unload() { launcheableTask = null; } } - + public void delete(String cause) { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Removing NPC Starter " + getId()); for (Quest qu : quests.keySet()) { @@ -382,13 +372,13 @@ public void delete(String cause) { } unload(); } - + public void toggleDebug() { if (debug) debug = false; else debug = true; } - + @Override public String toString() { String npcInfo = "NPC " + getId() + ", " + quests.size() + " quests, " + pools.size() + " pools"; @@ -406,28 +396,28 @@ public String toString() { } return npcInfo + " " + hologramsInfo; } - + public class Hologram { final boolean enabled; boolean visible; boolean canAppear; AbstractHolograms<?>.BQHologram hologram; - + String text; ItemStack item; - + public Hologram(boolean visible, boolean enabled, String text) { this.visible = visible; this.enabled = enabled; setText(text); } - + public Hologram(boolean visible, boolean enabled, ItemStack item) { this.visible = visible; this.enabled = enabled; setItem(item); } - + public void refresh(LivingEntity en) { Location lc = QuestUtils.upLocationForEntity(en, getYAdd()); if (debug) System.out.println("refreshing " + toString() + " (hologram null: " + (hologram == null) + ")"); @@ -437,26 +427,26 @@ public void refresh(LivingEntity en) { hologram.teleport(lc); } } - + public double getYAdd() { return item == null ? 0 : 1; } - + public void setVisible(List<Player> players) { if (hologram != null) hologram.setPlayersVisible(players); } - + public void setVisible(Player p, boolean visibility) { if (hologram != null) hologram.setPlayerVisibility(p, visibility); } - + public void setText(String text) { if (Objects.equals(text, this.text)) return; this.text = text; canAppear = enabled && !StringUtils.isEmpty(text) && !"none".equals(text); delete(); // delete to regenerate with new text } - + public void setItem(ItemStack item) { if (Objects.equals(item, this.item)) return; this.item = item; @@ -466,21 +456,21 @@ public void setItem(ItemStack item) { this.text = item.getItemMeta().getDisplayName(); delete(); // delete to regenerate with new item } - + public void create(Location lc) { if (hologram != null) return; hologram = QuestsAPI.getAPI().getHologramsManager().createHologram(lc, visible); if (text != null) hologram.appendTextLine(text); if (item != null) hologram.appendItem(item); } - + public void delete() { if (debug) System.out.println("deleting " + toString()); if (hologram == null) return; hologram.delete(); hologram = null; } - + @Override public String toString() { if (!enabled) return "disabled"; @@ -490,7 +480,7 @@ public String toString() { + (text == null ? "no text" : "text=" + text) + ", " + (hologram == null ? " not spawned" : "spawned"); } - + } - + } \ No newline at end of file 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 c8faea4a..44fd5c4a 100644 --- a/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/npcs/BqNpcManagerImplementation.java @@ -3,6 +3,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -23,6 +24,7 @@ public class BqNpcManagerImplementation implements BqNpcManager { private static final String SEPARATOR = "#"; + private static final Pattern FACTORY_KEY_PATTERN = Pattern.compile("[a-zA-Z0-9_-]*"); private final BiMap<String, BqInternalNpcFactory> internalFactories = HashBiMap.create(); private final Map<String, BqNpcImplementation> npcs = new HashMap<>(); @@ -33,8 +35,8 @@ public class BqNpcManagerImplementation implements BqNpcManager { return internalFactories.inverse().get(internalFactory); } - private String getNpcId(BqInternalNpcFactory factory, int id) { - return getFactoryKey(factory) + SEPARATOR + id; + private String getNpcId(BqInternalNpcFactory factory, String internalId) { + return getFactoryKey(factory) + SEPARATOR + internalId; } private BqInternalNpcFactory getMigrationFactory() { @@ -58,6 +60,8 @@ public boolean isEnabled() { public void addInternalFactory(@NotNull String key, @NotNull BqInternalNpcFactory internalFactory) { if (internalFactories.containsKey(key)) throw new IllegalArgumentException("Npc factory " + key + " is already registered"); + if (!FACTORY_KEY_PATTERN.matcher(key).matches()) + throw new IllegalArgumentException("Invalid factory key " + key); QuestsPlugin.getPlugin().getLoggerExpanded().info("Adding " + key + " as a npc factory"); internalFactories.put(key, internalFactory); @@ -97,29 +101,29 @@ public boolean isNPC(@NotNull Entity entity) { @Override public @Nullable BqNpcImplementation getById(String id) { BqInternalNpcFactory factory; - int npcId; + String internalId; int separatorIndex = id.indexOf(SEPARATOR); if (separatorIndex == -1) { // TODO migration 1.0 QuestsPlugin.getPlugin().getLoggerExpanded() .debug("Loading NPC with id " + id + " from a previous version of the plugin."); factory = getMigrationFactory(); - npcId = Integer.parseInt(id); + internalId = id; } else { String factoryKey = id.substring(0, separatorIndex); factory = internalFactories.get(factoryKey); - npcId = Integer.parseInt(id.substring(separatorIndex + SEPARATOR.length())); + internalId = id.substring(separatorIndex + SEPARATOR.length()); } if (factory == null) throw new IllegalArgumentException("Cannot find factory for NPC " + id + ". Is your NPC plugin installed?"); - return getByFactoryAndId(factory, npcId); + return getByFactoryAndId(factory, internalId); } - public @Nullable BqNpcImplementation getByFactoryAndId(@NotNull BqInternalNpcFactory factory, int id) { - return npcs.computeIfAbsent(getNpcId(factory, id), strId -> { - BqInternalNpc npc = factory.fetchNPC(id); + public @Nullable BqNpcImplementation getByFactoryAndId(@NotNull BqInternalNpcFactory factory, String internalId) { + return npcs.computeIfAbsent(getNpcId(factory, internalId), strId -> { + BqInternalNpc npc = factory.fetchNPC(internalId); if (npc == null) return null; @@ -128,23 +132,26 @@ public boolean isNPC(@NotNull Entity entity) { } @Override - public void npcRemoved(BqInternalNpcFactory npcFactory, int id) { - String npcId = getNpcId(npcFactory, id); + public void npcRemoved(BqInternalNpcFactory npcFactory, String internalId) { + String npcId = getNpcId(npcFactory, internalId); BqNpcImplementation npc = npcs.get(npcId); - if (npc == null) return; + if (npc == null) + return; npc.delete("NPC " + npcId + " removed"); npcs.remove(npcId); } @Override - public void npcClicked(BqInternalNpcFactory npcFactory, @Nullable Cancellable event, int npcID, @NotNull Player p, - @NotNull NpcClickType click) { + public void npcClicked(BqInternalNpcFactory npcFactory, @Nullable Cancellable event, String internalId, + @NotNull Player p, @NotNull NpcClickType click) { if (event != null && event.isCancelled()) return; - BQNPCClickEvent newEvent = new BQNPCClickEvent(getByFactoryAndId(npcFactory, npcID), p, click); - Bukkit.getPluginManager().callEvent(newEvent); - if (event != null) - event.setCancelled(newEvent.isCancelled()); + + BQNPCClickEvent newEvent = new BQNPCClickEvent(getByFactoryAndId(npcFactory, internalId), p, click); + if (event == null) + QuestUtils.runOrSync(() -> Bukkit.getPluginManager().callEvent(newEvent)); + else + QuestUtils.tunnelEventCancelling(event, newEvent); } @Override @@ -152,7 +159,7 @@ public void reload(BqInternalNpcFactory npcFactory) { npcs.forEach((id, npc) -> { if (npc.getWrappedNpc().factory != npcFactory) return; - BqInternalNpc newInternal = npcFactory.fetchNPC(npc.getWrappedNpc().id); + BqInternalNpc newInternal = npcFactory.fetchNPC(npc.getWrappedNpc().internalId); if (newInternal == null) { QuestsPlugin.getPlugin().getLoggerExpanded() .warning("Unable to find NPC with ID " + id + " after a NPCs manager reload."); @@ -170,17 +177,17 @@ public void unload() { class WrappedInternalNpc { private final BqInternalNpcFactory factory; - private final int id; + private final String internalId; private BqInternalNpc npc; public WrappedInternalNpc(BqInternalNpcFactory factory, BqInternalNpc npc) { this.factory = factory; this.npc = npc; - this.id = npc.getInternalId(); + this.internalId = npc.getInternalId(); } public @NotNull String getId() { - return getNpcId(factory, id); + return getNpcId(factory, internalId); } public @NotNull BqInternalNpc getNpc() { 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 7f4e51b2..56e3310c 100644 --- a/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java +++ b/core/src/main/java/fr/skytasul/quests/utils/QuestUtils.java @@ -2,6 +2,8 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.function.BiConsumer; import java.util.function.Consumer; import org.bukkit.Bukkit; @@ -10,12 +12,15 @@ import org.bukkit.entity.Firework; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.scoreboard.DisplaySlot; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.BeautyQuests; import fr.skytasul.quests.QuestsConfigurationImplementation; import fr.skytasul.quests.api.QuestsConfiguration; @@ -24,7 +29,9 @@ import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.utils.nms.NMS; -public class QuestUtils { +public final class QuestUtils { + + private QuestUtils() {} public static void openBook(Player p, ItemStack book) { int slot = p.getInventory().getHeldItemSlot(); @@ -89,6 +96,27 @@ public static void runAsync(Runnable run) { Bukkit.getScheduler().runTaskAsynchronously(BeautyQuests.getInstance(), run); } + public static void tunnelEventCancelling(@NotNull Cancellable eventFrom, @NotNull Event eventTo) { + Cancellable eventToCancellable = (Cancellable) eventTo; // to force type checking at the beginning + + CompletableFuture<Boolean> cancelled = new CompletableFuture<>(); + QuestUtils.runOrSync(() -> { + try { + Bukkit.getPluginManager().callEvent(eventTo); + cancelled.complete(eventToCancellable.isCancelled()); + } catch (Exception ex) { + cancelled.completeExceptionally(ex); + } + }); + try { + eventFrom.setCancelled(cancelled.get()); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } catch (ExecutionException ex) { + ex.printStackTrace(); + } + } + public static void playPluginSound(Player p, String sound, float volume) { playPluginSound(p, sound, volume, 1); } diff --git a/integrations/pom.xml b/integrations/pom.xml index c3ee4f8c..cb5917cb 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -14,7 +14,8 @@ <repositories> <repository> <id>placeholderapi</id> - <url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url> + <url> + https://repo.extendedclip.com/content/repositories/placeholderapi/</url> </repository> <repository> <id>dynmap</id> @@ -38,7 +39,8 @@ </repository> <repository> <id>teamvk-repo</id> - <url>https://raw.githubusercontent.com/TeamVK/maven-repository/master/release/</url> + <url> + https://raw.githubusercontent.com/TeamVK/maven-repository/master/release/</url> </repository> <repository> <id>lumine</id> @@ -68,16 +70,20 @@ <id>phoenix</id> <url>https://nexus.phoenixdevt.fr/repository/maven-public/</url> </repository> + <repository> + <id>pyr-snapshots</id> + <url>https://repo.pyr.lol/snapshots</url> + </repository> </repositories> <dependencies> - <dependency> - <groupId>fr.skytasul</groupId> - <artifactId>beautyquests-api</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - + <dependency> + <groupId>fr.skytasul</groupId> + <artifactId>beautyquests-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.jetbrains</groupId> <artifactId>annotations</artifactId> @@ -91,7 +97,7 @@ <version>1.19.4-R0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> - + <dependency> <groupId>net.citizensnpcs</groupId> <artifactId>citizens-main</artifactId> @@ -117,6 +123,12 @@ <version>1.0.8</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>lol.pyr</groupId> + <artifactId>znpcsplus-api</artifactId> + <version>2.0.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> <dependency> <groupId>com.github.MilkBowl</groupId> <artifactId>VaultAPI</artifactId> 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 0114ad68..b7e94780 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/IntegrationsLoader.java @@ -19,10 +19,7 @@ import fr.skytasul.quests.integrations.mcmmo.McCombatLevelRequirement; import fr.skytasul.quests.integrations.mcmmo.McMMOSkillRequirement; import fr.skytasul.quests.integrations.mobs.*; -import fr.skytasul.quests.integrations.npcs.BQCitizens; -import fr.skytasul.quests.integrations.npcs.BQSentinel; -import fr.skytasul.quests.integrations.npcs.BQServerNPCs; -import fr.skytasul.quests.integrations.npcs.BQZNPCsPlus; +import fr.skytasul.quests.integrations.npcs.*; import fr.skytasul.quests.integrations.placeholders.PapiMessageProcessor; import fr.skytasul.quests.integrations.placeholders.PlaceholderRequirement; import fr.skytasul.quests.integrations.placeholders.QuestsPlaceholders; @@ -56,8 +53,7 @@ public IntegrationsLoader() { manager.addDependency(new BQDependency("ServersNPC", () -> QuestsAPI.getAPI().addNpcFactory("znpcs", new BQServerNPCs()), null, this::isZnpcsVersionValid)); - manager.addDependency( - new BQDependency("ZNPCsPlus", () -> QuestsAPI.getAPI().addNpcFactory("znpcsplus", new BQZNPCsPlus()))); + manager.addDependency(new BQDependency("ZNPCsPlus", this::registerZnpcsPlus)); manager.addDependency(new BQDependency("Citizens", () -> { QuestsAPI.getAPI().addNpcFactory("citizens", new BQCitizens()); @@ -217,6 +213,18 @@ private boolean isZnpcsVersionValid(Plugin plugin) { return false; } + private void registerZnpcsPlus() { + try { + Class.forName("lol.pyr.znpcsplus.api.NpcApiProvider"); + QuestsAPI.getAPI().addNpcFactory("znpcsplus", new BQZNPCsPlus()); + } catch (ClassNotFoundException ex) { + QuestsAPI.getAPI().addNpcFactory("znpcsplus", new BQZNPCsPlusOld()); // TODO remove, old version of znpcs+ + + QuestsPlugin.getPlugin().getLoggerExpanded() + .warning("Your version of ZNPCsPlus will soon not be supported by BeautyQuests."); + } + } + public IntegrationsConfiguration getConfig() { return config; } diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java index 4b440dd0..200b5c5b 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQCitizens.java @@ -38,34 +38,36 @@ public boolean isNPC(Entity entity) { } @Override - public BqInternalNpc fetchNPC(int id) { - NPC npc = CitizensAPI.getNPCRegistry().getById(id); + public BqInternalNpc fetchNPC(String internalId) { + NPC npc = CitizensAPI.getNPCRegistry().getById(Integer.parseInt(internalId)); return npc == null ? null : new BQCitizensNPC(npc); } @Override - public Collection<Integer> getIDs() { - return StreamSupport.stream(CitizensAPI.getNPCRegistry().sorted().spliterator(), false).map(NPC::getId).collect(Collectors.toList()); + public Collection<String> getIDs() { + return StreamSupport.stream(CitizensAPI.getNPCRegistry().sorted().spliterator(), false) + .map(npc -> Integer.toString(npc.getId())) + .collect(Collectors.toList()); } @EventHandler (priority = EventPriority.HIGHEST) public void onNPCRightClick(NPCRightClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - npcClicked(e, e.getNPC().getId(), e.getClicker(), + npcClicked(e, Integer.toString(e.getNPC().getId()), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_RIGHT : NpcClickType.RIGHT); } @EventHandler (priority = EventPriority.HIGHEST) public void onNPCLeftClick(NPCLeftClickEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - npcClicked(e, e.getNPC().getId(), e.getClicker(), + npcClicked(e, Integer.toString(e.getNPC().getId()), e.getClicker(), e.getClicker().isSneaking() ? NpcClickType.SHIFT_LEFT : NpcClickType.LEFT); } @EventHandler public void onNPCRemove(NPCRemoveEvent e) { if (e.getNPC().getOwningRegistry() != CitizensAPI.getNPCRegistry()) return; - npcRemoved(e.getNPC().getId()); + npcRemoved(Integer.toString(e.getNPC().getId())); } @EventHandler @@ -108,8 +110,8 @@ public NPC getCitizensNPC() { } @Override - public int getInternalId() { - return npc.getId(); + public String getInternalId() { + return Integer.toString(npc.getId()); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java index 475df8ca..c8f052da 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQServerNPCs.java @@ -35,8 +35,10 @@ public int getTimeToWaitForNPCs() { } @Override - public Collection<Integer> getIDs() { - return NPC.all().stream().map(x -> x.getNpcPojo().getId()).collect(Collectors.toList()); + public Collection<String> getIDs() { + return NPC.all().stream() + .map(x -> Integer.toString(x.getNpcPojo().getId())) + .collect(Collectors.toList()); } @Override @@ -50,8 +52,8 @@ public boolean isNPC(Entity entity) { } @Override - public BqInternalNpc fetchNPC(int id) { - NPC npc = NPC.find(id); + public BqInternalNpc fetchNPC(String internalId) { + NPC npc = NPC.find(Integer.parseInt(internalId)); return npc == null ? null : new BQServerNPC(npc); } @@ -76,7 +78,7 @@ public boolean isValidEntityType(EntityType type) { @EventHandler public void onInteract(NPCInteractEvent e) { - npcClicked(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), + npcClicked(null, Integer.toString(e.getNpc().getNpcPojo().getId()), e.getPlayer(), NpcClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); } @@ -93,8 +95,8 @@ public NPC getServerNPC() { } @Override - public int getInternalId() { - return npc.getNpcPojo().getId(); + public String getInternalId() { + return Integer.toString(npc.getNpcPojo().getId()); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java index 0bf3f699..da24236b 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.integrations.npcs; -import java.util.Arrays; import java.util.Collection; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -12,112 +8,100 @@ import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import fr.skytasul.quests.api.npcs.BqInternalNpc; import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; import fr.skytasul.quests.api.npcs.NpcClickType; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.NPCModel; -import io.github.znetworkw.znpcservers.npc.NPCSkin; -import io.github.znetworkw.znpcservers.npc.NPCType; -import io.github.znetworkw.znpcservers.npc.interaction.NPCInteractEvent; -import lol.pyr.znpcsplus.ZNPCsPlus; +import lol.pyr.znpcsplus.api.NpcApiProvider; +import lol.pyr.znpcsplus.api.event.NpcInteractEvent; +import lol.pyr.znpcsplus.api.interaction.InteractionType; +import lol.pyr.znpcsplus.api.npc.NpcEntry; +import lol.pyr.znpcsplus.util.NpcLocation; public class BQZNPCsPlus implements BqInternalNpcFactoryCreatable, Listener { - private Cache<Integer, Boolean> cachedNpcs = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); - @Override public int getTimeToWaitForNPCs() { return 45; } @Override - public Collection<Integer> getIDs() { - return NPC.all().stream().map(x -> x.getNpcPojo().getId()).collect(Collectors.toList()); + public Collection<String> getIDs() { + return NpcApiProvider.get().getNpcRegistry().getAllIds(); } @Override public boolean isNPC(Entity entity) { - Boolean result = cachedNpcs.getIfPresent(entity.getEntityId()); - if (result == null) { - result = NPC.all().stream().anyMatch(npc1 -> npc1.getEntityID() == entity.getEntityId()); - cachedNpcs.put(entity.getEntityId(), result); - } - return result; + return false; } @Override - public BqInternalNpc fetchNPC(int id) { - NPC npc = NPC.find(id); - return npc == null ? null : new BQServerNPC(npc); + public BqInternalNpc fetchNPC(String internalId) { + NpcEntry npc = NpcApiProvider.get().getNpcRegistry().getById(internalId); + return npc == null ? null : new BQZnpcPlus(npc); } @Override public boolean isValidEntityType(EntityType type) { - return Arrays.stream(NPCType.values()).map(NPCType::name).anyMatch(name -> name.equals(type.name())); + return NpcApiProvider.get().getNpcTypeRegistry().getByName(type.name()) != null; } @Override public @NotNull BqInternalNpc create(@NotNull Location location, @NotNull EntityType type, @NotNull String name, @Nullable String skin) { - List<Integer> ids = ConfigurationConstants.NPC_LIST.stream().map(NPCModel::getId).collect(Collectors.toList()); - int id = ids.size(); - while (ids.contains(id)) - id++; - NPC npc = ZNPCsPlus.createNPC(id, NPCType.valueOf(type.name()), location, name); - npc.getNpcPojo().getFunctions().put("look", true); + String id; + int i = 1; + while (NpcApiProvider.get().getNpcRegistry().getById(id = name + "-" + i) != null) { + i++; + } - if (type == EntityType.PLAYER) - NPCSkin.forName(skin, (values, exception) -> npc.changeSkin(NPCSkin.forValues(values))); + NpcEntry npc = NpcApiProvider.get().getNpcRegistry().create( + id, + location.getWorld(), + NpcApiProvider.get().getNpcTypeRegistry().getByName(type.name()), + new NpcLocation(location)); - return new BQServerNPC(npc); + return new BQZnpcPlus(npc); } @EventHandler - public void onInteract(NPCInteractEvent e) { - npcClicked(null, e.getNpc().getNpcPojo().getId(), e.getPlayer(), - NpcClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); + public void onInteract(NpcInteractEvent e) { + npcClicked(null, e.getEntry().getId(), e.getPlayer(), + NpcClickType.of(e.getClickType() == InteractionType.LEFT_CLICK, e.getPlayer().isSneaking())); } - public static class BQServerNPC implements BqInternalNpc { + public static class BQZnpcPlus implements BqInternalNpc { - private final NPC npc; + private final NpcEntry npc; - private BQServerNPC(NPC npc) { + private BQZnpcPlus(NpcEntry npc) { this.npc = npc; } - public NPC getServerNPC() { - return npc; - } - @Override - public int getInternalId() { - return npc.getNpcPojo().getId(); + public String getInternalId() { + return npc.getId(); } @Override public String getName() { - return npc.getNpcPojo().getHologramLines().isEmpty() ? "ID: " + npc.getNpcPojo().getId() - : npc.getNpcPojo().getHologramLines().get(0); + return npc.getNpc().getHologram().lineCount() == 0 + ? "ID: " + npc.getId() + : npc.getNpc().getHologram().getLine(0); } @Override public boolean isSpawned() { - return npc.getBukkitEntity() != null; + return npc.getNpc().isEnabled(); } @Override public Entity getEntity() { - return (Entity) npc.getBukkitEntity(); + return null; } @Override public Location getLocation() { - return npc.getLocation(); + return npc.getNpc().getLocation().toBukkitLocation(npc.getNpc().getWorld()); } @Override diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlusOld.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlusOld.java new file mode 100755 index 00000000..5a1acbc3 --- /dev/null +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlusOld.java @@ -0,0 +1,132 @@ +package fr.skytasul.quests.integrations.npcs; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +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 com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import fr.skytasul.quests.api.npcs.BqInternalNpc; +import fr.skytasul.quests.api.npcs.BqInternalNpcFactory.BqInternalNpcFactoryCreatable; +import fr.skytasul.quests.api.npcs.NpcClickType; +import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; +import io.github.znetworkw.znpcservers.npc.NPC; +import io.github.znetworkw.znpcservers.npc.NPCModel; +import io.github.znetworkw.znpcservers.npc.NPCSkin; +import io.github.znetworkw.znpcservers.npc.NPCType; +import io.github.znetworkw.znpcservers.npc.interaction.NPCInteractEvent; +import lol.pyr.znpcsplus.ZNPCsPlus; + +public class BQZNPCsPlusOld implements BqInternalNpcFactoryCreatable, Listener { + + private Cache<Integer, Boolean> cachedNpcs = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + + @Override + public int getTimeToWaitForNPCs() { + return 45; + } + + @Override + public Collection<String> getIDs() { + return NPC.all().stream() + .map(x -> Integer.toString(x.getNpcPojo().getId())) + .collect(Collectors.toList()); + } + + @Override + public boolean isNPC(Entity entity) { + Boolean result = cachedNpcs.getIfPresent(entity.getEntityId()); + if (result == null) { + result = NPC.all().stream().anyMatch(npc1 -> npc1.getEntityID() == entity.getEntityId()); + cachedNpcs.put(entity.getEntityId(), result); + } + return result; + } + + @Override + public BqInternalNpc fetchNPC(String internalId) { + NPC npc = NPC.find(Integer.parseInt(internalId)); + return npc == null ? null : new BQServerNPC(npc); + } + + @Override + public boolean isValidEntityType(EntityType type) { + return Arrays.stream(NPCType.values()).map(NPCType::name).anyMatch(name -> name.equals(type.name())); + } + + @Override + public @NotNull BqInternalNpc create(@NotNull Location location, @NotNull EntityType type, @NotNull String name, + @Nullable String skin) { + List<Integer> ids = ConfigurationConstants.NPC_LIST.stream().map(NPCModel::getId).collect(Collectors.toList()); + int id = ids.size(); + while (ids.contains(id)) + id++; + NPC npc = ZNPCsPlus.createNPC(id, NPCType.valueOf(type.name()), location, name); + npc.getNpcPojo().getFunctions().put("look", true); + + if (type == EntityType.PLAYER) + NPCSkin.forName(skin, (values, exception) -> npc.changeSkin(NPCSkin.forValues(values))); + + return new BQServerNPC(npc); + } + + @EventHandler + public void onInteract(NPCInteractEvent e) { + npcClicked(null, Integer.toString(e.getNpc().getNpcPojo().getId()), e.getPlayer(), + NpcClickType.of(e.isLeftClick(), e.getPlayer().isSneaking())); + } + + public static class BQServerNPC implements BqInternalNpc { + + private final NPC npc; + + private BQServerNPC(NPC npc) { + this.npc = npc; + } + + public NPC getServerNPC() { + return npc; + } + + @Override + public String getInternalId() { + return Integer.toString(npc.getNpcPojo().getId()); + } + + @Override + public String getName() { + return npc.getNpcPojo().getHologramLines().isEmpty() ? "ID: " + npc.getNpcPojo().getId() + : npc.getNpcPojo().getHologramLines().get(0); + } + + @Override + public boolean isSpawned() { + return npc.getBukkitEntity() != null; + } + + @Override + public Entity getEntity() { + return (Entity) npc.getBukkitEntity(); + } + + @Override + public Location getLocation() { + return npc.getLocation(); + } + + @Override + public boolean setNavigationPaused(boolean paused) { + return true; + } + + } + +} From 183cfad3519c20f091072cd05aa903f8dc32df6e Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 25 Oct 2023 20:50:55 +0200 Subject: [PATCH 67/95] :bug: Fixed particle GUI not working properly --- .../gui/particles/ParticleEffectGUI.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index 9186af7d..c8b49443 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -26,27 +26,27 @@ import fr.skytasul.quests.utils.compatibility.Post1_13; public class ParticleEffectGUI extends LayoutedGUI.LayoutedRowsGUI { - + static final List<Particle> PARTICLES = Arrays.stream(Particle.values()).filter(particle -> { if (particle.getDataType() == Void.class) return true; if (MinecraftVersion.MAJOR >= 13) return particle.getDataType() == Post1_13.getDustOptionClass(); return false; }).collect(Collectors.toList()); - + private final Consumer<ParticleEffect> end; - + private Particle particle; private ParticleShape shape; private Color color; - + public ParticleEffectGUI(Consumer<ParticleEffect> end) { this(end, Particle.FLAME, ParticleShape.POINT, Color.AQUA); } - + public ParticleEffectGUI(Consumer<ParticleEffect> end, ParticleEffect effect) { this(end, effect.getParticle(), effect.getShape(), effect.getColor()); } - + public ParticleEffectGUI(Consumer<ParticleEffect> end, Particle particle, ParticleShape shape, Color color) { super(Lang.INVENTORY_PARTICLE_EFFECT.toString(), new HashMap<>(), new DelayCloseBehavior(() -> end.accept(null)), 1); this.end = end; @@ -54,6 +54,10 @@ public ParticleEffectGUI(Consumer<ParticleEffect> end, Particle particle, Partic this.shape = shape; this.color = color; + initButtons(); + } + + private void initButtons() { buttons.put(1, LayoutedButton.create(XMaterial.FIREWORK_STAR, Lang.particle_shape.toString(), () -> Arrays.asList(QuestOption.formatNullableValue(shape)), this::shapeClick)); buttons.put(3, LayoutedButton.create(XMaterial.PAPER, Lang.particle_type.toString(), @@ -105,9 +109,9 @@ private void colorClick(LayoutedClickEvent event) { private void cancelClick(LayoutedClickEvent event) { end.accept(null); } - + private void doneClick(LayoutedClickEvent event) { end.accept(new ParticleEffect(particle, shape, color)); } - + } From 3e1c751e05b973e2768610ce9cffb635113b5c5f Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 25 Oct 2023 20:51:33 +0200 Subject: [PATCH 68/95] :bug: Fixed "/quests edit" not working when clicking on an NPC --- .../main/java/fr/skytasul/quests/commands/CommandsAdmin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java index 98043839..0e2a0a22 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsAdmin.java @@ -74,7 +74,7 @@ public void edit(Player player, @Optional Quest quest) { if (!npc.getQuests().isEmpty()) { QuestsPlugin.getPlugin().getGuiManager().getFactory().createQuestSelection(clickedQuest -> { QuestCreationSession session = new QuestCreationSession(player); - session.setQuestEdited((QuestImplementation) quest); + session.setQuestEdited((QuestImplementation) clickedQuest); session.openStagesGUI(player); }, null, npc.getQuests()).open(player); }else { From 1dda66399687978445d2ec252c2932ca47782091 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Wed, 1 Nov 2023 19:02:25 +0100 Subject: [PATCH 69/95] :bug: Fixed ZNPCsPlus npcs not being persistent --- .../java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java index da24236b..715408cf 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/npcs/BQZNPCsPlus.java @@ -26,7 +26,7 @@ public int getTimeToWaitForNPCs() { @Override public Collection<String> getIDs() { - return NpcApiProvider.get().getNpcRegistry().getAllIds(); + return NpcApiProvider.get().getNpcRegistry().getAllPlayerMadeIds(); } @Override @@ -59,6 +59,7 @@ public boolean isValidEntityType(EntityType type) { location.getWorld(), NpcApiProvider.get().getNpcTypeRegistry().getByName(type.name()), new NpcLocation(location)); + npc.enableEverything(); return new BQZnpcPlus(npc); } From 0683d9c4561b1a8fabbb05a757d6ffae7bc0d095 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 2 Nov 2023 10:54:47 +0100 Subject: [PATCH 70/95] :bug: Fixed quest edition with branches --- .../java/fr/skytasul/quests/api/gui/AbstractGui.java | 9 +++++---- .../skytasul/quests/gui/creation/stages/StagesGUI.java | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java b/api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java index 3e437a77..2a38844a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/AbstractGui.java @@ -36,9 +36,10 @@ public final void reopen(@NotNull Player player, boolean refresh) { public final void repopulate(@NotNull Player player) { if (inventory == null) - return; + inventory = instanciate(player); + else + inventory.clear(); - inventory.clear(); populate(player, inventory); } @@ -47,10 +48,10 @@ public final void repopulate(@NotNull Player player) { protected abstract void populate(@NotNull Player player, @NotNull Inventory inventory); protected void refresh(@NotNull Player player, @NotNull Inventory inventory) {} - + @Override public @NotNull CloseBehavior onClose(@NotNull Player player) { return StandardCloseBehavior.CONFIRM; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index 3c452cff..ac01f7a9 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -101,7 +101,7 @@ public Line getLine(int id) { if (l.lineId == id) return l; } - return null; + throw new IllegalArgumentException("Unknown line " + id); } public boolean isEmpty(){ @@ -283,6 +283,7 @@ void setStageEdition(StageController stage, @Nullable QuestBranch branch) { StageCreation creation = setStageCreation(stage.getStageType()); if (branch != null) { + context.getEndingBranch().repopulate(session.getPlayer()); context.getEndingBranch().editBranch((QuestBranchImplementation) branch); } From 374d707e726cd1e8118daf7abb0082dc5c39726a Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 2 Nov 2023 18:05:54 +0100 Subject: [PATCH 71/95] :bug: Fixed "scoreboard" requirement --- .../quests/api/objects/QuestObject.java | 4 ++ .../api/requirements/AbstractRequirement.java | 4 -- .../api/requirements/RequirementList.java | 30 ++++++++-- .../quests/api/stages/AbstractStage.java | 56 +++++++++---------- .../quests/options/OptionRequirements.java | 24 ++++---- .../requirements/ScoreboardRequirement.java | 28 ++++++++-- .../logical/LogicalOrRequirement.java | 26 ++++----- .../rewards/RequirementDependentReward.java | 34 +++++------ .../quests/structure/QuestImplementation.java | 2 +- .../pools/QuestPoolImplementation.java | 13 +---- 10 files changed, 124 insertions(+), 97 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java index 4699920b..fd020b12 100644 --- a/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java +++ b/api/src/main/java/fr/skytasul/quests/api/objects/QuestObject.java @@ -64,6 +64,10 @@ public boolean isValid() { return true; } + protected @NotNull String getInvalidReason() { + return "invalid"; + } + @Override public final @NotNull PlaceholderRegistry getPlaceholdersRegistry() { if (placeholders == null) { diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java index cae5afec..32a07f6b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/AbstractRequirement.java @@ -79,10 +79,6 @@ else if (customReason != null) protected @Nullable String getDefaultReason(@NotNull Player player) { return null; } - - protected @NotNull String getInvalidReason() { - return "invalid requirement"; - } @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { diff --git a/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java b/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java index 39931042..156dda99 100644 --- a/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java +++ b/api/src/main/java/fr/skytasul/quests/api/requirements/RequirementList.java @@ -21,13 +21,17 @@ public RequirementList(@NotNull Collection<@NotNull AbstractRequirement> require super(requirements); } - public boolean testPlayer(@NotNull Player p, boolean message) { + public boolean allMatch(@NotNull Player p, boolean message) { + boolean match = true; for (AbstractRequirement requirement : this) { try { - if (!requirement.test(p)) { - if (message && !requirement.sendReason(p)) - continue; // means a reason has not yet been sent - return false; + if (!requirement.isValid() || !requirement.test(p)) { + if (!message || requirement.sendReason(p)) + return false; + + // if we are here, it means a reason has not yet been sent + // so we continue until a reason is sent OR there is no more requirement + match = false; } } catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded().severe( @@ -36,7 +40,21 @@ public boolean testPlayer(@NotNull Player p, boolean message) { return false; } } - return true; + return match; + } + + public boolean anyMatch(@NotNull Player p) { + for (AbstractRequirement requirement : this) { + try { + if (requirement.isValid() && requirement.test(p)) + return true; + } catch (Exception ex) { + QuestsPlugin.getPlugin().getLoggerExpanded().severe( + "Cannot test requirement " + requirement.getClass().getSimpleName() + " for player " + p.getName(), + ex); + } + } + return false; } public void attachQuest(@NotNull Quest quest) { diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java index 10b4d38d..396c4403 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/AbstractStage.java @@ -22,9 +22,9 @@ @AutoRegistered public abstract class AbstractStage implements HasPlaceholders { - + protected final @NotNull StageController controller; - + private @Nullable String startMessage = null; private @Nullable String customText = null; private @NotNull RewardList rewards = new RewardList(); @@ -33,18 +33,18 @@ public abstract class AbstractStage implements HasPlaceholders { private @NotNull List<@NotNull StageOption> options; private @Nullable PlaceholderRegistry placeholders; - + protected AbstractStage(@NotNull StageController controller) { this.controller = controller; options = controller.getStageType().getOptionsRegistry().getCreators().stream().map(SerializableCreator::newObject) .collect(Collectors.toList()); } - + public @NotNull StageController getController() { return controller; } - + public @NotNull Quest getQuest() { return controller.getBranch().getQuest(); } @@ -52,15 +52,15 @@ protected AbstractStage(@NotNull StageController controller) { public void setStartMessage(@Nullable String text) { this.startMessage = text; } - + public @Nullable String getStartMessage() { return startMessage; } - + public @NotNull RewardList getRewards() { return rewards; } - + public void setRewards(@NotNull RewardList rewards) { this.rewards = rewards; rewards.attachQuest(getQuest()); @@ -86,15 +86,15 @@ public void setOptions(@NotNull List<@NotNull StageOption> options) { public @Nullable String getCustomText() { return customText; } - + public void setCustomText(@Nullable String message) { this.customText = message; } - + public boolean sendStartMessage(){ return startMessage == null && QuestsConfiguration.getConfig().getQuestsConfig().playerStageStartMessage(); } - + public boolean hasAsyncEnd() { return rewards.hasAsync(); } @@ -120,34 +120,34 @@ protected final boolean canUpdate(@NotNull Player player) { } protected final boolean canUpdate(@NotNull Player player, boolean msg) { - return validationRequirements.testPlayer(player, msg); + return validationRequirements.allMatch(player, msg); } - + /** * Called internally when a player finish stage's objectives - * + * * @param player Player who finish the stage */ protected final void finishStage(@NotNull Player player) { controller.finishStage(player); } - + /** * Called internally to test if a player has the stage started - * + * * @param player Player to test * @see QuestBranch#hasStageLaunched(PlayerAccount, AbstractStage) */ protected final boolean hasStarted(@NotNull Player player) { return controller.hasStarted(PlayersManager.getPlayerAccount(player)); } - + /** * Called when the stage starts (player can be offline) * @param acc PlayerAccount for which the stage starts */ public void started(@NotNull PlayerAccount acc) {} - + /** * Called when the stage ends (player can be offline) * @param acc PlayerAccount for which the stage ends @@ -158,16 +158,16 @@ public void ended(@NotNull PlayerAccount acc) {} * Called when an account with this stage launched joins */ public void joined(@NotNull Player player) {} - + /** * Called when an account with this stage launched leaves */ public void left(@NotNull Player player) {} - + public void initPlayerDatas(@NotNull PlayerAccount acc, @NotNull Map<@NotNull String, @Nullable Object> datas) {} public abstract @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context); - + protected final void updateObjective(@NotNull Player p, @NotNull String dataKey, @Nullable Object dataValue) { controller.updateObjective(p, dataKey, dataValue); } @@ -187,29 +187,29 @@ public void unload(){ rewards.detachQuest(); validationRequirements.detachQuest(); } - + /** * Called when the stage loads */ public void load() {} - + protected void serialize(@NotNull ConfigurationSection section) {} - + public final void save(@NotNull ConfigurationSection section) { serialize(section); - + section.set("stageType", controller.getStageType().getID()); section.set("customText", customText); if (startMessage != null) section.set("text", startMessage); - + if (!rewards.isEmpty()) section.set("rewards", rewards.serialize()); if (!validationRequirements.isEmpty()) section.set("requirements", validationRequirements.serialize()); - + options.stream().filter(StageOption::shouldSave).forEach(option -> option.save(section.createSection("options." + option.getCreator().getID()))); } - + public final void load(@NotNull ConfigurationSection section) { if (section.contains("text")) startMessage = section.getString("text"); diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java index 4cf65fb8..499ebdda 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionRequirements.java @@ -21,22 +21,22 @@ public class OptionRequirements extends QuestOptionObject<AbstractRequirement, RequirementCreator, RequirementList> implements QuestDescriptionProvider { - + @Override protected AbstractRequirement deserialize(Map<String, Object> map) { return AbstractRequirement.deserialize(map); } - + @Override protected String getSizeString() { return RequirementList.getSizeString(getValue().size()); } - + @Override protected QuestObjectsRegistry<AbstractRequirement, RequirementCreator> getObjectsRegistry() { return QuestsAPI.getAPI().getRequirements(); } - + @Override protected RequirementList instanciate(Collection<AbstractRequirement> objects) { return new RequirementList(objects); @@ -46,28 +46,28 @@ protected RequirementList instanciate(Collection<AbstractRequirement> objects) { public XMaterial getItemMaterial() { return XMaterial.NETHER_STAR; } - + @Override public String getItemName() { return Lang.editRequirements.toString(); } - + @Override public String getItemDescription() { return Lang.editRequirementsLore.toString(); } - + @Override public List<String> provideDescription(QuestDescriptionContext context) { if (!context.getPlayerAccount().isCurrent()) return null; if (!context.getDescriptionOptions().showRequirements()) return null; if (context.getCategory() != PlayerListCategory.NOT_STARTED) return null; - + List<String> requirements = getValue().stream() .map(x -> { String description = x.getDescription(context.getPlayerAccount().getPlayer()); if (description != null) - description = MessageUtils.format(x.test(context.getPlayerAccount().getPlayer()) + description = MessageUtils.format(x.isValid() && x.test(context.getPlayerAccount().getPlayer()) ? context.getDescriptionOptions().getRequirementsValid() : context.getDescriptionOptions().getRequirementsInvalid(), PlaceholderRegistry.of("requirement_description", description)); @@ -76,11 +76,11 @@ public List<String> provideDescription(QuestDescriptionContext context) { .filter(Objects::nonNull) .collect(Collectors.toList()); if (requirements.isEmpty()) return null; - + requirements.add(0, Lang.RDTitle.toString()); return requirements; } - + @Override public String getDescriptionId() { return "requirements"; @@ -90,5 +90,5 @@ public String getDescriptionId() { public double getDescriptionPriority() { return 30; } - + } diff --git a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java index d700a8a9..80cc46a6 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/ScoreboardRequirement.java @@ -4,6 +4,8 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.scoreboard.Objective; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.ScoreboardObjectiveParser; import fr.skytasul.quests.api.gui.LoreBuilder; @@ -21,11 +23,13 @@ public class ScoreboardRequirement extends TargetNumberRequirement { public ScoreboardRequirement() { this(null, null, null, 0, ComparisonMethod.GREATER_OR_EQUAL); } - + public ScoreboardRequirement(String customDescription, String customReason, String objectiveName, double target, ComparisonMethod comparison) { super(customDescription, customReason, target, comparison); - if (objectiveName != null) this.objectiveName = objectiveName; + + if (objectiveName != null) + setObjectiveName(objectiveName); } @Override @@ -33,16 +37,28 @@ public double getPlayerTarget(Player p) { return objective.getScore(p.getName()).getScore(); } + @Override + public boolean isValid() { + return objective != null; + } + + @Override + protected @NotNull String getInvalidReason() { + return "cannot find scoreboard objective " + objectiveName; + } + private void setObjectiveName(String name) { objectiveName = name; objective = Bukkit.getScoreboardManager().getMainScoreboard().getObjective(name); + if (objective == null) + QuestsPlugin.getPlugin().getLogger().warning("Cannot find scoreboard objective " + name); } @Override public Class<? extends Number> numberClass() { return Double.class; } - + @Override protected String getPlaceholderName() { return "score"; @@ -52,13 +68,13 @@ protected String getPlaceholderName() { public void sendHelpString(Player p) { Lang.CHOOSE_SCOREBOARD_TARGET.send(p); } - + @Override protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription("§8Objective name: §7" + objectiveName); } - + @Override public void itemClick(QuestObjectClickEvent event) { Lang.CHOOSE_SCOREBOARD_OBJECTIVE.send(event.getPlayer()); @@ -74,7 +90,7 @@ public void itemClick(QuestObjectClickEvent event) { event.reopenGUI(); }, new ScoreboardObjectiveParser()).start(); } - + @Override public void save(ConfigurationSection section) { super.save(section); diff --git a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java index 9d91b16f..63586490 100644 --- a/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java +++ b/core/src/main/java/fr/skytasul/quests/requirements/logical/LogicalOrRequirement.java @@ -11,36 +11,36 @@ import fr.skytasul.quests.api.requirements.RequirementList; public class LogicalOrRequirement extends AbstractRequirement { - + private RequirementList requirements; - + public LogicalOrRequirement() { this(null, null, new RequirementList()); } - + public LogicalOrRequirement(String customDescription, String customReason, RequirementList requirements) { super(customDescription, customReason); this.requirements = requirements; } - + @Override public void attach(Quest quest) { super.attach(quest); requirements.attachQuest(quest); } - + @Override public void detach() { super.detach(); requirements.detachQuest(); } - + @Override protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(requirements.getSizeString()); } - + @Override public void itemClick(QuestObjectClickEvent event) { QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.OTHER, requirements -> { @@ -48,27 +48,27 @@ public void itemClick(QuestObjectClickEvent event) { event.reopenGUI(); }, requirements).open(event.getPlayer()); } - + @Override public boolean test(Player p) { - return requirements.stream().anyMatch(x -> x.test(p)); + return requirements.anyMatch(p); } - + @Override public AbstractRequirement clone() { return new LogicalOrRequirement(getCustomDescription(), getCustomReason(), new RequirementList(requirements)); } - + @Override public void save(ConfigurationSection section) { super.save(section); section.set("requirements", requirements.serialize()); } - + @Override public void load(ConfigurationSection section) { super.load(section); requirements = RequirementList.deserialize(section.getMapList("requirements")); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index 98eecff2..accbf4ae 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -25,71 +25,71 @@ import fr.skytasul.quests.api.utils.XMaterial; public class RequirementDependentReward extends AbstractReward { - + private RequirementList requirements; private RewardList rewards; - + public RequirementDependentReward() { this(null, new RequirementList(), new RewardList()); } - + public RequirementDependentReward(String customDescription, RequirementList requirements, RewardList rewards) { super(customDescription); this.requirements = requirements; this.rewards = rewards; } - + @Override public void attach(Quest quest) { super.attach(quest); requirements.attachQuest(quest); rewards.attachQuest(quest); } - + @Override public void detach() { super.detach(); requirements.forEach(AbstractRequirement::detach); rewards.forEach(AbstractReward::detach); } - + @Override public List<String> give(Player p) throws InterruptingBranchException { - if (requirements.stream().allMatch(requirement -> requirement.test(p))) + if (requirements.allMatch(p, false)) return rewards.giveRewards(p); return null; } - + @Override public boolean isAsync() { return rewards.stream().anyMatch(AbstractReward::isAsync); } - + @Override public AbstractReward clone() { return new RequirementDependentReward(getCustomDescription(), new RequirementList(requirements), new RewardList(rewards)); } - + @Override public String getDefaultDescription(Player p) { - return requirements.stream().allMatch(req -> req.test(p)) ? - rewards + return requirements.allMatch(p, false) + ? rewards .stream() .map(xreq -> xreq.getDescription(p)) .filter(Objects::nonNull) .collect(Collectors.joining("{JOIN}")) : null; } - + @Override protected void addLore(LoreBuilder loreBuilder) { super.addLore(loreBuilder); loreBuilder.addDescription(rewards.getSizeString()); loreBuilder.addDescription(requirements.getSizeString()); } - + @Override public void itemClick(QuestObjectClickEvent event) { LayoutedGUI.newBuilder() @@ -105,7 +105,7 @@ public void itemClick(QuestObjectClickEvent event) { .build() .open(event.getPlayer()); } - + private void editRequirements(LayoutedClickEvent event) { QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.OTHER, newRequirements -> { requirements = new RequirementList(newRequirements); @@ -126,12 +126,12 @@ public void save(ConfigurationSection section) { section.set("requirements", requirements.serialize()); section.set("rewards", rewards.serialize()); } - + @Override public void load(ConfigurationSection section) { super.load(section); requirements = RequirementList.deserialize(section.getMapList("requirements")); rewards = RewardList.deserialize(section.getMapList("rewards")); } - + } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java index 5a15d359..883867ee 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestImplementation.java @@ -294,7 +294,7 @@ public boolean testRequirements(@NotNull Player p, @NotNull PlayerAccount acc, b sendMessage = sendMessage && (!hasOption(OptionStarterNPC.class) || (QuestsConfiguration.getConfig().getQuestsConfig().requirementReasonOnMultipleQuests() || getOption(OptionStarterNPC.class).getValue().getQuests().size() == 1)); - return getOptionValueOrDef(OptionRequirements.class).testPlayer(p, sendMessage); + return getOptionValueOrDef(OptionRequirements.class).allMatch(p, sendMessage); } public boolean testQuestLimit(@NotNull Player p, @NotNull PlayerAccount acc, boolean sendMessage) { 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 bf06e427..b009f6ef 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 @@ -22,7 +22,6 @@ import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.pools.QuestPool; import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.requirements.AbstractRequirement; import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.XMaterial; @@ -198,14 +197,8 @@ public boolean canGive(Player p) { if (datas.getLastGive() + timeDiff > System.currentTimeMillis()) return false; - for (AbstractRequirement requirement : requirements) { - try { - if (!requirement.test(p)) return false; - }catch (Exception ex) { - QuestsPlugin.getPlugin().getLoggerExpanded().severe("Cannot test requirement " + requirement.getClass().getSimpleName() + " in pool " + id + " for player " + p.getName(), ex); - return false; - } - } + if (!requirements.allMatch(p, false)) + return false; List<Quest> notDoneQuests = avoidDuplicates ? quests.stream() .filter(quest -> !datas.getCompletedQuests().contains(quest.getId())).collect(Collectors.toList()) : quests; @@ -255,7 +248,7 @@ public CompletableFuture<String> give(Player p) { private CompletableFuture<PoolGiveResult> giveOne(Player p, PlayerAccount acc, PlayerPoolDatas datas, boolean hadOne) { - if (!requirements.testPlayer(p, !hadOne)) + if (!requirements.allMatch(p, !hadOne)) return CompletableFuture.completedFuture(new PoolGiveResult("")); List<Quest> notCompleted = avoidDuplicates ? quests.stream() From e1d021f241f0d434b72a0d0472f6d5dcfba6083e Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 2 Nov 2023 18:14:47 +0100 Subject: [PATCH 72/95] :bug: Fixed dialog lines not having placeholders parsed --- .../fr/skytasul/quests/api/npcs/dialogs/Message.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java index 9acc3861..78f55be5 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java @@ -87,13 +87,17 @@ public String formatMessage(@NotNull Player p, @Nullable BqNpc npc, @Nullable St PlaceholderRegistry registry = new PlaceholderRegistry() .registerIndexed("player_name", p.getName()) .registerIndexed("npc_name_message", npcCustomName) - .registerIndexed("text", text) .registerIndexed("message_id", id + 1) .registerIndexed("message_count", size); if (npc != null) registry.compose(npc); - String sent = null; + String sent = MessageUtils.finalFormat(text, registry.withoutIndexes("npc_name_message", "player_name"), + PlaceholdersContext.of(p, true, null)); + // ugly trick to have placeholders parsed in the message + + registry.registerIndexed("text", sent); + switch (sender) { case PLAYER: sent = MessageUtils.finalFormat(Lang.SelfText.toString(), registry.withoutIndexes("npc_name_message"), @@ -104,8 +108,7 @@ public String formatMessage(@NotNull Player p, @Nullable BqNpc npc, @Nullable St PlaceholdersContext.of(p, true, null)); break; case NOSENDER: - sent = MessageUtils.finalFormat(text, registry.withoutIndexes("npc_name_message", "player_name"), - PlaceholdersContext.of(p, true, null)); + sent = text; break; } return sent; From 966c8b820f5738eed7f9c09ce8f7e3fdb576a49c Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 4 Nov 2023 19:09:17 +0100 Subject: [PATCH 73/95] :bug: Fixed bug caused by last bugfix oops --- .../main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java index 78f55be5..5116a3dd 100644 --- a/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java +++ b/api/src/main/java/fr/skytasul/quests/api/npcs/dialogs/Message.java @@ -108,7 +108,7 @@ public String formatMessage(@NotNull Player p, @Nullable BqNpc npc, @Nullable St PlaceholdersContext.of(p, true, null)); break; case NOSENDER: - sent = text; + // nothing to do: the placeholders has already been parsed break; } return sent; From 429a144662e39f954071d63712e91267cba1173f Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 5 Nov 2023 10:09:37 +0100 Subject: [PATCH 74/95] :bug: Fixed outdated migration to DB algorithm --- .../PlayerQuestDatasImplementation.java | 4 + .../quests/players/PlayersManagerDB.java | 152 ++++++++---------- 2 files changed, 75 insertions(+), 81 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java index bc37ddfe..79fcaea4 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayerQuestDatasImplementation.java @@ -131,6 +131,10 @@ public void setInEndingStages() { setStage(-2); } + public Map<String, Object> getRawAdditionalDatas() { + return additionalDatas; + } + @Override public <T> T getAdditionalData(String key) { return (T) additionalDatas.get(key); 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 0b3432dc..37ee137f 100644 --- a/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java +++ b/core/src/main/java/fr/skytasul/quests/players/PlayersManagerDB.java @@ -1,19 +1,8 @@ package fr.skytasul.quests.players; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.sql.*; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; @@ -42,11 +31,11 @@ public class PlayersManagerDB extends AbstractPlayersManager { public final String POOLS_DATAS_TABLE; private final Database db; - + private final Map<SavableData<?>, SQLDataSaver<?>> accountDatas = new HashMap<>(); private String getAccountDatas; private String resetAccountDatas; - + /* Accounts statements */ private String getAccountsIDs; private String insertAccount; @@ -65,13 +54,13 @@ public class PlayersManagerDB extends AbstractPlayersManager { private String updateStage; private String updateDatas; private String updateFlow; - + /* Pool datas statements */ private String insertPoolData; private String removePoolData; private String getPoolData; private String getPoolAccountData; - + private String updatePoolLastGive; private String updatePoolCompletedQuests; @@ -85,7 +74,7 @@ public PlayersManagerDB(Database db) { public Database getDatabase() { return db; } - + @Override public void addAccountData(SavableData<?> data) { super.addAccountData(data); @@ -99,7 +88,7 @@ public void addAccountData(SavableData<?> data) { .map(x -> "`" + x.getWrappedData().getColumnName() + "` = " + x.getDefaultValueString()) .collect(Collectors.joining(", ", "UPDATE " + ACCOUNTS_TABLE + " SET ", " WHERE `id` = ?")); } - + private void retrievePlayerDatas(PlayerAccountImplementation acc) { try (Connection connection = db.getConnection()) { try (PreparedStatement statement = connection.prepareStatement(getQuestsData)) { @@ -137,7 +126,7 @@ private void retrievePlayerDatas(PlayerAccountImplementation acc) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while fetching account datas of " + acc.debugName(), ex); } } - + @Override public void load(AccountFetchRequest request) { try (Connection connection = db.getConnection()) { @@ -187,7 +176,7 @@ public void load(AccountFetchRequest request) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while loading account of " + request.getDebugPlayerName(), ex); } } - + @Override protected CompletableFuture<Void> removeAccount(PlayerAccountImplementation acc) { return CompletableFuture.runAsync(() -> { @@ -220,12 +209,12 @@ public CompletableFuture<Void> playerQuestDataRemoved(PlayerQuestDatasImplementa } }); } - + @Override public PlayerPoolDatasImplementation createPlayerPoolDatas(PlayerAccountImplementation acc, QuestPool pool) { return new PlayerPoolDatasDB(acc, pool.getId()); } - + @Override public CompletableFuture<Void> playerPoolDataRemoved(PlayerPoolDatasImplementation datas) { return CompletableFuture.runAsync(() -> { @@ -289,19 +278,19 @@ public void load() { getQuestsData = "SELECT * FROM " + QUESTS_DATAS_TABLE + " WHERE `account_id` = ?"; removeExistingQuestDatas = "DELETE FROM " + QUESTS_DATAS_TABLE + " WHERE `quest_id` = ?"; - + updateFinished = prepareDatasStatement("finished"); updateTimer = prepareDatasStatement("timer"); updateBranch = prepareDatasStatement("current_branch"); updateStage = prepareDatasStatement("current_stage"); updateDatas = prepareDatasStatement("additional_datas"); updateFlow = prepareDatasStatement("quest_flow"); - + insertPoolData = "INSERT INTO " + POOLS_DATAS_TABLE + " (`account_id`, `pool_id`) VALUES (?, ?)"; removePoolData = "DELETE FROM " + POOLS_DATAS_TABLE + " WHERE `account_id` = ? AND `pool_id` = ?"; getPoolData = "SELECT * FROM " + POOLS_DATAS_TABLE + " WHERE `account_id` = ?"; getPoolAccountData = "SELECT 1 FROM " + POOLS_DATAS_TABLE + " WHERE `account_id` = ? AND `pool_id` = ?"; - + updatePoolLastGive = "UPDATE " + POOLS_DATAS_TABLE + " SET `last_give` = ? WHERE `account_id` = ? AND `pool_id` = ?"; updatePoolCompletedQuests = "UPDATE " + POOLS_DATAS_TABLE + " SET `completed_quests` = ? WHERE `account_id` = ? AND `pool_id` = ?"; }catch (SQLException e) { @@ -317,7 +306,7 @@ private String prepareDatasStatement(String column) throws SQLException { public void save() { cachedAccounts.values().forEach(x -> saveAccount(x, false)); } - + private void createTables() throws SQLException { try (Connection connection = db.getConnection(); Statement statement = connection.createStatement()) { statement.execute("CREATE TABLE IF NOT EXISTS " + ACCOUNTS_TABLE + " (" @@ -348,14 +337,14 @@ private void createTables() throws SQLException { + "PRIMARY KEY (`id`)" + ")"); statement.execute("ALTER TABLE " + QUESTS_DATAS_TABLE + " MODIFY COLUMN finished INT(11) DEFAULT 0"); - + upgradeTable(connection, QUESTS_DATAS_TABLE, columns -> { if (!columns.contains("quest_flow")) { // 0.19 statement.execute("ALTER TABLE " + QUESTS_DATAS_TABLE + " ADD COLUMN quest_flow VARCHAR(8000) DEFAULT NULL"); QuestsPlugin.getPlugin().getLoggerExpanded().info("Updated database with quest_flow column."); } - + if (!columns.contains("additional_datas") || columns.contains("stage_0_datas")) { // 0.20 // tests for stage_0_datas: it's in the case the server crashed/stopped during the migration process. if (!columns.contains("additional_datas")) { @@ -363,11 +352,11 @@ private void createTables() throws SQLException { + " ADD COLUMN `additional_datas` longtext DEFAULT NULL AFTER `current_stage`"); QuestsPlugin.getPlugin().getLoggerExpanded().info("Updated table " + QUESTS_DATAS_TABLE + " with additional_datas column."); } - + QuestUtils.runAsync(this::migrateOldQuestDatas); } }); - + upgradeTable(connection, ACCOUNTS_TABLE, columns -> { for (SQLDataSaver<?> data : accountDatas.values()) { if (!columns.contains(data.getWrappedData().getColumnName().toLowerCase())) { @@ -393,15 +382,15 @@ private void upgradeTable(Connection connection, String tableName, ThrowingConsu columnsConsumer.accept(columns); } } - + private void migrateOldQuestDatas() { QuestsPlugin.getPlugin().getLoggerExpanded().info("---- CAUTION ----\n" + "BeautyQuests will now migrate old quest datas in database to the newest format.\n" + "This may take a LONG time. Players should NOT enter the server during this time, " + "or serious data loss can occur."); - + try (Connection connection = db.getConnection(); Statement statement = connection.createStatement()) { - + int deletedDuplicates = statement.executeUpdate("DELETE R1 FROM " + QUESTS_DATAS_TABLE + " R1" + " JOIN " + QUESTS_DATAS_TABLE + " R2" @@ -409,7 +398,7 @@ private void migrateOldQuestDatas() { + " AND R1.quest_id = R2.quest_id" + " AND R1.id < R2.id;"); if (deletedDuplicates > 0) QuestsPlugin.getPlugin().getLoggerExpanded().info("Deleted " + deletedDuplicates + " duplicated rows in the " + QUESTS_DATAS_TABLE + " table."); - + int batchCount = 0; PreparedStatement migration = connection.prepareStatement("UPDATE " + QUESTS_DATAS_TABLE + " SET `additional_datas` = ? WHERE `id` = ?"); ResultSet result = statement.executeQuery("SELECT `id`, `stage_0_datas`, `stage_1_datas`, `stage_2_datas`, `stage_3_datas`, `stage_4_datas` FROM " + QUESTS_DATAS_TABLE); @@ -419,7 +408,7 @@ private void migrateOldQuestDatas() { String stageDatas = result.getString("stage_" + i + "_datas"); if (stageDatas != null && !"{}".equals(stageDatas)) datas.put("stage" + i, CustomizedObjectTypeAdapter.deserializeNullable(stageDatas, Map.class)); } - + if (datas.isEmpty()) continue; migration.setString(1, CustomizedObjectTypeAdapter.serializeNullable(datas)); migration.setInt(2, result.getInt("id")); @@ -429,7 +418,7 @@ private void migrateOldQuestDatas() { QuestsPlugin.getPlugin().getLoggerExpanded().info("Migrating " + batchCount + "quest datas..."); int migrated = migration.executeBatch().length; QuestsPlugin.getPlugin().getLoggerExpanded().info("Migrated " + migrated + " quest datas."); - + statement.execute("ALTER TABLE " + QUESTS_DATAS_TABLE + " DROP COLUMN `stage_0_datas`," + " DROP COLUMN `stage_1_datas`," @@ -444,30 +433,32 @@ private void migrateOldQuestDatas() { + "The plugin failed to migrate old quest datas in database.", ex); } } - + public static synchronized String migrate(Database db, PlayersManagerYAML yaml) throws SQLException { try (Connection connection = db.getConnection()) { + PlayersManagerDB manager = new PlayersManagerDB(db); + ResultSet result = connection.getMetaData().getTables(null, null, "%", null); while (result.next()) { String tableName = result.getString(3); - if (tableName.equals("player_accounts") || tableName.equals("player_quests")) { + if (tableName.equals(manager.ACCOUNTS_TABLE) || tableName.equals(manager.QUESTS_DATAS_TABLE) + || tableName.equals(manager.POOLS_DATAS_TABLE)) { result.close(); return "§cTable \"" + tableName + "\" already exists. Please drop it before migration."; } } result.close(); - - PlayersManagerDB manager = new PlayersManagerDB(db); + manager.createTables(); - + PreparedStatement insertAccount = connection.prepareStatement("INSERT INTO " + manager.ACCOUNTS_TABLE + " (`id`, `identifier`, `player_uuid`) VALUES (?, ?, ?)"); PreparedStatement insertQuestData = connection.prepareStatement("INSERT INTO " + manager.QUESTS_DATAS_TABLE - + " (`account_id`, `quest_id`, `finished`, `timer`, `current_branch`, `current_stage`, `stage_0_datas`, `stage_1_datas`, `stage_2_datas`, `stage_3_datas`, `stage_4_datas`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + + " (`account_id`, `quest_id`, `finished`, `timer`, `current_branch`, `current_stage`, `additional_datas`, `quest_flow`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); PreparedStatement insertPoolData = connection.prepareStatement("INSERT INTO " + manager.POOLS_DATAS_TABLE + " (`account_id`, `pool_id`, `last_give`, `completed_quests`) VALUES (?, ?, ?, ?)"); - + int amount = 0, failed = 0; yaml.loadAllAccounts(); for (PlayerAccountImplementation acc : yaml.loadedAccounts.values()) { @@ -476,7 +467,7 @@ public static synchronized String migrate(Database db, PlayersManagerYAML yaml) insertAccount.setString(2, acc.abstractAcc.getIdentifier()); insertAccount.setString(3, acc.getOfflinePlayer().getUniqueId().toString()); insertAccount.executeUpdate(); - + for (Entry<Integer, PlayerQuestDatasImplementation> entry : acc.questDatas.entrySet()) { insertQuestData.setInt(1, acc.index); insertQuestData.setInt(2, entry.getKey()); @@ -484,13 +475,12 @@ public static synchronized String migrate(Database db, PlayersManagerYAML yaml) insertQuestData.setLong(4, entry.getValue().getTimer()); insertQuestData.setInt(5, entry.getValue().getBranch()); insertQuestData.setInt(6, entry.getValue().getStage()); - for (int i = 0; i < 5; i++) { - Map<String, Object> stageDatas = entry.getValue().getStageDatas(i); - insertQuestData.setString(7 + i, stageDatas == null ? null : CustomizedObjectTypeAdapter.GSON.toJson(stageDatas)); - } + insertQuestData.setString(7, entry.getValue().getRawAdditionalDatas().isEmpty() ? null + : CustomizedObjectTypeAdapter.serializeNullable(entry.getValue().getRawAdditionalDatas())); + insertQuestData.setString(8, entry.getValue().getQuestFlow()); insertQuestData.executeUpdate(); } - + for (Entry<Integer, PlayerPoolDatasImplementation> entry : acc.poolDatas.entrySet()) { insertPoolData.setInt(1, acc.index); insertPoolData.setInt(2, entry.getKey()); @@ -498,22 +488,22 @@ public static synchronized String migrate(Database db, PlayersManagerYAML yaml) insertPoolData.setString(4, getCompletedQuestsString(entry.getValue().getCompletedQuests())); insertPoolData.executeUpdate(); } - + amount++; }catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("Failed to migrate datas for account " + acc.debugName(), ex); failed++; } } - + insertAccount.close(); insertQuestData.close(); insertPoolData.close(); - + return "§aMigration succeed! " + amount + " accounts migrated, " + failed + " accounts failed to migrate.\n§oDatabase saving system is §lnot§r§a§o enabled. You need to reboot the server with the line \"database.enabled\" set to true."; } } - + @Override public void unloadAccount(PlayerAccountImplementation acc) { QuestUtils.runAsync(() -> saveAccount(acc, true)); @@ -525,7 +515,7 @@ public void saveAccount(PlayerAccountImplementation acc, boolean stop) { .map(PlayerQuestDatasDB.class::cast) .forEach(x -> x.flushAll(stop)); } - + protected static String getCompletedQuestsString(Set<Integer> completedQuests) { return completedQuests.isEmpty() ? null : completedQuests.stream().map(x -> Integer.toString(x)).collect(Collectors.joining(";")); } @@ -534,7 +524,7 @@ public class PlayerQuestDatasDB extends PlayerQuestDatasImplementation { private static final int DATA_QUERY_TIMEOUT = 15; private static final int DATA_FLUSHING_TIME = 10; - + private Map<String, Entry<BukkitRunnable, Object>> cachedDatas = new HashMap<>(5); private Lock datasLock = new ReentrantLock(); private Lock dbLock = new ReentrantLock(); @@ -557,13 +547,13 @@ public PlayerQuestDatasDB(PlayerAccountImplementation acc, int questID, ResultSe result.getString("quest_flow")); this.dbId = result.getInt("id"); } - + @Override public void incrementFinished() { super.incrementFinished(); setDataStatement(updateFinished, getTimesFinished(), false); } - + @Override public void setTimer(long timer) { super.setTimer(timer); @@ -581,26 +571,26 @@ public void setStage(int stage) { super.setStage(stage); setDataStatement(updateStage, stage, false); } - + @Override public <T> T setAdditionalData(String key, T value) { T additionalData = super.setAdditionalData(key, value); setDataStatement(updateDatas, super.additionalDatas.isEmpty() ? null : CustomizedObjectTypeAdapter.serializeNullable(super.additionalDatas), true); return additionalData; } - + @Override public void addQuestFlow(StageController finished) { super.addQuestFlow(finished); setDataStatement(updateFlow, getQuestFlow(), true); } - + @Override public void resetQuestFlow() { super.resetQuestFlow(); setDataStatement(updateFlow, null, true); } - + private void setDataStatement(String dataStatement, Object data, boolean allowNull) { if (disabled) return; try { @@ -611,7 +601,7 @@ private void setDataStatement(String dataStatement, Object data, boolean allowNu cachedDatas.get(dataStatement).setValue(data); }else { BukkitRunnable runnable = new BukkitRunnable() { - + @Override public void run() { if (disabled) return; @@ -660,7 +650,7 @@ public void run() { datasLock.unlock(); } } - + protected void flushAll(boolean stop) { try { if (datasLock.tryLock(DATA_QUERY_TIMEOUT * 2L, TimeUnit.SECONDS)) { @@ -680,7 +670,7 @@ protected void flushAll(boolean stop) { Thread.currentThread().interrupt(); } } - + protected void stop() { disabled = true; datasLock.lock(); @@ -691,7 +681,7 @@ protected void stop() { cachedDatas.clear(); datasLock.unlock(); } - + private void createDataRow(Connection connection) throws SQLException { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Inserting DB row of quest " + questID + " for account " + acc.index); try (PreparedStatement insertStatement = connection.prepareStatement(insertQuestData, new String[] {"id"})) { @@ -708,30 +698,30 @@ private void createDataRow(Connection connection) throws SQLException { QuestsPlugin.getPlugin().getLoggerExpanded().debug("Created row " + dbId + " for quest " + questID + ", account " + acc.index); } } - + } - + public class PlayerPoolDatasDB extends PlayerPoolDatasImplementation { - + public PlayerPoolDatasDB(PlayerAccountImplementation acc, int poolID) { super(acc, poolID); } - + public PlayerPoolDatasDB(PlayerAccountImplementation acc, int poolID, long lastGive, Set<Integer> completedQuests) { super(acc, poolID, lastGive, completedQuests); } - + @Override public void setLastGive(long lastGive) { super.setLastGive(lastGive); updateData(updatePoolLastGive, lastGive); } - + @Override public void updatedCompletedQuests() { updateData(updatePoolCompletedQuests, getCompletedQuestsString(getCompletedQuests())); } - + private void updateData(String dataStatement, Object data) { try (Connection connection = db.getConnection()) { try (PreparedStatement statement = connection.prepareStatement(getPoolAccountData)) { @@ -755,19 +745,19 @@ private void updateData(String dataStatement, Object data) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while updating a player's pool datas.", ex); } } - + } - + public class PlayerAccountDB extends PlayerAccountImplementation { - + public PlayerAccountDB(AbstractAccount account, int index) { super(account, index); } - + @Override public <T> void setData(SavableData<T> data, T value) { super.setData(data, value); - + SQLDataSaver<T> dataSaver = (SQLDataSaver<T>) accountDatas.get(data); try (Connection connection = db.getConnection(); PreparedStatement statement = connection.prepareStatement(dataSaver.getUpdateStatement())) { @@ -778,11 +768,11 @@ public <T> void setData(SavableData<T> data, T value) { QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error occurred while saving account data " + data.getId() + " to database", ex); } } - + @Override public void resetDatas() { super.resetDatas(); - + if (resetAccountDatas != null) { try (Connection connection = db.getConnection(); PreparedStatement statement = connection.prepareStatement(resetAccountDatas)) { @@ -793,7 +783,7 @@ public void resetDatas() { } } } - + } } From 6913ff5cdb29bee1e9e1234a6ca0eb8dd6815d53 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 5 Nov 2023 17:12:00 +0100 Subject: [PATCH 75/95] :bug: Fixed bug with multiple pages in some GUIs --- .../quests/api/gui/templates/PagedGUI.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java index 4c69ddb8..f407ed42 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java @@ -35,18 +35,18 @@ public abstract class PagedGUI<T> extends AbstractGui { protected Player player; protected int page = 0; protected int maxPage; - + private String name; private DyeColor color; protected List<T> objects; protected Consumer<List<T>> validate; private ItemStack validationItem = ItemUtils.itemDone; protected LevenshteinComparator<T> comparator; - + protected PagedGUI(String name, DyeColor color, Collection<T> objects) { this(name, color, objects, null, null); } - + protected PagedGUI(String name, DyeColor color, Collection<T> objects, Consumer<List<T>> validate, Function<T, String> searchName) { this.name = name; this.color = color; @@ -54,7 +54,7 @@ protected PagedGUI(String name, DyeColor color, Collection<T> objects, Consumer< this.validate = validate; if (searchName != null) this.comparator = new LevenshteinComparator<>(searchName); } - + @Override protected Inventory instanciate(@NotNull Player player) { return Bukkit.createInventory(null, 45, name); @@ -64,7 +64,7 @@ protected Inventory instanciate(@NotNull Player player) { protected void populate(@NotNull Player player, @NotNull Inventory inventory) { this.player = player; calcMaxPages(); - + setBarItem(0, ItemUtils.itemLaterPage); setBarItem(4, ItemUtils.itemNextPage); if (validate != null) setBarItem(2, validationItem); @@ -72,10 +72,10 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { for (int i = 0; i < 5; i++) inventory.setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); - + setItems(); } - + public PagedGUI<T> setValidate(Consumer<List<T>> validate, ItemStack validationItem) { if (this.validate != null) throw new IllegalStateException("A validation has already be added."); if (this.getInventory() != null) @@ -85,13 +85,13 @@ public PagedGUI<T> setValidate(Consumer<List<T>> validate, ItemStack validationI this.validationItem = validationItem; return this; } - + public PagedGUI<T> sortValuesByName() { Validate.notNull(comparator); sortValues(comparator.getFunction()); return this; } - + public <C extends Comparable<C>> PagedGUI<T> sortValues(Function<T, C> mapper) { objects.sort((o1, o2) -> { C map1; @@ -102,11 +102,11 @@ public <C extends Comparable<C>> PagedGUI<T> sortValues(Function<T, C> mapper) { }); return this; } - + protected void calcMaxPages() { this.maxPage = objects.isEmpty() ? 1 : (int) Math.ceil(objects.size() * 1D / 35D); } - + protected void setItems() { for (int i = 0; i < 35; i++) setMainItem(i, null); for (int i = page * 35; i < objects.size(); i++){ @@ -115,14 +115,14 @@ protected void setItems() { setMainItem(i - page * 35, getItemStack(obj)); } } - + private int setMainItem(int mainSlot, ItemStack is){ int line = (int) Math.floor(mainSlot * 1.0 / 7.0); int slot = mainSlot + (2 * line); setItem(is, slot); return slot; } - + private int setBarItem(int barSlot, ItemStack is){ int slot = barSlot * 9 + 8; setItem(is, slot); @@ -143,7 +143,7 @@ private void setItem(ItemStack is, int rawSlot) { } } } - + /** * @param object T object to get the slot from * @return slot in the inventory, -1 if the object is on another page @@ -151,12 +151,12 @@ private void setItem(ItemStack is, int rawSlot) { public int getObjectSlot(T object){ int index = objects.indexOf(object); if (index < page*35 || index > (page + 1)*35) return -1; - + int line = (int) Math.floor(index * 1.0 / 7.0); - return index + (2 * line); + return index + (2 * line) - page * 35; } - + @Override public void onClick(GuiClickEvent event) { switch (event.getSlot() % 9) { @@ -173,7 +173,7 @@ public void onClick(GuiClickEvent event) { page++; setItems(); break; - + case 2: validate.accept(objects); break; @@ -189,10 +189,10 @@ public void onClick(GuiClickEvent event) { break; } break; - + case 7: break; - + default: int line = (int) Math.floor(event.getSlot() * 1D / 9D); int objectSlot = event.getSlot() - line * 2 + page * 35; @@ -200,7 +200,7 @@ public void onClick(GuiClickEvent event) { //inv.setItem(slot, getItemStack(objects.get(objectSlot))); } } - + public final void reopen() { reopen(player); } From e4765315e97fc7ae564142691cb1828a54697c0e Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 5 Nov 2023 17:32:27 +0100 Subject: [PATCH 76/95] :green_heart: Usage of features from wrong Java version now checked --- .../quests/api/stages/types/AbstractCountableStage.java | 4 ++-- .../quests/api/utils/messaging/PlaceholderRegistry.java | 2 +- pom.xml | 1 + v1_17_R1/pom.xml | 1 + v1_18_R1/pom.xml | 1 + v1_18_R2/pom.xml | 1 + v1_19_R1/pom.xml | 1 + v1_19_R2/pom.xml | 1 + v1_19_R3/pom.xml | 1 + v1_20_R1/pom.xml | 1 + v1_20_R2/pom.xml | 6 ++++-- 11 files changed, 15 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index 3461285d..177316ce 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -62,7 +62,7 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { } if (remaining == null || remaining.isEmpty()) - return Map.of(); + return Collections.emptyMap(); Object object = remaining.keySet().iterator().next(); if (object instanceof Integer) { @@ -93,7 +93,7 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { public @NotNull Map<CountableObject<T>, Integer> getPlayerAmounts(@NotNull PlayerAccount account) { return getPlayerRemainings(account, true) .entrySet().stream() - .map(entry -> Map.entry(getObject(entry.getKey()).orElse(null), entry.getValue())) + .map(entry -> new AbstractMap.SimpleEntry<>(getObject(entry.getKey()).orElse(null), entry.getValue())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java index a2a36109..a6bcd4fc 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/messaging/PlaceholderRegistry.java @@ -148,7 +148,7 @@ public boolean hasPlaceholder(@NotNull String key) { * @return a copy of this registry without some indexed placeholders */ public @NotNull PlaceholderRegistry withoutIndexes(@NotNull Placeholder @NotNull... exceptedPlaceholders) { - PlaceholderRegistry result = new PlaceholderRegistry(this.placeholders.toArray(Placeholder[]::new)); + PlaceholderRegistry result = new PlaceholderRegistry(this.placeholders.toArray(new Placeholder[0])); out: for (Placeholder placeholder : indexed) { // NOSONAR: very simple label use for (Placeholder exceptedPlaceholder : exceptedPlaceholders) { diff --git a/pom.xml b/pom.xml index 76e6bd88..cd670fc6 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> + <maven.compiler.release>8</maven.compiler.release> <maven.javadoc.skip>true</maven.javadoc.skip> <build.number>unknown</build.number> <human.version>1.0</human.version> diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml index da20e321..65b80b38 100644 --- a/v1_17_R1/pom.xml +++ b/v1_17_R1/pom.xml @@ -15,6 +15,7 @@ <maven.deploy.skip>true</maven.deploy.skip> <maven.compiler.source>16</maven.compiler.source> <maven.compiler.target>16</maven.compiler.target> + <maven.compiler.release>16</maven.compiler.release> </properties> <dependencies> diff --git a/v1_18_R1/pom.xml b/v1_18_R1/pom.xml index 5aba4ecf..c23bcd03 100644 --- a/v1_18_R1/pom.xml +++ b/v1_18_R1/pom.xml @@ -15,6 +15,7 @@ <maven.deploy.skip>true</maven.deploy.skip> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.release>17</maven.compiler.release> </properties> <dependencies> diff --git a/v1_18_R2/pom.xml b/v1_18_R2/pom.xml index 74fc899e..f8e03ddc 100644 --- a/v1_18_R2/pom.xml +++ b/v1_18_R2/pom.xml @@ -15,6 +15,7 @@ <maven.deploy.skip>true</maven.deploy.skip> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.release>17</maven.compiler.release> </properties> <dependencies> diff --git a/v1_19_R1/pom.xml b/v1_19_R1/pom.xml index e480a5c5..5c7e455a 100644 --- a/v1_19_R1/pom.xml +++ b/v1_19_R1/pom.xml @@ -15,6 +15,7 @@ <maven.deploy.skip>true</maven.deploy.skip> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.release>17</maven.compiler.release> </properties> <repositories> diff --git a/v1_19_R2/pom.xml b/v1_19_R2/pom.xml index 4465a1fd..a0d3ccdc 100644 --- a/v1_19_R2/pom.xml +++ b/v1_19_R2/pom.xml @@ -15,6 +15,7 @@ <maven.deploy.skip>true</maven.deploy.skip> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.release>17</maven.compiler.release> </properties> <repositories> diff --git a/v1_19_R3/pom.xml b/v1_19_R3/pom.xml index 1e46d5ff..80b84a18 100644 --- a/v1_19_R3/pom.xml +++ b/v1_19_R3/pom.xml @@ -15,6 +15,7 @@ <maven.deploy.skip>true</maven.deploy.skip> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.release>17</maven.compiler.release> </properties> <repositories> diff --git a/v1_20_R1/pom.xml b/v1_20_R1/pom.xml index a38531f1..2ee2ca1f 100644 --- a/v1_20_R1/pom.xml +++ b/v1_20_R1/pom.xml @@ -15,6 +15,7 @@ <maven.deploy.skip>true</maven.deploy.skip> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.release>17</maven.compiler.release> </properties> <repositories> diff --git a/v1_20_R2/pom.xml b/v1_20_R2/pom.xml index 6aa50859..5a33ad14 100755 --- a/v1_20_R2/pom.xml +++ b/v1_20_R2/pom.xml @@ -13,9 +13,11 @@ <properties> <maven.deploy.skip>true</maven.deploy.skip> - <maven.compiler.source>17</maven.compiler.source> - <maven.compiler.target>17</maven.compiler.target> <spigot.version>1.20.2-R0.1-SNAPSHOT</spigot.version> + <java.version>17</java.version> + <maven.compiler.source>${java.version}</maven.compiler.source> + <maven.compiler.target>${java.version}</maven.compiler.target> + <maven.compiler.release>${java.version}</maven.compiler.release> </properties> <repositories> From b2ed1f8b423aac9a05cbf9d78d5cac005f0535c8 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 5 Nov 2023 17:47:51 +0100 Subject: [PATCH 77/95] :globe_with_meridians: Updated translations + added Finnish and Danish --- core/src/main/resources/locales/da_DK.yml | 79 +- core/src/main/resources/locales/fi_FI.yml | 320 +++++ core/src/main/resources/locales/hu_HU.yml | 1077 +++++++++++---- core/src/main/resources/locales/ko_KR.yml | 632 ++++++--- core/src/main/resources/locales/nl_NL.yml | 276 +++- core/src/main/resources/locales/pl_PL.yml | 1473 ++++++++++---------- core/src/main/resources/locales/ru_RU.yml | 1396 +++++++++---------- core/src/main/resources/locales/zh_CN.yml | 1508 +++++++++++---------- 8 files changed, 4065 insertions(+), 2696 deletions(-) create mode 100755 core/src/main/resources/locales/fi_FI.yml diff --git a/core/src/main/resources/locales/da_DK.yml b/core/src/main/resources/locales/da_DK.yml index 48f2c34b..65f0dc2f 100755 --- a/core/src/main/resources/locales/da_DK.yml +++ b/core/src/main/resources/locales/da_DK.yml @@ -1,59 +1,58 @@ --- msg: - dialogs: - skipped: '§8§o Dialog sprunget over.' - tooFar: '§7§oDu er for langt væk fra {npc_name}...' - experience: - edited: '§aDu har ændret XP vundet, fra {old_xp_amount} til {xp_amount} points.' - moveToTeleportPoint: '§aGå til den ønskede teleporterings placering.' - npcDoesntExist: '§cDen NPC med id {npc_id} eksisterer ikke.' - number: - negative: '§cDu skal indtaste et positivt tal!' - pools: - allCompleted: '§7Du har afsluttet alle quests!' - maxQuests: '§cDu kan ikke have mere end {pool_max_quests} quest(s) på samme tid...' - noAvailable: '§7Der er ikke flere quests tilgængelig...' - noTime: '§cDu skal vente {time_left} før du laver en anden quest.' quest: - alreadyStarted: '§cDu har allerede startet questen!' - cancelling: '§cProces for quest oprettelse annulleret.' - createCancelled: '§cOprettelsen eller redigeringen er blevet annulleret af et andet plugin!' - created: '§aTillykke! Du har oprettet questen §e{quest}§a som inkluderer {quest_branches} gren(e)!' - editCancelling: '§cProces for quest redigering annulleret.' - edited: '§aTillykke! Du har redigeret questen §e{quest}§a som inkluderer nu {quest_branches} gren(e)!' finished: base: '§aTillykke! Du er færdig med questen §e{quest_name}§a!' obtain: '§aDu får {rewards}!' + started: '§aDu har startet questen §r§e{quest_name}§o§6!' + created: '§aTillykke! Du har oprettet questen §e{quest}§a som inkluderer {quest_branches} gren(e)!' + edited: '§aTillykke! Du har redigeret questen §e{quest}§a som inkluderer nu {quest_branches} gren(e)!' + createCancelled: '§cOprettelsen eller redigeringen er blevet annulleret af et andet plugin!' + cancelling: '§cProces for quest oprettelse annulleret.' + editCancelling: '§cProces for quest redigering annulleret.' invalidID: '§cQuesten med id {quest_id} eksisterer ikke.' invalidPoolID: '§cPoolen {pool_id} eksisterer ikke.' + alreadyStarted: '§cDu har allerede startet questen!' notStarted: '§cDu er ikke på dennne quest i øjeblikket.' - started: '§aDu har startet questen §r§e{quest_name}§o§6!' - questItem: - craft: '§cDu kan ikke bruge et quest element til at crafte!' - drop: '§cDu kan ikke smide et quest element!' - eat: '§cDu kan ikke spise et quest element!' quests: - checkpoint: '§7Quest checkpoint nået!' - failed: '§cDu har fejlet questen {quest_name}...' maxLaunched: '§cDu kan ikke have mere end {quests_max_amount} quest(s) på samme tid...' updated: '§7Quest §e{quest_name}§7 opdateret.' - regionDoesntExists: '§cDette område eksisterer ikke. (Du skal være i den samme verden. "WorldGuard region")' - requirements: - money: '§cDu skal have {money}!' - waitTime: '§cDu skal vente {time_left} før du kan genstarte denne quest!' - restartServer: '§7Genstart din server for at se modifikationerne.' - selectNPCToKill: '§aVælg den NPC at dræbe.' + checkpoint: '§7Quest checkpoint nået!' + failed: '§cDu har fejlet questen {quest_name}...' + pools: + noTime: '§cDu skal vente {time_left} før du laver en anden quest.' + allCompleted: '§7Du har afsluttet alle quests!' + noAvailable: '§7Der er ikke flere quests tilgængelig...' + maxQuests: '§cDu kan ikke have mere end {pool_max_quests} quest(s) på samme tid...' + questItem: + drop: '§cDu kan ikke smide et quest element!' + craft: '§cDu kan ikke bruge et quest element til at crafte!' + eat: '§cDu kan ikke spise et quest element!' stageMobs: listMobs: '§aDu skal dræbe {mobs}.' - versionRequired: 'Version påkrævet: §l{version}' - writeChatMessage: '§aSkriv krævet besked: (Tilføj "{SLASH}" til begyndelsen, hvis du vil have en kommando.)' - writeMessage: '§aSkriv den besked, der vil blive sendt til spilleren' + writeNPCText: '§aSkriv den dialog, der vil blive sagt til spilleren af NPC''en: (Skriv "help" for at modtage hjælp.)' + writeRegionName: '§aSkriv navnet på den region der kræves for trinet:' + writeXPGain: '§aSkriv mængden af erfaringspoint spilleren vil få: (mindste værdi: {xp_amount})' writeMobAmount: '§aSkriv mængden af væsner at dræbe:' writeMobName: '§aSkriv det brugerdefinerede navn på væsnet til at dræbe:' - writeNPCText: '§aSkriv den dialog, der vil blive sagt til spilleren af NPC''en: (Skriv "help" for at modtage hjælp.)' + writeMessage: '§aSkriv den besked, der vil blive sendt til spilleren' + writeStartMessage: '§aSkriv den besked, der vil blive sendt i begyndelsen af questen, "null", hvis du ønsker standard eller "none", hvis du ønsker ingen:' + moveToTeleportPoint: '§aGå til den ønskede teleporterings placering.' writeNpcName: '§aSkriv navnet på NPC''en:' writeNpcSkinName: '§aSkriv navnet på udseendet på NPC''en:' writeQuestName: '§aSkriv navnet på din quest:' - writeRegionName: '§aSkriv navnet på den region der kræves for trinet:' - writeStartMessage: '§aSkriv den besked, der vil blive sendt i begyndelsen af questen, "null", hvis du ønsker standard eller "none", hvis du ønsker ingen:' - writeXPGain: '§aSkriv mængden af erfaringspoint spilleren vil få: (mindste værdi: {xp_amount})' + requirements: + money: '§cDu skal have {money}!' + waitTime: '§cDu skal vente {time_left} før du kan genstarte denne quest!' + experience: + edited: '§aDu har ændret XP vundet, fra {old_xp_amount} til {xp_amount} points.' + selectNPCToKill: '§aVælg den NPC at dræbe.' + regionDoesntExists: '§cDette område eksisterer ikke. (Du skal være i den samme verden. "WorldGuard region")' + npcDoesntExist: '§cDen NPC med id {npc_id} eksisterer ikke.' + number: + negative: '§cDu skal indtaste et positivt tal!' + versionRequired: 'Version påkrævet: §l{version}' + restartServer: '§7Genstart din server for at se modifikationerne.' + dialogs: + skipped: '§8§o Dialog sprunget over.' + tooFar: '§7§oDu er for langt væk fra {npc_name}...' diff --git a/core/src/main/resources/locales/fi_FI.yml b/core/src/main/resources/locales/fi_FI.yml new file mode 100755 index 00000000..372f3b67 --- /dev/null +++ b/core/src/main/resources/locales/fi_FI.yml @@ -0,0 +1,320 @@ +--- +msg: + quest: + finished: + base: '§aOnnittelut! Olet suorittanut tehtävän §e{quest_name}§!' + obtain: '§aPalkintosi: {rewards}!' + started: '§aOlet aloittanut tehtävän §r§e{quest_name}§o§6!' + created: '§aHienoa! Loit tehtävän: §e{quest}§a, jossa on {quest_branches} sivutehtävä(ä)!' + edited: '§aHienoa! Muokkasit tehtävää: §e{quest}§a, jossa on nyt {quest_branches} sivutehtävä(ä)!' + createCancelled: '§cTehtävän luonti tai muokkaus on peruttu toisen lisäosan toimesta!' + cancelling: '§cTehtävän luominen peruttu.' + editCancelling: '§cTehtävän muokkaaminen peruttu.' + invalidID: '§cTehtävä tunnuksella {quest_id} ei ole olemassa.' + alreadyStarted: '§cOlet jo aloittanut tehtävän!' + notStarted: '§cEt ole tällä hetkellä tekemässä tätä tehtävää.' + quests: + maxLaunched: '§cSinulla ei voi olla enempää kuin {quests_max_amount} tehtävä(ä) samanaikaisesti...' + updated: '§7Tehtävä §e{quest_name}§7 päivitetty.' + checkpoint: '§7Tehtävän välipiste saavutettu!' + failed: '§cOlet epäonnistunut tehtävässä: {quest_name}...' + pools: + noTime: '§cSinun täytyy odottaa {time_left} ennen kuin aloitat toista tehtävää.' + allCompleted: '§7Olet suorittanut kaikki tehtävät!' + noAvailable: '§7Tehtäviä ei ole enää saatavilla.' + maxQuests: '§cSinulla ei voi olla enempää kuin {pool_max_quests} tehtävä(ä) samanaikaisesti...' + questItem: + drop: '§cEt voi pudottaa tehtävääsi liittyviä esineitä!' + craft: '§cEt voi käyttää tehtäväesinettä tavaran luomiseen!' + eat: '§cEt voi syödä tehtäväesinettä!' + stageMobs: + listMobs: '§aSinun täytyy tappaa {mobs}.' + writeNPCText: '§aKirjoita vuoropuhelu, jonka NPC sanoo pelaajalle: (Kirjoita "help" saadaksesi apua.)' + writeRegionName: '§aKirjoita vaiheen vaatiman alueen nimi:' + writeXPGain: '§aKirjoita määrä kokemuspisteitä eli XP, jotka pelaaja saa: (Viimeinen arvo: {xp_amount})' + writeMobAmount: '§aKirjoita hirviöiden määrä, joka pelaajan on tapettava:' + writeMobName: '§aKirjoita tietyn hirviön nimi, joka pelaajan on tapettava:' + writeMessage: '§aKirjoita viesti, joka lähetetään pelaajalle' + writeStartMessage: '§aKirjoita viesti, joka lähetetään tehtävän alussa, ja "null" jos haluat sen olevan oletus tai "none", jos et halua viestiä:' + writeDescriptionText: '§aKirjoita teksti, joka kuvaa vaiheen tavoitetta:' + writeStageText: '§aKirjoita teksti, joka lähetetään pelaajalle vaiheen alussa:' + moveToTeleportPoint: '§aMene haluttuun teleporttauksen sijaintiin.' + writeNpcName: '§aKirjoita NPC:n nimi:' + writeNpcSkinName: '§aKirjoita NPC:n skinin nimi:' + writeQuestName: '§aKirjoita tehtävän nimi:' + writeHologramText: '§aKirjoita hologrammin teksti: (Kirjoita "none" jos et halua hologrammia ja "null" jos haluat oletustekstin.)' + writeQuestTimer: '§aKirjoita vaadittu aika (minuutteina) ennen kuin voit käynnistää tehtävän uudelleen: (Kirjoita "null" jos haluat oletusajan.)' + writeConfirmMessage: '§aKirjoita vahvistusviesti näytettäessä, kun pelaaja on aikeissa aloittaa tehtävän: (Kirjoita "null" jos haluat oletusviestin.)' + writeQuestDescription: '§aKirjoita etsinnän kuvaus, joka näkyy pelaajan etsinnän graafisessa käyttöliittymässä eli GUIssa.' + writeQuestMaterial: '§aKirjoita tehtävän esine.' + requirements: + quest: '§cSinun on täytynyt suorittaa ensin tehtävä §e{quest_name}§c!' + level: '§cTasosi on oltava {long_level}!' + money: '§cSinulla täytyy olla {money}!' + waitTime: '§cSinun täytyy odottaa {time_left} ennen kuin voit käynnistää tämän tehtävän uudelleen!' + selectNPCToKill: '§aValitse NPC, mikä pelaajan pitää tappaa.' + regionDoesntExists: '§cTätä aluetta ei ole olemassa. (Sinun täytyy olla samassa maailmassa.)' + npcDoesntExist: '§cNPC tunnisteella: {npc_id} ei ole olemassa.' + number: + negative: '§cSinun täytyy antaa positiivinen numero!' + zero: '§cSinun täytyy syöttää muu numero kuin 0!' + invalid: '§c{input} ei ole kelvollinen numero.' + notInBounds: '§cNumeron täytyy olla {min} ja {max} välissä.' + errorOccurred: '§cTapahtui virhe, ole hyvä ja ota yhteyttä ylläpitäjään! §4§lVirhekoodi: {error}' + indexOutOfBounds: '§cNumero {index} on yli sallitun rajan! Numeron pitää olla {min}-{max}.' + bringBackObjects: Tuo minulle takaisin {items}. + inventoryFull: '§cSinun tavaraluettelosi on täynnä, tavara on pudonnut maahan.' + versionRequired: 'Tarvitaan versio: §l{version}' + restartServer: '§7Käynnistä palvelin uudelleen nähdäksesi muutokset.' + dialogs: + skipped: '§8§o vuoropuhelu ohitettu.' + tooFar: '§7Olet liian kaukana {npc_name}sta...' + command: + checkpoint: + noCheckpoint: '§cTehtävälle: {quest} ei löytynyt välipistettä.' + questNotStarted: '§cEt tee tätä tehtävää.' + setStage: + branchDoesntExist: '§cSivua tunnuksella {branch_id} ei ole olemassa.' + startDialog: + alreadyIn: '§cPelaaja on jo vuoropuhelussa.' + leaveAll: '§aPakotit {success} tehtävä(ä) valmiiksi. Virheitä: {errors}' + startQuest: '§7Olet pakottanut aloittamaan tehtävän {quest} pelaajalle {player}.' + cancelQuest: '§7Olet peruuttanut tehtävän {quest}.' + adminModeEntered: '§aOlet nyt admin-tilassa.' + adminModeLeft: '§aOlet lähtenyt admin-tilasta.' + scoreboard: + lineSet: '§6Olet onnistuneesti muokannut riviä {line_id}.' + lineReset: '§6Olet onnistuneesti nollannut rivin {line_id}.' + lineRemoved: '§6Olet onnistuneesti poistanut rivin {line_id}.' + lineInexistant: '§cRiviä {line_id} ei ole olemassa.' + help: + header: '§6§lBeautyQuests — Ohje' + resetPlayer: '§6/{label} resetPlayer <player>: §ePoista kaikki tiedot pelaajasta.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §ePoista pelaajan tiedot tehtävästä.' + seePlayer: '§6/{label} seePlayer <player>: §eNäytä pelaajaa koskevat tiedot.' + reload: '§6/{label} reload: §eTallenna ja lataa kaikki asetukset ja tiedostot. (§cpoistettu käytöstä§e)' + start: '§6/{label} start <player> [id]: §ePakota pelaaja aloittamaan tehtävä.' + setItem: '§6/{label} setItem <talk|launch>: §eTallenna hologrammi.' + setFirework: '§6/{label} setFirework: §eMuokkaa oletusilotulitusta.' + adminMode: '§6/{label} adminMode: §eVaihda admin-tila pois tai päälle. (Hyödyllinen pienten lokiviestien näyttämiseen.)' + version: '§6/{label} version: §eKatso nykyinen lisäosan versio.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eLataa vanilla-pelistä käännöstiedosto.' + save: '§6/{label} save: §eTee manuaalinen lisäosan tallennus.' + list: '§6/{label} list: §eTarkasta tehtävälista. (Vain tuetuille versioille.)' + typeCancel: '§aKirjoita "peruuta" palataksesi viimeiseen tekstiin.' + editor: + blockAmount: '§aKirjoita palikoiden määrä:' + blockName: '§aKirjoita palikan nimi:' + blockData: '§aKirjoita palikan tiedot (saatavilla olevat tiedot: §7{available_datas}§a):' + blockTag: '§aKirjoita palikan tägi (saatavilla olevat tägit: §7{available_tags}§a):' + typeBucketAmount: '§aKirjoita täytettävien sankojen määrä.' + typeDamageAmount: 'Kirjoita määrä, joka pelaajan on tehtävä' + goToLocation: '§aSiirry haluttuun kohtaan vaiheessa.' + typeLocationRadius: '§aKirjoita tarvittava etäisyys sijainnista:' + typeGameTicks: '§aKirjoita vaaditut Minecraft-tickit:' + already: '§cOlet jo muokkaamassa.' + stage: + location: + typeWorldPattern: '§aKirjoita regex maailman nimille:' + enter: + title: '§6~ Muokkaus tila ~' + subtitle: '§6Kirjoita "/quests exitEditor" poistuaksesi editorista.' + list: '§c⚠ §7Olet nyt "listan" editorissa. Käytä "add" lisätäksesi rivejä. Vie "help" (ilman / -merkkiä) saadaksesi apua. §e§lKirjoita "close" poistuaksesi editorista.' + chat: '§6Olet tällä hetkellä Editor-tilassa. Kirjoita "/quests exitEditor" lähteäksesi editorista. (Ei suositella, harkitse "sulje" tai "peruuta" komentojen käyttämistä palataksesi edelliseen näkymään.)' + npc: + enter: '§aKlikkaa NPC tai kirjoita "cancel".' + choseStarter: '§aValitse NPC, joka aloittaa tehtävän.' + notStarter: '§cTämä NPC ei ole tehtävän käynnistäjä.' + text: + argNotSupported: '§cArgumenttia {arg} ei tueta.' + chooseLvlRequired: '§aKirjoita tarvittava määrä tasoja:' + chooseJobRequired: '§aKirjoita halutun työn nimi:' + choosePermissionRequired: '§aKirjoita vaadittu käyttöoikeus, jotta tehtävä voidaan aloittaa:' + choosePermissionMessage: '§aVoit valita hylkäysviestin, jos pelaajalla ei ole vaadittua käyttöoikeutta. (Ohita tämä vaihe, kirjoittamalla "null".)' + choosePlaceholderRequired: + identifier: '§aKirjoita vaaditun paikkamerkin nimi ilman prosenttilukua:' + value: '§aKirjoita paikkamerkille vaadittu arvo §e%§e{placeholder}§e%§a:' + chooseSkillRequired: '§aKirjoita vaaditun taidon nimi:' + chooseMoneyRequired: '§aKirjoita tarvittava rahamäärä:' + reward: + permissionName: '§aKirjoita käyttöoikeuden nimi.' + permissionWorld: '§aKirjoita maailma, jossa lupaa muokataan, tai "null" jos haluat kaikki maailmat.' + money: '§aKirjoita rahamäärä, jonka pelaaja saa:' + wait: '§aKirjoita odotettavien pelin tickien määrä (1 sekunti = 20 tickiä)' + random: + min: '§aKirjoita pelaajalle annettujen palkintojen vähimmäismäärä (mukaan lukien).' + max: '§aKirjoita pelaajalle annettujen palkintojen enimmäismäärä (mukaan lukien).' + chooseObjectiveRequired: '§aKirjoita kohteen nimi.' + chooseObjectiveTargetScore: '§aKirjoita kohteen tavoite pistemäärä.' + chooseRegionRequired: '§aKirjoita vaaditun alueen nimi (sinun täytyy olla samassa maailmassa).' + chooseRequirementCustomReason: 'Kirjoita mukautettu syy tähän vaatimukseen. Jos pelaaja ei täytä vaatimusta, mutta yrittää käynnistää tehtävän joka tapauksessa, tämä viesti näkyy chatissa.' + chooseRequirementCustomDescription: 'Kirjoita mukautettu kuvaus tälle vaatimukselle. Se tulee näkymään valikossa olevan tehtävän kuvauksessa.' +advancement: + notStarted: Ei aloitettu +inv: + validate: '§b§lVahvista' + cancel: '§c§lPeruuta' + search: '§e§lHaku' + addObject: '§aLisää objekti' + confirm: + name: Oletko varma? + 'yes': '§aVahvista' + 'no': '§cPeruuta' + create: + stageCreate: '§aLuo uusi vaihe' + stageRemove: '§cPoista tämä vaihe' + stageUp: Siirrä ylös + stageDown: Siirrä alas + stageType: '§7Vaiheen tyyppi: §e{stage_type}' + findNPC: '§aLöydä NPC' + bringBack: '§aTuo takaisin esineitä' + findRegion: '§aEtsi alue' + killMobs: '§aTapa hirviöitä' + mineBlocks: '§aRiko palikoita' + placeBlocks: '§aAseta palikoita' + talkChat: '§aKirjoita chattiin' + fish: '§aKalasta' + melt: '§7Sulata esineitä' + enchant: '§dLumoa esineitä' + craft: '§aLuo tavaraoita' + bucket: '§aTäytä sankoja' + location: '§aMene sijaintiin' + playTime: '§ePelaa' + breedAnimals: '§aKasvata eläin(tä)' + tameAnimals: '§aKesytä eläin(tä)' + death: '§cKuole' + dealDamage: '§cTee vahingoa hirviöön' + eatDrink: '§aSyö tai juo ruokaa tai juomia' + NPCText: '§eMuokkaa vuoropuhelua' + NPCSelect: '§eValitse tai luo NPC' + hideClues: Piilota hiukkaset ja hologrammit + stages: + nextPage: '§eSeuraava sivu' + laterPage: '§eEdellinen sivu' + chooseQuest: + name: Mikä tehtävistä? + menu: '§aTehtävävalikko' + requirements: + name: Vaatimukset + rewards: + name: Palkinnot + commands: 'Komennot: {amount}' + listAllQuests: + name: Tehtävät + listPlayerQuests: + name: '{player_name} tehtävät' + listQuests: + notStarted: Aloittamattomat tehtävät + finished: Suoritetut tehtävät + inProgress: Käynnissä olevat tehtävät + loreDialogsHistoryClick: '§7Näytä vuoropuhelut' + loreCancelClick: '§cPeruuta tehtävä' + loreStart: '§a§oKlikkaa aloittaaksesi tehtävän.' + loreStartUnavailable: '§c§oEt täytä vaatimuksia aloittaaksesi tehtävän.' + timeToWaitRedo: '§7§oVoit käynnistää tämän tehtävän uudelleen {time_left}...' + canRedo: '§e§oVoit aloittaa tämän tehtävän uudelleen!' + timesFinished: '§eSuoritettu §6{times_finished} x§e.' + format: + normal: '§6§l§o{quest_name}' + withId: '§6§l§o{quest_name}§f §e#{quest_id}' + listBook: + questName: Nimi + questStarter: Aloitus + questRewards: Palkinnot + questMultiple: Useita kertoja + requirements: Vaatimukset + questStages: Vaiheet + poolCreation: + maxQuests: '§aMaksimimäärä tehtäviä' + requirements: '§bVaatimukset aloittaaksesi tehtävän' + itemComparisons: + material: Esine + itemName: Esineen nimi + itemLore: Esineen tieto + enchants: Esineen lumous + editTitle: + title: '§7Otsikko' + subtitle: '§eAlaotsikko' + visibility: + notStarted: '"Aloittamattomat tehtävät" valikko' + inProgress: '"Kesken olevat tehtävät" valikko' + finished: '"Suoritetut tehtävät" valikko' + questObjects: + description: '§8Kuvaus: §7{description}' +scoreboard: + name: '§6§lTehtävät' + noLaunched: '§cEi tehtäviä käynnissä.' + noLaunchedName: '§c§lLadataan' + noLaunchedDescription: '§c§oLadataan' + textBetwteenBranch: '§e tai' + asyncEnd: '§ex' + stage: + region: '§eEtsi alue: §6{region_id}' + npc: '§eKeskustele NPClle: §6{dialog_npc_name}' + items: '§eTuo esineitä §6{dialog_npc_name}lle§e: {items}' + mobs: '§eTapa §6{mobs}' + mine: '§eHakkaa {blocks}' + placeBlocks: '§eAseta {blocks}' + chat: '§eKirjoita §6{text}' + interact: '§eKlikkaa kuutiota koordinaateissa: §6{x} {y} {z}' + interactMaterial: '§eKlikkaa §6{block}§e kuutiota' + fish: '§eKalasta §6{items}' + melt: '§eSulata §6{items}' + enchant: '§eLumoa §6{items}' + craft: '§eLuo §6{items}' + bucket: '§eTäytä §6{buckets}' + location: '§eMene koordinaatteihin: §6{target_x}§e, §6{target_y}§e, §6{target_z}§e §6{target_world}' + playTimeFormatted: '§ePelaa §6{time_remaining_human}' + breed: '§eKasvata §6{mobs}' + tame: '§eKesytä §6{mobs}' + die: '§cKuole' + dealDamage: + any: '§cVahingoita {damage_remaining} vahinkoa' + mobs: '§cVahingoita {damage_remaining} vahinkoa hirviöön: {target_mobs}' + eatDrink: '§ePue §6{items}' +indication: + startQuest: '§7Haluatko aloittaa tehtävän {quest_name}?' +description: + requirement: + title: '§8§lVaatimukset:' +misc: + stageType: + location: Etsi sijainti + playTime: Peliaika + breedAnimals: Kasvata eläin(tä) + tameAnimals: Kesytä eläin(tä) + die: Kuole + dealDamage: Tee vahinkoa + eatDrink: Syö tai juo + comparison: + equals: yhtä suuri kuin {number} + different: erilainen kuin {number} + less: paljon vähemmän kuin {number} + lessOrEquals: pienempi kuin {number} + greater: paljon suurempi kuin {number} + greaterOrEquals: suurempi kuin {number} + requirement: + logicalOr: '§dLooginen TAI (vaatimukset)' + permissions: '§3Vaadittu käyttöoikeus' + quest: '§aTehtävä vaaditaan' + bucket: + water: Vesiämpäri + lava: Laavaämpäri + milk: Maitoämpäri + snow: Lumiämpäri + click: + right: Oikea-klikkaus + left: Vasen-klikkaus + shift-right: Shift + oikea-klikkaus + shift-left: Shift + vasen-klikkaus + middle: Keski-klikkaus + amounts: + items: '{items_amount} esine(ttä)' + questItemLore: '§e§oTehtäväesine' + hologramText: '§8§lTehtävä NPC' + poolHologramText: '§eUusi tehtävä saatavilla!' + entityType: '§eKohdetyyppi: {entity_type}' + or: tai + 'yes': 'Kyllä' + 'no': 'Ei' + and: ja diff --git a/core/src/main/resources/locales/hu_HU.yml b/core/src/main/resources/locales/hu_HU.yml index e41dc448..33a54f89 100644 --- a/core/src/main/resources/locales/hu_HU.yml +++ b/core/src/main/resources/locales/hu_HU.yml @@ -1,316 +1,833 @@ --- +msg: + quest: + finished: + base: '&aSikeresen teljesítetted a(z) §e{quest_name}§a küldetést!' + obtain: '§aEzt kaptad: {rewards}!' + started: '&aElkezdted a(z) §r§e{quest_name}§o§6 küldetést!' + created: '&aSiker! Létrehoztad a(z) §e{quest}§a küldetést, amely tartalmaz {quest_branches} ágat!' + edited: '&aSiker! Módosítottad a(z) §e{quest}§a küldetést, amely tartalmaz {quest_branches} ágat!' + createCancelled: '§cA készítési, vagy módosítási folyamat megszakításra került egy másik plugin által!' + cancelling: '§cA küldetés elkészítése közben hiba történt.' + editCancelling: '§cA küldetés szerkesztése megszakítva.' + invalidID: '§cNem létezik küldetés {quest_id} ID-val.' + invalidPoolID: A(z) {pool_id} gyűjtemény nem létezik. + alreadyStarted: '§cMár elkezdted ezt a küldetést!' + notStarted: '§cJelenleg nem csinálod ezt a küldetést.' + quests: + maxLaunched: '§cNem lehet több mint {quests_max_amount} küldetésed elkezdve egy időben!' + updated: '§7A(z) §e{quest_name}§7 küldetés frissítésre került.' + checkpoint: '§7Küldetés ellenőrzőpont elérve!' + failed: '§cNem sikerült teljesítened a(z) {quest_name} küldetés...' + pools: + noTime: '§cVárnod kell még {time_left} mielőtt elkezdenél egy újabb küldetést.' + allCompleted: '§7Az összes küldetést teljesítetted!' + noAvailable: '§7Nincsenek elérhető küldetések.' + maxQuests: '§cNem lehet több mint {pool_max_quests} küldetésed egy időben!' + questItem: + drop: '§cKüldetés tárgyat nem dobhatsz el!' + craft: '§cNem barkácsolhatsz küldetés tárggyal!' + eat: '§cNem ehetsz meg egy küldetés tárgyat!' + stageMobs: + listMobs: '§aMeg kell ölnöd {mobs} mobot.' + writeNPCText: '§aÍrd be a dialógust, amelyet az NPC a játékosnak fog mondani: (Használd a "help" paramétert a segítés kéréséhez.)' + writeRegionName: '§aAdd meg az állomáshoz szükséges régiót:' + writeXPGain: '§Írd ide az xp mennyiséget amit a játékos kapni fog: (Utolsó érték:{xp_amount})' + writeMobAmount: '§aÍrd ide a megöldenő mobok mennyiségét:' + writeMobName: '§aÍrd ide a megölni kívánt mob nevét:' + writeChatMessage: '§aÍrd ide a megkövetelt üzenetet: (Írj az elejére "\{SLASH}" szimbólumot, ha parancsot szeretnél.)' + writeMessage: '§aÍrd be az üzenetet amit a játékos látni fog' + writeStartMessage: '§aÍrd be az üzenetet, amit a játékos a küldetés elkezdésénél látni fog. Írj "null"-t ha az alapértelmezett szöveget szeretnéd, vagy írj "none"-t ha nem szeretnél szöveget:' + writeEndMsg: '§aÍrd be az üzenetet, amit a játékos a küldetés teljesítésénél látni fog. Írj "null"-t ha az alapértelmezett szöveget szeretnéd, vagy írj "none"-t ha nem szeretnél szöveget. Használhatod a "\{rewards}" paramétert, amely a megkapott jutalmakat jeleníti meg.' + writeEndSound: '§aÍrd be a hang nevét, amely a küldetés végeztével lejátszásra kerül. Írj "null"-t ha az alapértelmezett hangot szeretnéd, vagy írj "none"-t ha nem szeretnél hangot:' + writeDescriptionText: '§aAdd meg az állomás leírását:' + writeStageText: '§aAdd meg az üzenetet, amit a játékos kapni fog az állomás megkezdésénél:' + moveToTeleportPoint: '§aMenj a helyre, amely a teleport célja lesz.' + writeNpcName: '§aÍrd ide az NPC nevét:' + writeNpcSkinName: '§aAdd meg az NPC kinézetének nevét:' + writeQuestName: '§aAdd meg a küldetés nevét:' + writeCommand: '§aÍrd be a parancsot: (A parancsot "/" szimbólum nélkül írd, a "\{player}" paraméter támogatott. A paraméter helyére a játékos neve kerül.)' + writeHologramText: '§aAdd meg a hologram nevét: (Használd a "none" paramétert ha nem szeretnél hologramot, vagy a "null" paramétert ha az alapértelmezett szöveget szeretnéd.)' + writeQuestTimer: '§aAdd meg, mennyi idő után kezdhető újra a küldetés (percekben): (Használd a "null" paramétert ha az alapértelmezett időt szertnéd használni.)' + writeConfirmMessage: '§aAdd meg a kezdésnél megjelenő megerősítő üzenetet: (Használd a "null" paramétert ha az alapértelmezett üzenetet szertnéd használni.)' + writeQuestDescription: '§aAdd meg a leírást, amelyet a játékos a Küldetés Menüben látni fog.' + writeQuestMaterial: '§aÍrd ide a küldetés tárgy anyagát.' + requirements: + quest: '§cBe kell fejezned a §e{quest_name}§c küldetést!' + level: '§cA szintednek {long_level}-nak/nek kell lennie!' + job: '§cA §e{job_name}§c munkához szükséges szinted {long_level} kell, hogy legyen!' + skill: '§cA §e{skill_name}§c képességhez szükséges szinted {long_level} kell, hogy legyen!' + combatLevel: '§aA harc szintednek {long_level}-nak/nek kell lennie!' + money: '§c{money} összeggel kell rendelkezned}!' + waitTime: '§cVárnod kell {time_left} időt, mielőtt újra kezdheted ezt a küldetést!' + experience: + edited: '§aMegváltoztattad az exp hozamot {old_xp_amount}-ról/ről {xp_amount}-ra/re.' + selectNPCToKill: '§aVálaszd ki a megölendő NPC-t.' + regionDoesntExists: '§cEz a hely nem létezik. (Ugyanabban a világban kell lenned.)' + npcDoesntExist: '§cNPC {npc_id} azonosítóval nem létezik..' + number: + negative: '§cEgy pozitív számot kell megadnod!' + zero: '§cMás számot kell írnod mint 0!' + invalid: '§c{input} nem egy érvényes szám.' + notInBounds: '§cA számodnak {min} és {max} érték között kell lennie!' + errorOccurred: '§cEgy hiba lépett fel, keress megy egy Admint! §4§lHiba kód: {error}' + indexOutOfBounds: '§cA(z) {index} szám a határokon kívűlre esik. {min} és {max} között kell lennie.' + invalidBlockData: '§cA {block_data} blockdata érvénytelen vagy inkompatibilis a(z) {block_material} blokknál.' + invalidBlockTag: '§cNem elérhető block tag: {block_tag}.' + bringBackObjects: Hozz nekem {items} tárgy(ak)at. + inventoryFull: '§cAz eszköztárad tele van, a tárgy a földre lett dobva.' + versionRequired: 'Szükséges verzió: §l{version}' + restartServer: '§7Indítsd újra a szervert, hogy lásd a módosításokat.' + dialogs: + skipped: '§8§o Dialógus átugorva.' + tooFar: '§7§oTúl messze vagy {npc_name} NPC-től...' + command: + downloadTranslations: + syntax: '§cA letöltéshez meg kell adnod egy nyelvet. Például: "/quests downloadTranslations en_US".' + notFound: '§c A(z) {lang} nyelv nem található a(z) {version} verzióhoz. ' + exists: '§c A(z) {file_name} nevű fájl már már létezik! A parancs végén használd az "-overwrite" paramétert ahhoz, hogy felülírd. /quests downloadTranslations <lang> -overwrite)' + downloaded: '§aA(z) {lang} nyelv letöltésre került! §7Módosítsd a "/plugins/BeautyQuests/config.yml" fájlt ahhoz, hogy kicseréld a §ominecraftTranslationsFile§7 értékét a {lang} nyelvre, majd indítsd újra a szervert.' + checkpoint: + noCheckpoint: '§cNem találtunk checkpoint-ot a {quest} küldetéshez.' + questNotStarted: '§cNem csinálod ezt a küldetést.' + setStage: + branchDoesntExist: '§cNem létezik elágazás {branch_id} azonosítóval.' + doesntExist: '§cA következő szint {stage_id} nem létezik.' + next: '§aÁllomás átugorva.' + nextUnavailable: '§cAz "átugrás" opció nem lehetséges, ha a játékos az elágazás végére ért.' + set: '§a{stage_id} azonosítójú szint elindítva.' + startDialog: + impossible: '§cA dialógus elindítása nem lehetséges!' + noDialog: '§cA játékosnak nincs folyamatban lévő dialógusa.' + alreadyIn: '§cA játékos már dialógusban van.' + success: '§aA dialógus elkezdődött {player} játékosnak a {quest} küldetésben!' + invalidCommand: + simple: '§cA parancs nem létezik, a segítséghez használd a §ehelp§c paramétert.' + itemChanged: '§aA tárgy módosítva. A változtatások az újraindítás után lépnek életbe.' + itemRemoved: '§aA holgramhoz beállított tárgy törölve lett.' + removed: '§aA(z) {quest_name} küldetés törlésre került.' + leaveAll: '§aA(z) {success} küldetés(eke)t leadatták veled. Hibák: {errors}' + resetPlayer: + player: '§6{quest_amount} küldetés minden adata törölve lett {deleter_name} által.' + remover: '§6{quest_amount} küldetés információ (és {quest_pool} küldetés gyűjtemény) törölve lett {player} játékosnál!' + resetPlayerQuest: + player: '§6{quest} küldetés minden adata törlésre került {deleter_name} által.' + remover: '§6{player} adatai törlésre kerültek a(z) {quest} küldetésből.' + resetQuest: '§6{player_amount} játékos küldetés adatai törlésre kerültek.' + startQuest: '§6Elindítottad a {quest} küldetést {player} játékosnál!' + startQuestNoRequirements: '§cA játékos nem felel meg a(z) {quest} küldetés követelményeinek. A követelmény ellenőrzés átugrásához használd az "-overrideRequirements" paramétert a parancs végén.' + cancelQuest: '§6Félbeszakítottad a(z) {quest} küldetést!' + cancelQuestUnavailable: '§cA(z) {quest} küldetés nem utasítható el.' + backupCreated: '§6Sikeres mentést készítettél az összes küldetés és játékos információról.' + backupPlayersFailed: '§cA játékos informáicó mentése sikertelen.' + backupQuestsFailed: '§cA küldetés információ mentése sikertelen.' + adminModeEntered: '§aBeléptél az Admin Módba.' + adminModeLeft: '§aKiléptél az Admin Módból.' + resetPlayerPool: + timer: '§aVisszaállítottad {player} játékos időzítőjét a {pool} küldetés gyűjteménynél.' + full: '§aVisszaállítottad {player} játékos adatait a(z) {pool} küldetés gyüjteménynél!' + startPlayerPool: + error: 'A(z) {pool} küldetés gyűjtemény elindítása sikertelen {player} játékosnál.' + success: 'Elindítottad a(z) {pool} küldetés gyűjteményt {player} játékosnál. Eredménye: {result}.' + scoreboard: + lineSet: '§6Sikeresen átírtad a(z) {line_id}. sort.' + lineReset: '§6Sikeresen visszaállítottad a(z) {line_id}. sort.' + lineRemoved: '§6Sikeresen eltávolítottad a(z) {line_id}. sort.' + lineInexistant: '§cA(z) {line_id}. sor nem létezik.' + resetAll: '§6Sikeres visszaállítottad {player_name} játékos scoreboard-ját.' + hidden: '§6A scoreboard {player_name} játékos számára elrejtve.' + shown: '§6A scoreboard {player_name} játékos számára megjelenítve.' + own: + hidden: '§6A scoreboard mostantól el van rejtve.' + shown: '§6A scoreboard mostantól látható.' + help: + header: '§6§lBeautyQuests - Súgó' + create: '§6/{label} create: §eKüldetés létrehozása.' + edit: '§6/{label} edit: §eKüldetés módosítása.' + remove: '§6/{label} remove <id>:§Kitörli a megadott ID-jű Küldetést, vagy kattints az NPC-re, ha nem adtál meg ID-t.' + finishAll: '§6/{label} finishAll <player>: §eA játékos összes küldetésének teljesítése.' + setStage: '§6/{label} setStage <player> <id> [new branch] [new stage]: §eA jelenlegi állomás átugrása.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eElindítja a függőben lévő dialógust egy NPC állomásnál, vagy a küldetés kezdő dialógusát.' + resetPlayer: '§6/{label} resetPlayer <player>: §eMinden játékos adat törlése.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eEgy játékos adott küldetés adatainak törlése.' + seePlayer: '§6/{label} seePlayer <player>: §eJátékos információ megtekintése.' + reload: '§6/{label} reload: §eMenti, majd ujratölti a konfigurációt és a fájlokat. (§cdeprecated§e)' + start: '§6/{label} start <player> [id]: §eKényszeríti a küldetés elkezdését.' + setItem: '§6/{label} setItem <talk|launch>: §eElmenti a hologramnak beállított tárgyat.' + setFirework: '§6/{label} setFirework: §eSzerkezti az alapértelmezett záró tüzijátékot.' + adminMode: '§6/{label} adminMode: §eAdmin mód váltása. (Log üzenetek megjelenítésénél hasznos.)' + version: '§6/{label} version: §eA jelenlegi plugin verzió megjelenítése.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eLetölti a megadott nyelv fordítását.' + save: '§6/{label} save: §eEgy kézi mentés készítése.' + list: '§6/{label} list: §eKüldetés lista megjelenítése. (Csak a támogatott verziók esetén.)' + typeCancel: '§aÍrd be, hogy "cancel" ahhoz, hogy visszatérj az utolsó üzenethez.' + editor: + blockAmount: '§aÍrd be a blokkok mennyiségét:' + blockName: '§aÍrd be a blokk nevét:' + blockData: '§aÍrd be a block data-t (rendelkezésre álló block data-k: §7{available_datas}§a):' + blockTag: '§aÍrd be a block tag-et (rendelkezésre álló block tag-ek: §7{available_tags}§a):' + typeBucketAmount: '§aÍrd be a megtöltendő vödrök számát:' + typeDamageAmount: 'Írd be a játékos által okozandó sebzés mennyiségét:' + goToLocation: '§aMenj az állomás teljesítéséhez szükséges helyre.' + typeLocationRadius: '§aÍrd be a céltól számított maximális távolságot:' + typeGameTicks: '§aÍrd be a szükséges game tick-ek számát:' + already: '§cMár a szerkeztőben vagy.' + stage: + location: + typeWorldPattern: '§aÍrd be a világ nevekhez szükséges regex-et:' + enter: + title: '§6~ Szerkeztői Mód ~' + subtitle: '§6Írd be a "/quests exitEditor" parancsot, a szerkeztőből való kilépéshez.' + list: '§c⚠ §7Beléptél egy listás szerkeztőbe. Használd az "add" parancsot sor hozzáadáshoz. A segítséghez használd a "help" paramétert ("/" jel nélkül). §e§lÍrd be a "close" paramétert a szerkeztőből való kilépéshez.' + chat: '§6Jelenleg szerkeztő módban vagy! A kilpéshez használd a "/quests exitEditor" parancsot. (Nem ajánlatos, használd inkább a "clos" vagy "cancel" paramétert, hogy visszatérj eszköztárad előző állapotához.)' + npc: + enter: '§aKattints az NPC-re, vagy használd a "cancel" paramétert.' + choseStarter: '§aVálaszd ki a küldetés adó NPC-t.' + notStarter: '§cEz nem egy küldetés adó NPC.' + text: + argNotSupported: '§cA(z) {arg} kifejezés nem támogatott.' + chooseLvlRequired: '§aÍrd be a szükséges szintek számát:' + chooseJobRequired: '§aÍrd be a szükséges szakma nevét:' + choosePermissionRequired: '§aÍrd be a küldetés elkezdéséhez szükséges jogot:' + choosePermissionMessage: '§aMegadhatsz egy üzenetet, amennyiben a játékos nem rendelkezik a szükséges joggal. (Ennek kihagyásához használsz a "null" paramétert.)' + choosePlaceholderRequired: + identifier: '$aÍrd be a szükséges placeholder-t a százalékjel (%) karakterek nélkül:' + value: '§aÍrd be a §e%§e{placeholder}§e%§a placeholder szükséges értékét:' + chooseSkillRequired: '§aÍrd be a szükséges képesség nevét:' + chooseMoneyRequired: '§aÍrd be a szükséges pénz mennyiségét:' + reward: + permissionName: '§aÍrd be a jogosultság nevét.' + permissionWorld: '§aÍrd be a világ nevét, amelyben a jogosultság módosítva lesz, vagy használd a "null" paramétert, amennyiben azt szeretnéd, hogy globális legyen.' + money: '§aÍrd be a kapott pénz mennyiségét:' + wait: '§aÍrd be, mennyi game tick-et várjon (1 másodperc = 20 game tick-kel)' + random: + min: '§aÍrd be a jutalmak minimális számát (inklúzív érték).' + max: '§aÍrd be a jutalmak maximális számát (inklúzív érték).' + chooseObjectiveRequired: '§aÍrd be az objective nevét.' + chooseObjectiveTargetScore: '§aÍrd be az objective teljesítéséhez szükséges pontszámot.' + chooseRegionRequired: '§aÍrd be a szükséges régió nevét (ugyanabban a világban kell lenned).' + chooseRequirementCustomReason: 'Írd be a követelmény miértjét. Ha a játékos nem felel meg a követelményeknek, de megpróbálja elindítani a küldetést, ez az üzenet jelenik meg számára a chat-en.' + chooseRequirementCustomDescription: 'Írj be leírást a követelmény számára. Ez a küldetés leírásában fog megjelenni a menüben.' + chooseRewardCustomDescription: 'Írj be leírást a jutalom számára. Ez a küldetés leírásában fog megjelenni a menüben.' + selectWantedBlock: '§aKattints bottal a szükséges blokkra ehhez az állomáshoz.' + itemCreator: + itemType: '§aÍrd be a kívánt tárgy típusát:' + itemAmount: '§aÍrd be a tárgyak mennyiségét:' + itemName: '§aÍrd be a tárgy nevét:' + itemLore: '§aMódosítsd a tárgy leírását (Használd a "help" paramétert segítség kéréshez.)' + unknownItemType: '§cIsmeretlen tárgy típus.' + invalidItemType: '§cÉrvénytelen tárgy típus. (Ez a tárgy nem lehet blokk.)' + unknownBlockType: '§cIsmeretlen blokk típus.' + invalidBlockType: '§cÉrvénytelen blokk típus.' + dialog: + syntaxMessage: '§cHelyes szintaxis: {command} <message>' + syntaxRemove: '§cHelyes szintaxis: remove <id>' + player: '§aA(z) "§7{msg}§a" üzenet hozzáadva a játékoshoz.' + npc: '§aA(z) "§7{msg}§a" üzenet hozzáadva a NPC-hez.' + noSender: '§aA(z) "§7{msg}§a" üzenet hozzáadva küldő nélkül.' + messageRemoved: '§aA(z) "§7{msg}§a" üzenet törölve.' + edited: '§aA(z) "§7{msg}§a" üzenet módosítva.' + soundAdded: '§aA(z) "§7{sound}§a" hang hozzáadva a(z) "§7{msg}§a" üzenethez.' + cleared: '§2§l{amount}§a számú üzenet törölve.' + help: + header: '§6§lBeautyQuests — Dialógus szerkeztő sugó' + npc: '§6npc <message>: §eÜzenet hozzáadása az NPC-hez.' + player: '§6player <message>: §eJátékos által írt szöveg hozzáadása.' + nothing: '§6noSender <message>: §eHozzáad egy szöveget küldő nélkül.' + remove: '§6remove <id>: §eSzöveg eltávolítása' + list: '§6list: §eÖsszes szöveg megtekintése.' + npcInsert: '§6npcInsert <id> <message>: §eNPC által mondott szöveg hozzáadása.' + playerInsert: '§6npcInsert <id> <message>: §eJátékos által mondott szöveg hozzáadása.' + nothingInsert: '§6nothingInsert <id> <message>: §eÜzenet hozzáadása prefixum nélkül.' + edit: '§6edit <id> <message>: §eÜzenet szerkeztése.' + addSound: '§6addSound <id> <sound>: §eHang hozzáadása az üzenethez.' + clear: '§6clear: §eÖsszes üzenet kitrölése.' + close: '§6close: §eMinden üzenet mentése és kilépés.' + setTime: '§6setTime <id> <time>: §eA szövegek automatikus lejátszása közötti idő megadása (tick-ekben).' + npcName: '§6npcName [egyedi NPC név]: §eSet (vagy visszaállítás alapértelmezettre) egyedi NPC név beállítása a dialógusban' + skippable: '§6skippable [true|false]: §eA dilaógus átugorhatóságát szerkeztheted vele.' + timeSet: '§aA(z) {msg} szöveg szüneteltetése módosítva {time} tick-re.' + timeRemoved: '§aSzüneteltetés eltávolítva a(z) {msg} üzenetről.' + npcName: + set: '§aAz NPC neve módosításra került: §7{new_name}§a (régi név: §7{old_name}§a)' + unset: '§aAz NPC neve visszaállítva az alapértelmezettre (régi név: §7{old_name}§a)' + skippable: + set: '§aA dialógus átugorhatósága módosításra került (régi érték: §7{old_state}§a).' + unset: '§aA dialógus átugorhatósága visszaállítva alapértelmezettre (régi érték: §7{old_state}§a).' + mythicmobs: + list: '§aA Mythic Mobok listája:' + isntMythicMob: '§cEz a Mythic Mob nem létezik.' + disabled: '§cMythicMob kikapcsolva.' + advancedSpawnersMob: 'Írd be a megöldendő spawner-es mob nevét:' + textList: + syntax: '§cHelyes szintaxis: {command}' + added: '§a"§7{msg}§a" üzenet hozzáadva.' + removed: '§a"§7{msg}§a" üzenet törölve.' + help: + header: '§6§lBeautyQuests - Lista szerkesztő súgó' + add: '§6add <message>: §eSzöveg hozzáadása.' + remove: '§6remove <id>: §eSzöveg eltávolítása.' + list: '§6list: §eMinden hozzáadott szöveg megtekintése.' + close: '§6close: §eHozzáadott szövegek mentése és bezárás.' + availableElements: 'Elérhető elemek: §e{available_elements}' + noSuchElement: '§cNincs ilyen elem. Engedélyezett elemek: §e{available_elements}' + invalidPattern: '§cHelytelen regex: §4{input}§c.' + comparisonTypeDefault: '§aVálassza ki az összehasonlítás típusát a(z) {available} közül. Alapértelmezett összehasonlítás: §e§l{default}§r§a. Írd be a §onull§r§a-t a használathoz.' + scoreboardObjectiveNotFound: '§cIsmeretlen scoreboard objective.' + pool: + hologramText: 'Írd be ezen küldetés gyűjtemény hologram szövegét (Használd a "null" paramétert, ha az alapértelmezettet szeretnéd).' + maxQuests: 'Írd be a maximum elkezdhető küldetések számát.' + questsPerLaunch: 'Írd be az egyszerre elkezdhető küldetések maximum számát.' + timeMsg: 'Írd be mennyi idő után vehet fel a játékos új küldetést. (Alapértelmezett: 1 nap)' + title: + title: 'Add meg a title szöveget (Használd a "null" paramétert, ha ne szeretnél).' + subtitle: 'Add meg a subtitle szöveget (Használd a "null" paramétert, ha ne szeretnél).' + fadeIn: 'Add meg a "fade-in" hosszát tick-ekben (20 tick = 1 másodperc).' + stay: 'Add meg a "stay" hosszát tick-ekben (20 tick = 1 másodperc).' + fadeOut: 'Add meg a "fade-out" hosszát tick-ekben (20 tick = 1 másodperc).' + colorNamed: 'Add meg a szín nevét.' + color: 'Add meg a színt hexadecimális formátumban (#XXXXXX) vagy használj RGB formátumot (piros, zöld, kék).' + invalidColor: 'A megadott szín érvénytelen. Használj hexadecimális vagy RGB formátumot.' + firework: + invalid: 'A megadott tárgy nem egy érvényes tüzijáték.' + invalidHand: 'Egy tüzijátékot kell a kezedben tartanod.' + edited: 'Módosítottad a küldetés végi tüzijátékot!' + removed: 'Eltávolítottad a küldetés végi tüzijátékot!' + writeCommandDelay: '§aÍrd be a parancs késleltetését tick-ekben.' advancement: - finished: Teljesítve + finished: Teljesítetted {times_finished} alkalommal notStarted: Nem elkezdett -description: - requirement: - level: Szint {short_level} -indication: - cancelQuest: '§7Biztos vagy benne, hogy megakarod szakítani ezt a küldetést {quest_name}?' - removeQuest: '§7Biztos vagy benne, hogy elakarod távolítani ezt a küldetést {quest}?' inv: + validate: '§b§lMegerősítés' cancel: '§c§lElutasítás' - chooseQuest: - name: Melyik küldetés? + search: '§e§lKeresés' + addObject: '§aAdj meg egy object-et' confirm: name: Biztos vagy benne? - 'no': '§cElutasít' - 'yes': '§aElfogad' + 'yes': '§aElfogadás' + 'no': '§cElutasítás' create: - bringBack: '§aHozz vissza tárgyakat' - bucket: '§aTölts meg vödröket' - craft: '§aKészíts tárgyakat' + stageCreate: '§aÚj szint hozzáadás' + stageRemove: '§cSzint eltávolítás' + stageUp: Előre mozgatás + stageDown: Hátra mozgatás + stageType: '§7Állomás típusa: §e{stage_type}' + cantFinish: '§7Legalább egy állomást létre kell hoznod a küldetés készítés befejezéséhez!' findNPC: '§aTaláld meg az NPC-t' + bringBack: '§aHozz tárgy(ak)at' findRegion: '§aTaláld meg a helyet' - fish: '§aFogj halakat' - interact: '§aKattints rá a blokkra' killMobs: '§aÖlj szörnyeket' - location: '§aMenj el a helyre' mineBlocks: '§aTörj blokkokat' - stageCreate: '§aÚj szint hozzáadás' - stageRemove: '§cSzint eltávolítás' + placeBlocks: '§aRakj le blokkokat' talkChat: '§aÍrj a chatbe' + interact: '§aKattints rá a blokk típusra' + interactLocation: '§aInteraktálj blokkokkal megadott helyen' + fish: '§aFogj halakat' + melt: '§6Süss sütőben' + enchant: '§dBűvölj meg tárgyakat' + craft: '§aKészíts tárgyakat' + bucket: '§aTölts meg vödröket' + location: '§aMenj el a helyre' + playTime: '§eJátssz' + breedAnimals: '§aSzaporíts állatokat' + tameAnimals: '§aSzelidíts meg állatokat' + death: '§cHalj meg' + dealDamage: '§cOkozz sebzést moboknak' + eatDrink: '§aFogyassz el ételeket vagy bájitalokat' + NPCText: '§eDialógus szerkeztése' + NPCSelect: '§eNPC kiválasztása vagy készítése' + hideClues: Részecskék és hologramok elrejtése + editMobsKill: '§eMegölendő mobok módosítása' + mobsKillFromAFar: Lövedékkel kell megölni + editBlocksMine: '$eKiszedendő blokkok módosítása' + preventBlockPlace: Saját blokkok kiszedésének megakadályozása + editBlocksPlace: '$eLerakandó blokkok módosítása' + editMessageType: '§eKiírandó szöveg módosítása' + cancelMessage: Küldés megakadályozása + ignoreCase: Kis-nagy betűk figyelmen kívűl hagyása + replacePlaceholders: '\{PLAYER} és placeholder-ek kicserélése PAPI-ból' + selectItems: '§eSzükséges tárgyak módosítása' + selectItemsMessage: '§eKérő üzenet módosítása' + selectItemsComparisons: '§eTárgy összehasonlítása beállítása (HALADÓ)' + selectRegion: '§7Régió kiválasztása' + toggleRegionExit: Kilépéskor + stageStartMsg: '§eKezdő üzened módosítása' + selectBlockLocation: '§eBlokk helyzetének kiválasztása' + selectBlockMaterial: '§eBlokk anyagának kiválasztása' + leftClick: Bal-klikk-nek kell történnie + editFishes: '§eKifogandó halak módosítása' + editItemsToMelt: '§eKiégetendő tárgyak módosítása' + editItemsToEnchant: '§eBűvölendő tárgyak módosítása' + editItem: '§eElkészítendő tárgyak módosítása' + editBucketType: '§eMegtöltendő vödör típus módosítása' + editBucketAmount: '§eVödrök számának módosítása' + editLocation: '§eLokáció módosítása' + editRadius: '§eHelytől való távolság módosítása' + currentRadius: '§eJelenlegi távolság: §6{radius}' + changeTicksRequired: '§eLejátszandó tick-ek változtatása' + changeEntityType: '§eEntitás típus változtatása' + stage: + location: + worldPattern: '§eVilág elnevezési sablon beállítása §d(HALADÓ)' + worldPatternLore: 'Ha azt szeretnéd, hogy az állomás bármely világban teljesíthető legyen, adj meg egy regex-et.' + death: + causes: '§aHalál indok megadása §d(HALADÓ)' + anyCause: Bármely halál indok + setCauses: '{causes_amount} halálozási ok' + dealDamage: + damage: '§eOkozandó sebzés' + targetMobs: '§cSebzendő mobok' + eatDrink: + items: '§eElfogyasztandó tárgyak módosítása' + stages: + name: Állomás létrehozása + nextPage: '§eKövetkező oldal' + laterPage: Előző oldal + endingItem: '§eBefejező jutalmak módosítása' + descriptionTextItem: '§eLeírás módosítása' + regularPage: '§aSima állomások' + branchesPage: '§dElágazó állomások' + previousBranch: '§eVissza az előző elágazáshoz' + newBranch: '§eÚj elágazáshoz' + validationRequirements: '§eElfogadási követelmények' + validationRequirementsLore: A játékosnak minden követelménynek meg kell felelni ahhoz, hogy befejezze az állomást. Ha nem, az állomás nem teljesíthető. details: - customMaterial: '§eTárgy id megváltoztatása' - editRequirements: '§eKövetelmények szerkesztése' + hologramLaunch: '§e"Kezdés" hologram tárgy módosítása' + hologramLaunchLore: A hologram a küldetés adó NPC fölött lesz, ha a játékos el tudja kezdeni a küldetést. + hologramLaunchNo: '§e"A kezdés nem lehetséges" tárgy módosítása' + hologramLaunchNoLore: A hologram a küldetés adó NPC fölött lesz, ha a játékos NEM tudja elkezdeni a küldetést. + customConfirmMessage: '§eKüldetés megerősítő üzenet szerkeztése' + customConfirmMessageLore: Az üzented meg fog jelenni a megerősítő panelen, amikor a játékos elkezdené a küldetést. + customDescription: '§eKüldetés leírás szerkeztése' + customDescriptionLore: A leírás a küldetés neve alatt található a GUI-ban. + name: Utolsó küldetés adatai + multipleTime: + itemName: Ismételhetőség állítása + itemLore: A küldetés elvégezhető-e többször is? + cancellable: Játékos általi megszakítás + cancellableLore: Lehetővé teszi a játékos számára a küldetés megszakítását a Küldetés Menün keresztül. + startableFromGUI: GUI-ból indítható + startableFromGUILore: Lehetővé teszi a játékos számára a küldetés elindítását a Küldetés Menün keresztül. + scoreboardItem: Scoreborad engedélyezése + scoreboardItemLore: Ha nincs engedélyezve, a scoreboard-on nem jelenik meg a küldetés. + hideNoRequirementsItem: Rejtsd el, ha nem felel meg a követelményeknek + hideNoRequirementsItemLore: Ha engedélyezve van, a küldetés nem látható a Küldetések Menüben, ha a játékos nem felel meg a követelményeknek. + bypassLimit: Ne számítson a küldetés limitbe + bypassLimitLore: Ha engedélyezve van, a küldetés az esetben is elindítható, ha a játékos elérte az elindítható küldetések limitjét. + auto: Automatikus indítás első csatlakozáskor + autoLore: Ha engedélyezve van a küldetés automatikusan elindul, amikor a játékos először csatlakozik a szerverre. + questName: '§a§lKüldetés nevének szerkeztése' + questNameLore: A név megadása kötelező a küldetés elkészítéséhez. + setItemsRewards: '§eJutalom szerkeztése' + removeItemsReward: '§eTárgyak eltávolítása az eszköztárból' + setXPRewards: '§eJutalom exp szerkeztése' + setCheckpointReward: '§eCheckpoint jutalom szerkeztése' + setRewardStopQuest: '§cKüldetés megállítása' + setRewardsWithRequirements: '§eJutalom követelményekkel' + setRewardsRandom: '§dRandom jutalmak' + setPermReward: '§eJogosultság szerkeztése' + setMoneyReward: '§ePénz jutalom szerkeztése' + setWaitReward: '§e"Várakozás" jutalom szerkeztése' + setTitleReward: '§eTitle jutalom szerkeztése' + selectStarterNPC: '§e§lKezdő NPC beállítása' + selectStarterNPCLore: A kezdő NPC-re való kattintás elindítja a küldetést. + selectStarterNPCPool: '§c⚠ Küldetés gyűjtemény kiválasztva' + createQuestName: '§lKüldetés létrehozása' + createQuestLore: Be kell állítanod a küldetés nevét + editQuestName: '§lKüldetés szerkeztése' endMessage: '§eBefejező üzenet szerkesztése' - hologramText: '§eHologram szöveg' - requirements: '{amount} követelmények' - rewards: '{amount} jutalmak' + endMessageLore: Az üzenet a küldetés végeztével el lesz küldve a játékosnak. + endSound: '§eBefejező hang módosítása' + endSoundLore: A hang, ami a küldetés végeztével lejátszásra kerül. + startMessage: '§eKezdő üzenet módosítása' + startMessageLore: Az üzenet, amelyet a játékos lát a küldetés felvételekor. startDialog: '§eKezdő üzenet szerkesztése' + startDialogLore: A dialógus, amely lejátszásra került a küldetés megkezdése előtt, ha a játékos az NPC-re kattint. + editRequirements: '§eKövetelmények szerkesztése' + editRequirementsLore: A játékosnak minden követelménynek meg kell felelnie a küldetés elkezdése előtt. startRewards: '§6Índítási jutalmak' - entityType: - name: Entitás tipus kiválasztása - itemCreator: - itemFlags: Tárgy funkciók bekapcsolása - itemType: '§bTárgy tipus' - name: Tárgy készítő - itemSelect: - name: Tárgy választás + startRewardsLore: A küldetés elkezdésekor végbemenő müveletek. + cancelRewards: '§cMegszakítási müveletek' + cancelRewardsLore: Müveletek, amik akkor mennek végbe, ha a játékos félbeszakítja a küldetést. + hologramText: '§eHologram szöveg' + hologramTextLore: A szöveg, amely az NPC feje feletti hologramon jelenik meg. + timer: '§bÚjrakezdési időzítő' + timerLore: Az idő, ami után a játékos újrakezdheti a küldetést. + requirements: '{amount} követelmény(ek)' + rewards: '{amount} jutalom' + actions: '{amount} művelet' + rewardsLore: Műveletek, amelyek akkor mennek végbe, ha a küldetést teljesítik. + customMaterial: '§eKüldetés tárgy anyagának megváltoztatása' + customMaterialLore: A tárgy, ami a küldetést jelöli a Küldetés Menüben. + failOnDeath: Kudarc halál esetén + failOnDeathLore: A küldetés megszakadjon, ha a játékos meghal? + questPool: '§eKüldetés Gyűjtemény' + questPoolLore: Küldetés hozzáadása egy küldetés gyűjteményhez + firework: '§dKüldetés végi tüzijáték' + fireworkLore: A tüzijáték, amely akkor kerül kilövésre, ha a játékos teljesíti a küldetést. + fireworkLoreDrop: Tedd az egyedi tüzijátékodat ide + visibility: '§bKüldetés láthatósága' + visibilityLore: Válaszd ki, melyik fülön legyen látható a küldetés a menün, vagy dynamic map-en belül. + keepDatas: Játékos adatok megőrzése + keepDatasLore: |- + A játékos adatok kényszerített megörzése, akkor is, ha az adott állomás módosítva lett. + §c§lVIGYÁZAT §c- az opció engedélyezése tönkre teheti a játékos adatokat. + loreReset: '§e§lMinden játékos előrehaladása törlésre kerül' + optionValue: '§8Érték: §7{value}' + defaultValue: '§8(alapértelmezett érték)' + requiredParameter: '§7Szükséges paraméter' itemsSelect: - name: Tárgyak szerkesztése - none: '§aHúzz egy tárgyat ide vagy katt az tárgy szerkszető megnyitásához.' - listAllQuests: - name: Küldetések - listPlayerQuests: - name: '{player_name} küldetései' - listQuests: - canRedo: '§3§oÚjratudod kezdeni ezt a küldetést!' - finished: Befejezett küldetések - inProgress: Folyamatban lévő küldetések - notStarted: Nem elindított küldetések - mobSelect: - boss: '§6Boss Kiválasztása' - bukkitEntityType: '§eEntitás tipus kiválasztása' - epicBoss: '§6Epic Boss kiválasztása' - mythicMob: '§6Mythic Mob kiválasztása' - name: Szörny tipus kiválasztása - mobs: - name: Szörnyek kiválasztása - none: '§aKattints a szörny hozzáadásához.' + name: Tárgyak módosítása + none: |- + §aHúzz ide egy tárgyat, vagy kattints a tárgy szerkeztő megnyitásához. + itemSelect: + name: Válassz tárgyat npcCreate: + name: NPC készítés + setName: '§eNPC nevének módosítása' + setSkin: '§eNPC kinézetének szerkeztése' + setType: '§eNPC tipusának szerkeztése' move: - itemLore: '§aNPC hely megváltoztatás.' - itemName: '§eElmozdít' + itemName: '§eMozgatás' + itemLore: '§aNPC helyének megváltoztatása.' moveItem: '§a§lHely megerősítése' - name: NPC készítés - setName: '§eNPC név szerkesztés' - setSkin: '§eNPC kinézet szerkesztés' - setType: '§eNPC tipus szerkesztés' npcSelect: - createStageNPC: '§eNPC létrehozás' - name: Kiválaszt vagy készít? - selectStageNPC: '§eVálassz ki egy meglévő NPC-t' + name: Kiválasztás vagy készítés? + selectStageNPC: '§eMeglévő NPC kiválasztása' + createStageNPC: '§eNPC létrehozása' + entityType: + name: Entitás tipus kiválasztása + chooseQuest: + name: 'Küldetés választó:' + menu: '§aKüldetés Menü' + menuLore: A Küldetés Menübe irányít. + mobs: + name: Szörnyek kiválasztása + none: '§aKattints a szörny hozzáadásához.' + editAmount: Mennyiség módosítása + editMobName: Mob nevének módosítása + setLevel: Minimum szint beállítása + mobSelect: + name: Szörny tipus kiválasztása + bukkitEntityType: '§eEntitás tipus kiválasztása' + mythicMob: '§6Mythic Mob kiválasztása' + epicBoss: '§6Epic Boss kiválasztása' + boss: '§6Boss kiválasztása' + advancedSpawners: '§6AdvancedSpawners-es mob kiválasztása' + stageEnding: + locationTeleport: '§eTeleport hely módosítása' + command: '§eParancs megváltoztatása' requirements: name: Követelmények + setReason: Egyedi indok beállítása + reason: '§8Egyedi indok: §7{reason}' rewards: - commands: 'Parancsok: {amount}' name: Jutalmak - search: '§e§lKeresés' - stageEnding: - command: '§eParancs megváltoztatása' - locationTeleport: '§eTeleportálási hely szerkesztése' - stages: - laterPage: Előző oldal - validate: '§b§lMegerősítés' + commands: 'Parancsok: {amount}' + random: + rewards: Jutalmak módosítása + minMax: Minimum és maximum módosítása + checkpointActions: + name: Checkpoint műveletek + cancelActions: + name: Megszakítási műveletek + rewardsWithRequirements: + name: Jutalmak követelménnyel + listAllQuests: + name: Küldetések + listPlayerQuests: + name: '{player_name} küldetései' + listQuests: + notStarted: Nem elindított küldetések + finished: Befejezett küldetések + inProgress: Folyamatban lévő küldetések + loreDialogsHistoryClick: '§7Dialógusok megtekintése' + loreCancelClick: '§cKüldetés megszakítása' + loreStart: '§a§oKattints a küldetés elkezdéséhez.' + loreStartUnavailable: '§c§oNem felelsz meg a megfelelő követelményeknek, a küldetés elindításához.' + timeToWaitRedo: '§7§oA küldetést {time_left} múlva újraindíthatod...' + canRedo: '§3§oÚjratudod kezdeni ezt a küldetést!' + timesFinished: '§6{times_finished}§e alkalommal teljesítve.' + format: + normal: '§6§l§o{quest_name}' + withId: '§6§l§o{quest_name}§r §e#{quest_id}' + itemCreator: + name: Tárgy készítő + itemType: '§bTárgy tipus' + itemFlags: Tárgy flag-ek váltása + itemName: '§bTárgy név' + itemLore: '§bTárgy leírása' + isQuestItem: '§bKüldetés tárgy:' + command: + name: Parancs + value: '§eParancs' + console: Konzol + parse: Placeholder-ek összehasonlítása + delay: '§bKésleltetés' + chooseAccount: + name: Milyen felhasználó? + listBook: + questName: Név + questStarter: Kezdő + questRewards: Jutalmak + questMultiple: Többször + requirements: Követelmények + questStages: Állomások + noQuests: Még nem lettek küldetések létrehozva. + commandsList: + name: Parancs lista + value: '§eParancs: {command_label}' + console: '§eKonzol: {command_console}' + block: + name: Válassz blokkot + material: '§eAnyag: {block_type}' + materialNotItemLore: 'A kiválasztott blokk nem jeleníthető meg tárgyként. Továbbra is helyesen van tárolva mint: {block_material}.' + blockName: '§bEgyedi blokk név' + blockData: '§dBlockdata (haladó)' + blockTag: '§dTag (haladó)' + blockTagLore: 'Válassz egy tag-et, amely leírja a lehetséges blokkok listáját. A tag-ek datapack segítségével személyre szabhatóak. A tag-ek listáját a Minecraft Wiki-n megtalálhatod.' + blocksList: + name: Válassz blokkokat + addBlock: '§aKattints blokk hozzáadásához.' + blockAction: + name: Válassz blokk műveletet + location: '§eVálassz egy precíz lokációt' + material: '§eVálassz blokk anyagot' + buckets: + name: Vödör típus + permission: + name: Válassz jogosultságot + perm: '§aJogosultság' + world: '§aVilág' + worldGlobal: '§b§lGlobális' + remove: Jogosultság eltávolítása + removeLore: '§7A jogosultság el lesz véve\n§7odaadás helyett.' + permissionList: + name: Jogosultság lista + removed: '§eElvéve: §6{permission_removed}' + world: '§eVilág: §6{permission_world}' + classesRequired.name: Kaszt szükséges + classesList.name: Kaszt lista + factionsRequired.name: Frakció szükséges + factionsList.name: Frakció lista + poolsManage: + name: Küldetés Gyűjtemény + itemName: '$aGyűjtemény {pool}' + poolNPC: '§8NPC: §7{pool_npc_id}' + poolMaxQuests: '§8Küldetések maximális száma: §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Indításkor adott küldetések száma: §7{pool_quests_per_launch}' + poolRedo: '§8Újrakezdhetőek-e a teljesített küldetések: §7{pool_redo}' + poolTime: '§8Küldetések közti idő: §7{pool_time}' + poolHologram: '§8Hologram szövege: §7{pool_hologram}' + poolAvoidDuplicates: '§8Küldetés duplikáció mellőzése: §7{pool_duplicates}' + poolQuestsList: '§7{pool_quests_amount} §8gyűjtemény küldetései: §7{pool_quests}' + create: '§aKüldetés gyűjtemény létrehozása' + edit: '§e> §6§oGyűjtemény szerkeztése... §e<' + choose: '§e> §6§oEzen gyűjtemény kiválasztása §e<' + poolCreation: + name: Küldetés gyűjtemény létrehozása + hologramText: '§eGyűjtemény egyedi hologramja' + maxQuests: '§aMaximum küldetés szám' + questsPerLaunch: '§aIndításkor megkezdett küldetések száma' + time: '§bKüldetések közt eltelt idő' + redoAllowed: Újraindítás engedélyezett-e + avoidDuplicates: Küldetés duplikáció mellőzése + avoidDuplicatesLore: '§8> §7Ugyanazon küldetés folyamatosan\n történő felvételének megakadályozása' + requirements: '§bKüldetés kezdéséhez szükséges követelmények' + poolsList.name: Küldetés gyűjtemények + itemComparisons: + name: Tárgy összehasonlítások + bukkit: Bukkit natív összehasonlítás + bukkitLore: "A Bukkit alapértelmezett összehasonlítási rendszere.\nÖsszehasonlítja az anyagot, tartósságot, NBT tag-eket..." + customBukkit: Bukkit natív összehasonlítás - NBT ellenőrzés nélkül + customBukkitLore: "A Bukkit alapértelmzett összehasonlítását használja, de figyelmen kívűl hagyja az NBT tag-eket.\nÖsszehasonlítja az anyagat és a tartósságot..." + material: Tárgy anyaga + materialLore: 'Összehasonlítja a tárgy anyagát (pl. kő, vas kard...)' + itemName: Tárgy neve + itemNameLore: Összehasonlítja a tárgy nevét + itemLore: Tárgy leírása + itemLoreLore: Összehasonlítja a tárgy leírását + enchants: Tárgy varázslatai + enchantsLore: Összehasonlítja a tárgyon található varázslatokat + repairCost: Javítási költség + repairCostLore: Páncélok és kardok esetében összehasonlítja a javítási költséget + itemsAdder: ItemsAdder + itemsAdderLore: Összehasonlítja az ItemsAdder ID-ket + mmoItems: MMOItems tárgy + mmoItemsLore: Összehasonlítja az MMOItems típusokat és ID-ket + editTitle: + name: Title szerkeztése + title: '§6Title' + subtitle: '§eSubtitle' + fadeIn: '§aFade-in időtartama' + stay: '§bStay időtartama' + fadeOut: '§bFade-out időtartama' + particleEffect: + name: Particle effekt létrehozása + shape: Particle formája + type: '§eParticle típusa' + color: '§bParticle színe' + particleList: + name: Particle lista + colored: Színezett particle + damageCause: + name: Sebzés fajtája + damageCausesList: + name: Sebzés típusok listája + visibility: + name: Küldetés láthatósága + notStarted: '"Nem elkezdett" menü fül' + inProgress: '"Folyamatban" menü fül' + finished: '"Befejezett" menü fül' + maps: 'Térképek (pl. dynmap vagy BlueMap)' + equipmentSlots: + name: Felszerelés helyek + questObjects: + setCustomDescription: 'Egyedi leírás megadása' + description: '§8Leírás: §7{description}' +scoreboard: + name: '§6§lKüldetések' + noLaunched: '§cNincsen folyamatban lévő küldetésed.' + noLaunchedName: '§c§lBetöltés' + noLaunchedDescription: '§c§oBetöltés' + textBetwteenBranch: '§e vagy' + asyncEnd: '§ex' + stage: + region: '§eTaláld meg a(z) §6{region_id} területet' + npc: Beszélj az {dialog_npc_name} NPC-vel + items: '§eHozz {items} tárgyakat §6{dialog_npc_name}§e NPC-nek!' + mobs: '§eÖlj §6{mobs}-t' + mine: '§eTörj {blocks}-t' + placeBlocks: '§eRakj le {blocks}-t' + chat: '§eÍrd ki a következőt: §6{text}' + interact: '§eKattints a(z) §6{x} {y} {z}§e koordinátán található blokkra' + interactMaterial: '§eKattints egy §6{block}§e blokkra' + fish: '§eFogj ki §6{items}-t' + melt: '§eÉgess §6{items}-t' + enchant: '§eBűvölj meg §6{items}-t' + craft: '§eKészíts §6{items}-t' + bucket: '§eTölts meg §6{buckets}-t' + location: '§eMenj §6{target_x}§e, §6{target_y}§e, §6{target_z}§e koordinátára a(z) §6{target_world}§e világban' + playTimeFormatted: '§eJátsz §6{time_remaining_human}§e időt a szerveren' + breed: '§eSzaporíts §6{mobs}-t' + tame: '§eSzelidíts meg §6{mobs}-t' + die: '§cHalj meg' + dealDamage: + any: '§cOkozz {damage_remaining} sebzést' + mobs: '§cOkozz {damage_remaining} sebzést {target_mobs} mobnak' + eatDrink: '§eFogyassz el §6{items}-t' +indication: + startQuest: '§7El akarod kezdeni a(z) {quest_name} küldetést?' + closeInventory: '§7Biztosan be akarod zárni a GUI-t?' + cancelQuest: '§7Biztos vagy benne, hogy meg akarod szakítani a(z) {quest_name} küldetést?' + removeQuest: '§7Biztos vagy benne, hogy törölni szeretnéd a(z) {quest} küldetést?' + removePool: '§7Biztosan ki akarod törölni a(z) {pool} gyűjteményt?' +description: + requirement: + title: '§8§lKövetelmények:' + level: '{short_level}. szint' + jobLevel: '{short_level} szint a {job_name} szakmában' + combatLevel: '{short_level} harc szint' + skillLevel: '{short_level} szint a {skill_name} képességben' + class: '{class_name} kaszt' + faction: '{faction_name} frakció' + quest: '§e{quest_name}§r küldetés befejezése' + reward: + title: '§8§lJutalmak:' misc: - amount: '§eMennyiség: {amount}' - and: és + format: + prefix: '§6<§e§lKüldetések§r§6> §r' + npcText: '§6[{message_id}/{message_count}] §e§l{npc_name_message}: §r§e {text}' + selfText: essage_id}/{message_count}] §e§l{player_name}:§r§e {text} + time: + weeks: '{weeks_amount} hét' + days: '{days_amount} nap' + hours: '{hours_amount} óra' + minutes: '{minutes_amount} perc' + lessThanAMinute: 'néhány másodperc' + stageType: + region: Találd meg a helyet + npc: Találd meg az NPC-t + items: Hozz vissza tárgyakat + mobs: Ölj meg szörnyeket + mine: Törj blokkokat + placeBlocks: Tegyél le blokkokat + chat: Írj a chat-re + interact: Lépj interakcióba blokkokal + interactLocation: Interaktálj blokkokkal a lokáción + Fish: Fogj halakat + Melt: Égess ki tárgyakat + Enchant: Bűvölj meg tárgyakat + Craft: Készíts tárgyakat + Bucket: Tölts meg vödröket + location: Találd meg a helyet + playTime: Játssz + breedAnimals: Szaporíts állatokat + tameAnimals: Szelidíts meg állatokat + die: Halj meg + dealDamage: Okozz sebzést + eatDrink: Fogyassz el + comparison: + equals: egyenlő legyen {number}-val/vel + different: ne legyen egyenlő {number}-val/vel + less: kicsivel kevesebb mint {number} + lessOrEquals: kevesebb mint {number} + greater: kicsivel több mint {number} + greaterOrEquals: több mint {number} + requirement: + logicalOr: '§dLogikai VAGY (követelmények)' + skillAPILevel: '§bSkillAPI szint szükséges' + class: '§bKaszt(ok) szükséges(ek)' + faction: '§bFrakció(k) szükséges(ek)' + jobLevel: '§bMunka szint szükséges' + combatLevel: '§bHarc szint szükséges' + experienceLevel: '§bExp szint szükséges' + permissions: '§3Jogosultság szükséges' + scoreboard: '§dPont szükséges' + region: '§dRégió szükséges' + placeholder: '§bPlaceholder érték szükséges' + quest: '§aKüldetés szükséges' + mcMMOSkillLevel: '§dKépesség szint szükséges' + money: '§dPénz összes szükséges' + equipment: '§eFelszerelés szükséges' + reward: + skillApiXp: SkillAPI XP jutalom bucket: + water: Vizes vödör lava: Lávás vödör milk: Tejes vödör - water: Vizes vödör + snow: Havas vödör click: - left: Bal klikk right: Jobb klikk - shift-left: Shift+Bal klikk - shift-right: Shift+Jobb klikk - disabled: Kikapcsolva - enabled: Engedélyezve - entityType: '§eEntitás tipus: {entity_type}' - format: - npcText: '§6[{message_id}/{message_count}] §e§l{npc_name_message}: §r§e {text}' - prefix: '§6<§e§lKüldetések§r§6> §r' + left: Bal klikk + shift-right: Shift + Jobb klikk + shift-left: Shift + Bal klikk + middle: Középső kattintás + amounts: + items: '{items_amount} db tárgy' + comparisons: '{comparisons_amount} összehasonlítása' + dialogLines: '{lines_amount} sor' + permissions: '{permissions_amount} jogosultság' + mobs: '{mobs_amount} mob' + xp: '{xp_amount} tapasztalati pont' + ticks: '{ticks} tick' + location: |- + Koordináta: {x} {y} {z} + Világ: {world} + questItemLore: '§e§oKüldetés tárgy' hologramText: '§7§lKüldetés NPC' - 'no': 'Nem' + poolHologramText: '§eÚj küldetés elérhető!' + entityType: '§eEntitás tipus: {entity_type}' + entityTypeAny: '§eBármilyen entitás' + enabled: Engedélyezve + disabled: Kikapcsolva + unknown: ismeretlen notSet: '§cnincs beállítva' + removeRaw: Eltávolítás + reset: Visszaállítás or: vagy - questItemLore: '§e§o Küldetés Tárgy' - requirement: - class: '§bKaszt szükséges' - combatLevel: '§bHarc szint szükséges' - experienceLevel: '§bXp szint szükséges' - faction: '§bFrakció szükséges' - jobLevel: '§bMunka szint szükséges' - mcMMOSkillLevel: '§dSkill szint szükséges' - money: '§dArany szükséges' - permissions: '§3Jog szükséges' - placeholder: '§bPlaceholder szám szükséges' - quest: '§aKüldetés szükséges' - scoreboard: '§dPont szükséges' - stageType: - Bucket: Tölts meg vödröket - Craft: Készíts tárgyakat - Fish: Fogj halakat - chat: Írj chatbe - interact: Lépj interakcióba blokkokal - items: Hozz vissza tárgyakat - location: Találd meg a helyet - mine: Törj blokkokat - mobs: Ölj meg szörnyeket - npc: Találd meg őt - placeBlocks: Tegyél le egy blokkot - region: Találd meg a helyet - time: - days: '{days_amount} nap' - hours: '{hours_amount} óra' - lessThanAMinute: kisebb mint egy perc - minutes: '{minutes_amount} perc' - weeks: '{weeks_amount} hét' - unknown: ismeretlen + amount: '§eMennyiség: {amount}' 'yes': 'Igen' -msg: - bringBackObjects: Hozz nekem {items}. - command: - adminModeEntered: '§aBeléptél az Admin Módba.' - adminModeLeft: '§aKiléptél az Admin Módból.' - backupCreated: '§6Sikeresen csináltál mentést.' - backupPlayersFailed: '§cA mentés sikertelen.' - backupQuestsFailed: '§cA mentés sikertelen.' - cancelQuest: '§6Elutasítottad a következő küldetést {quest}.' - cancelQuestUnavailable: '§cA küldetés nem elutasítható {quest}.' - checkpoint: - noCheckpoint: '§cNem találtunk ellenörző pontot a küldetéshez {quest}' - questNotStarted: '§cNem ezt a küldetést csinálod.' - help: - create: '§6/{label} létrehoz: §eLétrehoz egy küldetést.' - edit: '§6/{label} szerkesztés: §eSzerkesz egy küldetést.' - finishAll: '§6/{label} befejezmindent <player>: §eBefejezi az összes küldetést.' - header: '§6§lBeautyQuests - Segítség' - reload: '§6/{label} reload: §eSave, majd újra konfigurációk, valamint a fájlok. (§cdeprecated§e)' - remove: '§6/{label} eltávolít <id>:§EKitöröl egy küldetést a meghatározott id-vel vagy kattints az NPC-re.' - resetPlayer: '§6/{label} resetPlayer <player>: §eTöröl minden információt.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eDelete információk egy küldetést, hogy egy játékos.' - seePlayer: '§6/{label} seePlayer <player>: §eView információt a játékos.' - setStage: '§6/{label} setStage <player> <id> új ág új szint: §eTovábblépi a jelenlegi szintet.' - start: '§6/{label} start <player> [id]: §eForce a kezdő a küldetést.' - invalidCommand: - simple: '§cEz a parancs nem létezik, használd §ehelp§c.' - itemChanged: '§aA tárgy szerkesztve. A változtatások az újraindítás után fognak működni.' - itemRemoved: '§aA tárgy hologram eltávolítva.' - leaveAll: '§aKényszerítve lettél, hogy befejezd a következő küldetést {success}. Hibák:{errors}' - removed: '§aA következő küldetés sikeresen eltávolítva {quest_name}.' - resetPlayer: - player: '§6Az összes információ a következő küldetésedből {quest_amount} törölve lett általa {deleter_name}.' - resetPlayerQuest: - player: '§6Az összes infó a küldetésről {quest} törölve lett általa {deleter_name}.' - remover: '§6Küldetés infó törölve {player} ennyiből {quest}.' - resetQuest: '§6Küldetés adat törölve neki {player_amount}.' - scoreboard: - hidden: '§6A lista a következő játékosnak {player_name} láthatatlan.' - lineInexistant: '§cA sor {line_id} nem létezik.' - lineRemoved: '§6Sikeresen eltávolítottad a sort {line_id}.' - lineReset: '§6Sikeresen újraraktad a sort {line_id}.' - lineSet: '§6Sikeresen átírtad a sort {line_id}.' - own: - hidden: '§6A scoreboard mostantól elvan rejtve.' - shown: '§6A scoreboard mostantól látható.' - resetAll: '§6Sikeres újrarakás a következő játékosnak {player_name}.' - shown: '§6A lista következő játékosnak látható {player_name}.' - setStage: - branchDoesntExist: '§cA következő ág nem létezik {branch_id}.' - doesntExist: '§cA következő szint {stage_id} nem létezik.' - next: '§aA szint kihagyva.' - nextUnavailable: '§c A "kihagyás" opció nem elérhető mikor a játékos az ág végén van.' - set: '§aSzint {stage_id} elindítva.' - startDialog: - alreadyIn: '§cA játékos már párbeszédben van.' - noDialog: '§cA megadott játékosnak nincsen folyamatban lévő párbeszéde.' - startQuest: '§6Kényszerítve lettél, hogy elkezd a következő küldetést {quest} (Játékos UUID: {player}).' - startQuestNoRequirements: '§cA megadott játékosnak nincsen meg a szükséges követelményei a(z) {quest} küldetéshez... Mellékeld a a "-overrideRequirements" szót a parancsod végére, hogy átugord a követelményeket.' - dialogs: - skipped: '§8§oPárbeszéd átugorva.' - tooFar: '§7§oTúl messze vagy ettől: {npc_name}...' - editor: - dialog: - help: - addSound: '§6addSound <id> <sound>: §eHangot ad hozzá az üzenethez.' - clear: '§6clear: §eKitörli az összes üzenetet.' - close: '§6close: §eMinden üzenetet ment és kilép.' - list: '§6list: §eÖsszes szöveg megnézése.' - nothing: '§6noSender <message>: §eHozzáad egy szöveget küldő nélkül.' - nothingInsert: '§6nothingInsert <id> <message>: §eHozzáad egy üzenetet prefix nélkül.' - npcInsert: '§6npcInsert <id> <message>: §eHozzáadja az összes üzenetet amit az NPC mond.' - player: '§6játékos <message>: §eHozzáad egy szöveget amit a játékos ír.' - playerInsert: '§6playerinsert <id> <message>: §eHozzáad minden üzenetet amit a játékos mond.' - remove: '§6remove <id>: §eEltávolít egy szöveget.' - setTime: '§6setTime <id> <time>: §eIdőt ad hozzá a szövegek közt.' - timeRemoved: '§aIdő eltávolítva ennek az üzenetnek {msg}.' - timeSet: '§aAz idő szerkesztve az üzenetnek {msg}: mostmár {time} tick.' - itemCreator: - itemName: '§aÍrd le az item nevét:' - unknownItemType: '§cIsmeretlen item típus.' - mythicmobs: - disabled: '§cMythicMob kikapcsolva.' - isntMythicMob: '§cEz a Mythic Mob nem létezik.' - list: '§aAz összes Mythic Mob lista:' - noSuchElement: '§cNincs ilyen elem. Engedélyezett elemek: §e{available_elements}' - scoreboardObjectiveNotFound: '§cIsmeretlen lista objektum.' - textList: - help: - add: '§6add <message>: §eHozzáad egy szöveget.' - close: '§6close: §eHozzáadott szöveg megerősítése.' - header: '§6§lBeautyQuests - Lista szerkesztő segítség' - list: '§6list: §eÖsszes szöveg megnézése.' - remove: '§6remove <id>: §eEltávolít egy szöveget.' - syntax: '§cHelyes szintax: ' - errorOccurred: '§cHiba történt, lépj kapcsolatba egy adminisztrátorral! §4§lHiba kód: {error}' - experience: - edited: '§aMegkell változtatnod az xp-t {old_xp_amount} ről ennyire {xp_amount}.' - indexOutOfBounds: '§cA szám {index} nem jó! Muszály {min} és {max} között lennie.' - inventoryFull: '§cTele van a táskád, a tárgy el lett dobva a földre.' - moveToTeleportPoint: '§aMenj a kért teleportálás helyszínére.' - npcDoesntExist: '§cEz az NPC nem létezik {npc_id}.' - number: - invalid: '§c{input} nem érvényes szám.' - negative: '§cMuszály pozitív számot írnod!' - zero: '§cNagyobb számot kell írnod 0-nál!' - pools: - allCompleted: '§7Az összes küldetést teljesítetted!' - maxQuests: '§cNem lehet több mint {pool_max_quests} küldetésed egy időben!' - noAvailable: '§7Nincsen elérhető küldetések.' - noTime: '§cVárnod kell még {time_left} mielőtt elkezdenél egy újabb küldetést.' - quest: - alreadyStarted: '§cMár elkezdted ezt a küldetést!' - cancelling: '§cA küldetés elkészítése közben hiba történt.' - createCancelled: '§cA szerkesztés vagy az elkészítés megszakítva egy másik plugin miatt!' - created: '&aSiker! Létrehoztad a következő küldetést §e{quest}§a ami tartalmaz {quest_branches} ágat!' - editCancelling: '§cA küldetés szerkesztése megszakítva.' - edited: '§aSiker! Szerkeszetted a következő küldetést §e{quest}§a ami tartalmaz {quest_branches} ágat!' - finished: - base: '&aSikeresen teljesítetted a következő küldetést §e{quest_name}§a!' - obtain: '§aEzt kaptad: {rewards}!' - invalidID: '§cA következő küldetés {quest_id} nem létezik.' - invalidPoolID: A(z) {pool_id} nem létezik. - notStarted: '§cJelenleg nem csinálod ezt a küldetést.' - started: '&aElkezdted a következő küldetést §r§e{quest_name}§o§6!' - questItem: - craft: '§cNem barkácsolhatsz küldetés itemmel!' - drop: '§cKüldetés itemet nem dobhatsz el!' - eat: '§cNem ehetsz meg egy Küldetés tárgyat!' - quests: - checkpoint: '§7Küldetés ellenőrző pont elérve!' - failed: '§cNem sikerült a küldetés{quest_name}' - maxLaunched: '§cNem lehet több mint {quests_max_amount} küldetésed egy időben!' - updated: '§7A következő küldetés §e{quest_name}§7 frissítve.' - regionDoesntExists: '§cNem létezik ilyen hely. (Ugyanabban a világban kell lenned.)' - requirements: - combatLevel: '§aA harc szinted a következőnek kell lennie{long_level}!' - level: '§cA szintednek a következőnek kell lennie{long_level}!' - money: '§cEnnyi kell lennied nállad {money}!' - quest: '§cBekell fejezned a következő küldetést §e{quest_name}§c!' - restartServer: '§7Indítsd újra a szervert, hogy lásd a módosításokat.' - selectNPCToKill: '§aVálazd ki az NPC akit megkell ölni.' - stageMobs: - listMobs: '§aEnnyit megkell ölnöd {mobs}.' - versionRequired: 'Szükséges verzió: §l{version}' - writeChatMessage: '§aÍrd a következő üzenetet: (Add {SLASH}" az elkezdéshez.)' - writeCommand: '§aÍrd ide a parancsot: (A parancs "/" nélkül és a szó "{PLAYER}" engedélyezett. Átlesz helyezve.)' - writeCommandDelay: '§aÍrd a kívánt parancs késleltetést, tickben.' - writeConfirmMessage: '§aÍrd a megerősítő üzenetet ide:(Írd "null" az alap szöveghez.)' - writeDescriptionText: '§aÍrd ide a szöveget ami leírja a lépéseket:' - writeHologramText: '§aÍrd a hologram nevét ide: (Írd "none ha nem akarsz semmit és "null" ha az alap szöveget akarod.)' - writeMobAmount: '§aÍrd ide a mennyiséget,hogy mennyi szörnyet kell megölni:' - writeNPCText: '§aÍrd le a párbeszédet amelyet a játékos fog folytatni az NPC vel: (Használd a "help" a segítségért)' - writeNpcName: '§aÍrd ide az NPC nevét:' - writeNpcSkinName: '§aÍrd ide az NPC skin nevét:' - writeQuestDescription: '§aÍrd ide a leírást amit a játékos látni fog.' - writeQuestMaterial: '§aÍrd ide,hogy milyen tárgy legyen a küldetés.' - writeQuestName: '§aÍrd ide a küldetést nevét:' - writeQuestTimer: '§aÍrd a szükséges időt (percben) amielött újratudod indítani a küldetést: (Írd "null" ha az alapot akarod.)' - writeRegionName: '§aÍrd a helyet amit kér a küldetés:' - writeStageText: '§aÍrd ide a szöveget amit a játékos fog kapni mikor elkezdi a lépést:' - writeXPGain: '§Írd ide az xp mennyiséget amit a játékos kapni fog:(Utolsó érték:{xp_amount})' -scoreboard: - stage: - npc: Beszélj az {dialog_npc_name} npc-vel + 'no': 'Nem' + and: és + \ No newline at end of file diff --git a/core/src/main/resources/locales/ko_KR.yml b/core/src/main/resources/locales/ko_KR.yml index 67a723b7..75934606 100755 --- a/core/src/main/resources/locales/ko_KR.yml +++ b/core/src/main/resources/locales/ko_KR.yml @@ -1,222 +1,500 @@ --- +msg: + quest: + finished: + base: '§a축하합니다! §e{quest_name}§a 퀘스트를 완료하셨습니다.' + obtain: '§a{rewards}를 얻었습니다!' + started: '§r§e{quest_name}§o§6 §a퀘스트를 시작하셨습니다.' + created: '§a축하합니다! {quest_branches} 를(을) 포함하는 퀘스트 §e{quest}§a를(을) 제작했습니다!' + edited: '§a축하합니다! §e{quest}§a 를(을) 포함한 퀘스트를 수정했습니다.' + createCancelled: '§c다른 플러그인으로 인해 생성 또는 수정이 취소되었습니다.' + cancelling: '§c퀘스트 생성 프로세스가 취소되었습니다.' + editCancelling: '§c퀘스트 에디션의 프로세스가 취소되었습니다.' + invalidID: '§cID가 {quest_id} 인 퀘스트가 존재하지 않습니다.' + invalidPoolID: '§c{pool_id}이(가) 존재하지 않습니다.' + alreadyStarted: '§c퀘스트를 이미 시작하셨습니다!' + notStarted: '§8§l[퀘스트 시스템] §c현재 해당 퀘스트를 할 수 없습니다' + quests: + maxLaunched: '§c당신은 {quests_max_amount}개 이상의 퀘스트를 동시에 가질 수 없습니다...' + updated: '§7퀘스트 §e{quest_name}§7가 업데이트 되었습니다.' + checkpoint: '§7퀘스트 체크포인트에 도달 하였습니다!' + failed: '§c당신은 {quest_name} 퀘스트를 실패했습니다...' + pools: + noTime: '§c다른 퀘스트를 하기위해 {time_left}만큼 기다려야 합니다.' + allCompleted: '§7모든 퀘스트를 완료했습니다!' + noAvailable: '§7완료 가능한 퀘스트가 존재하지 않습니다.' + maxQuests: '§c당신은 {pool_max_quests}개 이상의 퀘스트를 동시에 가질 수 없습니다...' + questItem: + drop: '§c퀘스트 아이템은 버릴 수 없습니다!' + craft: '§c퀘스트용 아이템을 조합에 사용할 수 없습니다!' + eat: 퀘스트 아이템은 팔 수 없습니다. + stageMobs: + listMobs: '§a당신은 {mobs}를 죽여야만 합니다.' + writeNPCText: '§aNPC가 플레이어에게 말할 대사를 작성해주세요: (도움말을 보려면 "help"를 입력하세요.)' + writeRegionName: '§a해당 단계에 필요한 지역의 이름을 입력하세요:' + writeXPGain: '§a플레이어가 획득할 경험치량을 입력하세요: (최근 값: {xp_amount})' + writeMobAmount: '§a죽일 몹의 수를 적어 주세요:' + writeMobName: '§8§l[퀘스트 시스템] §a해당 퀘스트에 죽일 몹의 대상을 작성하세요!' + writeChatMessage: '§8§l[퀘스트 시스템] §a해당 퀘스트의 작성시킬 메시지를 작성하세요! : (커맨드는 "\{SLASH}" 를 원하시는 명령어 앞에 추가하여 주십시오 )' + writeMessage: '§8§l[퀘스트 시스템] §a플레이어에게 보여질 메시지를 작성하세요' + writeStartMessage: '§8§l[퀘스트 시스템] §a퀘스트가 시작될때 보낼 메시지를 작성해주세요! §e 기본값 : null / 없음 : none' + writeEndMsg: '§8§l[퀘스트 시스템] §a퀘스트가 끝날때 보낼 메시지를 작성해주세요! §e 기본값 : null / 없음 : none' + writeEndSound: '§8§l[퀘스트 시스템] §a퀘스트가 끝날때 재생될 소리를 작성해주세요! §e 기본값 : null / 없음 : none' + writeDescriptionText: '§8§l[퀘스트 시스템] §a퀘스트의 내용 묘사에 쓰일 문장을 작성해주세요' + writeStageText: '§8§l[퀘스트 시스템] §a퀘스트의 첫번째 단계에 보여줄 메시지를 작성해주세요!' + moveToTeleportPoint: '§8§l[퀘스트 시스템] §a지정된 순간이동 지점에 이동합니다' + writeNpcName: '§aNPC의 이름을 적어주세요:' + writeNpcSkinName: '§aNPC 스킨의 이름을 입력하세요:' + writeQuestName: '§a퀘스트의 이름을 입력하세요:' + writeCommand: '§8§l[퀘스트 시스템] §a원하는 커맨드를 입력하세요: (커맨드는 "/"와 "{player}" 를 제외하고 써도 좋습니다. 자동으로 실행하는 사람을 대상으로 설정할 것입니다.)' + writeHologramText: '§8§l[퀘스트 시스템] §a홀로그램의 내용을 작성해 주십시오! §e "기본값" : null / "없음" : none' + writeQuestTimer: '§8§l[퀘스트 시스템] §a퀘스트 진행에 필요한 쿨타임을 작성해주세요 §e "기본값" : null / "없음" : none )' + writeConfirmMessage: '§8§l[퀘스트 시스템] §a퀘스트 시작에 보여질 확인 메시지를 작성해 주세요! §e "기본값" : null / "없음" : none )' + writeQuestDescription: '§8§l[퀘스트 시스템] §a플레이어의 퀘스트 창에 보여질 퀘스트의 설명을 작성해주세요!' + writeQuestMaterial: '§8§l[퀘스트 시스템] §a퀘스트 아이템의 타입을 작성해주세요' + requirements: + quest: '§c먼저 §e{quest_name}§c 퀘스트를 완료 해야합니다.' + level: '§c퀘스트를 받기 위한 레벨이 부족합니다! {long_level}!' + job: '§8§l[퀘스트 시스템] §c{job_name}의 레벨이 {long_level} 이 되어야 합니다!' + skill: '§8§l[퀘스트 시스템] §c{skill_name}의 레벨이 {long_level} 이 되어야 합니다!' + combatLevel: '§8§l[퀘스트 시스템] §a §c퀘스트를 받기 위한 레벨이 부족합니다! {long_level}!' + money: '§c{money}를 가져야합니다!' + waitTime: '§8§l[퀘스트 시스템]§c이 퀘스트를 다시 하기 위해 당신은 총 {time_left} 분(초)를 기다려야 합니다.' + experience: + edited: '§8§l[퀘스트 시스템] §a퀘스트 수락 조건을 경험치 필요량 {old_xp_amount}에서 {xp_amount} 으로 수정하였습니다' + selectNPCToKill: '§8§l[퀘스트 시스템] §a죽일 NPC를 선택하세요!' + regionDoesntExists: '§8§l[퀘스트 시스템] §a해당 지역은 존재하지 않습니다. (같은 월드에 있어야 합니다)' + npcDoesntExist: '§8§l[퀘스트 시스템] §aID가 {npc_id} 인 퀘스트가 존재하지 않습니다.' + number: + negative: '§8§l[퀘스트 시스템] §a양수를 입력해야합니다!' + zero: '§8§l[퀘스트 시스템] §a0보다 큰 수를 입력해야 합니다!' + invalid: '§c{input}는 유효한 숫자가 아닙니다.' + notInBounds: '§8§l[퀘스트 시스템] §a{min}부터 {max}까지의 수를 입력해야 합니다!' + errorOccurred: '§c에러가 발생했습니다. 관리자에게 문의하세요! §4§lError code: {error}' + indexOutOfBounds: '§c {index}는 범위를 벗어난 값입니다! {min} 과 {max} 사이여야 합니다.' + invalidBlockData: '§8§l[퀘스트 시스템] §a해당 블럭 데이터 {block_data}는 유효하지 않거나 {block_material}과 맞지 않습니다!' + invalidBlockTag: '§8§l[퀘스트 시스템] §a{block_tag}는 이용할 수 없는 블럭입니다!' + bringBackObjects: '§8§l[퀘스트 시스템] §a{items}를 들고 다시 오세요!' + inventoryFull: '§8§l[퀘스트 시스템] §a당신의 인벤토리에 공간이 없습니다! 지급된 아이템에 땅에 떨어졌으니 찾아보세요!' + versionRequired: '버전 요구 사항: §l{version}' + restartServer: '§8§l[퀘스트 시스템] §a수정된 데이터를 보기 위해 서버를 재시작 합니다.' + dialogs: + skipped: '§8§l[퀘스트 시스템] §a대화가 스킵되었습니다.' + tooFar: '§8§l[퀘스트 시스템] §a{npc_name}에게서 떨어져서 퀘스트를 받지 못하였습니다..' + command: + downloadTranslations: + syntax: '§8§l[퀘스트 시스템] §a언어를 다운로드하여 적용하세요! 예시: "/quests downloadTranslations en_US".' + notFound: '§8§l[퀘스트 시스템] §a{version}에서 {lang}를 찾지 못하였습니다.' + exists: '§8§l[퀘스트 시스템] §a파일 {file_name}은 이미 존재합니다. "-overwrite"를 추가하여 그것을 덮어씌울 수 있습니다! §e(/quests downloadTranslations <lang> -overwrite)' + downloaded: '§8§l[퀘스트 시스템] §a{lang}언어를 다운로드 하였습니다!' + checkpoint: + noCheckpoint: '§8§l[퀘스트 시스템] §a퀘스트 {quest}에서 체크포인트를 찾지 못하였습니다.' + questNotStarted: '§8§l[퀘스트 시스템] §c현재 해당 퀘스트를 할 수 없습니다' + setStage: + branchDoesntExist: '§8§l[퀘스트 시스템] §aID가 {branch_id} 인 분기점이 존재하지 않습니다.' + doesntExist: '§8§l[퀘스트 시스템] §aID가 {stage_id} 인 퀘스트 스테이지가 존재하지 않습니다.' + next: '§a단계를 건너뛰었습니다.' + nextUnavailable: '§8§l[퀘스트 시스템] §a"스킵" 선택지는 퀘스트의 마지막 단계에 있을때 사용할 수 없습니다!' + set: '§a스테이지 {stage_id} 이 시작되었습니다.' + startDialog: + impossible: '§8§l[퀘스트 시스템] §a현재 대화를 시작할 수 없습니다.' + noDialog: '§8§l[퀘스트 시스템] §a해당 플레이어는 보류중인 대화가 없습니다.' + alreadyIn: '§8§l[퀘스트 시스템] §a해당 플레이어는 이미 해당 대화를 진행중 입니다!' + success: '§8§l[퀘스트 시스템] §a플레이어 {player}가 퀘스트 {quest}를 진행하였습니다!' + invalidCommand: + simple: '§c알수없는 커맨드입니다. §ehelp §c를 입력해주세요.' + itemChanged: '§a항목이 재편집 되었습니다. 변경사항은 재시작 후 적용될것입니다.' + itemRemoved: '§a홀로그램 항목이 제거 되었습니다.' + removed: '§a{quest_name} 퀘스트가 성공적으로 제거되었습니다.' + leaveAll: '§a{success}퀘스트를 건너뛰었습니다. §c에러 : {errors}' + resetPlayer: + player: '§6당신의 {quest_amount} 퀘스트(들)에 대한 모든 설명이 {deleter_name}에 의해 삭제되었습니다.' + remover: '§8§l[퀘스트 시스템] §a플레이어 {player}의 {quest_amount}개의 퀘스트 정보, {quest_pool}풀이 삭제되었습니다.' + resetPlayerQuest: + player: '§8§l[퀘스트 시스템] §a당신의 {quest} 퀘스트(들)에 대한 모든 설명이 {deleter_name}에 의해 삭제되었습니다.' + remover: '§8§l[퀘스트 시스템] §a퀘스트 {quest}의 플레이어 {player} 정보가 삭제되었습니다!' + resetQuest: '§8§l[퀘스트 시스템]§e {player_amount}명의 플레이어의 퀘스트 데이터를 삭제하였습니다.' + startQuest: '§8§l[퀘스트 시스템]§e 플레이어 {player}에게 퀘스트 {quest}를 강제로 시작하게 하였습니다!' + startQuestNoRequirements: '§8§l[퀘스트 시스템]§e 플레이어가 퀘스트 {quest}의 요구 사항을 충족하지 않습니다... 요구 사항 확인을 우회하려면 명령 끝에 "-overrideRequirements"를 추가하세요.' + cancelQuest: '§8§l[퀘스트 시스템]§e 당신은 {quest} 퀘스트를 취소하였습니다.' + cancelQuestUnavailable: '§8§l[퀘스트 시스템]§e {quest} 퀘스트는 취소 할 수 없습니다.' + backupCreated: '§8§l[퀘스트 시스템]§e 성공적으로 모든 플레이어의 퀘스트 데이터를 백업하였습니다!' + backupPlayersFailed: '§8§l[퀘스트 시스템]§e 모든 플레이어의 백업을 생성하는데 실패하였습니다.' + backupQuestsFailed: '§8§l[퀘스트 시스템]§e 백업을 생성하는데 실패하였습니다.' + adminModeEntered: '§8§l[퀘스트 시스템]§e Admin 모드에 진입하였습니다.' + adminModeLeft: '§8§l[퀘스트 시스템]§e Admin 모드가 종료되었습니다.' + resetPlayerPool: + timer: '§8§l[퀘스트 시스템]§e 플레이어 {player}의 반복 타이머 {pool}을 초기화하였습니다.' + full: '§8§l[퀘스트 시스템]§e 플레이어 {player}의 반복 데이터 {pool}을 초기화하였습니다.' + startPlayerPool: + error: '§8§l[퀘스트 시스템]§e 플레이어 {player} 에게서 풀 {pool}을 시작하는데 실패하였습니다.' + success: '§8§l[퀘스트 시스템]§e 플레이어 {player}에게 풀 {pool}을 시작시켰습니다. 결과 : {result}' + scoreboard: + lineSet: '§8§l[퀘스트 시스템]§e 성공적으로 {line_id} 를 수정하였습니다.' + lineReset: '§8§l[퀘스트 시스템]§e 성공적으로 {line_id} 를 리셋하였습니다.' + lineRemoved: '§8§l[퀘스트 시스템]§e 성공적으로 {line_id} 를 제거하였습니다.' + lineInexistant: '§8§l[퀘스트 시스템]§e {line_id}이(가) 존재하지 않습니다.' + resetAll: '§8§l[퀘스트 시스템]§e 성공적으로 플레이어 {player}의 스코어보드를 초기화하였습니다.' + hidden: '§8§l[퀘스트 시스템]§e 플레이어 {player}의 스코어보드가 사라졌습니다.' + shown: '§8§l[퀘스트 시스템]§e 플레이어 {player}의 스코어보드가 나타났습니다.' + own: + hidden: '§8§l[퀘스트 시스템]§e 스코어보드가 사라졌습니다.' + shown: '§8§l[퀘스트 시스템]§e 스코어보드가 나타났습니다.' + help: + header: '§8§l[퀘스트 시스템]§e 도움말' + create: '§8§l[퀘스트 시스템]§e /{label} create: 퀘스트를 생성합니다.' + edit: '§8§l[퀘스트 시스템]§e /{label} eidt: 퀘스트를 수정합니다.' + remove: '§8§l[퀘스트 시스템]§e /{label} remove <id>: 특정 아이디 또는 NPC를 클릭하여 퀘스트를 삭제합니다.' + finishAll: '§8§l[퀘스트 시스템]§e /{label} finishAll <player>: 플레이어의 모든 퀘스트를 완료시킵니다.' + setStage: '§8§l[퀘스트 시스템]§e /{label} setStage <player> <id> [새로운 분기점] [새로운 스테이지]: 현재 스테이지를 스킵하거나, branch를 시작, 분기점의 스테이지로 설정합니다.' + startDialog: '§8§l[퀘스트 시스템]§e /{label} startDialog <player> <quest id>: NPC와의 대화를 시작시킵니다.' + resetPlayer: '§8§l[퀘스트 시스템]§e /{label} resetPlayer <player>: 플레이어에 대한 모든 정보를 삭제합니다.' + resetPlayerQuest: '§8§l[퀘스트 시스템]§e /{label} resetPlayerQuest <player> [id]: 플레이어의 퀘스트 정보를 삭제합니다.' + seePlayer: '§8§l[퀘스트 시스템]§e /{label} seePlayer <player>: 플레이어에 대한 모든 정보를 열람합니다.' + reload: '§8§l[퀘스트 시스템]§e /{label} reload: 콘피그 파일은 리로드하고 저장합니다.' + start: '§8§l[퀘스트 시스템]§e /{label} start <player> [id]: 퀘스트를 강제적으로 시작시킵니다.' + setItem: '§8§l[퀘스트 시스템]§e /{label} setItem <talk|launch>: 홀로그램 아이템을 저장합니다.' + setFirework: '§8§l[퀘스트 시스템]§e /{label} setFirework: 기본 엔딩 폭죽을 수정합니다.' + adminMode: '§8§l[퀘스트 시스템]§e /{label} adminMode: 어드민 모드를 활성화 합니다.' + version: '§8§l[퀘스트 시스템]§e /{label} version: 현재 플러그인 버전을 봅니다.' + downloadTranslations: '§8§l[퀘스트 시스템]§e /{label} downloadTranslations <language>: 언어 파일을 다운로드 합니다.' + save: '§8§l[퀘스트 시스템]§e /{label} save: 플러그인을 저장합니다.' + list: '§8§l[퀘스트 시스템]§e /{label} list: 퀘스트 목록을 봅니다.' + typeCancel: '§8§l[퀘스트 시스템]§e "cancel"을 작성하여 이전 내용으로 돌아올 수 있습니다.' + editor: + blockAmount: '§8§l[퀘스트 시스템] §e아이템의 개수를 입력하세요:' + blockName: '§8§l[퀘스트 시스템] §e아이템의 이름을 입력하세요:' + blockData: '§8§l[퀘스트 시스템]§e 블럭 데이터를 입력하세요 (available blockdatas: §7{available_datas}§a):' + blockTag: '§8§l[퀘스트 시스템]§e 블럭 태그를 입력하세요 (available blockdatas: §7{available_tags}§a):' + typeBucketAmount: '§8§l[퀘스트 시스템]§e 채울 양동이의 갯수를 입력하세요:' + typeDamageAmount: '§8§l[퀘스트 시스템]§e 플레이어가 입힐 데미지의 양을 입력하세요:' + goToLocation: '§8§l[퀘스트 시스템]§e 해당 스테이지의 원하는 위치에 가세요!' + typeLocationRadius: '§8§l[퀘스트 시스템] §a위치에서 부터 요구되는 거리를 작성해주세요.' + typeGameTicks: '§8§l[퀘스트 시스템] §a요구하는 게임 틱을 작성해주세요' + already: '§8§l[퀘스트 시스템] §a이미 편집 모드에 있습니다.' + stage: + location: + typeWorldPattern: '§8§l[퀘스트 시스템]§e 월드 이름을 입력하세요:' + enter: + title: '§8§l[퀘스트 시스템] §a에디터 모드' + subtitle: '§8§l[퀘스트 시스템] §a강제적으로 에디터를 나가시려면 "/quests exitEditor"를 입력해 주세요!' + list: '§8§l[퀘스트 시스템] §c⚠ §7당신은 "목록" 에디터에 입장하였습니다. "add"를 작성해 줄을 추가하세요. 도움말을 보시려면 "help" 를 작성해주세요! §e§l에디터를 종료하려면 "close"를 입력하세요.' + chat: '§8§l[퀘스트 시스템] §a현제 에디터 모드에 있습니다. 강제적으로 에디터를 나가시려면 "/quests exitEditor"를 입력해 주세요!' + npc: + enter: '§8§l[퀘스트 시스템] §aNPC를 클릭하세요! 또는 "cancel"을 작성해주세요!' + choseStarter: '§8§l[퀘스트 시스템] §a퀘스트를 시작할 NPC를 선택해주세요!' + notStarter: '§8§l[퀘스트 시스템] §a해당 NPC는 퀘스트가 적용되지 않았습니다.' + text: + argNotSupported: '§8§l[퀘스트 시스템] §a{arg}는 지원되지 않습니다.' + chooseLvlRequired: '§8§l[퀘스트 시스템] §e요구할 레벨의 양을 입력하세요:' + chooseJobRequired: '§8§l[퀘스트 시스템] §e원하시는 직업의 이름을 입력하세요:' + choosePermissionRequired: '§8§l[퀘스트 시스템] §e요구할 펄미션을 입력하세요:' + choosePermissionMessage: '§8§l[퀘스트 시스템] §e해당 플레이어가 펄미션을 보유하고 있지 않을시, 보여질 거부 메시지를 입력하세요: ( "null"을 입력시 해당 단계를 스킵합니다. )' + choosePlaceholderRequired: + identifier: '§8§l[퀘스트 시스템] §e요구되는 placeholder의 이름(%제외)을 입력하세요:' + value: '§8§l[퀘스트 시스템] §eplaceholder {placeholder}의 요구되는 값을 입력하세요:' + chooseSkillRequired: '§8§l[퀘스트 시스템] §e요구되는 스킬의 이름을 입력하세요:' + chooseMoneyRequired: '§8§l[퀘스트 시스템] §e요구할 돈의 양을 입력하세요:' + reward: + permissionName: '§8§l[퀘스트 시스템] §e펄미션의 이름을 입력하세요!' + permissionWorld: '§8§l[퀘스트 시스템] §e펄미션이 수정될 월드를 입력하세요! 동일하게 하려면 "null"을 입력하세요!' + money: '§8§l[퀘스트 시스템] §e받을 돈의 양을 입력하세요:' + wait: '§8§l[퀘스트 시스템] §e기다릴 틱의 양을 입력하세요: ( 1초당 20틱 )' + random: + min: '§8§l[퀘스트 시스템] §e플레이어에게 지급할 보상의 최소 양을 입력하세요' + max: '§8§l[퀘스트 시스템] §e플레이어에게 지급할 보상의 최대 양을 입력하세요' + chooseObjectiveRequired: '§8§l[퀘스트 시스템] §e오브젝티브 이름을 입력하세요' + chooseObjectiveTargetScore: '§8§l[퀘스트 시스템] §e해당 오브젝티브의 목표 점수를 입력하세요' + chooseRegionRequired: '§8§l[퀘스트 시스템] §e요구되는 지역의 이름을 입력하세요 (같은 월드에 있어야합니다)' + chooseRequirementCustomReason: '§8§l[퀘스트 시스템] §e수락 조건의 커스텀 이유를 입력하세요! 플레이어가 요구 사항을 충족하지 못하더라도 퀘스트를 시작하려고 하면 이 메시지가 채팅에 표시됩니다.' + chooseRequirementCustomDescription: '§8§l[퀘스트 시스템] §e수락 조건의 커스텀 설명을 작성하세요! 이것은 메뉴에 있는 퀘스트의 설명에 나타납니다!' + chooseRewardCustomDescription: '§8§l[퀘스트 시스템] §e해당 보상의 커스텀 설명을 작성하세요! 이것은 메뉴에 있는 퀘스트의 설명에 나타납니다!' + selectWantedBlock: '§8§l[퀘스트 시스템] §e막대기로 해당 단계에 원하는 블럭을 클릭하세요!' + itemCreator: + itemType: '§8§l[퀘스트 시스템] §e원하는 아이템 타입을 입력하세요:' + itemAmount: '§8§l[퀘스트 시스템] §e아이템의 개수를 입력하세요:' + itemName: '§8§l[퀘스트 시스템] §e아이템의 이름을 입력하세요:' + itemLore: '§8§l[퀘스트 시스템] §e아이템의 Lore를 설정하세요: ("help"를 입력시 도움말을 볼 수 있습니다!)' + unknownItemType: '§8§l[퀘스트 시스템] §e알려지지 않은 아이템 타입입니다.' + invalidItemType: '§8§l[퀘스트 시스템] §e유효하지 않은 타입입니다. (블럭은 적용되지 않습니다.)' + unknownBlockType: '§8§l[퀘스트 시스템] §e알려지지 않은 블럭 타입입니다.' + invalidBlockType: '§8§l[퀘스트 시스템] §e알려지지 않은 블럭 타입입니다.' + dialog: + syntaxMessage: '§8§l[퀘스트 시스템] §e알맞지 않은 명령어 입니다. 명령어 : {command} <message>' + syntaxRemove: '§8§l[퀘스트 시스템] §e알맞지 않은 명령어 입니다. 명령어 : remove <id>' + player: '§8§l[퀘스트 시스템] §e플레이어 메시지 §7"{msg}" §e가 추가되었습니다.' + npc: '§8§l[퀘스트 시스템] §eNPC 메시지 §7"{msg}" §e가 추가되었습니다.' + noSender: '§8§l[퀘스트 시스템] §e메시지 §7"{msg}" §e가 추가되었습니다.' + messageRemoved: '§8§l[퀘스트 시스템] §e메시지 §7"{msg}" §e가 삭제 되었습니다.' + edited: '§8§l[퀘스트 시스템] §e메시지 §7"{msg}" §e가 수정되었습니다.' + soundAdded: '§8§l[퀘스트 시스템] §e메시지 §7"{msg}" §e에 사운드 "§7{sound}" §e가 추가되었습니다.' + cleared: '§8§l[퀘스트 시스템] §7{amount} §e개의 메시지가 삭제되었습니다.' + help: + header: '§8§l[퀘스트 시스템]§e 대화 편집 도움말' + npc: '§8§l[퀘스트 시스템]§e npc <message>: NPC가 말하는 메시지를 추가합니다.' + player: '§8§l[퀘스트 시스템]§e player<message>: 플레이어가 말할 메시지를 추가합니다.' + nothing: '§8§l[퀘스트 시스템]§e noSender <message>: 발언자 없는 메시지를 추가합니다.' + remove: '§8§l[퀘스트 시스템]§e remove <id>: §e텍스트를 삭제합니다.' + list: '§8§l[퀘스트 시스템]§e list: §e추가된 모든 텍스트를 확인합니다.' + npcInsert: '§8§l[퀘스트 시스템]§e npc <message>: NPC가 말하는 메시지를 추가합니다.' + playerInsert: '§8§l[퀘스트 시스템]§e playerinsert <id> <message>: 플레이어가 말하는 메시지를 추가합니다.' + nothingInsert: '§8§l[퀘스트 시스템]§e notinginsert <id> <message>: 발언자 없이 말하는 메시지를 추가합니다.' + edit: '§8§l[퀘스트 시스템]§e edit <id> <message>: 해당되는 id의 메시지를 수정합니다' + mythicmobs: + list: '§a모든 미스틱 몹 목록:' + isntMythicMob: '§c이 미스틱 몹은 존재하지 않습니다.' + disabled: '§c미스틱몹이 비활성화됩니다..' + textList: + help: + header: '§6§lBeautyQuests — 리스트 편집 도움말' + add: '§6add <message>: §e텍스트를 추가합니다.' + remove: '§6remove <id>: §e텍스트를 삭제합니다.' + list: '§6list: §e추가된 모든 텍스트를 확인합니다.' + close: '§6close: §e추가된 텍스트의 유효성을 확인하십시오.' advancement: - finished: 완료됨 notStarted: 시작되지 않음 -description: - requirement: - class: '직업: {class_name}' - level: 레벨 {short_level} - skillLevel: 레벨 {short_level}/{skill_name} -indication: - cancelQuest: '§7{quest_name} 퀘스트를 포기 하시겠습니까?' - removeQuest: '§7{quest} 퀘스트를 삭제 하시겠습니까?' inv: - addObject: '§a오브젝트 추가' - blocksList: - name: 블록 선택 + validate: '§b§l저장하다.' cancel: '§c§l취소' - chooseQuest: - name: 어떤 퀘스트? - commandsList: - name: 명령어 목록 + search: '§e§l검색' + addObject: '§a오브젝트 추가' confirm: name: 계속하시겠습니까? - 'no': '§c아니오' 'yes': '§a예' + 'no': '§c아니오' create: - NPCText: '§e엔피시 대화 편집' - bringBack: '§a아이템 가져오기' - cancelMessage: 발송 취소 - craft: '§a아이템 만들기' - currentRadius: '§e현재 거리: §6{radius}' - editBlocksMine: '§e부술 블럭 설정' - editBucketAmount: '§e채울 양동이의 갯수 편집' - editBucketType: '§e채울 양동이 유형 편집' - editFishes: '§e잡을 물고기 편집' - editItem: '§e만들 아이템 편집' - editLocation: '§e좌표 편집' - editMessageType: '§e채팅 치기 편집' - editMobsKill: '§e죽일 몬스터 설정하기' - editRadius: '§e좌표로부터의 거리 편집' + stageCreate: '§a새로운 퀘스트 만들기' + stageRemove: '§c단계 삭제' + stageUp: 위로 이동하기 + stageDown: 아래로 이동하기 + stageType: '§7스테이지 타입 : §e{stage_type}' + cantFinish: '§7당신은 해당 퀘스트 제작을 끝내기 전에 최소 하나의 스테이지를 생성해야 합니다!' findNPC: '§aNPC 찾아가기' + bringBack: '§a아이템 가져오기' findRegion: '§a지역 찾아가기' - fish: '§a물고기 잡기' - hideClues: 파티클 및 홀로그램 숨기기 - ignoreCase: 채팅치기 대소문자 구분 여부 - interact: '§a블럭 상호작용' killMobs: '§a사냥하기' - leftClick: 좌클릭만 감지 - location: '§a특정 좌표로 이동하기' mineBlocks: '§a블럭 부수기' + placeBlocks: '§a블럭 설치' + talkChat: '§a채팅치기' + interact: '§a블럭 상호작용' + interactLocation: '§a위치에 있는 블럭과 상호작용' + fish: '§a물고기 잡기' + melt: '§6아이템 녹이기' + enchant: '§d아이템 인챈트하기' + craft: '§a아이템 만들기' + bucket: '§a양동이 채우기' + location: '§a특정 좌표로 이동하기' + playTime: '§e시간 조정' + breedAnimals: '§e동물에게 먹이 주기' + tameAnimals: '§e동물 길들이기' + death: '§e죽기' + dealDamage: '§e몬스터에게 데미지 입히기' + eatDrink: '§e음식 섭취' + NPCText: '§e엔피시 대화 편집' + NPCSelect: '§eNPC선택 혹은 생성' + hideClues: 파티클 및 홀로그램 숨기기 + editMobsKill: '§e죽일 몬스터 설정하기' mobsKillFromAFar: 발사체로 죽일지 여부 + editBlocksMine: '§e부술 블럭 설정' preventBlockPlace: 자신이 설치한 블럭 가능 여부 - selectBlockLocation: '§e블럭 위치 선택' + editBlocksPlace: '§e설치할 블럭 편집' + editMessageType: '§e채팅 치기 편집' + cancelMessage: 발송 취소 + ignoreCase: 채팅치기 대소문자 구분 여부 selectItems: '§e필수 항목 편집' + selectItemsMessage: '§e퀘스트 시작 메시지 편집' selectRegion: '§7지역 선택' - stageCreate: '§a새로운 퀘스트 만들기' - stageDown: 아래로 이동하기 - stageRemove: '§c단계 삭제' + toggleRegionExit: '§e퇴장' stageStartMsg: '§e퀘스트 시작 메시지 편집' - stageUp: 위로 이동하기 - talkChat: '§a채팅치기' + selectBlockLocation: '§e블럭 위치 선택' + selectBlockMaterial: '§e블럭 타입 선택' + leftClick: 좌클릭만 감지 + editFishes: '§e잡을 물고기 편집' + editItemsToMelt: '§e녹일 아이템 편집' + editItemsToEnchant: '§e인첸트 할 아이템 편집' + editItem: '§e만들 아이템 편집' + editBucketType: '§e채울 양동이 유형 편집' + editBucketAmount: '§e채울 양동이의 갯수 편집' + editLocation: '§e좌표 편집' + editRadius: '§e좌표로부터의 거리 편집' + currentRadius: '§e현재 거리: §6{radius}' + changeTicksRequired: '§e요구될 틱 수정' + changeEntityType: '§e엔티티 타입 수정' + stages: + name: 스테이지 작성 + nextPage: '§e다음 페이지' + laterPage: '§e이전 페이지' + endingItem: '§e최종 보상 설정' + descriptionTextItem: '§e퀘스트 설정 설명' + regularPage: '§a정규 페이지' + branchesPage: '§d분기 페이지' + previousBranch: '§e이전 지점' + newBranch: '§e새 페이지로 이동' details: + hologramLaunch: '§e"launch" 홀로그램 아이템 편집' + hologramLaunchNo: '§e"launch 이용불가" 홀로그램 아이템 편집' + customDescriptionLore: 퀘스트 GUI 아래에 설명이 표시됩니다. + scoreboardItem: 스코어보드 활성화하기 auto: 접속시 자동으로 수령 autoLore: 활성화시 서버에 처음 접속하는 사람에게 해당 퀘스트가 시작됩니다. - createQuestLore: 퀘스트 이름을 정해야합니다. - customDescriptionLore: 퀘스트 GUI 아래에 설명이 표시됩니다. - failOnDeath: 사망 시 실패하기 - keepDatas: 플레이어 데이터 유지하기 questName: 퀘스트 이름 정하기 questNameLore: 퀘스트 편집을 끝내기 위해선 퀘스트 이름을 설정해야 합니다. - removeItemsReward: 인벤토리에서 아이템 제거 - scoreboardItem: 스코어보드 활성화하기 setItemsRewards: 보상 설정하기 - setRewardStopQuest: 퀘스트 종료 + removeItemsReward: 인벤토리에서 아이템 제거 setXPRewards: 보상으로 받을 경험치 양 설정하기 - itemComparisons: - itemLore: 아이템 설명 - itemName: 아이템 이름 + setCheckpointReward: '§e체크포인트 보상 편집' + setRewardStopQuest: 퀘스트 종료 + setRewardsWithRequirements: '§e조건 보상' + setRewardsRandom: '§e랜덤 보상' + setPermReward: '§e펄미션 편집' + createQuestLore: 퀘스트 이름을 정해야합니다. + failOnDeath: 사망 시 실패하기 + keepDatas: 플레이어 데이터 유지하기 itemsSelect: name: 아이템 수정 - listBook: - questStages: 단계 + npcCreate: + name: NPC 생성 + setName: '§eNPC 이름 설정' + setSkin: '§eNPC 스킨 설정' + setType: '§eNPC 타입 설정' + chooseQuest: + name: 어떤 퀘스트? + mobs: + name: 몹 선택하기 + mobSelect: + mythicMob: '§6미스틱 몹 선택' listPlayerQuests: name: '{player_name}의 퀘스트' listQuests: - canRedo: '§3§o이 퀘스트를 다시 수행할 수 있습니다!' + notStarted: 시작 가능한 퀘스트 finished: 완료한 퀘스트 inProgress: 진행중인 퀘스트 - loreCancelClick: '§c퀘스트 포기하기' loreDialogsHistoryClick: '§7퀘스트 내용 다시보기' + loreCancelClick: '§c퀘스트 포기하기' loreStart: '§a클릭해서 퀘스트 시작하기' - notStarted: 시작 가능한 퀘스트 - timeToWaitRedo: '§3§o이 퀘스트는 {time_left} 뒤에 다시 시작할 수 있습니다.' - timesFinished: '§3퀘스트를 {times_finished} 번 완료함.' - mobSelect: - mythicMob: '§6미스틱 몹 선택' - mobs: - name: 몹 선택하기 - npcCreate: - name: NPC 생성 - setName: '§eNPC 이름 설정' - setSkin: '§eNPC 스킨 설정' - setType: '§eNPC 타입 설정' + canRedo: '§3§o이 퀘스트를 다시 수행할 수 있습니다!' + listBook: + questStages: 단계 + commandsList: + name: 명령어 목록 + blocksList: + name: 블록 선택 + permissionList: + name: 권한 리스트 + world: '§e월드: §6{permission_world}' + classesRequired.name: '§e클래스가 필요합니다.' + classesList.name: 클래스 리스트 poolsManage: poolQuestsList: '§7{pool_quests_amount} §8퀘스트: §7{pool_quests}' - search: '§e§l검색' - stages: - branchesPage: '§d분기 페이지' - descriptionTextItem: '§e퀘스트 설정 설명' - endingItem: '§e최종 보상 설정' - laterPage: '§e이전 페이지' - name: 스테이지 작성 - newBranch: '§e새 페이지로 이동' - nextPage: '§e다음 페이지' - previousBranch: '§e이전 지점' - regularPage: '§a정규 페이지' - validate: '§b§l저장하다.' + itemComparisons: + itemName: 아이템 이름 + itemLore: 아이템 설명 + questObjects: + description: '§8설명 : §7{description}' +scoreboard: + name: '§6§l퀘스트' + noLaunched: '§진행중인 퀘스트가 없습니다.' + noLaunchedName: '§e§l로딩중..' + noLaunchedDescription: '§e§l로딩중..' + textBetwteenBranch: '§e 또는' + asyncEnd: '§eX' + stage: + region: '§6{region_id} §e지역 찾아가기' + npc: '§eNPC {dialog_npc_name}와 대화하세요' + items: '§eNPC {dialog_npc_name}에게 {items}을 가지고 오세요' + mobs: '&e사냥하기 §6{mobs}' + mine: '&e블록 캐기 {blocks}' + placeBlocks: '§e{blocks}을 설치하세요' + chat: '§e{text}을 입력하세요' + interact: '§e좌표 x : {x} y : {y} z : {z} 의 블럭을 클릭하세요' + interactMaterial: '§e{block} 블럭을 클릭하세요' + fish: '§e{items}을 낚으세요' + melt: '§e{items}을 녹이세요' + enchant: '§e{items}을 인챈트 하세요' + craft: '§e{items}을 제작하세요' + bucket: '§e{buckets}을 채우세요' + playTimeFormatted: '§e{time_remaining_human}을 기다리세요' + breed: '§e{mobs}에게 먹이를 주세요' + tame: '§e{mobs}을 길들이세요' + die: '§e죽으세요' + dealDamage: + any: '§e{damage_remaining}데미지를 입히세요' + mobs: '§e{target_mobs}에게 {damage_remaining} 데미지를 입히세요' + eatDrink: '§e{items}를 섭취하세요' +indication: + startQuest: '§7{quest_name} 퀘스트를 시작 하시겠습니까?' + closeInventory: '§7 퀘스트 창을 닫으시겠습니까?' + cancelQuest: '§7{quest_name} 퀘스트를 포기 하시겠습니까?' + removeQuest: '§7{quest} 퀘스트를 삭제 하시겠습니까?' + removePool: '§ePool {pool}을 제거하시겠습니까?' +description: + requirement: + title: '§8§l수락 조건 :' + level: '레벨 {short_level}' + jobLevel: '§e{job_name}의 레벨 {short_level}' + combatLevel: '§e전투 레벨 {short_level}' + skillLevel: '레벨 {short_level}/{skill_name}' + class: '직업: {class_name}' + quest: '§e{quest_name} 퀘스트 끝내기' + reward: + title: '§8§l보상 :' misc: - amount: '§e갯수: {amount}' - and: 그리고 - click: - left: 좌클릭 - right: 우클릭 - shift-left: Shift-좌클릭 - shift-right: Shift-우클릭 - comparison: - greaterOrEquals: '{number} 이상' - disabled: 비활성화 - enabled: 활성화 format: prefix: '§6<§e§l퀘스트§r§6> §r' - hologramText: 퀘스트 NPC - 'no': '아니오' - or: 또는 - stageType: - mobs: 사냥하기 - npc: NPC 찾기 - region: 지역 찾아가기 + npcText: '§e{message_id}/{message_count}/ §e§l{npc_name_message}: §r§e{text}' + selfText: '§6[{message_id}/{message_count}] §e§l{player_name}:§r§e {text}' time: + weeks: '{weeks_amount}주' days: '{days_amount}일' hours: '{hours_amount}시간' minutes: '{minutes_amount}분' - weeks: '{weeks_amount}주' + lessThanAMinute: '몇 초' + stageType: + region: 지역 찾아가기 + npc: NPC 찾기 + mobs: 사냥하기 + comparison: + greaterOrEquals: '{number} 이상' + requirement: + placeholder: '§dPlaceHolder 값이 필요합니다.' + quest: '§d퀘스트가 필요합니다.' + mcMMOSkillLevel: '§d스킬 레벨이 필요합니다.' + money: '§d돈이 필요합니다.' + equipment: '§e장비가 필요합니다.' + bucket: + water: 물 양동이 + lava: 용암 양동이 + milk: 우유 양동이 + snow: 눈 양동이 + click: + right: 우클릭 + left: 좌클릭 + shift-right: Shift-우클릭 + shift-left: Shift-좌클릭 + middle: 중간 버튼 클릭 + amounts: + items: '아이템 {items_amount} 개' + dialogLines: '{lines_amount} 줄' + permissions: '펄미션 {permissions_amount} 개' + mobs: '몬스터 {mobs_amount} 마리' + xp: '경험치 양 {xp_amount}' + ticks: '{ticks} 틱' + location: |- + 위치 : x {x} y{y} z{z} + 월드 이름 : {world} + questItemLore: '§e§o 퀘스트 아이템' + hologramText: 퀘스트 NPC + poolHologramText: '§e새 퀘스트를 받을 수 있습니다!' + entityType: '§e엔티티 타입 : {entity_type}' + entityTypeAny: '§e아무 엔티티' + enabled: 활성화 + disabled: 비활성화 unknown: 알 수 없음 + notSet: '§e설정되지 않았습니다.' + removeRaw: 제거 + reset: 초기화 + or: 또는 + amount: '§e갯수: {amount}' 'yes': '예' -msg: - command: - invalidCommand: - simple: '§c알수없는 커맨드입니다. §ehelp §c를 입력해주세요.' - itemChanged: '§a항목이 재편집 되었습니다. 변경사항은 재시작 후 적용될것입니다.' - itemRemoved: '§a홀로그램 항목이 제거 되었습니다.' - leaveAll: '§a{success}퀘스트를 건너뛰었습니다. §c에러 : {errors}' - removed: '§a{quest_name} 퀘스트가 성공적으로 제거되었습니다.' - resetPlayer: - player: '§6당신의 {quest_amount} 퀘스트(들)에 대한 모든 설명이 {deleter_name}에 의해 삭제되었습니다.' - setStage: - next: '§a단계를 건너뛰었습니다.' - set: '§a스테이지 {stage_id} 이 시작되었습니다.' - editor: - mythicmobs: - disabled: '§c미스틱몹이 비활성화됩니다..' - isntMythicMob: '§c이 미스틱 몹은 존재하지 않습니다.' - list: '§a모든 미스틱 몹 목록:' - textList: - help: - add: '§6add <message>: §e텍스트를 추가합니다.' - close: '§6close: §e추가된 텍스트의 유효성을 확인하십시오.' - header: '§6§lBeautyQuests — 리스트 편집 도움말' - list: '§6list: §e추가된 모든 텍스트를 확인합니다.' - remove: '§6remove <id>: §e텍스트를 삭제합니다.' - errorOccurred: '§c에러가 발생했습니다. 관리자에게 문의하세요! §4§lError code: {error}' - indexOutOfBounds: '§c {index}는 범위를 벗어난 값입니다! {min} 과 {max} 사이여야 합니다.' - number: - invalid: '§c{input}는 유효한 숫자가 아닙니다.' - pools: - allCompleted: '§7모든 퀘스트를 완료했습니다!' - maxQuests: '§c당신은 {pool_max_quests}개 이상의 퀘스트를 동시에 가질 수 없습니다...' - noAvailable: '§7완료 가능한 퀘스트가 존재하지 않습니다.' - noTime: '§c다른 퀘스트를 하기위해 {time_left}만큼 기다려야 합니다.' - quest: - alreadyStarted: '§c퀘스트를 이미 시작하셨습니다!' - cancelling: '§c퀘스트 생성 프로세스가 취소되었습니다.' - createCancelled: '§c다른 플러그인으로 인해 생성 또는 수정이 취소되었습니다.' - created: '§a축하합니다! {quest_branches} 를(을) 포함하는 퀘스트 §e{quest}§a를(을) 제작했습니다!' - editCancelling: '§c퀘스트 에디션의 프로세스가 취소되었습니다.' - edited: '§a축하합니다! §e{quest}§a 를(을) 포함한 퀘스트를 수정했습니다.' - finished: - base: '§a축하합니다! §e{quest_name}§a 퀘스트를 완료하셨습니다.' - obtain: '§a{rewards}를 얻었습니다!' - invalidID: '§cID가 {quest_id} 인 퀘스트가 존재하지 않습니다.' - invalidPoolID: '§c{pool_id}이(가) 존재하지 않습니다.' - started: '§r§e{quest_name}§o§6 §a퀘스트를 시작하셨습니다.' - questItem: - craft: '§c퀘스트용 아이템을 조합에 사용할 수 없습니다!' - drop: '§c퀘스트 아이템은 버릴 수 없습니다!' - eat: 퀘스트 아이템은 팔 수 없습니다. - quests: - checkpoint: '§7퀘스트 체크포인트에 도달 하였습니다!' - failed: '§c당신은 {quest_name} 퀘스트를 실패했습니다...' - maxLaunched: '§c당신은 {quests_max_amount}개 이상의 퀘스트를 동시에 가질 수 없습니다...' - updated: '§7퀘스트 §e{quest_name}§7가 업데이트 되었습니다.' - requirements: - level: '§c퀘스트를 받기 위한 레벨이 부족합니다! {long_level}!' - money: '§c{money}를 가져야합니다!' - quest: '§c먼저 §e{quest_name}§c 퀘스트를 완료 해야합니다.' - stageMobs: - listMobs: '§a당신은 {mobs}를 죽여야만 합니다.' - versionRequired: '버전 요구 사항: §l{version}' - writeCommand: '§a원하는 커맨드를 입력하세요: (커맨드는 "/"와 "{PLAYER}" 를 제외하고 써도 좋습니다. 자동으로 실행하는 사람을 대상으로 설정할 것입니다.)' - writeMobAmount: '§a죽일 몹의 수를 적어 주세요:' - writeNPCText: '§aNPC가 플레이어에게 말할 대사를 작성해주세요: (도움말을 보려면 "help"를 입력하세요.)' - writeNpcName: '§aNPC의 이름을 적어주세요:' - writeNpcSkinName: '§aNPC 스킨의 이름을 입력하세요:' - writeQuestName: '§a퀘스트의 이름을 입력하세요:' - writeRegionName: '§a해당 단계에 필요한 지역의 이름을 입력하세요:' - writeXPGain: '§a플레이어가 획득할 경험치량을 입력하세요: (최근 값: {xp_amount})' -scoreboard: - name: '§6§l퀘스트' - stage: - mine: '&e블록 캐기 {blocks}' - mobs: '&e사냥하기 §6{mobs}' - region: '§6{region_id} §e지역 찾아가기' + 'no': '아니오' + and: 그리고 diff --git a/core/src/main/resources/locales/nl_NL.yml b/core/src/main/resources/locales/nl_NL.yml index 78f2c86d..95d5b2df 100755 --- a/core/src/main/resources/locales/nl_NL.yml +++ b/core/src/main/resources/locales/nl_NL.yml @@ -1,43 +1,267 @@ --- msg: - pools: - allCompleted: U hebt de Quest voltooid - maxQuests: '§cJe kunt niet meer dan {pool_max_quests} quest(s) tegelijk hebben...' - noAvailable: '§7Er is geen quest meer beschikbaar...' - noTime: '§cJe moet {time_left} wachten voordat je een andere quest kunt doen.' quest: - alreadyStarted: '§cJe hebt de quest al begonnen!' - cancelling: '§cProces van de vorming van de quest is geannuleerd.' - createCancelled: '§cDe creatie of editie is geannuleerd door een andere plugin!' - created: '§aGefeliciteerd! Je hebt de quest §e{quest}§a gemaakt met {quest_branches} branches!' - editCancelling: '§cProces van quest editie geannuleerd.' - edited: '§aGefeliciteerd! Je hebt de quest §e{quest}§a bewerkt met nu {quest_branches} branches!' finished: base: '§aGefeliciteerd! Je hebt de quest §e{quest_name}§a voltooid!' obtain: '§aU krijgt {rewards}!' + started: '§aJe hebt de quest §r§f{quest_name}§o§6begonnen!' + created: '§aGefeliciteerd! Je hebt de quest §e{quest}§a gemaakt met {quest_branches} branches!' + edited: '§aGefeliciteerd! Je hebt de quest §e{quest}§a bewerkt met nu {quest_branches} branches!' + createCancelled: '§cDe creatie of editie is geannuleerd door een andere plugin!' + cancelling: '§cProces van de vorming van de quest is geannuleerd.' + editCancelling: '§cProces van quest editie geannuleerd.' invalidID: '§cDe quest met de id {quest_id} bestaat niet.' invalidPoolID: De {pool_id} bestaat niet. + alreadyStarted: '§cJe hebt de quest al begonnen!' notStarted: '§cJe doet momenteel niet deze quest.' - started: '§aJe hebt de quest §r§f{quest_name}§o§6begonnen!' - questItem: - craft: '§cJe kan geen Quest voorwerp gebruiken om te craften!' - drop: '§cJe kan geen Quest item laten vallen!' - eat: '§cJe kan geen Quest item eten!' quests: - checkpoint: '§7Zoektocht controlepunt bereikt!' - failed: '§cJe hebt de quest {quest_name} gefaald...' maxLaunched: '§cJe kunt niet meer dan {quests_max_amount} quest(s) tegelijk hebben...' updated: '§7Quest §e{quest_name}§7 bijgewerkt.' + checkpoint: '§7Zoektocht controlepunt bereikt!' + failed: '§cJe hebt de quest {quest_name} gefaald...' + pools: + noTime: '§cJe moet {time_left} wachten voordat je een andere quest kunt doen.' + allCompleted: U hebt de Quest voltooid + noAvailable: '§7Er is geen quest meer beschikbaar...' + maxQuests: '§cJe kunt niet meer dan {pool_max_quests} quest(s) tegelijk hebben...' + questItem: + drop: '§cJe kan geen Quest item laten vallen!' + craft: '§cJe kan geen Quest voorwerp gebruiken om te craften!' + eat: '§cJe kan geen Quest item eten!' stageMobs: listMobs: '§aJe moet {mobs} doden.' - writeChatMessage: '§aSchrijf vereiste bericht: (Voeg "{SLASH}" toe aan het begin als je een opdracht wilt.)' - writeDescriptionText: '§aSchrijf de tekst die het doel van het stadium beschrijft:' - writeEndMsg: '§aSchrijf het bericht dat aan het einde van de quest zal worden verstuurd, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben. U kunt "{rewards}" gebruiken die vervangen zal worden door de verkregen beloningen.' - writeEndSound: '§aSchrijf het bericht dat zal worden verzonden aan het begin van de quest, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben:' - writeMessage: '§aSchrijf het bericht dat naar de speler wordt gestuurd' - writeMobAmount: '§aSchrijf de hoeveelheid mobs om te doden:' - writeMobName: '§aSchrijf de aangepaste naam van de mob om te doden:' writeNPCText: '§aSchrijf het dialoogvenster dat door de NPC''s tegen de speler wordt gezegd: (Schrijf "help" om hulp te ontvangen.)' writeRegionName: '§aSchrijf de naam van de regio die nodig is voor de stap:' - writeStartMessage: '§aSchrijf het bericht dat zal worden verzonden aan het begin van de quest, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben:' writeXPGain: '§aSchrijf de hoeveelheid experience punten die de speler zal krijgen: (Laatste waarde: {xp_amount})' + writeMobAmount: '§aSchrijf de hoeveelheid mobs om te doden:' + writeMobName: '§aSchrijf de aangepaste naam van de mob om te doden:' + writeChatMessage: '§aTyp verplicht bericht: (Voeg "{SLASH}" toe aan het begin van je bericht als je een commando wilt uitvoeren.)' + writeMessage: '§aSchrijf het bericht dat naar de speler wordt gestuurd' + writeStartMessage: '§aSchrijf het bericht dat zal worden verzonden aan het begin van de quest, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben:' + writeEndMsg: '§aTyp het bericht dat aan het einde van de Quest zal worden verstuurd. Typ "null" als je de standaard wilt of "none" als je géén bericht wilt hebben. Gebruik "\{rewards}". Dit zal vervangen worden door de beloningen.' + writeEndSound: '§aSchrijf het bericht dat zal worden verzonden aan het begin van de quest, "null" als je de standaard wilt of "none" als je geen bericht wilt hebben:' + writeDescriptionText: '§aSchrijf de tekst die het doel van het stadium beschrijft:' + writeStageText: '§aTyp het bericht dat aan het begin van deze stap naar de speler wordt verstuurd:' + moveToTeleportPoint: '§aGa naar de gewenste teleportatie locatie.' + writeNpcName: '§aTyp de naam van de NPC:' + writeNpcSkinName: '§aTyp de naam op van de skin van de NPC:' + writeQuestName: '§aTyp de naam van je quest:' + writeCommand: '§aTyp het gewenste commando: (Het commando is zonder de "/" en de placeholder "\{player}" wordt ondersteund en zal worden vervangen door de naam van degene die het commando uitvoert.)' + writeHologramText: '§aTyp de tekst van deze hologram: (Typ "none" als je geen hologram wilt en "null" wilt als je een standaard tekst wilt.)' + writeQuestTimer: '§aTyp de tijd (in minuten) voordat je de quest kunt herstarten: (Schrijf "null" als je een standaard timer wilt.)' + writeConfirmMessage: '§aTyp het bevestigingsbericht dat de speler krijgt wanneer die op het punt staat de quest te starten: (Schrijf "null" als je een standaardbericht wilt.)' + writeQuestDescription: '§aTyp de beschrijving van de quest. Deze wordt getoond in de quest GUI van de speler.' + writeQuestMaterial: '§aTyp het materiaal van het quest item.' + requirements: + quest: '§cJe moet eerst de §e{quest_name} quest voltooien!' + level: '§cJe moet level {long_level} zijn!' + job: '§cJe level voor de job §e{job_name}§c moet {long_level} zijn!' + skill: '§cJe level voor de job §e{skill_name}§c moet {long_level} zijn!' + combatLevel: '§cJe vecht-level moet {long_level} zijn!' + money: '§cJe moet {money} hebben!' + waitTime: '§cJe moet {time_left} wachten voordat je deze quest kan herstarten!' + experience: + edited: '§aJe hebt de experience bonus veranderd van {old_xp_amount} naar {xp_amount}.' + selectNPCToKill: '§aSelecteer de NPC om te doden.' + regionDoesntExists: '§cDeze regio bestaat niet. (Je moet in dezelfde wereld zijn.)' + npcDoesntExist: '§cDe NPC met de id {npc_id} bestaat niet.' + number: + negative: '§cJe moet een positief getal invoeren!' + zero: '§cJe moet een ander nummer dan 0 invoeren!' + invalid: '§c{input} is geen geldig nummer.' + notInBounds: '§cJouw nummer moet tussen {min} en {max} liggen.' + errorOccurred: '§cEr is een fout opgetreden, neem contact op met een adminstrator! §4§lError code: {error}' + indexOutOfBounds: '§cHet nummer {index} is buiten bereik! Dit moet tussen {min} en {max} zijn.' + invalidBlockData: '§cDe blockdata {block_data} is ongeldig of niet compatibel met het blok {block_material}.' + invalidBlockTag: '§cBlok-tag {block_tag} is niet beschikbaar.' + bringBackObjects: Breng mij {items} terug. + inventoryFull: '§cJe inventaris is vol. Je item is gevallen op de vloer.' + versionRequired: 'Versie vereist: §l{version}' + restartServer: '§7Herstart de server om je wijzigingen toe te passen.' + dialogs: + skipped: '§8§o Gesprek overgeslagen.' + tooFar: '§7§oJe bent te ver weg van {npc_name}...' + command: + downloadTranslations: + syntax: '§cJe moet een taal specificeren om te downloaden. Voorbeeld: "/quests downloadTranslations du_NL".' + notFound: '§cTaal {lang} niet gevonden voor versie {version}.' + exists: '§cHet bestand {file_name} bestaat al. Voeg "-overwrite" aan het eind toe om te overschrijven. (/quests downloadTranslations <lang> -overwrite)' + downloaded: "§aTaal {lang} is gedownload! §7Je moet nu het bestand \"/plugins/BeautyQuests/config.yml\" bewerken om de waarde van §ominecraftTranslationsFile§7 naar {lang} te wijzigen. Herstart \ndaarna de server." + checkpoint: + noCheckpoint: '§cGeen checkpoint gevonden voor de {quest} quest.' + questNotStarted: '§cJe bent momenteel niet bezig met deze quest.' + setStage: + branchDoesntExist: '§cDe vertakking met de id {branch_id} bestaat niet.' + doesntExist: '§cDe fase met de id {stage_id} bestaat niet.' + next: '§aDeze fase is overgeslagen.' + nextUnavailable: '§cDe "skip" optie is niet beschikbaar wanneer de speler aan het einde van een vertakking is.' + set: '§aFase {stage_id} gelanceerd.' + startDialog: + impossible: '§cHet is momenteel niet mogelijk om een conversatie te starten.' + noDialog: '§cDe speler heeft geen openstaande conversatie.' + alreadyIn: '§cDe speler zit momenteel al in een conversatie.' + success: '§aConversatie voor speler {player} in de {quest} quest is gestart!' + invalidCommand: + simple: '§cDit commando bestaat niet, typ §ehelp§c.' + itemChanged: '§aDit item is bewerkt. De wijzigingen zullen toegepast worden na een restart.' + itemRemoved: '§aDe hologram item is verwijderd.' + removed: '§aDe quest {quest_name} is succesvol verwijderd.' + leaveAll: '§aJe hebt het einde van {success} quest(s) geforceerd. Errors: {errors}' + resetPlayer: + player: '§6Alle informatie van je {quest_amount} quest(s) is/zijn verwijderd door {deleter_name}.' + remover: '§6{quest_amount} quest informatie(s) (en {quest_pool} pools) van {player} heeft/zijn verwijderd.' + resetPlayerQuest: + player: '§6Alle informatie van de {quest} quest is/zijn verwijderd door {deleter_name}.' + remover: '§6{player} informatie over de quest {quest} heeft/zijn verwijderd.' + resetQuest: '§6Data van de quest voor {player_amount} spelers verwijderd.' + startQuest: '§6Je hebt quest {quest} op {player} geforceerd.' + startQuestNoRequirements: '§cDe speler voldoet niet aan de minimale eisen voor de quest {quest}... Voeg "-overrideRequirements" toe aan het einde van je commando om de controle van de vereisten te omzeilen.' + cancelQuest: '§6Je hebt de quest {quest} geannuleerd.' + cancelQuestUnavailable: '§cDe quest "{quest}" kan niet worden gestopt.' + backupCreated: '§6Je hebt een back-ups gemaakt van alle quests en spelersinformatie.' + backupPlayersFailed: '§cMaken van een back-up voor alle spelersinformatie is mislukt.' + backupQuestsFailed: '§cHet maken van een back-up voor alle quests, is mislukt.' + adminModeEntered: '§aJe hebt de Admin modus geactiveerd.' + adminModeLeft: '§aJe hebt de Admin modus gedeactiveerd.' + resetPlayerPool: + timer: '§aJe hebt de {pool} pool timer van {player} gereset.' + full: '§aJe hebt de {pool} pool data van {player} gereset.' + startPlayerPool: + error: 'Het starten van de pool {pool} voor {player}, is mislukt.' + success: 'Begonnen met {pool} naar {player}. Resultaat: {result}' + scoreboard: + lineSet: '§6Je hebt regel {line_id} bewerkt.' + lineReset: '§6Je hebt regel {line_id} gereset.' + lineRemoved: '§6Je hebt lijn {line_id} verwijderd.' + lineInexistant: '§cRegel {line_id} bestaat niet.' + resetAll: '§6Je hebt de scorebord van {player_name} gereset.' + hidden: '§6De scorebord van {player_name} is verborgen.' + shown: '§6De scorebord van {player_name} is getoond.' + own: + hidden: '§6Je scorebord is verborgen.' + shown: '§6Je scorebord is zichtbaar.' + help: + header: '§6§lBeautyQuests — Help' + create: '§6/{label} create: §eCreate a quest.' + edit: '§6/{label} edit: §eBewerk een quest.' + remove: '§6/{label} remove <id>: §eVerwijder een quest met een opgegeven id of klik op de NPC wanneer je geed id gedefinieerd.' + finishAll: '§6/{label} finishAll <player>: §eVoltooi alle quests van een speler.' + setStage: '§6/{label} setStage <player> <id> [nieuwe branch] [nieuwe fase]: §eSla de huidige fase over/start de vertakking/set een fase in voor een branche.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eStart de eerstvolgende conversatie voor een NPC status of het startgesprek voor een quest.' + resetPlayer: '§6/{label} resetPlayer <player>: §eVerwijder alle informatie van een speler.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <player> [id]: §eVerwijder informatie van een quest voor een speler.' + seePlayer: '§6/{label} seePlayer <player>: §eBekijk informatie van een speler.' + reload: '§6/{label} reload: §eSlaat op en herlaad alle configuraties en bestanden. (§cdeprecated§)' + start: '§6/{label} start <player> [id]: §eForceer het starten van een quest.' + setItem: '§6/{label} setItem <talk|launch>: §eOpslaan van het hologram item.' + setFirework: '§6/{label} setFirework: §eBewerk het standaard einde van vuurwerk.' + adminMode: '§6/{label} adminMode: §eSchakel de Admin modus. aan/uit (Handig voor het weergeven van kleine log berichten.)' + version: '§6/{label} versie: §eBekijk de huidige versie van de plugin.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eDownload een standaard vertaling-file.' + save: '§6/{label} save: §eLaat een handmatige plugin opslaan.' + list: '§6/{label} list: §eBekijk de lijst van alle quests. (Alleen voor ondersteunde versies).' + typeCancel: '§aTyp "cancel" om terug te gaan naar de laatste tekst.' + editor: + blockAmount: '§aTyp de hoeveelheid blokken in:' + blockName: '§aTyp de naam van het blok:' + blockData: '§aTyp de blokdata (beschikbare blokdatas: §7{available_datas}§a):' + blockTag: '§aTyp de blok-tag (beschikbare tags: §7{available_tags}§a):' + typeBucketAmount: '§aTyp hoeveel emmers er gevuld moeten worden:' + typeDamageAmount: 'Typ de hoeveelheid schade die spelers moeten aanrichten:' + goToLocation: '§aGa naar de gewenste locatie voor het speelveld.' + typeLocationRadius: '§aTyp de vereiste afstand vanaf de locatie:' + typeGameTicks: '§aTyp de vereiste gameticks:' + already: '§cJe bent al in de editor.' + stage: + location: + typeWorldPattern: '§aSchrijf een regex voor wereldnamen:' + enter: + title: '§6~ Editor Modus ~' + subtitle: '§6Typ "/quests exitEditor" om de editor geforceerd te stoppen.' + list: '§c⚠️ §7Je hebt een "list" editor geopend. Gebruik "add" om lijnen toe te voegen. Raadpleeg "help" (zonder slash) voor hulp. §e§lTyp "close" om de editor af te sluiten.' + chat: '§6Je bent momenteel in de Editor Modus. Typ "/quests exitEditor" om de editor gedwongen te verlaten. (Hoewel dit niet is aanbevolen, overweeg het gebruik van commando''s zoals "close" of "cancel" om terug te komen op de vorige inventaris.)' + npc: + enter: '§aKlik op een NPC, of typ "annuleren".' + choseStarter: '§aKies de NPC waar spelers de quest beginnen.' + notStarter: '§cDeze NPC is geen starter van een quest.' + text: + argNotSupported: '§cHet argument {arg} wordt niet ondersteund.' + chooseLvlRequired: '§aTyp het vereiste aantal levels:' + chooseJobRequired: '§aTyp de naam van de gewenste taak:' + choosePermissionRequired: '§aTyp de vereiste rechten om de quest te starten:' + choosePermissionMessage: '§aJe kunt een afwijzend bericht kiezen als de speler niet de vereiste rechten heeft. (Wil je dit overslaan? Typ "null".)' + choosePlaceholderRequired: + identifier: '§aTyp de naam van de vereiste placeholder zónder percentage symbolen:' + value: '§aTyp de vereiste waarde van de placeholder §e%§e{placeholder}§e%§a:' + chooseSkillRequired: '§aTyp de naam van de vereiste vaardigheid:' + chooseMoneyRequired: '§aTyp het minimale bedrag:' + reward: + permissionName: '§aTyp de naam de machtiging.' + permissionWorld: '§aTyp de wereld waarin de rechten worden bewerkt of "null" als je deze globaal wilt instellen.' + money: '§aTyp het geldbedrag dat de speler ontvangt:' + wait: '§aTyp het aantal game ticks dat de speler moet wachten: (1 seconde = 20 game ticks)' + random: + min: '§aTyp het minimaal aantal beloningen dat de speler krijgt (inclusief).' + max: '§aTyp het maximaal aantal beloningen dat de speler krijgt (inclusief).' + chooseObjectiveRequired: '§aTyp de naam van het doel.' + chooseObjectiveTargetScore: '§aWelke score moet men halen voor het doel?' + chooseRegionRequired: '§aTyp de naam van de vereiste regio (je moet in dezelfde wereld zijn).' + chooseRequirementCustomReason: 'Typ de reden voor dit vereiste. Als de speler niet aan de vereiste voldoet, maar probeert toch de quest te starten, zal dit bericht verschijnen in de chat.' + chooseRequirementCustomDescription: 'Type de beschrijving voor dit vereiste. Dit is de quest-beschrijving die je terugziet in het menu.' + chooseRewardCustomDescription: 'Typ de beschrijving voor de beloning. Dit verschijnt in de beschrijving van de quest in het menu.' + selectWantedBlock: '§aKlik met de stok op het gewenste blok voor deze fase van de quest.' + itemCreator: + itemType: '§aTyp de naam van het gewenste item type:' + itemAmount: '§aTyp de hoeveelheid items:' + itemName: '§aTyp de naam van het item:' + itemLore: '§aWijzig de lore van het item: (Schrijf "help" voor hulp.)' + unknownItemType: '§cOnbekend item type.' + invalidItemType: '§cOngeldig item type. (Het item kan geen blok zijn.)' + unknownBlockType: Onbekend blok-type + invalidBlockType: Ongeldige blok-type + dialog: + syntaxMessage: '§cCorrecte syntax: {command} <message>' + syntaxRemove: '§cCorrecte syntax: remove <id>' + player: '§aBericht "§7{msg}§a" toegevoegd aan de speler.' + npc: '§aBericht "§7{msg}§a" toegevoegd aan de NPC.' + noSender: '§aBericht "§7{msg}§a" toegevoegd zonder afzender.' + messageRemoved: '§aBericht "§7{msg}§a" verwijderd.' + edited: '§aBericht "§7{msg}§a" aangepast.' + soundAdded: '§aGeluid "§7{sound}§a" toegevoegd voor het bericht "§7{msg}§a".' + cleared: '§aVerwijderd §2§l{amount}§a bericht(en).' + help: + header: '§6§lBeautyQuests — Conversatie-editor help' + npc: '§6npc <message>: §eVoeg een bericht toe dat de NPC zegt.' + player: '§6player <message>: §eVoeg een bericht toe dat de speler zegt.' + nothing: '§6noSender <message>: §eVoeg een bericht toe zonder afzender.' + remove: '§6remove <id>: §eVerwijder een bericht.' + list: '§6list: §eBekijk alle berichten.' + npcInsert: '§6npc <message>: §eTyp een bericht dat de NPC zegt.' + playerInsert: '§6playerInsert <id> <message>: §eTyp een bericht dat de speler zegt.' + nothingInsert: '§6Niet-invoegen <id> <message>: §eTyp een bericht zonder een voorvoegsel.' + edit: '§6edit <id> <message>: §eBewerk een bericht.' + addSound: '§6addSound <id> <sound>: §eVoeg een geluid toe aan een bericht.' + clear: '§6clear: §eVerwijder alle berichten.' + close: '§6close: §eValideer alle berichten.' + setTime: '§6setTime <id> <time>: §eStel de tijd in, in game ticks, voordat het volgende bericht automatisch wordt afgespeeld. (1 seconde = 20 game ticks.)' + npcName: '§6npcName [NPC-naam aanpassen]: §eStel (of reset naar standaard) aangepaste naam van de NPC in, in de conversatie.' + skippable: '§6skippable [true|false] §eStel in of men de conversatie mag skippen of niet' +inv: + details: + setPermReward: '§eBewerk rechten' + permission: + name: Kies rechten + perm: '§aRechten' + world: '§aWereld' + worldGlobal: '§b§lGlobaal' + remove: Verwijder rechten + removeLore: '§7Rechten zal van\n§7 worden afgenomen in plaats van gegeven.' + permissionList: + name: Rechten Lijst + removed: '§7Afgenomen: §6{permission_removed}' + world: '§eWereld: §6{permission_world}' +misc: + requirement: + permissions: '§3Recht(en) vereist' + amounts: + permissions: '{permissions_amount} recht(en)' diff --git a/core/src/main/resources/locales/pl_PL.yml b/core/src/main/resources/locales/pl_PL.yml index 286bcfac..28a9aa96 100644 --- a/core/src/main/resources/locales/pl_PL.yml +++ b/core/src/main/resources/locales/pl_PL.yml @@ -1,799 +1,794 @@ --- -advancement: - finished: Zakończono - notStarted: Nie rozpoczęto -description: - requirement: - class: Klasa {class_name} - combatLevel: Poziom bojowy {short_level} - faction: Frakcja {faction_name} - jobLevel: Poziom {short_level} dla {job_name} - level: Poziom {short_level} - quest: Zakończ zadanie §e{quest_name} - skillLevel: Poziom {short_level} dla {skill_name} - title: '§8§lWymagania:' - reward: - title: '§8§lNagrody:' -indication: - cancelQuest: '§7Czy na pewno chcesz anulować zadanie {quest_name}?' - closeInventory: '§7Czy na pewno chcesz zamknąć GUI?' - removeQuest: '§7Czy na pewno chcesz usunąć zadanie {quest}?' - startQuest: '§7Czy chcesz rozpocząć zadanie {quest_name}?' -inv: - addObject: '§aDodaj obiekt' - block: - blockData: '§dBlockdata (zaawansowane)' - blockName: '§bWłasna nazwa bloku' - blockTag: '§dTag (zaawansowane)' - blockTagLore: Wybierz tag, który opisuje listę możliwych bloków. Tagi można dostosować za pomocą apacków. Listę tagów można znaleźć na wiki Minecraft. - material: '§eMateriał: {block_type}' - materialNotItemLore: Wybrany blok nie może być wyświetlany jako element. Nadal jest poprawnie przechowywany jako {block_material}. - name: Wybierz blok - blockAction: - location: '§eWybierz dokładną lokalizację' - material: '§eWybierz materiał bloku' - name: Wybierz akcję bloku - blocksList: - addBlock: '§aKliknij, aby dodać blok.' - name: Wybierz bloki - buckets: - name: Typ wiadra - cancel: '§c§lAnuluj' - cancelActions: - name: Anuluj akcje - checkpointActions: - name: Akcje punktu kontrolnego - chooseAccount: - name: Jakie konto? - chooseQuest: - menu: '§aQuests Menu' - menuLore: Pobiera cię do menu Zadań. - name: Wybór zadania - classesList.name: Lista klas - classesRequired.name: Wymagane klasy - command: - console: Konsola - delay: '§bOpóźnienie' - name: Komenda - parse: Parsetowe symbole zastępcze - value: '§eKomenda' - commandsList: - console: '§eKonsola: {command_console}' - name: Lista komend - value: '§Komenda: {command_label}' - confirm: - name: Jesteś pewien? - 'no': '§cAnuluj' - 'yes': '§aPotwierdź' - create: - NPCSelect: '§eWybierz lub utwórz NPC' - NPCText: '§eEdytuj okno dialogowe' - breedAnimals: '§aRozmnóż zwierzęta' - bringBack: '§aPrzynieś przedmioty' - bucket: '§aWypełnij wiadra' - cancelMessage: Anuluj wysyłanie - cantFinish: '§7Musisz utworzyć co najmniej jeden etap przed zakończeniem tworzenia misji!' - changeEntityType: '§eZmień typ obiektu/jednostki' - changeTicksRequired: '§eZmiana ticków jest wymagana' - craft: '§aStwórz przedmiot' - currentRadius: '§eObecna odległość: §6{radius}' - dealDamage: '§cZadaj obrażenia mobom' - death: '§cZgiń' - eatDrink: '§aZjedz lub pij jedzenie lub mikstury' - editBlocksMine: '§eEdytuj bloki do zniszczenia' - editBlocksPlace: '§eEdytuj bloki do postawienia' - editBucketAmount: '§eEdytuj ilość wiader do wypełnienia' - editBucketType: '§eEdytuj typ wiadra do wypełnienia' - editFishes: '§eEdytuj ryby do złowienia' - editItem: '§eEdytuj przedmioty do stworzenia' - editItemsToEnchant: '§eEdytuj przedmioty do zaczarowania' - editItemsToMelt: '§eEdytuj przedmioty do stopienia' - editLocation: '§eEdytuj lokalizację' - editMessageType: '§eEdytuj wiadomość do napisania' - editMobsKill: '§eEdytuj moby do zabicia' - editRadius: '§eEdytuj odległość od lokalizacji' - enchant: '§dZaklnij przedmioty' - findNPC: '§aZnajdź NPC' - findRegion: '§aZnajdź region' - fish: '§aZłap ryby' - hideClues: Ukryj cząsteczki i hologramy - ignoreCase: Ignoruj wielkość liter w wiadomości - interact: '§aInterakcja z blokiem' - killMobs: '§aZabij potwora' - leftClick: Musisz kliknąć lewym przyciskiem myszy - location: '§aIdź do lokalizacji' - melt: '§7Wytopione przedmioty' - mineBlocks: '§aZniszcz bloki' - mobsKillFromAFar: Należy zabić pociskiem - placeBlocks: '§aPołóż bloki' - playTime: '§eCzas gry' - preventBlockPlace: Zablokuj graczom możliwość niszczenia własnych bloków - replacePlaceholders: Zastąp {PLAYER} i placeholdery z PAPI - selectBlockLocation: '§eWybierz lokalizację bloku' - selectBlockMaterial: '§eWybierz materiał bloku' - selectItems: '§eEdytuj wymagane przedmioty' - selectItemsComparisons: '§eWybierz porównania przedmiotów (ZAAWANSOWANE)' - selectItemsMessage: '§eEdytuj wiadomość z pytaniem' - selectRegion: '§7Wybierz region' - stage: - dealDamage: - damage: '§eObrażenia' - targetMobs: '§cMoby do obrażeń' - death: - anyCause: Każda przyczyna zgonu - causes: '§aUstaw śmierć powoduje §d(ADVANCED)' - setCauses: '{causes_amount} przyczyna zgonu' - eatDrink: - items: '§eEdytuj przedmioty do jedzenia lub picia' - location: - worldPattern: '§aUstaw wzór nazwy świata §d(ADVANCED)' - worldPatternLore: Jeśli chcesz, aby etap został ukończony dla dowolnego świata pasującego do określonego wzoru, wprowadź wyrażenie regularne tutaj tutaj. - stageCreate: '§aUtwórz nowy krok' - stageDown: Przesuń w dół - stageRemove: '§cUsuń ten krok' - stageStartMsg: '§eEdytuj wiadomość początkową' - stageType: '§7Rodzaj sceny: §e{stage_type}' - stageUp: Przesuń w górę - talkChat: '§aNapisz na czacie' - tameAnimals: '§aOswój zwierzęta' - toggleRegionExit: Przy wyjściu - damageCause: - name: Powód obrażeń - damageCausesList: - name: Lista przyczyn obrażeń - details: - actions: '{amount} akcja(j)' - auto: Uruchom automatycznie po zalogowaniu - autoLore: Jeśli włączone, zadanie zostanie uruchomione automatycznie, gdy gracz dołączy do serwera po raz pierwszy. - bypassLimit: Nie licz limitu zadań - bypassLimitLore: Jeśli włączone, zadanie będzie uruchamialne, nawet jeśli gracz osiągnie maksymalną liczbę rozpoczętych zadań. - cancelRewards: '§cAnuluj akcje' - cancelRewardsLore: Akcje wykonywane, gdy gracze anulują to zadanie. - cancellable: Możliwość anulowania przez gracza - cancellableLore: Pozwala graczowi anulować zadanie przez menu zadań. - createQuestLore: Musisz zdefiniować nazwę zadania. - createQuestName: '§lUtwórz zadanie' - customConfirmMessage: '§eEdytuj wiadomość potwierdzającą zadanie' - customConfirmMessageLore: Wiadomość wyświetlana w interfejsie potwierdzania, gdy gracz ma wkrótce rozpocząć zadanie. - customDescription: '§eEdytuj opis zadania' - customDescriptionLore: Opis pokazany pod nazwą zadania w GUI. - customMaterial: '§eEdytuj przedmiot zadania' - customMaterialLore: Przedmiot reprezentujący to zadanie znajduje się w menu zadań. - defaultValue: '§8(domyślna wartość)' - editQuestName: '§lEdytuj zadanie' - editRequirements: '§eEdytuj wymagania' - editRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, zanim będzie mógł on rozpocząć zadanie. - endMessage: '§eEdytuj wiadomość końcową' - endMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. - endSound: '§eEdytuj dźwięk końca' - endSoundLore: Dźwięk, który będzie odtwarzany na końcu zadania. - failOnDeath: Niepowodzenie podczas śmierci - failOnDeathLore: Czy zadanie zostanie anulowane po śmierci gracza? - firework: '§dKończenie fajerwerków' - fireworkLore: Fajerwerk wystrzelony po zakończeniu misji - fireworkLoreDrop: Upuść niestandardowe fajerwerki tutaj - hideNoRequirementsItem: Ukryj gdy wymagania nie są spełnione - hideNoRequirementsItemLore: Jeśli włączone, zadanie nie będzie wyświetlane w Menu Zadań, gdy wymagania nie zostaną spełnione. - hologramLaunch: '§eEdytuj hologram - "launch"' - hologramLaunchLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz może rozpocząć zadanie. - hologramLaunchNo: '§eEdytuj hologram - "launch unavailable"' - hologramLaunchNoLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz nie może rozpocząć zadania. - hologramText: '§eTekst Hologramu' - hologramTextLore: Tekst wyświetlany na hologramie nad głową startowego NPC. - keepDatas: Zachowaj dane graczy - keepDatasLore: 'Wymuś, aby plugin zachował dane graczy, nawet jeśli etapy zostały edytowane. §c§lOSTRZEŻENIE §c- włączenie tej opcji może zepsuć dane Twoich gracza.' - loreReset: '§e§lPostęp wszystkich graczy zostanie zresetowany' - multipleTime: - itemLore: Czy zadanie można wykonać kilkakrotnie? - itemName: Włącz/wyłącz możliwość powtarzania - name: Szczegóły ostatniego zadania - optionValue: '§8Wartość: §7{value}' - questName: '§a§lEdytuj nazwę zadania' - questNameLore: Nazwa musi być ustawiona, aby ukończyć tworzenie zadania. - questPool: '§ePula Zadań' - questPoolLore: Dołącz to zadanie do puli zadań - removeItemsReward: '§eUsuń przedmioty z ekwipunku' - requiredParameter: '§7Wymagany parametr' - requirements: '{amount} wymaganie(a)' - rewards: '{amount} nagroda(ód)' - rewardsLore: Akcje wykonywane po zakończeniu misji. - scoreboardItem: Włącz tabelę wyników - scoreboardItemLore: Jeśli wyłączone, zadanie nie będzie śledzone przez tablicę wyników. - selectStarterNPC: '§e§lWybierz NPC startowego' - selectStarterNPCLore: Kliknięcie na wybranego NPC rozpocznie zadanie. - selectStarterNPCPool: '§c⚠ Wybrana pula zadań' - setCheckpointReward: '§eEdytuj nagrody punktu kontrolnego' - setItemsRewards: '§eEdytuj nagrody przedmiotowe' - setMoneyReward: '§eEdytuj nagrodę pieniężną' - setPermReward: '§eEdytuj uprawnienia' - setRewardStopQuest: '§cZatrzymaj zadanie' - setRewardsRandom: '§dLosowe nagrody' - setRewardsWithRequirements: '§eNagrody z wymaganiami' - setTitleReward: '§eEdytuj tytuł nagrody' - setWaitReward: '§eEdytuj nagrodę "czekania"' - setXPRewards: '§eEdytuj nagrody doświadczenia' - startDialog: '§eEdytuj okno startowe' - startDialogLore: Okno dialogowe, które będzie wyświetlane przed rozpoczęciem zadań, kiedy gracze klikną na NPC Startowego. - startMessage: '§eEdytuj wiadomość początkową' - startMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. - startRewards: '§6Nagrody startowe' - startRewardsLore: Akcje wykonywane w momencie rozpoczęcia misji. - startableFromGUI: Możliwość uruchomienia z GUI - startableFromGUILore: Pozwala graczowi rozpocząć zadanie z menu zadań. - timer: '§bZrestartuj zegar' - timerLore: Czas zanim gracz może ponownie rozpocząć zadanie. - visibility: '§bWidoczność Zadań' - visibilityLore: Wybierz, w których zakładkach menu będą wyświetlane zadania, a jeśli zadanie będzie widoczne na mapach dynamicznych. - editTitle: - fadeIn: '§aCzas pojawiania' - fadeOut: '§aCzas zanikania' - name: Edytuj tytuł - stay: '§bCzas trwania' - subtitle: '§ePodtytuł' - title: '§6Tytuł' - entityType: - name: Wybierz typ jednostki - equipmentSlots: - name: Miejsca na wyposażenie - factionsList.name: Lista frakcji - factionsRequired.name: Wymagane frakcje - itemComparisons: - bukkit: Porównanie natywne Bukkit - bukkitLore: Używa domyślnego systemu porównywania przedmiotów Bukkit. Porównuje materiał, trwałość, tagi nbt... - customBukkit: Porównanie natywne Bukkit - NO NBT - customBukkitLore: Używa domyślnego systemu porównywania przedmiotów Bukkit, ale usuwa znaczniki NBT. Porównuje materiał, trwałość... - enchants: Zaklęcia przedmiotów - enchantsLore: Porównuje zaklęcia przedmiotów - itemLore: Opis przedmiotu - itemLoreLore: Porównuje opisy przedmiotów - itemName: Nazwa przedmiotu - itemNameLore: Porównuje nazwy przedmiotów - itemsAdder: ItemsAdder - itemsAdderLore: Porównuje ID ItemsAdder'a - material: Materiał przedmiotu - materialLore: Porównuje materiał przedmiotu (tj. kamień, żelazny miecz...) - name: Porównania pozycji - repairCost: Koszt naprawy - repairCostLore: Porównuje koszty naprawy pancerza i mieczy - itemCreator: - isQuestItem: '§bPrzedmiot misji:' - itemFlags: Przełącz flagi przedmiotu - itemLore: '§bLore przedmiotu' - itemName: '§bNazwa przedmiotu' - itemType: '§bTyp przedmiotu' - name: Kreator przedmiotów - itemSelect: - name: Wybierz przedmiot - itemsSelect: - name: Edytuj przedmioty - none: '§aPrzenieś tutaj przedmiot lub kliknij, aby otworzyć edytor przedmiotu.' - listAllQuests: - name: Zadania - listBook: - noQuests: Nie utworzono wcześniej żadnych zadań. - questMultiple: Kilka razy - questName: Nazwa - questRewards: Nagrody - questStages: Etapy - questStarter: Starter - requirements: Wymagania - listPlayerQuests: - name: 'Zadania {player_name}' - listQuests: - canRedo: '§3§oMożesz ponownie uruchomić to zadanie!' - finished: Ukończone zadania - inProgress: Aktywne zadania - loreCancelClick: '§cAnuluj zadanie' - loreDialogsHistoryClick: '§7Zobacz okna dialogowe' - loreStart: '§a§oKliknij aby rozpocząć zadanie' - loreStartUnavailable: '§c§oNie spełniasz wymagań do rozpoczęcia zadania' - notStarted: Nierozpoczęte zadania - timeToWaitRedo: '§3§oMożesz ponownie uruchomić to zadanie za {time_left}.' - timesFinished: '§3Zadanie wykonano {times_finished} razy.' - mobSelect: - boss: '§6Wybierz Bossa' - bukkitEntityType: '§eWybierz typ jednostki' - epicBoss: '§6Wybierz Epickiego Bossa' - mythicMob: '§6Wybierz Mitycznego moba' - name: Wybierz typ moba - mobs: - name: Wybierz moby - none: '§aKliknij, aby dodać moba.' - setLevel: Ustaw minimalny poziom - npcCreate: - move: - itemLore: '§aZmień lokalizację NPC.' - itemName: '§ePrzenieś' - moveItem: '§a§lPotwierdź miejsce' - name: Utwórz NPC - setName: '§eEdytuj nazwę NPC' - setSkin: '§eEdytuj skórkę NPC' - setType: '§eEdytuj typ NPC' - npcSelect: - createStageNPC: '§eUtwórz NPC' - name: Wybrać czy stworzyć? - selectStageNPC: '§eWybierz istniejącego NPC' - particleEffect: - color: '§bKolor cząsteczek' - name: Utwórz efekt cząsteczek - shape: '§dKształt cząsteczek' - type: '§eTyp cząsteczek' - particleList: - colored: Kolorowe cząstki - name: Lista cząsteczek - permission: - name: Wybierz uprawnienie - perm: '§aUprawnienia' - remove: Usuń uprawnienie - removeLore: '§7Uprawnienie zostanie odebrane\n§7zamiast dodane.' - world: '§aŚwiat' - worldGlobal: '§b§lGlobalny' - permissionList: - name: Lista uprawnień - removed: '§eOdebrane: §6{permission_removed}' - world: '§eŚwiat: §6{permission_world}' - poolCreation: - avoidDuplicates: Unikaj duplikatów - avoidDuplicatesLore: '§8> §7Spróbuj unikać wykonywania\n tego samego zadania' - hologramText: '§ePool niestandardowy hologram' - maxQuests: '§aMaks. zadań' - name: Tworzenie puli zadań - questsPerLaunch: '§8Zadania podane podczas startu' - redoAllowed: Jest dozwolone ponawianie - requirements: '§bWymagania do rozpoczęcia zadania' - time: '§bUstaw czas pomiędzy zadaniami' - poolsList.name: Pule zadań - poolsManage: - choose: '§e> §6§oWybierz tę pulę §e<' - create: '§aUtwórz pulę zadań' - edit: '§e> §6§oEdytuj pulę... §e<' - itemName: '§aPula #{pool}' - name: Pula Zadań - poolAvoidDuplicates: '§8Unikaj duplikatów: §7{pool_duplicates}' - poolHologram: '§8Tekst hologramu: §7{pool_hologram}' - poolMaxQuests: '§8Maks. zadań: §7{pool_max_quests}' - poolQuestsList: '§7{pool_quests_amount} §8zadań(ia): §7{pool_quests}' - poolQuestsPerLaunch: '§8Zadania podane podczas startu: §7{pool_quests_per_launch}' - poolRedo: '§8Można wykonywać ponownie ukończone zadania: §7{pool_redo}' - poolTime: '§8Czas pomiędzy zadaniami: §7{pool_time}' - requirements: - name: Wymagania - rewards: - commands: 'Komendy: {amount}' - name: Nagrody - random: - minMax: Edytuj min. i maks. - rewards: Edytuj nagrody - rewardsWithRequirements: - name: Nagrody z wymaganiami - search: '§e§lSzukaj' - stageEnding: - command: '§eEdytuj wykonywaną komendę' - locationTeleport: '§eEdytuj lokalizację teleportu' - stages: - branchesPage: '§dEtapy gałęzi' - descriptionTextItem: '§eEdytuj opis' - endingItem: '§eEdytuj końcowe nagrody' - laterPage: '§ePoprzednia strona' - name: Stwórz etapy - newBranch: '§ePrzejdź do nowej gałęzi' - nextPage: '§eNastępna strona' - previousBranch: '§eWróć do poprzedniej gałęzi' - regularPage: '§aZwykłe etapy' - validationRequirements: '§eWymagania sprawdzające' - validationRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, który chce ukończyć poziom. Bez tego poziom nie może zostać ukończony. - validate: '§b§lPotwierdź' - visibility: - finished: 'Zakładka menu "Zakończone"' - inProgress: 'Zakładka menu "W toku"' - maps: Mapy (takie jak dynmapa lub BlueMap) - name: Widoczność zadań - notStarted: 'Zakładka menu "Nie rozpoczęte"' -misc: - amount: '§eIlość: {amount}' - amounts: - comparisons: '{comparisons_amount} comparaison(s)' - dialogLines: '{lines_amount} wiersze' - items: '{items_amount} element(ów)' - mobs: '{mobs_amount} mobów' - permissions: '{permissions_amount} uprawnień' - and: i - bucket: - lava: Wiadro lawy - milk: Wiadro mleka - snow: Śnieżne wiadro - water: Wiadro wody - click: - left: Kliknij lewym przyciskiem myszy - middle: Kliknij środkowo - right: Prawy przycisk myszy - shift-left: Shift i kliknięcie lewym przyciskiem myszki - shift-right: Shift i kliknięcie prawym przyciskiem myszki - comparison: - different: inne niż {number} - equals: równe {number} - greater: ściśle więcej niż {number} - greaterOrEquals: więcej niż {number} - less: ściśle mniej niż {number} - lessOrEquals: mniej niż {number} - disabled: Wyłączone - enabled: Włączone - entityType: '§eTyp jednostki: {entity_type}' - entityTypeAny: '§eDowolny obiekt/jednostka' - format: - prefix: '§6<§e§lZadania§r§6> §r' - hologramText: '§8§lNPC zadań' - 'no': 'Nie' - notSet: '§cnie ustawione' - or: lub - poolHologramText: '§eNowe zadanie jest dostępne!' - questItemLore: '§e§oPrzedmiot zadań' - removeRaw: Usuń - requirement: - class: '§bKlasa(y) wymagane' - combatLevel: '§bWymagany poziom walki' - equipment: '§eWymagane Wyposażenie' - experienceLevel: '§bWymagane poziomy doświadczenia' - faction: '§bFrakcja(e) wymagana(e)' - jobLevel: '§bWymagany poziom pracy' - logicalOr: '§dLogiczne LUB (wymagania)' - mcMMOSkillLevel: '§dWymagany poziom umiejętności' - money: '§dWymagane pieniądze' - permissions: '§3Uprawnienie(a) jest/są wymagane' - placeholder: '§bWymagana jest wartość Placeholdera' - quest: '§aZadanie jest wymagane' - region: '§dRegion jest wymagany' - scoreboard: '§dWymagany wynik' - skillAPILevel: '§bWymagany poziom SkillAPI' - reset: Reset - stageType: - Bucket: Wypełnij wiadro - Craft: Wytwórz przedmiot - Enchant: Zaklinaj przedmioty - Fish: Złap ryby - Melt: Elementy stopu - breedAnimals: Rozmnóż zwierzęta - chat: Napisz na czacie - dealDamage: Zadaj obrażenia - die: Giń - eatDrink: Jedz lub napój - interact: Interakcja z blokiem - items: Przynieś przedmioty z powrotem - location: Znajdź lokalizację - mine: Zniszcz bloki - mobs: Zabij potwory - npc: Znajdź NPC - placeBlocks: Postaw bloki - playTime: Czas w grze - region: Znajdź region - tameAnimals: Oswój zwierzęta - ticks: '{ticks} ticków' - time: - days: '{days_amount} dni' - hours: '{hours_amount} godzin' - lessThanAMinute: mniej niż minutę - minutes: '{minutes_amount} minut' - weeks: '{weeks_amount} tygodni' - unknown: nieznany - 'yes': 'Tak' msg: + quest: + finished: + base: '§aGratulacje! Ukończyłeś/aś zadanie §e{quest_name}§a!' + obtain: '§aOtrzymujesz {rewards}!' + started: '§aRozpocząłeś zadanie §r§e{quest_name}§o§6!' + created: '§aGraulacje! Stworzyłeś zadanie §e{quest}§a które zawiera {quest_branches} wielokrotnych wyborów!' + edited: '§aGratulacje! Zmodyfikowałeś zadanie§e{quest}§a które zawiera {quest_branches} wielokrotnych wyborów!' + createCancelled: '§cTworzenie lub modyfikowanie zostało anulowane przez inny plugin!' + cancelling: '§cAnulowano proces tworzenia misji.' + editCancelling: '§cAnulowano proces edytowania misji.' + invalidID: '§cZadanie o id {quest_id} nie istnieje' + invalidPoolID: '§cPula {pool_id} nie istnieje.' + alreadyStarted: '§cJuż rozpocząłeś te zadanie!' + notStarted: '§cObecnie nie wykonujesz tego zadania.' + quests: + maxLaunched: '§cNie możesz mieć aktywnych więcej niż {quests_max_amount} zadań jednocześnie...' + updated: '§7Zadanie §e{quest_name}§7 zostało zaktualizowane.' + checkpoint: '§7Osiągnięto punkt kontrolny misji!' + failed: '§cNie udało Ci się wykonać zadania {quest_name}...' + pools: + noTime: '§cMusisz poczekać {time_left} przed wykonaniem kolejnego zadania.' + allCompleted: '§7Wykonałeś/aś wszystkie zadania!' + noAvailable: '§7Nie ma więcej dostępnych zadań...' + maxQuests: '§cNie możesz mieć aktywnych więcej niż {pool_max_quests} zadań jednocześnie...' + questItem: + drop: '§cNie możesz wyrzucić przedmiotu misji!' + craft: '§cNie możesz użyć przedmiotu misji do stworzenia innych przedmiotów!' + eat: '§cNie możesz zjeść przedmiotu misji!' + stageMobs: + listMobs: '§aMusisz zabić {mobs}' + writeNPCText: '§aNapisz wiadomość, która została powiedziana graczowi przez NPC: (Wpisz "help" żeby otrzymać pomoc.)' + writeRegionName: '§aNapisz nazwę regionu wymaganego dla tego etapu:' + writeXPGain: '§aNapisz liczbę punktów doświadczenia jaką otrzyma gracz: (Poprzednia wartość: {xp_amount})' + writeMobAmount: '§aNapisz liczbę potworów do zabicia:' + writeMobName: '§aNapisz niestandardową nazwę potwora do zabicia:' + writeMessage: '§aNapisz wiadomość, która zostanie wysłana graczowi' + writeStartMessage: '§aNapisz wiadomość która będzie się wyświetlać na początku zadania, wpisz "null" aby pozostawić domyślną, wpisz "none" aby zostawić puste:' + writeEndSound: '§aWpisz nazwę dźwięku, który usłyszy gracz na końcu zadania, wpisz "null" aby pozostawić domyślny dźwięk lub "none", aby pozostawić puste:' + writeDescriptionText: '§aNapisz tekst, który opisuje cel tego etapu:' + writeStageText: '§aNapisz tekst, który zostanie wysłany do gracza na początku tego etapu:' + moveToTeleportPoint: '§aUdaj się do poszukiwanej lokalizacji.' + writeNpcName: '§aNapisz nazwę NPC' + writeNpcSkinName: '§aNapisz nazwę skina NPC' + writeQuestName: '§aNapisz nazwę zadania' + writeHologramText: '§aNapisz tekst hologramu: (Napisz "none" jeśli nie chcesz hologramu, a "null" jeśli chcesz domyślną wiadomość)' + writeQuestTimer: '§aNapisz wymagany czas (w minutach) przed ponownym uruchomieniem zadania: (Napisz "null" jeśli chcesz ustawić domyślną wartość)' + writeConfirmMessage: '§aNapisz wiadomość potwierdzającą w momencie kiedy gracz rozpoczyna zadanie: (Napisz "null" jeśli chcesz użyć domyślnej wiadomości)' + writeQuestDescription: '§aNapisz opis zadania, który zostanie wyświetlony w GUI zadań gracza.' + writeQuestMaterial: '§aNapisz typ przedmiotu zadania.' + requirements: + quest: '§cMusisz ukończyć zadanie §e{quest_name}§c!' + level: '§cMusisz mieć {long_level} poziom!' + job: '§cMusisz mieć {long_level} poziom Twojej pracy §e{job_name}!' + skill: '§cMusisz mieć {long_level} poziom umiejętności §e{skill_name}!' + combatLevel: '§cMusisz mieć {long_level} poziom walki!' + money: '§cMusisz posiadać {money}!' + waitTime: '§cMusisz poczekać {time_left} zanim będziesz mógł ponownie uruchomić to zadanie!' + experience: + edited: '§aZmieniłeś zdobywane doświadczenie z {old_xp_amount} na {xp_amount} punktów.' + selectNPCToKill: '§aWybierz NPC do zabicia.' + regionDoesntExists: '§cRegion o takie nazwie nie istnieje (musisz być w tym samym świecie).' + npcDoesntExist: '§cNPC z id {npc_id} nie istnieje' + number: + negative: '§cMusisz wprowadzić liczbę dodatnią!' + zero: '§cMusisz podać liczbę inną od 0!' + invalid: '§c{input} nie jest prawidłową liczbą.' + notInBounds: '§cWartość, którą wpiszesz musi mieścić się w zakresie od {min} do {max}' + errorOccurred: '§cWystąpił błąd, skontaktuj się z administratorem! §4§lKod błędu: {error}' + indexOutOfBounds: '§cLiczba {index} jest poza granicami! Musi być pomiędzy {min} a {max}.' + invalidBlockData: '§cBlokada danych {block_data} jest nieprawidłowa lub niezgodna z blokiem {block_material}.' + invalidBlockTag: '§cNiedostępny tag bloku {block_tag}.' bringBackObjects: Przynieś mnie z powrotem {items}. + inventoryFull: '§cTwój ekwipunek jest pełny, przedmiot został wyrzucony na podłogę.' + versionRequired: 'Wymagana wersja: §l{version}' + restartServer: '§7Uruchom ponownie serwer, aby zobaczyć zmiany.' + dialogs: + skipped: '§8Dialog pominięty.' + tooFar: '§7§oJesteś za daleko od {npc_name}...' command: - adminModeEntered: '§aWłączyłeś/aś tryb administratora.' - adminModeLeft: '§aWyłączyłeś/aś tryb administratora.' - backupCreated: '§6Pomyślnie utworzyłeś kopie zapasowe wszystkich zadań i informacji o graczach.' - backupPlayersFailed: '§cTworzenie kopii zapasowej dla wszystkich graczy nie powiodło się.' - backupQuestsFailed: '§cTworzenie kopii zapasowej dla wszystkich zadań nie powiodło się.' - cancelQuest: '§6Anulowałeś zadanie {quest}.' - cancelQuestUnavailable: '§cZadanie {quest} nie może zostać anulowane.' + downloadTranslations: + syntax: '§cMusisz określić język do pobrania. Przykład: "/quests downloadTranslations en_US".' + notFound: '§cJęzyk {lang} nie został znaleziony dla wersji {version}. .' + exists: '§cPlik {file_name} już istnieje. Dołącz "-overwrite" do swojej komendy aby ją nadpisać. (/quests downloadTranslations <lang> -overwrite)' + downloaded: '§aJęzyk {lang} został pobrany! §7Musisz teraz edytować plik "/plugins/BeautyQuests/config.yml" aby zmienić wartość §ominecraftTranslationsFile§7 na {lang}, a następnie zrestartować serwer.' checkpoint: noCheckpoint: '§cNie znaleziono punktu kontrolnego dla zadania {quest}.' questNotStarted: '§cNie wykonujesz tego zadania.' - downloadTranslations: - downloaded: '§aJęzyk {lang} został pobrany! §7Musisz teraz edytować plik "/plugins/BeautyQuests/config.yml" aby zmienić wartość §ominecraftTranslationsFile§7 na {lang}, a następnie zrestartować serwer.' - exists: '§cPlik {file_name} już istnieje. Dołącz "-overwrite" do swojej komendy aby ją nadpisać. (/quests downloadTranslations <lang> -overwrite)' - notFound: '§cJęzyk {lang} nie został znaleziony dla wersji {version}. .' - syntax: '§cMusisz określić język do pobrania. Przykład: "/quests downloadTranslations en_US".' - help: - adminMode: '§6/{label} adminMode: §ePrzełącz tryb administratora. (Przydatne do wyświetlania małych wiadomości dziennika.)' - create: '§6/{label} create: §eUtwórz zadanie.' - downloadTranslations: '§6/{label} downloadTranslations <język>: §ePobiera plik z tłumaczeniem vanilla' - edit: '§6/{label} edit: §eEdytuj zadanie.' - finishAll: '§6/{label} finishAll <player>: §eZakończ wszystkie zadania gracza.' - header: '§6§lBeautyQuests - Pomoc' - list: '§6/{label} list: §eZobacz listę zadań. (Tylko dla obsługiwanych wersji.)' - reload: '§6/{label} reload: §eZapisz i odśwież wszystkie konfiguracje i pliki. (§cprzestarzałe§e)' - remove: '§6/{label} remove <id>: §eUsuń zadanie z podanym id lub kliknij na NPC jeśli nie zdefiniowano.' - resetPlayer: '§6/{label} resetPlayer <gracz>: §eUsuń wszystkie informacje o graczu.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <gracz> [id]: §eUsuń informacje o zadaniu danego gracza.' - save: '§6/{label} save: §eZapisz ręcznie plugin (postęp/zmiany).' - seePlayer: '§6/{label} SeePlayer <gracz>: §eWyświetl informacje o graczu.' - setFirework: '§6/{label} setFirework: §eEdytuj domyślny końcowy efekt fajerwerki.' - setItem: '§6/{label} setItem <talk|launch>: §eZapisz hologram.' - setStage: '§6/{label} setStage <gracz> <id> [nowa gałąź] [nowy etap]: §ePomiń bieżący etap/uruchom gałąź/ustaw etap dla gałęzi.' - start: '§6/{label} start <gracz> [id]: §eWymuś rozpoczęcie zadania.' - startDialog: '§7/{label} startDialog <player> <quest id>: §eUruchamia oczekujące okno dialogowe dla etapu NPC lub startowego okna dialogowego dla zadania.' - version: '§6/{label} version: §eZobacz aktualną wersję pluginu.' + setStage: + branchDoesntExist: '§cGałąź z id {branch_id} nie istnieje' + doesntExist: '§cEtap z id {stage_id} nie istnieje' + next: '§aEtap został pominięty.' + nextUnavailable: '§cOpcja pominięcia nie jest dostępna kiedy gracz jest na końcu gałęzi.' + set: '§aEtap {stage_id} został uruchomiony.' + startDialog: + impossible: '§cNie można teraz uruchomić dialogu.' + noDialog: '§cGracz nie ma oczekującego dialogu.' + alreadyIn: '§cGracz jest już w trakcie dialogu.' + success: '§aRozpoczęto dialog dla gracza {player} w misji {quest}!' invalidCommand: simple: '§cTa komenda nie istnieje, napisz §ehelp§c.' itemChanged: '§aElement został edytowany. Zmiany będą dostępne po ponownym uruchomieniu.' itemRemoved: '§aHologram został usunięty.' - leaveAll: '§aWymusiłeś/aś koniec {success} zadań. Błędy: {errors}' removed: '§aZadanie {quest_name} zostało pomyślnie usunięte.' + leaveAll: '§aWymusiłeś/aś koniec {success} zadań. Błędy: {errors}' resetPlayer: player: '§6Wszystkie informacje o twoich zadaniach {quest_amount} zostały usunięte przez {deleter_name}.' remover: '§6{quest_amount} informacja(e) o zadaniu (oraz {quest_pool}puli) {player} zostało usunięte.' - resetPlayerPool: - full: '§aZresetowałeś dane puli {pool} {player}.' - timer: '§aZresetowałeś {pool} zegar puli {player}.' resetPlayerQuest: player: '§6Wszystkie informacje o zadaniu {quest} zostały usunięte przez {deleter_name}.' remover: '§6{player} informacja(e/i) o zadaniu {quest} została(y) usunięta(e).' resetQuest: '§6Usunięto dane zadania dla {player_amount} graczy.' - scoreboard: - hidden: '§6Tablica wyników gracza {player_name} została ukryta.' - lineInexistant: '§cWiersz {line_id} nie istnieje.' - lineRemoved: '§6Pomyślnie usunąłeś/aś wiersz {line_id}.' - lineReset: '§6Pomyślnie zresetowałeś/aś wiersz {line_id}.' - lineSet: '§6Pomyślnie edytowałeś/aś linię {line_id}.' - own: - hidden: '§6Twoja tablica wyników jest teraz ukryta.' - shown: '§6Twoja tablica wyników pojawiła się ponownie.' - resetAll: '§6Pomyślnie zresetowałeś/aś tablicę wyników gracza {player_name}.' - shown: '§6Tablica wyników gracza {player_name} została pokazana.' - setStage: - branchDoesntExist: '§cGałąź z id {branch_id} nie istnieje' - doesntExist: '§cEtap z id {stage_id} nie istnieje' - next: '§aEtap został pominięty.' - nextUnavailable: '§cOpcja pominięcia nie jest dostępna kiedy gracz jest na końcu gałęzi.' - set: '§aEtap {stage_id} został uruchomiony.' - startDialog: - alreadyIn: '§cGracz jest już w trakcie dialogu.' - impossible: '§cNie można teraz uruchomić dialogu.' - noDialog: '§cGracz nie ma oczekującego dialogu.' - success: '§aRozpoczęto dialog dla gracza {player} w misji {quest}!' + startQuestNoRequirements: '§cGracz nie spełnia wymagań dla zadania {quest}... Dołącz "-overrideRequirements" na końcu twojej komendy aby ominąć sprawdzanie wymagań.' + cancelQuest: '§6Anulowałeś zadanie {quest}.' + cancelQuestUnavailable: '§cZadanie {quest} nie może zostać anulowane.' + backupCreated: '§6Pomyślnie utworzyłeś kopie zapasowe wszystkich zadań i informacji o graczach.' + backupPlayersFailed: '§cTworzenie kopii zapasowej dla wszystkich graczy nie powiodło się.' + backupQuestsFailed: '§cTworzenie kopii zapasowej dla wszystkich zadań nie powiodło się.' + adminModeEntered: '§aWłączyłeś/aś tryb administratora.' + adminModeLeft: '§aWyłączyłeś/aś tryb administratora.' + resetPlayerPool: + timer: '§aZresetowałeś {pool} zegar puli {player}.' + full: '§aZresetowałeś dane puli {pool} {player}.' startPlayerPool: - error: Nie udało się uruchomić puli {pool} dla {player}. + error: 'Nie udało się uruchomić puli {pool} dla {player}.' success: 'Rozpoczęto pulę od {pool} do {player}. Wynik: {result}' - startQuest: '§6Wymusiłeś/aś rozpoczęcie zadania {quest} (UUID gracza: {player}).' - startQuestNoRequirements: '§cGracz nie spełnia wymagań dla zadania {quest}... Dołącz "-overrideRequirements" na końcu twojej komendy aby ominąć sprawdzanie wymagań.' - dialogs: - skipped: '§8Dialog pominięty.' - tooFar: '§7§oJesteś za daleko od {npc_name}...' + scoreboard: + lineSet: '§6Pomyślnie edytowałeś/aś linię {line_id}.' + lineReset: '§6Pomyślnie zresetowałeś/aś wiersz {line_id}.' + lineRemoved: '§6Pomyślnie usunąłeś/aś wiersz {line_id}.' + lineInexistant: '§cWiersz {line_id} nie istnieje.' + resetAll: '§6Pomyślnie zresetowałeś/aś tablicę wyników gracza {player_name}.' + hidden: '§6Tablica wyników gracza {player_name} została ukryta.' + shown: '§6Tablica wyników gracza {player_name} została pokazana.' + own: + hidden: '§6Twoja tablica wyników jest teraz ukryta.' + shown: '§6Twoja tablica wyników pojawiła się ponownie.' + help: + header: '§6§lBeautyQuests - Pomoc' + create: '§6/{label} create: §eUtwórz zadanie.' + edit: '§6/{label} edit: §eEdytuj zadanie.' + remove: '§6/{label} remove <id>: §eUsuń zadanie z podanym id lub kliknij na NPC jeśli nie zdefiniowano.' + finishAll: '§6/{label} finishAll <player>: §eZakończ wszystkie zadania gracza.' + setStage: '§6/{label} setStage <gracz> <id> [nowa gałąź] [nowy etap]: §ePomiń bieżący etap/uruchom gałąź/ustaw etap dla gałęzi.' + startDialog: '§7/{label} startDialog <player> <quest id>: §eUruchamia oczekujące okno dialogowe dla etapu NPC lub startowego okna dialogowego dla zadania.' + resetPlayer: '§6/{label} resetPlayer <gracz>: §eUsuń wszystkie informacje o graczu.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <gracz> [id]: §eUsuń informacje o zadaniu danego gracza.' + seePlayer: '§6/{label} SeePlayer <gracz>: §eWyświetl informacje o graczu.' + reload: '§6/{label} reload: §eZapisz i odśwież wszystkie konfiguracje i pliki. (§cprzestarzałe§e)' + start: '§6/{label} start <gracz> [id]: §eWymuś rozpoczęcie zadania.' + setItem: '§6/{label} setItem <talk|launch>: §eZapisz hologram.' + setFirework: '§6/{label} setFirework: §eEdytuj domyślny końcowy efekt fajerwerki.' + adminMode: '§6/{label} adminMode: §ePrzełącz tryb administratora. (Przydatne do wyświetlania małych wiadomości dziennika.)' + version: '§6/{label} version: §eZobacz aktualną wersję pluginu.' + downloadTranslations: '§6/{label} downloadTranslations <język>: §ePobiera plik z tłumaczeniem vanilla' + save: '§6/{label} save: §eZapisz ręcznie plugin (postęp/zmiany).' + list: '§6/{label} list: §eZobacz listę zadań. (Tylko dla obsługiwanych wersji.)' + typeCancel: '§aNapisz "cancel" aby wrócić do ostatniego tekstu.' editor: - advancedSpawnersMob: 'Napisz nazwę niestandardowego moba spawnera, aby zabić:' - already: '§cJesteś już w edytorze.' - availableElements: 'Dostępne elementy: §e{available_elements}' blockAmount: '§aNapisz liczbę bloków:' - blockData: '§aNapisz dane bloków (dostępne dane bloków: {available_datas}):' blockName: '§aNapisz nazwę bloku:' + blockData: '§aNapisz dane bloków (dostępne dane bloków: {available_datas}):' blockTag: '§aWpisz tag bloku (dostępne tagi: §7{available_tags}§a):' - chat: '§6Jesteś obecnie w trybie edytora. Napisz "/quests exitEditor", aby wymusić opuszczenie edytora. (Wysoko niezalecane, rozważ użycie poleceń, takich jak "close" lub "cancel", aby wrócić do poprzedniego ekwipunku)' - color: 'Wprowadź kolor w formacie szesnastkowym (#XXXXX) lub formatu RGB (RED GRE BLU).' - colorNamed: Wprowadź nazwę koloru. - comparisonTypeDefault: '§aWybierz typ porównania, który chcesz wśród {available}. Domyślne porównanie to: §e§l{default}§r§a. Wpisz §onull§r§a aby go użyć.' - dialog: - cleared: '§aUsunięto {amount} wiadomość(ci).' - edited: '§aWiadomość "§7{msg}§a" została edytowana.' - help: - addSound: '§6addSound <id> <dźwięk>: §eDodaj dźwięk do wiadomości.' - clear: '§6clear: §eUsuń wszystkie wiadomości.' - close: '§6close: §ePotwierdź wszystkie wiadomości.' - edit: '§7edytuj <id> <message>: §eEdytuj wiadomość.' - header: '§6§lBeautyQuests - Pomoc do edytora okna dialogowego' - list: '§6list: §eWyświetl wszystkie wiadomości.' - nothing: '§6noSender <wiadomość>: §eDodaj wiadomość bez nadawcy.' - nothingInsert: '§6nothingInsert <id> <wiadomość>: §eWstaw wiadomość bez żadnego prefiksu.' - npc: '§6npc <wiadomość>: §eDodaj wiadomość wysłaną przez NPC.' - npcInsert: '§6npcInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez NPC.' - npcName: '§7npcName [niestandardowa nazwa NPC]: §eUstaw (lub zresetuj do domyślnej) niestandardową nazwę NPC w oknie dialogowym' - player: '§6player <wiadomość>: §eDodaj wiadomość wysłaną przez gracza.' - playerInsert: '§6playerInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez gracza.' - remove: '§6remove <id>: §eUsuń wiadomość.' - setTime: '§6setTime <id> <czas>: §eUstaw czas (w tickach) zanim następna automatyczna wiadomość zostanie wysłana.' - skippable: '§7pomijalne [true|false]: §eUstaw jeśli okno dialogowe może być pominięte lub nie' - messageRemoved: '§aWiadomość "§7{msg}§a" usunięta.' - noSender: '§aWiadomość "§7{msg}§a" została dodana bez nadawcy.' - npc: '§aWiadomość "§7{msg}§a" została dodana dla NPC.' - npcName: - set: '§aWłasna nazwa NPC ustawiona na §7{new_name}§a (był §7{old_name}§a)' - unset: '§aWłasna nazwa NPC została przywrócona do domyślnej (była §7{old_name}§a)' - player: '§aWiadomość "§7{msg}§a" została dodana dla gracza.' - skippable: - set: '§aPominięty status okna dialogowego jest ustawiony na §7{new_state}§a (był §7{old_state}§a)' - unset: '§aPominięty status okna dialogowego jest przywrócony do domyślnego (był §7{old_state}§a)' - soundAdded: '§aDźwięk "§7{sound}§a" dodał do wiadomości "§7{msg}§a".' - syntaxRemove: '§cPoprawna składnia: remove <id>' - timeRemoved: '§aCzas został usunięty dla wiadomości {msg}.' - timeSet: '§aCzas został edytowany dla wiadomości {msg}: teraz {time} ticków.' + typeBucketAmount: '§aNapisz liczbę wiader do napełnienia:' + typeDamageAmount: 'Zapisz ilość obrażeń gracza:' + goToLocation: '§aIdź do pożądanej lokalizacji dla tego etapu.' + typeLocationRadius: '§aNapisz wymaganą odległość od lokalizacji:' + typeGameTicks: '§aNapisz wymaganą ilość ticków gry:' + already: '§cJesteś już w edytorze.' + stage: + location: + typeWorldPattern: '§aNapisz regex dla nazw świata:' enter: - list: '§c⚠ §7Otworzyłeś edytor "listy". Użyj "add", aby dodać linie. Aby uzyskać pomoc, wpisz "help" (bez znaku ukośnika). §e§lWpisz "close", aby opuścić edytor.' - subtitle: '§7Napisz "/quests exitEditor" aby wymusić opuszczenie edytora.' title: '§6~ Tryb edytora ~' - firework: - edited: Edytowałeś fajerwerk misji! - invalid: Ten przedmiot nie jest poprawnym fajerwerkiem. - invalidHand: Musisz trzymać fajerwerk w swojej głównej ręce. - removed: Usunięto fajerwerk misji! - goToLocation: '§aIdź do pożądanej lokalizacji dla tego etapu.' - invalidColor: Wprowadzony kolor jest nieprawidłowy. Musi być szesnastkowy lub RGB. - invalidPattern: '§cNieprawidłowy wzór regex §4{input}§c.' - itemCreator: - invalidBlockType: '§cNieprawidłowy typ bloku.' - invalidItemType: '§cNieprawidłowy typ przedmiotu. (Przedmiot nie może być blokiem.)' - itemAmount: '§aNapisz liczbę przedmiotow:' - itemLore: '§aModyfikuj lore przedmiotu: (Napisz "help", aby wyświetlić pomoc.)' - itemName: '§aNapisz nazwę przedmiotu:' - itemType: '§aNapisz nazwę pożądanego typu przedmiotu:' - unknownBlockType: '§cNieznany typ bloku.' - unknownItemType: '§cNieznany typ przedmiotu.' - mythicmobs: - disabled: '§cMythicMob jest wyłączony.' - isntMythicMob: '§cTen Mityczny Mob nie istnieje.' - list: '§aLista wszystkich Mitycznych mobów:' - noSuchElement: '§cNie ma takiego elementu. Dozwolone elementy to: §e{available_elements}' + subtitle: '§7Napisz "/quests exitEditor" aby wymusić opuszczenie edytora.' + list: '§c⚠ §7Otworzyłeś edytor "listy". Użyj "add", aby dodać linie. Aby uzyskać pomoc, wpisz "help" (bez znaku ukośnika). §e§lWpisz "close", aby opuścić edytor.' + chat: '§6Jesteś obecnie w trybie edytora. Napisz "/quests exitEditor", aby wymusić opuszczenie edytora. (Wysoko niezalecane, rozważ użycie poleceń, takich jak "close" lub "cancel", aby wrócić do poprzedniego ekwipunku)' npc: - choseStarter: '§aWybierz NPC który rozpoczyna zadanie.' enter: '§aKliknij na NPC, lub napisz "cancel".' + choseStarter: '§aWybierz NPC który rozpoczyna zadanie.' notStarter: '§cTen NPC nie rozpoczyna misji.' - pool: - hologramText: Napisz niestandardowy tekst hologramu dla tej puli (lub "null" jeśli chcesz domyślnie). - maxQuests: Wpisz maksymalną ilość zadań uruchamianych z tej puli. - questsPerLaunch: Napisz liczbę zadań, gdy gracze klikną na NPC. - timeMsg: 'Napisz czas, zanim gracze mogą zająć nowe zadanie. (domyślna jednostka: dni)' - scoreboardObjectiveNotFound: '§cNieznany cel tablicy wyników.' - selectWantedBlock: '§aKliknij patykiem na pożądany blok dla etapu.' - stage: - location: - typeWorldPattern: '§aNapisz regex dla nazw świata:' text: argNotSupported: '§cArgument {arg} nie jest obsługiwany.' - chooseJobRequired: '§aNapisz nazwę wymaganej pracy:' chooseLvlRequired: '§aNapisz wymaganą ilość poziomów:' - chooseMoneyRequired: '§aNapisz wymaganą ilość pieniędzy:' - chooseObjectiveRequired: '§aNapisz nazwę celu.' - chooseObjectiveTargetScore: '§aNapisz docelowy wynik dla celu.' - choosePermissionMessage: '§aMożesz wybrać wiadomość o odrzuceniu jeśli gracz nie ma wymaganego uprawnienia (aby pominąć ten krok, napisz "null")' + chooseJobRequired: '§aNapisz nazwę wymaganej pracy:' choosePermissionRequired: '§aNapisz wymagane uprawnienia, aby rozpocząć zadanie:' + choosePermissionMessage: '§aMożesz wybrać wiadomość o odrzuceniu jeśli gracz nie ma wymaganego uprawnienia (aby pominąć ten krok, napisz "null")' choosePlaceholderRequired: identifier: '§aWpisz nazwę wymaganego placeholdera bez procentu znaków:' value: '§aNapisz wymaganą wartość dla tego placeholdera §e%§e{placeholder}§e%§a:' - chooseRegionRequired: '§aNapisz nazwę wymaganego regionu (musisz być w tym samym świecie).' chooseSkillRequired: '§aNapisz nazwę wymaganej umiejętności:' + chooseMoneyRequired: '§aNapisz wymaganą ilość pieniędzy:' reward: - money: '§aNapisz ilość otrzymanych pieniędzy:' permissionName: '§aNapisz nazwę uprawnień.' permissionWorld: '§aNapisz świat, w którym uprawnienia będą edytowane, lub "null" jeśli chcesz żeby były globalnie.' + money: '§aNapisz ilość otrzymanych pieniędzy:' + wait: '§aNapisz ilość ticków do poczekania: (1 sekunda = 20 ticków w grze)' random: - max: '§aZapisz maksymalną ilość nagród przyznanych graczowi (włącznie).' min: '§aZapisz minimalną ilość nagród przyznanych graczowi (włącznie).' - wait: '§aNapisz ilość ticków do poczekania: (1 sekunda = 20 ticków w grze)' + max: '§aZapisz maksymalną ilość nagród przyznanych graczowi (włącznie).' + chooseObjectiveRequired: '§aNapisz nazwę celu.' + chooseObjectiveTargetScore: '§aNapisz docelowy wynik dla celu.' + chooseRegionRequired: '§aNapisz nazwę wymaganego regionu (musisz być w tym samym świecie).' + selectWantedBlock: '§aKliknij patykiem na pożądany blok dla etapu.' + itemCreator: + itemType: '§aNapisz nazwę pożądanego typu przedmiotu:' + itemAmount: '§aNapisz liczbę przedmiotow:' + itemName: '§aNapisz nazwę przedmiotu:' + itemLore: '§aModyfikuj lore przedmiotu: (Napisz "help", aby wyświetlić pomoc.)' + unknownItemType: '§cNieznany typ przedmiotu.' + invalidItemType: '§cNieprawidłowy typ przedmiotu. (Przedmiot nie może być blokiem.)' + unknownBlockType: '§cNieznany typ bloku.' + invalidBlockType: '§cNieprawidłowy typ bloku.' + dialog: + syntaxRemove: '§cPoprawna składnia: remove <id>' + player: '§aWiadomość "§7{msg}§a" została dodana dla gracza.' + npc: '§aWiadomość "§7{msg}§a" została dodana dla NPC.' + noSender: '§aWiadomość "§7{msg}§a" została dodana bez nadawcy.' + messageRemoved: '§aWiadomość "§7{msg}§a" usunięta.' + edited: '§aWiadomość "§7{msg}§a" została edytowana.' + soundAdded: '§aDźwięk "§7{sound}§a" dodał do wiadomości "§7{msg}§a".' + cleared: '§aUsunięto {amount} wiadomość(ci).' + help: + header: '§6§lBeautyQuests - Pomoc do edytora okna dialogowego' + npc: '§6npc <wiadomość>: §eDodaj wiadomość wysłaną przez NPC.' + player: '§6player <wiadomość>: §eDodaj wiadomość wysłaną przez gracza.' + nothing: '§6noSender <wiadomość>: §eDodaj wiadomość bez nadawcy.' + remove: '§6remove <id>: §eUsuń wiadomość.' + list: '§6list: §eWyświetl wszystkie wiadomości.' + npcInsert: '§6npcInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez NPC.' + playerInsert: '§6playerInsert <id> <wiadomość>: §eWstaw wiadomość wysłaną przez gracza.' + nothingInsert: '§6nothingInsert <id> <wiadomość>: §eWstaw wiadomość bez żadnego prefiksu.' + edit: '§7edytuj <id> <message>: §eEdytuj wiadomość.' + addSound: '§6addSound <id> <dźwięk>: §eDodaj dźwięk do wiadomości.' + clear: '§6clear: §eUsuń wszystkie wiadomości.' + close: '§6close: §ePotwierdź wszystkie wiadomości.' + setTime: '§6setTime <id> <czas>: §eUstaw czas (w tickach) zanim następna automatyczna wiadomość zostanie wysłana.' + npcName: '§7npcName [niestandardowa nazwa NPC]: §eUstaw (lub zresetuj do domyślnej) niestandardową nazwę NPC w oknie dialogowym' + skippable: '§7pomijalne [true|false]: §eUstaw jeśli okno dialogowe może być pominięte lub nie' + timeSet: '§aCzas został edytowany dla wiadomości {msg}: teraz {time} ticków.' + timeRemoved: '§aCzas został usunięty dla wiadomości {msg}.' + npcName: + set: '§aWłasna nazwa NPC ustawiona na §7{new_name}§a (był §7{old_name}§a)' + unset: '§aWłasna nazwa NPC została przywrócona do domyślnej (była §7{old_name}§a)' + skippable: + set: '§aPominięty status okna dialogowego jest ustawiony na §7{new_state}§a (był §7{old_state}§a)' + unset: '§aPominięty status okna dialogowego jest przywrócony do domyślnego (był §7{old_state}§a)' + mythicmobs: + list: '§aLista wszystkich Mitycznych mobów:' + isntMythicMob: '§cTen Mityczny Mob nie istnieje.' + disabled: '§cMythicMob jest wyłączony.' + advancedSpawnersMob: 'Napisz nazwę niestandardowego moba spawnera, aby zabić:' textList: + syntax: '§cPoprawna składnia: ' added: '§aTekst "§7{msg}§a" dodany.' + removed: '§aTekst "§7{msg}§a" usunięty.' help: - add: '§6add <wiadomość>: §eDodaj tekst.' - close: '§6close: §ePotwierdź dodane teksty.' header: '§6§lBeautyQuests — Pomoc edytora list' - list: '§6list: §eZobacz wszystkie dodane teksty.' + add: '§6add <wiadomość>: §eDodaj tekst.' remove: '§6remove <id>: §eUsuń tekst.' - removed: '§aTekst "§7{msg}§a" usunięty.' - syntax: '§cPoprawna składnia: ' - title: - fadeIn: Wpisz czas "fade-in" w tickach (20 ticków = 1 sekunda). - fadeOut: Napisz czas "fade-out" w tickach (20 ticków = 1 sekunda). - stay: Wpisz czas "stay" w tickach (20 ticków = 1 sekunda). - subtitle: Napisz podtytuł teksu (lub wpisz "null" aby pozostawić puste). - title: Napisz tytuł teksu (lub wpisz "null" aby pozostawić puste). - typeBucketAmount: '§aNapisz liczbę wiader do napełnienia:' - typeDamageAmount: 'Zapisz ilość obrażeń gracza:' - typeGameTicks: '§aNapisz wymaganą ilość ticków gry:' - typeLocationRadius: '§aNapisz wymaganą odległość od lokalizacji:' - errorOccurred: '§cWystąpił błąd, skontaktuj się z administratorem! §4§lKod błędu: {error}' - experience: - edited: '§aZmieniłeś zdobywane doświadczenie z {old_xp_amount} na {xp_amount} punktów.' - indexOutOfBounds: '§cLiczba {index} jest poza granicami! Musi być pomiędzy {min} a {max}.' - invalidBlockData: '§cBlokada danych {block_data} jest nieprawidłowa lub niezgodna z blokiem {block_material}.' - invalidBlockTag: '§cNiedostępny tag bloku {block_tag}.' - inventoryFull: '§cTwój ekwipunek jest pełny, przedmiot został wyrzucony na podłogę.' - moveToTeleportPoint: '§aUdaj się do poszukiwanej lokalizacji.' - npcDoesntExist: '§cNPC z id {npc_id} nie istnieje' - number: - invalid: '§c{input} nie jest prawidłową liczbą.' - negative: '§cMusisz wprowadzić liczbę dodatnią!' - notInBounds: '§cWartość, którą wpiszesz musi mieścić się w zakresie od {min} do {max}' - zero: '§cMusisz podać liczbę inną od 0!' - pools: - allCompleted: '§7Wykonałeś/aś wszystkie zadania!' - maxQuests: '§cNie możesz mieć aktywnych więcej niż {pool_max_quests} zadań jednocześnie...' - noAvailable: '§7Nie ma więcej dostępnych zadań...' - noTime: '§cMusisz poczekać {time_left} przed wykonaniem kolejnego zadania.' - quest: - alreadyStarted: '§cJuż rozpocząłeś te zadanie!' - cancelling: '§cAnulowano proces tworzenia misji.' - createCancelled: '§cTworzenie lub modyfikowanie zostało anulowane przez inny plugin!' - created: '§aGraulacje! Stworzyłeś zadanie §e{quest}§a które zawiera {quest_branches} wielokrotnych wyborów!' - editCancelling: '§cAnulowano proces edytowania misji.' - edited: '§aGratulacje! Zmodyfikowałeś zadanie§e{quest}§a które zawiera {quest_branches} wielokrotnych wyborów!' - finished: - base: '§aGratulacje! Ukończyłeś/aś zadanie §e{quest_name}§a!' - obtain: '§aOtrzymujesz {rewards}!' - invalidID: '§cZadanie o id {quest_id} nie istnieje' - invalidPoolID: '§cPula {pool_id} nie istnieje.' - notStarted: '§cObecnie nie wykonujesz tego zadania.' - started: '§aRozpocząłeś zadanie §r§e{quest_name}§o§6!' - questItem: - craft: '§cNie możesz użyć przedmiotu misji do stworzenia innych przedmiotów!' - drop: '§cNie możesz wyrzucić przedmiotu misji!' - eat: '§cNie możesz zjeść przedmiotu misji!' - quests: - checkpoint: '§7Osiągnięto punkt kontrolny misji!' - failed: '§cNie udało Ci się wykonać zadania {quest_name}...' - maxLaunched: '§cNie możesz mieć aktywnych więcej niż {quests_max_amount} zadań jednocześnie...' - updated: '§7Zadanie §e{quest_name}§7 zostało zaktualizowane.' - regionDoesntExists: '§cRegion o takie nazwie nie istnieje (musisz być w tym samym świecie).' - requirements: - combatLevel: '§cMusisz mieć {long_level} poziom walki!' - job: '§cMusisz mieć {long_level} poziom Twojej pracy §e{job_name}!' - level: '§cMusisz mieć {long_level} poziom!' - money: '§cMusisz posiadać {money}!' - quest: '§cMusisz ukończyć zadanie §e{quest_name}§c!' - skill: '§cMusisz mieć {long_level} poziom umiejętności §e{skill_name}!' - waitTime: '§cMusisz poczekać {time_left} zanim będziesz mógł ponownie uruchomić to zadanie!' - restartServer: '§7Uruchom ponownie serwer, aby zobaczyć zmiany.' - selectNPCToKill: '§aWybierz NPC do zabicia.' - stageMobs: - listMobs: '§aMusisz zabić {mobs}' - typeCancel: '§aNapisz "cancel" aby wrócić do ostatniego tekstu.' - versionRequired: 'Wymagana wersja: §l{version}' - writeChatMessage: '§aNapisz wymaganą wiadomość: (Dodaj "{SLASH}" na początku wiadomości jeśli chcesz wymagać komendy)' - writeCommand: '§aNapisz żądane polecenie (Napisz polecenie bez "/", a "{PLAYER}" zostanie zastąpione nazwą wykonawcy)' + list: '§6list: §eZobacz wszystkie dodane teksty.' + close: '§6close: §ePotwierdź dodane teksty.' + availableElements: 'Dostępne elementy: §e{available_elements}' + noSuchElement: '§cNie ma takiego elementu. Dozwolone elementy to: §e{available_elements}' + invalidPattern: '§cNieprawidłowy wzór regex §4{input}§c.' + comparisonTypeDefault: '§aWybierz typ porównania, który chcesz wśród {available}. Domyślne porównanie to: §e§l{default}§r§a. Wpisz §onull§r§a aby go użyć.' + scoreboardObjectiveNotFound: '§cNieznany cel tablicy wyników.' + pool: + hologramText: 'Napisz niestandardowy tekst hologramu dla tej puli (lub "null" jeśli chcesz domyślnie).' + maxQuests: 'Wpisz maksymalną ilość zadań uruchamianych z tej puli.' + questsPerLaunch: 'Napisz liczbę zadań, gdy gracze klikną na NPC.' + timeMsg: 'Napisz czas, zanim gracze mogą zająć nowe zadanie. (domyślna jednostka: dni)' + title: + title: 'Napisz tytuł teksu (lub wpisz "null" aby pozostawić puste).' + subtitle: 'Napisz podtytuł teksu (lub wpisz "null" aby pozostawić puste).' + fadeIn: 'Wpisz czas "fade-in" w tickach (20 ticków = 1 sekunda).' + stay: 'Wpisz czas "stay" w tickach (20 ticków = 1 sekunda).' + fadeOut: 'Napisz czas "fade-out" w tickach (20 ticków = 1 sekunda).' + colorNamed: 'Wprowadź nazwę koloru.' + color: 'Wprowadź kolor w formacie szesnastkowym (#XXXXX) lub formatu RGB (RED GRE BLU).' + invalidColor: 'Wprowadzony kolor jest nieprawidłowy. Musi być szesnastkowy lub RGB.' + firework: + invalid: 'Ten przedmiot nie jest poprawnym fajerwerkiem.' + invalidHand: 'Musisz trzymać fajerwerk w swojej głównej ręce.' + edited: 'Edytowałeś fajerwerk misji!' + removed: 'Usunięto fajerwerk misji!' writeCommandDelay: '§aNapisz żądane opóźnienie komendy, w tickach.' - writeConfirmMessage: '§aNapisz wiadomość potwierdzającą w momencie kiedy gracz rozpoczyna zadanie: (Napisz "null" jeśli chcesz użyć domyślnej wiadomości)' - writeDescriptionText: '§aNapisz tekst, który opisuje cel tego etapu:' - writeEndMsg: '§aNapisz wiadomość, która zostanie wysłana na koniec zadania, "null" jeśli chcesz domyślną lub "none" jeśli nie chcesz. Możesz użyć "{rewards}", które zostanie zastąpione otrzymanymi nagrodami.' - writeEndSound: '§aWpisz nazwę dźwięku, który usłyszy gracz na końcu zadania, wpisz "null" aby pozostawić domyślny dźwięk lub "none", aby pozostawić puste:' - writeHologramText: '§aNapisz tekst hologramu: (Napisz "none" jeśli nie chcesz hologramu, a "null" jeśli chcesz domyślną wiadomość)' - writeMessage: '§aNapisz wiadomość, która zostanie wysłana graczowi' - writeMobAmount: '§aNapisz liczbę potworów do zabicia:' - writeMobName: '§aNapisz niestandardową nazwę potwora do zabicia:' - writeNPCText: '§aNapisz wiadomość, która została powiedziana graczowi przez NPC: (Wpisz "help" żeby otrzymać pomoc.)' - writeNpcName: '§aNapisz nazwę NPC' - writeNpcSkinName: '§aNapisz nazwę skina NPC' - writeQuestDescription: '§aNapisz opis zadania, który zostanie wyświetlony w GUI zadań gracza.' - writeQuestMaterial: '§aNapisz typ przedmiotu zadania.' - writeQuestName: '§aNapisz nazwę zadania' - writeQuestTimer: '§aNapisz wymagany czas (w minutach) przed ponownym uruchomieniem zadania: (Napisz "null" jeśli chcesz ustawić domyślną wartość)' - writeRegionName: '§aNapisz nazwę regionu wymaganego dla tego etapu:' - writeStageText: '§aNapisz tekst, który zostanie wysłany do gracza na początku tego etapu:' - writeStartMessage: '§aNapisz wiadomość która będzie się wyświetlać na początku zadania, wpisz "null" aby pozostawić domyślną, wpisz "none" aby zostawić puste:' - writeXPGain: '§aNapisz liczbę punktów doświadczenia jaką otrzyma gracz: (Poprzednia wartość: {xp_amount})' +advancement: + notStarted: Nie rozpoczęto +inv: + validate: '§b§lPotwierdź' + cancel: '§c§lAnuluj' + search: '§e§lSzukaj' + addObject: '§aDodaj obiekt' + confirm: + name: Jesteś pewien? + 'yes': '§aPotwierdź' + 'no': '§cAnuluj' + create: + stageCreate: '§aUtwórz nowy krok' + stageRemove: '§cUsuń ten krok' + stageUp: Przesuń w górę + stageDown: Przesuń w dół + stageType: '§7Rodzaj sceny: §e{stage_type}' + cantFinish: '§7Musisz utworzyć co najmniej jeden etap przed zakończeniem tworzenia misji!' + findNPC: '§aZnajdź NPC' + bringBack: '§aPrzynieś przedmioty' + findRegion: '§aZnajdź region' + killMobs: '§aZabij potwora' + mineBlocks: '§aZniszcz bloki' + placeBlocks: '§aPołóż bloki' + talkChat: '§aNapisz na czacie' + interact: '§aInterakcja z blokiem' + fish: '§aZłap ryby' + melt: '§7Wytopione przedmioty' + enchant: '§dZaklnij przedmioty' + craft: '§aStwórz przedmiot' + bucket: '§aWypełnij wiadra' + location: '§aIdź do lokalizacji' + playTime: '§eCzas gry' + breedAnimals: '§aRozmnóż zwierzęta' + tameAnimals: '§aOswój zwierzęta' + death: '§cZgiń' + dealDamage: '§cZadaj obrażenia mobom' + eatDrink: '§aZjedz lub pij jedzenie lub mikstury' + NPCText: '§eEdytuj okno dialogowe' + NPCSelect: '§eWybierz lub utwórz NPC' + hideClues: Ukryj cząsteczki i hologramy + editMobsKill: '§eEdytuj moby do zabicia' + mobsKillFromAFar: Należy zabić pociskiem + editBlocksMine: '§eEdytuj bloki do zniszczenia' + preventBlockPlace: Zablokuj graczom możliwość niszczenia własnych bloków + editBlocksPlace: '§eEdytuj bloki do postawienia' + editMessageType: '§eEdytuj wiadomość do napisania' + cancelMessage: Anuluj wysyłanie + ignoreCase: Ignoruj wielkość liter w wiadomości + selectItems: '§eEdytuj wymagane przedmioty' + selectItemsMessage: '§eEdytuj wiadomość z pytaniem' + selectItemsComparisons: '§eWybierz porównania przedmiotów (ZAAWANSOWANE)' + selectRegion: '§7Wybierz region' + toggleRegionExit: Przy wyjściu + stageStartMsg: '§eEdytuj wiadomość początkową' + selectBlockLocation: '§eWybierz lokalizację bloku' + selectBlockMaterial: '§eWybierz materiał bloku' + leftClick: Musisz kliknąć lewym przyciskiem myszy + editFishes: '§eEdytuj ryby do złowienia' + editItemsToMelt: '§eEdytuj przedmioty do stopienia' + editItemsToEnchant: '§eEdytuj przedmioty do zaczarowania' + editItem: '§eEdytuj przedmioty do stworzenia' + editBucketType: '§eEdytuj typ wiadra do wypełnienia' + editBucketAmount: '§eEdytuj ilość wiader do wypełnienia' + editLocation: '§eEdytuj lokalizację' + editRadius: '§eEdytuj odległość od lokalizacji' + currentRadius: '§eObecna odległość: §6{radius}' + changeTicksRequired: '§eZmiana ticków jest wymagana' + changeEntityType: '§eZmień typ obiektu/jednostki' + stage: + location: + worldPattern: '§aUstaw wzór nazwy świata §d(ADVANCED)' + worldPatternLore: 'Jeśli chcesz, aby etap został ukończony dla dowolnego świata pasującego do określonego wzoru, wprowadź wyrażenie regularne tutaj tutaj.' + death: + causes: '§aUstaw śmierć powoduje §d(ADVANCED)' + anyCause: Każda przyczyna zgonu + setCauses: '{causes_amount} przyczyna zgonu' + dealDamage: + damage: '§eObrażenia' + targetMobs: '§cMoby do obrażeń' + eatDrink: + items: '§eEdytuj przedmioty do jedzenia lub picia' + stages: + name: Stwórz etapy + nextPage: '§eNastępna strona' + laterPage: '§ePoprzednia strona' + endingItem: '§eEdytuj końcowe nagrody' + descriptionTextItem: '§eEdytuj opis' + regularPage: '§aZwykłe etapy' + branchesPage: '§dEtapy gałęzi' + previousBranch: '§eWróć do poprzedniej gałęzi' + newBranch: '§ePrzejdź do nowej gałęzi' + validationRequirements: '§eWymagania sprawdzające' + validationRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, który chce ukończyć poziom. Bez tego poziom nie może zostać ukończony. + details: + hologramLaunch: '§eEdytuj hologram - "launch"' + hologramLaunchLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz może rozpocząć zadanie. + hologramLaunchNo: '§eEdytuj hologram - "launch unavailable"' + hologramLaunchNoLore: Hologram wyświetlany nad głową startowego NPC, gdy gracz nie może rozpocząć zadania. + customConfirmMessage: '§eEdytuj wiadomość potwierdzającą zadanie' + customConfirmMessageLore: Wiadomość wyświetlana w interfejsie potwierdzania, gdy gracz ma wkrótce rozpocząć zadanie. + customDescription: '§eEdytuj opis zadania' + customDescriptionLore: Opis pokazany pod nazwą zadania w GUI. + name: Szczegóły ostatniego zadania + multipleTime: + itemName: Włącz/wyłącz możliwość powtarzania + itemLore: Czy zadanie można wykonać kilkakrotnie? + cancellable: Możliwość anulowania przez gracza + cancellableLore: Pozwala graczowi anulować zadanie przez menu zadań. + startableFromGUI: Możliwość uruchomienia z GUI + startableFromGUILore: Pozwala graczowi rozpocząć zadanie z menu zadań. + scoreboardItem: Włącz tabelę wyników + scoreboardItemLore: Jeśli wyłączone, zadanie nie będzie śledzone przez tablicę wyników. + hideNoRequirementsItem: Ukryj gdy wymagania nie są spełnione + hideNoRequirementsItemLore: Jeśli włączone, zadanie nie będzie wyświetlane w Menu Zadań, gdy wymagania nie zostaną spełnione. + bypassLimit: Nie licz limitu zadań + bypassLimitLore: Jeśli włączone, zadanie będzie uruchamialne, nawet jeśli gracz osiągnie maksymalną liczbę rozpoczętych zadań. + auto: Uruchom automatycznie po zalogowaniu + autoLore: Jeśli włączone, zadanie zostanie uruchomione automatycznie, gdy gracz dołączy do serwera po raz pierwszy. + questName: '§a§lEdytuj nazwę zadania' + questNameLore: Nazwa musi być ustawiona, aby ukończyć tworzenie zadania. + setItemsRewards: '§eEdytuj nagrody przedmiotowe' + removeItemsReward: '§eUsuń przedmioty z ekwipunku' + setXPRewards: '§eEdytuj nagrody doświadczenia' + setCheckpointReward: '§eEdytuj nagrody punktu kontrolnego' + setRewardStopQuest: '§cZatrzymaj zadanie' + setRewardsWithRequirements: '§eNagrody z wymaganiami' + setRewardsRandom: '§dLosowe nagrody' + setPermReward: '§eEdytuj uprawnienia' + setMoneyReward: '§eEdytuj nagrodę pieniężną' + setWaitReward: '§eEdytuj nagrodę "czekania"' + setTitleReward: '§eEdytuj tytuł nagrody' + selectStarterNPC: '§e§lWybierz NPC startowego' + selectStarterNPCLore: Kliknięcie na wybranego NPC rozpocznie zadanie. + selectStarterNPCPool: '§c⚠ Wybrana pula zadań' + createQuestName: '§lUtwórz zadanie' + createQuestLore: Musisz zdefiniować nazwę zadania. + editQuestName: '§lEdytuj zadanie' + endMessage: '§eEdytuj wiadomość końcową' + endMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. + endSound: '§eEdytuj dźwięk końca' + endSoundLore: Dźwięk, który będzie odtwarzany na końcu zadania. + startMessage: '§eEdytuj wiadomość początkową' + startMessageLore: Wiadomość, która zostanie wysłana do gracza po zakończeniu zadania. + startDialog: '§eEdytuj okno startowe' + startDialogLore: Okno dialogowe, które będzie wyświetlane przed rozpoczęciem zadań, kiedy gracze klikną na NPC Startowego. + editRequirements: '§eEdytuj wymagania' + editRequirementsLore: Wszystkie wymagania muszą zostać spełnione przez gracza, zanim będzie mógł on rozpocząć zadanie. + startRewards: '§6Nagrody startowe' + startRewardsLore: Akcje wykonywane w momencie rozpoczęcia misji. + cancelRewards: '§cAnuluj akcje' + cancelRewardsLore: Akcje wykonywane, gdy gracze anulują to zadanie. + hologramText: '§eTekst Hologramu' + hologramTextLore: Tekst wyświetlany na hologramie nad głową startowego NPC. + timer: '§bZrestartuj zegar' + timerLore: Czas zanim gracz może ponownie rozpocząć zadanie. + requirements: '{amount} wymaganie(a)' + rewards: '{amount} nagroda(ód)' + actions: '{amount} akcja(j)' + rewardsLore: Akcje wykonywane po zakończeniu misji. + customMaterial: '§eEdytuj przedmiot zadania' + customMaterialLore: Przedmiot reprezentujący to zadanie znajduje się w menu zadań. + failOnDeath: Niepowodzenie podczas śmierci + failOnDeathLore: Czy zadanie zostanie anulowane po śmierci gracza? + questPool: '§ePula Zadań' + questPoolLore: Dołącz to zadanie do puli zadań + firework: '§dKończenie fajerwerków' + fireworkLore: Fajerwerk wystrzelony po zakończeniu misji + fireworkLoreDrop: Upuść niestandardowe fajerwerki tutaj + visibility: '§bWidoczność Zadań' + visibilityLore: Wybierz, w których zakładkach menu będą wyświetlane zadania, a jeśli zadanie będzie widoczne na mapach dynamicznych. + keepDatas: Zachowaj dane graczy + keepDatasLore: |- + Wymuś, aby plugin zachował dane graczy, nawet jeśli etapy zostały edytowane. §c§lOSTRZEŻENIE §c- włączenie tej opcji może zepsuć dane Twoich gracza. + loreReset: '§e§lPostęp wszystkich graczy zostanie zresetowany' + optionValue: '§8Wartość: §7{value}' + defaultValue: '§8(domyślna wartość)' + requiredParameter: '§7Wymagany parametr' + itemsSelect: + name: Edytuj przedmioty + none: |- + §aPrzenieś tutaj przedmiot lub kliknij, aby otworzyć edytor przedmiotu. + itemSelect: + name: Wybierz przedmiot + npcCreate: + name: Utwórz NPC + setName: '§eEdytuj nazwę NPC' + setSkin: '§eEdytuj skórkę NPC' + setType: '§eEdytuj typ NPC' + move: + itemName: '§ePrzenieś' + itemLore: '§aZmień lokalizację NPC.' + moveItem: '§a§lPotwierdź miejsce' + npcSelect: + name: Wybrać czy stworzyć? + selectStageNPC: '§eWybierz istniejącego NPC' + createStageNPC: '§eUtwórz NPC' + entityType: + name: Wybierz typ jednostki + chooseQuest: + name: Wybór zadania + menu: '§aQuests Menu' + menuLore: Pobiera cię do menu Zadań. + mobs: + name: Wybierz moby + none: '§aKliknij, aby dodać moba.' + editAmount: Edytuj Ilość + editMobName: Edytuj nazwę moba + setLevel: Ustaw minimalny poziom + mobSelect: + name: Wybierz typ moba + bukkitEntityType: '§eWybierz typ jednostki' + mythicMob: '§6Wybierz Mitycznego moba' + epicBoss: '§6Wybierz Epickiego Bossa' + boss: '§6Wybierz Bossa' + stageEnding: + locationTeleport: '§eEdytuj lokalizację teleportu' + command: '§eEdytuj wykonywaną komendę' + requirements: + name: Wymagania + setReason: Ustaw niestandardowy powód + reason: '§8Własny powód: §7{reason}' + rewards: + name: Nagrody + commands: 'Komendy: {amount}' + random: + rewards: Edytuj nagrody + minMax: Edytuj min. i maks. + checkpointActions: + name: Akcje punktu kontrolnego + cancelActions: + name: Anuluj akcje + rewardsWithRequirements: + name: Nagrody z wymaganiami + listAllQuests: + name: Zadania + listPlayerQuests: + name: 'Zadania {player_name}' + listQuests: + notStarted: Nierozpoczęte zadania + finished: Ukończone zadania + inProgress: Aktywne zadania + loreDialogsHistoryClick: '§7Zobacz okna dialogowe' + loreCancelClick: '§cAnuluj zadanie' + loreStart: '§a§oKliknij aby rozpocząć zadanie' + loreStartUnavailable: '§c§oNie spełniasz wymagań do rozpoczęcia zadania' + canRedo: '§3§oMożesz ponownie uruchomić to zadanie!' + itemCreator: + name: Kreator przedmiotów + itemType: '§bTyp przedmiotu' + itemFlags: Przełącz flagi przedmiotu + itemName: '§bNazwa przedmiotu' + itemLore: '§bLore przedmiotu' + isQuestItem: '§bPrzedmiot misji:' + command: + name: Komenda + value: '§eKomenda' + console: Konsola + parse: Parsetowe symbole zastępcze + delay: '§bOpóźnienie' + chooseAccount: + name: Jakie konto? + listBook: + questName: Nazwa + questStarter: Starter + questRewards: Nagrody + questMultiple: Kilka razy + requirements: Wymagania + questStages: Etapy + noQuests: Nie utworzono wcześniej żadnych zadań. + commandsList: + name: Lista komend + value: '§Komenda: {command_label}' + console: '§eKonsola: {command_console}' + block: + name: Wybierz blok + material: '§eMateriał: {block_type}' + materialNotItemLore: 'Wybrany blok nie może być wyświetlany jako element. Nadal jest poprawnie przechowywany jako {block_material}.' + blockName: '§bWłasna nazwa bloku' + blockData: '§dBlockdata (zaawansowane)' + blockTag: '§dTag (zaawansowane)' + blockTagLore: 'Wybierz tag, który opisuje listę możliwych bloków. Tagi można dostosować za pomocą apacków. Listę tagów można znaleźć na wiki Minecraft.' + blocksList: + name: Wybierz bloki + addBlock: '§aKliknij, aby dodać blok.' + blockAction: + name: Wybierz akcję bloku + location: '§eWybierz dokładną lokalizację' + material: '§eWybierz materiał bloku' + buckets: + name: Typ wiadra + permission: + name: Wybierz uprawnienie + perm: '§aUprawnienia' + world: '§aŚwiat' + worldGlobal: '§b§lGlobalny' + remove: Usuń uprawnienie + removeLore: '§7Uprawnienie zostanie odebrane\n§7zamiast dodane.' + permissionList: + name: Lista uprawnień + removed: '§eOdebrane: §6{permission_removed}' + world: '§eŚwiat: §6{permission_world}' + classesRequired.name: Wymagane klasy + classesList.name: Lista klas + factionsRequired.name: Wymagane frakcje + factionsList.name: Lista frakcji + poolsManage: + name: Pula Zadań + poolMaxQuests: '§8Maks. zadań: §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Zadania podane podczas startu: §7{pool_quests_per_launch}' + poolRedo: '§8Można wykonywać ponownie ukończone zadania: §7{pool_redo}' + poolTime: '§8Czas pomiędzy zadaniami: §7{pool_time}' + poolHologram: '§8Tekst hologramu: §7{pool_hologram}' + poolAvoidDuplicates: '§8Unikaj duplikatów: §7{pool_duplicates}' + poolQuestsList: '§7{pool_quests_amount} §8zadań(ia): §7{pool_quests}' + create: '§aUtwórz pulę zadań' + edit: '§e> §6§oEdytuj pulę... §e<' + choose: '§e> §6§oWybierz tę pulę §e<' + poolCreation: + name: Tworzenie puli zadań + hologramText: '§ePool niestandardowy hologram' + maxQuests: '§aMaks. zadań' + questsPerLaunch: '§8Zadania podane podczas startu' + time: '§bUstaw czas pomiędzy zadaniami' + redoAllowed: Jest dozwolone ponawianie + avoidDuplicates: Unikaj duplikatów + avoidDuplicatesLore: '§8> §7Spróbuj unikać wykonywania\n tego samego zadania' + requirements: '§bWymagania do rozpoczęcia zadania' + poolsList.name: Pule zadań + itemComparisons: + name: Porównania pozycji + bukkit: Porównanie natywne Bukkit + customBukkit: Porównanie natywne Bukkit - NO NBT + material: Materiał przedmiotu + materialLore: 'Porównuje materiał przedmiotu (tj. kamień, żelazny miecz...)' + itemName: Nazwa przedmiotu + itemNameLore: Porównuje nazwy przedmiotów + itemLore: Opis przedmiotu + itemLoreLore: Porównuje opisy przedmiotów + enchants: Zaklęcia przedmiotów + enchantsLore: Porównuje zaklęcia przedmiotów + repairCost: Koszt naprawy + repairCostLore: Porównuje koszty naprawy pancerza i mieczy + itemsAdder: ItemsAdder + itemsAdderLore: Porównuje ID ItemsAdder'a + mmoItems: Item MMOItems + editTitle: + name: Edytuj tytuł + title: '§6Tytuł' + subtitle: '§ePodtytuł' + fadeIn: '§aCzas pojawiania' + stay: '§bCzas trwania' + fadeOut: '§aCzas zanikania' + particleEffect: + name: Utwórz efekt cząsteczek + shape: '§dKształt cząsteczek' + type: '§eTyp cząsteczek' + color: '§bKolor cząsteczek' + particleList: + name: Lista cząsteczek + colored: Kolorowe cząstki + damageCause: + name: Powód obrażeń + damageCausesList: + name: Lista przyczyn obrażeń + visibility: + name: Widoczność zadań + notStarted: 'Zakładka menu "Nie rozpoczęte"' + inProgress: 'Zakładka menu "W toku"' + finished: 'Zakładka menu "Zakończone"' + maps: 'Mapy (takie jak dynmapa lub BlueMap)' + equipmentSlots: + name: Miejsca na wyposażenie + questObjects: + setCustomDescription: 'Ustaw własny opis' scoreboard: - asyncEnd: '§ex' name: '§7§lZadania' noLaunched: '§cBrak zadań w toku.' - noLaunchedDescription: '§c§lŁadowanie' noLaunchedName: '§c§lŁadowanie' + noLaunchedDescription: '§c§lŁadowanie' + textBetwteenBranch: '§e lub' + asyncEnd: '§ex' stage: - breed: '§eRozmnóż §6{mobs}' - bucket: '§eUzupełnij §6{buckets}' + region: '§eZnajdź region §6{region_id}' + npc: '§ePorozmawiaj z NPC §6{dialog_npc_name}' + mobs: '§eZabij §6{mobs}' + mine: '§eWykop {blocks}' + placeBlocks: '§ePostaw {blocks}' chat: '§eNapisz §6{text}' + interactMaterial: '§eKliknij na blok §6{block}' + fish: '§eZłów §6{items}' + enchant: '§eZaklinaj §6{items}' craft: '§eStwórz §6{items}' + bucket: '§eUzupełnij §6{buckets}' + location: '§eIdź do §7{target_x}§e, §7{target_y}§e, §7{target_z}§e w §6{target_world}' + playTimeFormatted: '§eGraj §7{time_remaining_human}' + breed: '§eRozmnóż §6{mobs}' + tame: '§eOswój §6{mobs}' + die: '§cDie' dealDamage: any: '§cZadaj {damage_remaining} obrażeń' mobs: '§cZadaj {damage_remaining} obrażeń {target_mobs}' - die: '§cDie' eatDrink: '§eZużyj §7{items}' - enchant: '§eZaklinaj §6{items}' - fish: '§eZłów §6{items}' - interact: '§eKliknij na blok na §6{x}' - interactMaterial: '§eKliknij na blok §6{block}' - items: '§ePrzynieś przedmioty do §6{dialog_npc_name}§e:' - location: '§eIdź do §7{target_x}§e, §7{target_y}§e, §7{target_z}§e w §6{target_world}' - mine: '§eWykop {blocks}' - mobs: '§eZabij §6{mobs}' - npc: '§ePorozmawiaj z NPC §6{dialog_npc_name}' - placeBlocks: '§ePostaw {blocks}' - playTimeFormatted: '§eGraj §7{time_remaining_human}' - region: '§eZnajdź region §6{region_id}' - tame: '§eOswój §6{mobs}' - textBetwteenBranch: '§e lub' +indication: + startQuest: '§7Czy chcesz rozpocząć zadanie {quest_name}?' + closeInventory: '§7Czy na pewno chcesz zamknąć GUI?' + cancelQuest: '§7Czy na pewno chcesz anulować zadanie {quest_name}?' + removeQuest: '§7Czy na pewno chcesz usunąć zadanie {quest}?' +description: + requirement: + title: '§8§lWymagania:' + level: 'Poziom {short_level}' + jobLevel: 'Poziom {short_level} dla {job_name}' + combatLevel: 'Poziom bojowy {short_level}' + skillLevel: 'Poziom {short_level} dla {skill_name}' + class: 'Klasa {class_name}' + faction: 'Frakcja {faction_name}' + quest: 'Zakończ zadanie §e{quest_name}' + reward: + title: '§8§lNagrody:' +misc: + format: + prefix: '§6<§e§lZadania§r§6> §r' + time: + weeks: '{weeks_amount} tygodni' + days: '{days_amount} dni' + hours: '{hours_amount} godzin' + minutes: '{minutes_amount} minut' + lessThanAMinute: 'mniej niż minutę' + stageType: + region: Znajdź region + npc: Znajdź NPC + items: Przynieś przedmioty z powrotem + mobs: Zabij potwory + mine: Zniszcz bloki + placeBlocks: Postaw bloki + chat: Napisz na czacie + interact: Interakcja z blokiem + Fish: Złap ryby + Melt: Elementy stopu + Enchant: Zaklinaj przedmioty + Craft: Wytwórz przedmiot + Bucket: Wypełnij wiadro + location: Znajdź lokalizację + playTime: Czas w grze + breedAnimals: Rozmnóż zwierzęta + tameAnimals: Oswój zwierzęta + die: Giń + dealDamage: Zadaj obrażenia + eatDrink: Jedz lub napój + comparison: + equals: równe {number} + different: inne niż {number} + less: ściśle mniej niż {number} + lessOrEquals: mniej niż {number} + greater: ściśle więcej niż {number} + greaterOrEquals: więcej niż {number} + requirement: + logicalOr: '§dLogiczne LUB (wymagania)' + skillAPILevel: '§bWymagany poziom SkillAPI' + class: '§bKlasa(y) wymagane' + faction: '§bFrakcja(e) wymagana(e)' + jobLevel: '§bWymagany poziom pracy' + combatLevel: '§bWymagany poziom walki' + experienceLevel: '§bWymagane poziomy doświadczenia' + permissions: '§3Uprawnienie(a) jest/są wymagane' + scoreboard: '§dWymagany wynik' + region: '§dRegion jest wymagany' + placeholder: '§bWymagana jest wartość Placeholdera' + quest: '§aZadanie jest wymagane' + mcMMOSkillLevel: '§dWymagany poziom umiejętności' + money: '§dWymagane pieniądze' + equipment: '§eWymagane Wyposażenie' + bucket: + water: Wiadro wody + lava: Wiadro lawy + milk: Wiadro mleka + snow: Śnieżne wiadro + click: + right: Prawy przycisk myszy + left: Kliknij lewym przyciskiem myszy + shift-right: Shift i kliknięcie prawym przyciskiem myszki + shift-left: Shift i kliknięcie lewym przyciskiem myszki + middle: Kliknij środkowo + amounts: + items: '{items_amount} element(ów)' + dialogLines: '{lines_amount} wiersze' + permissions: '{permissions_amount} uprawnień' + mobs: '{mobs_amount} mobów' + ticks: '{ticks} ticków' + questItemLore: '§e§oPrzedmiot zadań' + hologramText: '§8§lNPC zadań' + poolHologramText: '§eNowe zadanie jest dostępne!' + entityType: '§eTyp jednostki: {entity_type}' + entityTypeAny: '§eDowolny obiekt/jednostka' + enabled: Włączone + disabled: Wyłączone + unknown: nieznany + notSet: '§cnie ustawione' + removeRaw: Usuń + reset: Reset + or: lub + amount: '§eIlość: {amount}' + 'yes': 'Tak' + 'no': 'Nie' + and: i diff --git a/core/src/main/resources/locales/ru_RU.yml b/core/src/main/resources/locales/ru_RU.yml index 891f1128..946818de 100644 --- a/core/src/main/resources/locales/ru_RU.yml +++ b/core/src/main/resources/locales/ru_RU.yml @@ -1,755 +1,761 @@ --- -advancement: - finished: Завершено - notStarted: Не начато -description: - requirement: - class: Класс {class_name} - combatLevel: Боевой уровень {short_level} - faction: Фракция {faction_name} - jobLevel: Уровень {short_level} для {job_name} - level: Уровень {short_level} - quest: Закончите квест §e{quest_name} - skillLevel: Уровень {short_level} для {skill_name} - title: '§8§lТребования:' - reward: - title: '§8§lНаграды:' -indication: - cancelQuest: '§7Вы уверены, что хотите отменить квест {quest_name}?' - closeInventory: '§7Вы уверены, что хотите закрыть этот интерфейс?' - removeQuest: '§7Вы уверены, что хотите удалить квест {quest}?' - startQuest: '§7Вы хотите начать квест {quest_name}?' -inv: - addObject: '§aДобавить объект' - block: - blockData: '§dБлокировать данные (дополнительно)' - material: '§eМатериал: {block_type}' - name: Выбрать блок - blockAction: - location: '§eВыберите точное место' - material: '§eВыберите материал блока' - name: Выберите действие блока - blocksList: - addBlock: '§aНажмите, чтобы добавить блок.' - name: Выбрать блок - buckets: - name: Тип ведра - cancel: '§c§lОтменить' - cancelActions: - name: Отменить действия - checkpointActions: - name: Значок контрольной точки - chooseAccount: - name: Какой аккаунт? - chooseQuest: - menu: '§aМеню квестов' - menuLore: Приведет вас к меню ваших квестов. - name: Какой квест? - classesList.name: Список классов - classesRequired.name: Требуются классы - command: - console: Консоль - delay: '§bЗадержка' - name: Команда - parse: Разбор заполнителей - value: '§eКоманда' - commandsList: - console: '§eКонсоль: {command_console}' - name: Список команд - value: '§Команды: {command_label}' - confirm: - name: Вы уверены? - 'no': '§cОтменить' - 'yes': '§aПодтвердить' - create: - NPCSelect: '§eВыберите или создайте NPC' - NPCText: '§eОтредактировать диалог' - breedAnimals: '§aРазводите животных' - bringBack: '§aВернуть предметы' - bucket: '§aЗаполнить ведро' - cancelMessage: Отменить отправку - cantFinish: '§7Вы должны создать хотя бы один этап, чтобы закончить создание квеста!' - changeEntityType: '§eИзменить тип объекта' - changeTicksRequired: '§eТребуются изменения галочек игры' - craft: '§aСкрафтить предмет' - currentRadius: '§eТекущее расстояние: §6{radius}' - dealDamage: '§cНаносить урон мобам' - death: '§cСкончался' - eatDrink: '§aЕшьте или пейте пищу, зелья' - editBlocksMine: '§eСменить блоки для разрушения' - editBlocksPlace: '§eСменить блоки для размещения' - editBucketAmount: '§aНапишите количество вёдер для заполнения' - editBucketType: '§eРедактировать тип ведра для заполнения' - editFishes: '§eРедактируйте рыбы, чтобы поймать' - editItem: '§eРедактировать предмет для создания' - editItemsToEnchant: '§eРедактируйте предметы для зачарования' - editItemsToMelt: '§eОтредактируйте элементы, чтобы расплавить' - editLocation: '§eРедактировать местоположение' - editMessageType: '§eРедактировать сообщение для записи' - editMobsKill: '§eСменить мобов, для убийства' - editRadius: '§eРедактировать расстояние от места' - enchant: '§dЗачаровываные предметы' - findNPC: '§aНайти NPC' - findRegion: '§aНайти регион' - fish: '§aНаловить рыбы' - hideClues: Скрыть частицы и голограммы - ignoreCase: Игнорировать регистр сообщения - interact: '§aВзаимодействовать с блоком' - killMobs: '§aУбить мобов' - leftClick: Щелчок должен быть левой кнопкой - location: '§aДойти до локации' - melt: '§6Плавка предметов' - mineBlocks: '§aСломать блоки' - mobsKillFromAFar: Требует убийства снарядом - placeBlocks: '§aПоставить блоки' - playTime: '§eВремя игры' - preventBlockPlace: Запретить игрокам ломать свои блоки - replacePlaceholders: Заменить {PLAYER} и заполнители из PAPI - selectBlockLocation: '§eВыберите местоположение блока' - selectBlockMaterial: '§eВыбрать материал блока' - selectItems: '§eОтредактировать требуемые предметы' - selectItemsComparisons: '§eВыбор сравнения товаров (ADVANCED) (РАСШИРЕННЫЙ)' - selectItemsMessage: '§eРедактировать запрашивающее сообщение' - selectRegion: '§7Выберите регион' - stage: - dealDamage: - damage: '§eНаносить урон' - targetMobs: '§cМобы, наносящие урон' - death: - anyCause: Любая причина смерти - causes: '§aУстановить причины смерти §d(ДОПОЛНИТЕЛЬНО)' - setCauses: '{causes_amount} причина(ы) смерти' - eatDrink: - items: '§eРедактировать предметы для еды или питья' - location: - worldPattern: '§aУстановить шаблон имени мира §d(ДОПОЛНИТЕЛЬНО)' - worldPatternLore: Если вы хотите, чтобы этап был завершен для любого мира, соответствующего определенному шаблону, введите здесь regex (регулярное выражение). - stageCreate: '§aСоздать новый этап' - stageDown: Переместить ниже - stageRemove: '§cУдалить этот этап' - stageStartMsg: '§eОтредактировать стартовое сообщение' - stageType: '§7Тип этапа: §e{stage_type}' - stageUp: Переместиться выше - talkChat: '§aНаписать в чат' - tameAnimals: '§aПриручите животных' - toggleRegionExit: При выходе - damageCause: - name: Причина повреждения - damageCausesList: - name: Список причин повреждений - details: - actions: '{amount} действие(s)' - auto: Запускать автоматически при первом подключении - autoLore: Если этот параметр включен, задание будет запускаться автоматически, когда игрок впервые присоединяется к серверу. - bypassLimit: Не считайте лимит квестов - bypassLimitLore: Если этот параметр включен, квест будет запущен, даже если игрок достиг максимального количества начатых квестов. - cancelRewards: '§cОтменить действия' - cancelRewardsLore: Действия, выполняемые, когда игроки отменяют это задание. - cancellable: Отменяется игроком - cancellableLore: Позволяет игроку отменить квест через меню квестов. - createQuestLore: Вы должны определить название квеста. - createQuestName: '§lСоздать квест' - customConfirmMessage: '§eОтредактировать сообщение для подтверждения квеста' - customConfirmMessageLore: Сообщение, отображаемое в интерфейсе подтверждения когда игрок собирается начать квест. - customDescription: '§eРедактировать описание' - customDescriptionLore: Описание, показанное под названием квеста в GUI. - customMaterial: '§eРедактировать материал квестового предмета ' - customMaterialLore: Предмет этого квеста в меню квестов. - defaultValue: '§f(значение по умолчанию)' - editQuestName: '§lИзменить квест' - editRequirements: '§eИзменить требования' - editRequirementsLore: Все требования должны применяться к игроку, прежде чем он сможет начать квест. - endMessage: '§eИзменить конечное сообщение' - endMessageLore: Сообщение, которое будет отправлено игроку в конце квеста. - endSound: '§eРедактировать конечный звук' - endSoundLore: Звук, который будет воспроизведен в конце квеста. - failOnDeath: Неудача при смерти - failOnDeathLore: Будет ли квест отменен после смерти игрока? - firework: '§dЗавершение Фейерверка' - fireworkLore: Фейерверк запускается, когда игрок заканчивает задание - fireworkLoreDrop: Перетащите свой собственный фейерверк здесь - hideNoRequirementsItem: Скрыть когда требования не выполнены - hideNoRequirementsItemLore: Если включено, задание не будет отображаться в меню заданий, когда требования не выполняются. - hologramLaunch: '§eРедактировать пункт "Launch" голограммы' - hologramLaunchLore: Когда игрок может начать квест, голограмма отображается над головой Стартового NPC. - hologramLaunchNo: '§eРедактировать голограмму "Запуск недоступен"' - hologramLaunchNoLore: Голограмма отображается над головой стартового NPC, когда игрок НЕ может начать задание. - hologramText: '§eТекст голограммы' - hologramTextLore: Текст отображается на голограмме над головой стартового NPC. - keepDatas: Сохранять данные игроков - keepDatasLore: 'Заставить плагин сохранять данные игроков, даже если этапы были отредактированы. §c§lПРЕДУПРЕЖДЕНИЕ§c- включение этой опции может нарушить данные ваших игроков.' - loreReset: '§e§lДостижения всех игроков будут сброшены' - multipleTime: - itemLore: Можно ли выполнить квест несколько раз? - itemName: Переключить повтор. - name: Информация о последней ошибке - optionValue: '§fЗначение: §7{value}' - questName: '§a§lИзменить название квеста' - questNameLore: Для завершения создания квеста необходимо указать имя. - questPool: '§eБассейн заданий' - questPoolLore: Прикрепить это задание к бассейну заданий - removeItemsReward: '§eУдалить предметы из инвентаря' - requiredParameter: '§7Необходимый параметр' - requirements: '{amount} требование(я)' - rewards: '{amount} награда(ы)' - rewardsLore: Действия, выполняемые по окончании квеста. - scoreboardItem: Включить табло - scoreboardItemLore: Если этот параметр отключен, квест не будет отслеживаться на табло. - selectStarterNPC: '§e§lВыберите NPC, который будет начинать квест ' - selectStarterNPCLore: Щелчок по выбранному NPC запустит квест. - selectStarterNPCPool: '§c⚠ Выбрана группа квестов' - setCheckpointReward: '§eИзменить награды контрольной точки' - setItemsRewards: '§eРедактировать награды' - setMoneyReward: '§eИзменить денежное вознаграждение' - setPermReward: '§eРедактировать разрешения' - setRewardStopQuest: '§cОстановить задание' - setRewardsRandom: '§dСлучайные награды' - setRewardsWithRequirements: '§eНаграды с требованиями' - setTitleReward: '§eИзменить название награды' - setWaitReward: '§eИзменить награду "ждать"' - setXPRewards: '§eИзменить опыт вознаграждения' - startDialog: '§eРедактировать стартовый диалог' - startDialogLore: Диалог, который будет воспроизведен перед началом квестов, когда игроки нажмут на стартового NPC. - startMessage: '§eИзменить стартовое сообщение' - startMessageLore: Сообщение, которое будет отправлено игроку в начале задания. - startRewards: '§6Начальные награды' - startRewardsLore: Действия, выполняемые при запуске квеста. - startableFromGUI: Запускается из графического интерфейса - startableFromGUILore: Позволяет игроку начать квест из меню квестов. - timer: '§bПерезапустить таймер' - timerLore: Время до того, как игрок сможет снова начать квест. - visibility: '§bВидимость задания' - visibilityLore: Выберите, на каких вкладках меню будет отображаться задание, и будет ли оно отображаться на динамических картах. - editTitle: - fadeIn: '§aПродолжительность постепенного появления' - fadeOut: '§aПродолжительность затухания' - name: Изменить заголовок - stay: '§bПродолжительность пребывания' - subtitle: '§eПодзаголовок' - title: '§6Заголовок' - entityType: - name: Выберите тип сущности - factionsList.name: Список фракций - factionsRequired.name: Требуются фракции - itemComparisons: - bukkit: Bukkit родное сравнение - bukkitLore: Использует систему сравнения элементов Bukkit по умолчанию. Сравнивает материал, долговечность, NBT... - customBukkit: Bukkit родное сравнение - NO NBT - customBukkitLore: Использует систему сравнения элементов Bukkit по умолчанию, но стирает теги NBT. Сравнивает материал, прочность ... - enchants: Чары предметов - enchantsLore: Сравнивает зачарованные предметы - itemLore: Описание предмета - itemLoreLore: Сравнивает данные предметов - itemName: Название предмета - itemNameLore: Сравнивает названия предметов - material: Материал предмета - materialLore: Сравнивает материал предмета (например, камень, железный меч ...) - name: Сравнение предметов - repairCost: Стоимость ремонта - repairCostLore: Сравнивает стоимость ремонта доспехов и мечей. - itemCreator: - isQuestItem: '§bQuest предмет:' - itemFlags: Вкл/выкл флаги элемента - itemLore: '§bЛор' - itemName: '§bНазвание предмета' - itemType: '§bТип предмета' - name: Создатель предмета - itemSelect: - name: Выбрать предмет - itemsSelect: - name: Редактировать предметы - none: '§aПереместите предмет здесь или кликните, чтобы открыть редактор предметов' - listAllQuests: - name: Квесты - listBook: - noQuests: Ранее заданий не создано. - questMultiple: Несколько раз - questName: Имя - questRewards: Награды - questStages: Этапы - questStarter: Старт - requirements: Требования - listPlayerQuests: - name: 'Задания {player_name}' - listQuests: - canRedo: '§3§oВы можете перевыполнить этот квест!' - finished: Завершенные квесты - inProgress: Квесты в процессе выполнения - loreCancelClick: '§cОтменить квест' - loreDialogsHistoryClick: '§7Просмотр диалоговых окон' - loreStart: '§a§oНажмите, чтобы начать задание.' - loreStartUnavailable: '§c§oВы не соответствуете требованиям для начала задания.' - notStarted: Не начатые квесты - timeToWaitRedo: '§3§oВы можете возобновить это задание через {time_left}.' - timesFinished: '§3задание выполнен {times_finished} раз.' - mobSelect: - boss: '§6Выберите босса' - bukkitEntityType: '§eВыберите тип объекта' - epicBoss: '§6Выберите эпического босса' - mythicMob: '§6Выберите мифический моб' - name: Установите тип моба - mobs: - name: Выберите мобов - none: '§aНажмите, чтобы добавить моба.' - setLevel: Установите минимальный уровень - npcCreate: - move: - itemLore: '§aИзменить местоположение NPC.' - itemName: '§eПередвинуть' - moveItem: '§a§lПроверить место' - name: Создать NPC - setName: '§eРедактировать имя NPC' - setSkin: '§eРедактировать скин NPC' - setType: '§eРедактировать тип NPC' - npcSelect: - createStageNPC: '§eСоздать NPC' - name: Выбрать или создать? - selectStageNPC: '§eВыберите существующий NPC' - permission: - name: Выберите разрешение - perm: '§aРазрешение' - remove: Удалить разрешение - removeLore: '§7Разрешение будет снято\n§7вместо данного.' - world: '§aМир' - worldGlobal: '§b§lГлобальный' - permissionList: - name: Список разрешений - removed: '§eСнятый: §6{permission_removed}' - world: '§eМир: §6{permission_world}' - poolCreation: - avoidDuplicates: Избегайте дублирования - avoidDuplicatesLore: '§8> §7Старайтесь не выполнять\n одно и то же задание снова и снова.' - hologramText: '§eПользовательское объединенние голограмм' - maxQuests: '§aМаксимум заданий' - name: Создание Объединенных заданий - questsPerLaunch: '§aКоличество заданий, выдаваемых за запуск' - redoAllowed: Повтор разрешён - requirements: '§bТребования для начала задания' - time: '§bУстановить время между заданиями' - poolsList.name: Бассейны квестов - poolsManage: - choose: '§e> §6§oВыберите этот список §e<' - create: '§aСоздать Объединенные задания' - edit: '§e> §6§oРедактировать Объединенные... §e<' - itemName: '§aОбъединенные #{pool}' - name: Объединенные задания - poolAvoidDuplicates: '§8Избегайте дублирования: §7{pool_duplicates}' - poolHologram: '§8Текст голограммы: §7{pool_hologram}' - poolMaxQuests: '§8Максимум заданий: §7{pool_max_quests}' - poolQuestsList: '§7{pool_quests_amount} §8задание(й): §7{pool_quests}' - poolQuestsPerLaunch: '§8Количество заданий, выдаваемых за запуск: §7{pool_quests_per_launch}' - poolRedo: '§8Можно переделывать выполненные задания: §7{pool_redo}' - poolTime: '§8Время между заданиями: §7{pool_time}' - requirements: - name: Требования - rewards: - commands: 'Команды: {amount}' - name: Награды - random: - minMax: Редактировать минимальное и максимальное значение - rewards: Редактировать награды - rewardsWithRequirements: - name: Награды с требованиями - search: '§e§lПоиск' - stageEnding: - command: '§eРедактировать выполненную команду' - locationTeleport: '§eРедактировать местоположение телепорта' - stages: - branchesPage: '§dЭтапы ответвления' - descriptionTextItem: '§eРедактировать описание' - endingItem: '§eРедактировать конечные награды' - laterPage: '§eПредыдущая страница' - name: Создать этапы - newBranch: '§eПерейти к новому ответвлению' - nextPage: '§eСледующая страница' - previousBranch: '§eВернуться к предыдущему ответвлению' - regularPage: '§aОбычные этапы' - validationRequirements: '§eТребования к валидации' - validationRequirementsLore: Все требования должны соответствовать игроку, который пытается завершить стадию. Если нет, стадия не может быть завершена. - validate: '§b§lПодтвердить' - visibility: - name: Видимость квеста - notStarted: 'Вкладка меню "Не запущено"' -misc: - amount: '§eКоличество: {amount}' - and: и - bucket: - lava: Ведро лавы - milk: Ведро молока - water: Ведро воды - click: - left: ЛКМ - right: ПКМ - shift-left: Shift+щелчок левой - shift-right: Shift+щелчок правой - comparison: - different: отличается от {number} - equals: равно {number} - greater: строго больше {number} - greaterOrEquals: больше чем {number} - less: строго меньше {number} - lessOrEquals: меньше чем {number} - disabled: Выключено - enabled: Включено - entityType: '§eТип объекта: {entity_type}' - entityTypeAny: '§eЛюбая сущность' - format: - prefix: '§6<§e§lКвесты§r§6> §r' - hologramText: '§8§lКвестовый NPC' - 'no': 'Нет' - notSet: '§cне установлено' - or: или - poolHologramText: '§eДоступно новое задание!' - questItemLore: '§e§oКвестовый предмет' - requirement: - class: '§bТребуются классы' - combatLevel: '§bТребуется боевой уровень' - experienceLevel: '§bНеобходимый уровень опыта' - faction: '§bТребуются фракции' - jobLevel: '§bТребуемый уровень должности' - logicalOr: '§dЛогическое ИЛИ (требования)(requirements)' - mcMMOSkillLevel: '§dТребуемый уровень mcMMOSkillLevel' - money: '§dТребуются деньги' - permissions: '§3Требуется разрешение(а)' - placeholder: '§bТребуется значение placeholder' - quest: '§aТребуется квест' - region: '§dТребуется регион' - scoreboard: '§dТребуется оценка' - skillAPILevel: '§bтребуемый уровень SkillAPI' - reset: Перезагрузка - stageType: - Bucket: Наполнить ведро - Craft: Создать предмет - Fish: Ловить рыбу - breedAnimals: Разводите животных - chat: Пиши в чат - interact: Взаимодействовать с блоком - items: Вернуть предметы - location: Найти место - mine: Сломать блоки - mobs: Убивать мобов - npc: Найти NPC - placeBlocks: Разместите блоки - playTime: Время игры - region: Найти регион - tameAnimals: Приручить животных - ticks: '{ticks} тиков' - time: - days: '{days_amount} дней' - hours: '{hours_amount} часов' - lessThanAMinute: меньше минуты - minutes: '{minutes_amount} минут' - weeks: '{weeks_amount} недель' - unknown: неизвестно - 'yes': 'Да' msg: + quest: + finished: + base: '§aПоздравляем! Вы успешно выполнили квест §e{quest_name}§a!' + obtain: '§aВы получили {rewards}!' + started: '§aВы начали квест §r§e{quest_name}§o§6!' + created: '§aПоздравляем! Вы создали квест §е{quest}§a, в который входит {quest_branches} ответвление(я)!' + edited: '§aПоздравляем! Вы отредактировали квест §е{quest}§a, в который входит {quest_branches} ответвление(я)!' + createCancelled: '§cСоздание или редактирование было отменено другим плагином!' + cancelling: '§cПроцесс создания квеста был прерван.' + editCancelling: '§cПроцесс редактирования квеста был прерван.' + invalidID: '§cКвест под номером {quest_id}, не найден.' + invalidPoolID: '§cВетка {pool_id} не существует.' + alreadyStarted: '§cВы уже начали квест!' + notStarted: '§cВ данный момент вы не выполняете этот квест.' + quests: + maxLaunched: '§cВы не можете взять больше {quests_max_amount} задания(й) одновременно...' + updated: '§7Квест §e{quest_name}§7 был обновлён.' + checkpoint: '§7Квест достиг контрольной точки!' + failed: '§cВы провалили задание {quest_name}...' + pools: + noTime: '§cВы должны подождать {time_left} перед выполнением другого задания.' + allCompleted: '§7Вы завершили все задания!' + noAvailable: '§7Заданий больше не осталось...' + maxQuests: '§cУ вас не может быть более {pool_max_quests} заданий одновременно...' + questItem: + drop: '§cВы не можете выбросить предмет из задания!' + craft: '§cВы не можете использовать предмет задания для крафта!' + eat: '§cВы не можете съесть это!' + stageMobs: + listMobs: '§aВам нужно убить {mobs}.' + writeNPCText: '§aНапишите диалог, который будет отправлен игроку от NPC: (Напишите "help" для помощи.)' + writeRegionName: '§aВведите название региона, необходимого для этапа:' + writeXPGain: '§aНапишите количество очков опыта, которые получит игрок: (Крайнее значение: {xp_amount})' + writeMobAmount: '§aНапишите количество мобов для убийства:' + writeMobName: '§aЗапишите Имя моба которого надо убить:' + writeMessage: '§aНапишите сообщение, которое будет отправлено игроку' + writeStartMessage: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' + writeEndSound: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' + writeDescriptionText: '§aНапишите текст, который описывает цель этапа:' + writeStageText: '§aНапишите текст, который будет отправлен игроку в начале этапа:' + moveToTeleportPoint: '§aПерейдите к локации для телепорта.' + writeNpcName: '§aНапишите название NPC:' + writeNpcSkinName: '§aНапишите название скина NPC:' + writeQuestName: '§aНапишите название вашего квеста:' + writeHologramText: '§aЗапишите текст голограммы: (Напишите "none", если вы не желаете добавлять голограмму и «null", если хотите текст по умолчанию.)' + writeQuestTimer: '§aЗапишите необходимое время (в минутах), прежде чем вы сможете перезагрузить квест: (Напишите "null", если вы хотите установить время по умолчанию.)' + writeConfirmMessage: '§aНапишите сообщение для подтверждения, которое будет показано когда игрок собирается начать задание: (Напишите "null", если вы хотите отправить сообщение по умолчанию.)' + writeQuestDescription: '§aНапишите описание квеста, которое будет отображаться в квестовом интерфейсе игрока.' + writeQuestMaterial: '§aНапишите материал квестового предмета.' + requirements: + quest: '§cВы должны выполнить квест §e{quest_name}§c!' + level: '§cВаш уровень должен быть {long_level}!' + job: '§cВаш уровень для работы §e{job_name}должен быть {long_level}!' + skill: '§cВаш уровень навыка §e{skill_name}§c должен быть {long_level}!' + combatLevel: '§cВаш уровень боя должен быть {long_level}!' + money: '§cВы должны иметь {money}!' + waitTime: '§o{time_left} минут(ы), прежде чем вы сможете перезапустить задание!' + experience: + edited: '§aВы изменили добычу опыта с {old_xp_amount} до {xp_amount} очков.' + selectNPCToKill: '§aВыберите NPC для удаления.' + regionDoesntExists: '§cЭтот регион не существует. (Вы должны быть в том же мире.)' + npcDoesntExist: '§cNPC с идентификатором {npc_id} не существует.' + number: + negative: '§cВы должны ввести положительное число!' + zero: '§cВы должны ввести число, отличное от 0!' + invalid: '§c{input} не допустимое число.' + notInBounds: Число должно быть между {min} и {max} + errorOccurred: '§cПроизошла ошибка, свяжитесь с администратором! §4§lКод ошибки: {error}' + indexOutOfBounds: '§cЧисло {index} за пределами! Оно должно между {min} и {max}.' + invalidBlockData: '§cДанные блока {block_data} недопустимы или несовместимы с блоком {block_material}.' + invalidBlockTag: '§cНедоступный блочный тег {block_tag}.' bringBackObjects: Принеси мне {items}. + inventoryFull: '§cВаш инвентарь переполнен, предмет выпал на землю.' + versionRequired: 'Требуемая версия: §l{version}' + restartServer: '§7Перезагрузите сервер, чтобы увидеть изменения.' + dialogs: + skipped: '§8§o Диалог пропущен.' + tooFar: '§7§oТы слишком далеко от {npc_name}...' command: - adminModeEntered: '§aВы вошли в режим администратора.' - adminModeLeft: '§aВы вышли из режима администратора.' - backupCreated: '§6Вы успешно создали резервную копию всех квестов и информации о игроках.' - backupPlayersFailed: '§cНе удалось создать резервную копию всей информации о игроках.' - backupQuestsFailed: '§cНе удалось создать резервную копию всех квестов.' - cancelQuest: '§6Вы отменили квест {quest}.' - cancelQuestUnavailable: '§cЗадание {quest} не может быть отменено.' + downloadTranslations: + syntax: '§cНеобходимо указать язык для загрузки. Пример: "/quests downloadTranslations ru_RU".' + notFound: '§cЯзык {lang} не найден для версии {version}.' + exists: '§cФайл {file_name} уже существует. Добавьте "-overwrite" к вашей команде, чтобы перезаписать ее. (/quests downloadTranslations <lang> -overwrite)' + downloaded: '§aЯзык {lang} загружен! §7Вы должны отредактировать файл "/plugins/BeautyQuests/config.yml", чтобы изменить значение §ominecraftTranslationsFile§7 с {lang}, а затем перезапустить сервер.' checkpoint: noCheckpoint: '§cКонтрольная точка для задания {quest} не найдена.' questNotStarted: '§cВы не выполняете это задание.' - downloadTranslations: - downloaded: '§aЯзык {lang} загружен! §7Вы должны отредактировать файл "/plugins/BeautyQuests/config.yml", чтобы изменить значение §ominecraftTranslationsFile§7 с {lang}, а затем перезапустить сервер.' - exists: '§cФайл {file_name} уже существует. Добавьте "-overwrite" к вашей команде, чтобы перезаписать ее. (/quests downloadTranslations <lang> -overwrite)' - notFound: '§cЯзык {lang} не найден для версии {version}.' - syntax: '§cНеобходимо указать язык для загрузки. Пример: "/quests downloadTranslations ru_RU".' - help: - adminMode: '§6/{label} adminMode: §eПереключить режим администратора. (полезно для отображения небольших log сообщений.)' - create: '§6/{label} create: §eСоздать квест.' - downloadTranslations: '§6/{label} downloadTranslations <language>: §eЗагружает файл ванильного перевода' - edit: '§6/{label} edit: §eОтредактировать квест.' - finishAll: '§6/{label} finishAll <игрок>: §eЗавершить все квесты игрока.' - header: '§6§lBeautyQuests — Помощь' - list: '§6/{label} list: §eПосмотреть список заданий. (Только для поддерживаемых версий.)' - reload: '§6/{label} reload: §eСохранить и перезагрузить все настройки и файлы. (§cустарело§e)' - remove: '§6/{label} remove <id>: §eУдалить квест с указанным идентификатором или нажать на NPC, если квест не будет определен.' - resetPlayer: '§6/{label} resetPlayer <игрок>: §eУдалить всю информацию о игроке.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <игрок> [id]: §eУдалить информацию о квестах игрока.' - save: '§6/{label} save: §eСохранить справочник плагина.' - seePlayer: '§6/{label} seePlayer <игрок>: §e Посмотреть информацию об игроке.' - setFirework: '§6/{label} setFirework: Отредактируйте конечный фейерверк по умолчанию.' - setItem: '§6/{label} setitem <talk|launch>: §eСохранить голографический предмет.' - setStage: '§6/{label} setStage <игрок> <id> [новое ответвление] [новый этап]: §eПропустить текущий этап/запустить ответвление/установить этап для ответвления.' - start: '§6/{label} start <игрок> [id]: §eПринудительно начинает квест.' - startDialog: '§6/{label} startDialog <player> <quest id>: Запускает ожидающий диалог для этапа NPC или начальный диалог для задания.' - version: '§6/{label} version: §eПосмотреть текущую версию плагина.' + setStage: + branchDoesntExist: '§cОтветвление с id {branch_id} не существует.' + doesntExist: '§cЭтап с идентификатором {stage_id} не существует.' + next: '§aЭтап пропущен.' + nextUnavailable: '§c"Пропустить" недоступно, когда игрок находится в конце ответвления.' + set: '§Этап {stage_id} запущен.' + startDialog: + impossible: '§cНевозможно запустить диалог сейчас.' + noDialog: У игрока нет ожидающего диалога. + alreadyIn: '§cИгрок уже воспроизводит диалог.' + success: '§aЗапущен диалог для игрока {player} в квесте {quest}!' invalidCommand: simple: '§cЭта команда не существует, напишите §ehelp§c.' itemChanged: '§aПредмет отредактирован. Изменения вступят в силу после перезапуска.' itemRemoved: '§aГолографический предмет удален.' - leaveAll: '§aВы принудительно завершили {success} квест(а). Ошибки: {errors}' removed: '§aКвест {quest_name} успешно удален.' + leaveAll: '§aВы принудительно завершили {success} квест(а). Ошибки: {errors}' resetPlayer: player: '§6Все данные вашего {quest_amount} задания удалены/были удалены пользователем {deleter_name}.' remover: '§6{quest_amount} информация о задание(ях) (и {quest_pool} этапах) {player} удалена.' - resetPlayerPool: - full: '§aВы сбросили данные {pool} из {player}.' - timer: '§aВы сбросили значение таймера {pool} на {player}.' resetPlayerQuest: player: '§6Все данные о квесте {quest} были удалены пользователем {deleter_name}.' remover: '§6{player} Данные о квесте(ах) {quest} удалены.' resetQuest: '§6Удалены данные квеста для {player_amount} игроков.' + startQuest: 'Вы принудительно запустили задание {quest} для {player}.' + startQuestNoRequirements: '§cИгрок не соответствует требованиям для выполнения задания {quest}... Добавьте "-overrideRequirements" в конце вашей команды, чтобы обойти проверку требований.' + cancelQuest: '§6Вы отменили квест {quest}.' + cancelQuestUnavailable: '§cЗадание {quest} не может быть отменено.' + backupCreated: '§6Вы успешно создали резервную копию всех квестов и информации о игроках.' + backupPlayersFailed: '§cНе удалось создать резервную копию всей информации о игроках.' + backupQuestsFailed: '§cНе удалось создать резервную копию всех квестов.' + adminModeEntered: '§aВы вошли в режим администратора.' + adminModeLeft: '§aВы вышли из режима администратора.' + resetPlayerPool: + timer: '§aВы сбросили значение таймера {pool} на {player}.' + full: '§aВы сбросили данные {pool} из {player}.' + startPlayerPool: + error: 'Не удалось запустить пул {pool} для {player}.' + success: 'Запустил пул {pool} для {player}. Результат: {result}' scoreboard: - hidden: '§6Табло игрока {player_name} был скрыт.' - lineInexistant: '§cСтрока {line_id} не существует.' - lineRemoved: '§6Вы успешно удалили строку {line_id}.' - lineReset: '§6Вы успешно сбросили строку {line_id}.' lineSet: '§6Вы успешно отредактировали строку {line_id}.' + lineReset: '§6Вы успешно сбросили строку {line_id}.' + lineRemoved: '§6Вы успешно удалили строку {line_id}.' + lineInexistant: '§cСтрока {line_id} не существует.' + resetAll: '§6Вы успешно сбросили табло игрока {player_name}.' + hidden: '§6Табло игрока {player_name} был скрыт.' + shown: '§6Табло игрока {player_name} показано.' own: hidden: '§6Ваше табло теперь скрыто.' shown: '§6Снова отобразится ваше табло.' - resetAll: '§6Вы успешно сбросили табло игрока {player_name}.' - shown: '§6Табло игрока {player_name} показано.' - setStage: - branchDoesntExist: '§cОтветвление с id {branch_id} не существует.' - doesntExist: '§cЭтап с идентификатором {stage_id} не существует.' - next: '§aЭтап пропущен.' - nextUnavailable: '§c"Пропустить" недоступно, когда игрок находится в конце ответвления.' - set: '§Этап {stage_id} запущен.' - startDialog: - alreadyIn: '§cИгрок уже воспроизводит диалог.' - impossible: '§cНевозможно запустить диалог сейчас.' - noDialog: У игрока нет ожидающего диалога. - success: '§aЗапущен диалог для игрока {player} в квесте {quest}!' - startQuest: '§6Вы принудительно начали задание {quest} (UUID игрока: {player}).' - startQuestNoRequirements: '§cИгрок не соответствует требованиям для выполнения задания {quest}... Добавьте "-overrideRequirements" в конце вашей команды, чтобы обойти проверку требований.' - dialogs: - skipped: '§8§o Диалог пропущен.' - tooFar: '§7§oТы слишком далеко от {npc_name}...' + help: + header: '§6§lBeautyQuests — Помощь' + create: '§6/{label} create: §eСоздать квест.' + edit: '§6/{label} edit: §eОтредактировать квест.' + remove: '§6/{label} remove <id>: §eУдалить квест с указанным идентификатором или нажать на NPC, если квест не будет определен.' + finishAll: '§6/{label} finishAll <игрок>: §eЗавершить все квесты игрока.' + setStage: '§6/{label} setStage <игрок> <id> [новое ответвление] [новый этап]: §eПропустить текущий этап/запустить ответвление/установить этап для ответвления.' + startDialog: '§6/{label} startDialog <player> <quest id>: Запускает ожидающий диалог для этапа NPC или начальный диалог для задания.' + resetPlayer: '§6/{label} resetPlayer <игрок>: §eУдалить всю информацию о игроке.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <игрок> [id]: §eУдалить информацию о квестах игрока.' + seePlayer: '§6/{label} seePlayer <игрок>: §e Посмотреть информацию об игроке.' + reload: '§6/{label} reload: §eСохранить и перезагрузить все настройки и файлы. (§cустарело§e)' + start: '§6/{label} start <игрок> [id]: §eПринудительно начинает квест.' + setItem: '§6/{label} setitem <talk|launch>: §eСохранить голографический предмет.' + setFirework: '§6/{label} setFirework: Отредактируйте конечный фейерверк по умолчанию.' + adminMode: '§6/{label} adminMode: §eПереключить режим администратора. (полезно для отображения небольших log сообщений.)' + version: '§6/{label} version: §eПосмотреть текущую версию плагина.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §eЗагружает файл ванильного перевода' + save: '§6/{label} save: §eСохранить справочник плагина.' + list: '§6/{label} list: §eПосмотреть список заданий. (Только для поддерживаемых версий.)' + typeCancel: '§aНапишите "cancel", чтобы вернуться к прежнему тексту.' editor: - advancedSpawnersMob: 'Напишите имя пользовательского моба-спавнера, которого нужно убить:' - already: '§cВы уже в редакторе.' - availableElements: 'Доступные элементы: §e{available_elements}' blockAmount: '§aНапишите количество блоков:' - blockData: '§aЗапишите данные блоков (доступные данные: {available_datas}):' blockName: '§aНапишите название блока:' + blockData: '§aЗапишите данные блоков (доступные данные: {available_datas}):' blockTag: '§aНапишите тег блока (доступные теги: §7{available_tags}§a):' + typeBucketAmount: '§aНапишите количество вёдер для заполнения:' + typeDamageAmount: 'Напишите количество урона, который игрок должен нанести:' + goToLocation: '§aПерейдите в нужное место для этапа.' + typeLocationRadius: '§aЗапишите требуемое расстояние от локации:' + typeGameTicks: '§aНапишите необходимое количество игровых тактов:' + already: '§cВы уже в редакторе.' + stage: + location: + typeWorldPattern: '§aНапишите регулярное выражение для мировых названий:' + enter: + title: '§6~ Режим редактирования ~' + subtitle: '§6Напишите "/quests exitEditor" чтобы принудительно закрыть редактор.' + list: '§c⚠ §7Вы вошли в режим редактирования списка. Используйте "add" для добавления новых строк. Обратитесь к "help" (без слэша) для получения помощи. §e§lВведите "close" для выхода из редактора.' chat: '§6В настоящее время вы находитесь в режиме редактора. Напишите "/quests exitEditor", чтобы принудительно выйти из редактора. (Крайне не рекомендуется, рассмотрите возможность использования таких команд, как «close» или «cancel», чтобы вернуться к предыдущей инвентаризации.)' - color: 'Введите цвет в шестнадцатеричном формате (#XXXXX) или формате RGB (RED GRE BLU).' - colorNamed: Введите название цвета. - comparisonTypeDefault: '§aВыберите нужный вам тип сравнения среди {available}. Сравнение по умолчанию: §e§l{default}§r§a. Введите §onull§r§a, чтобы использовать его.' + npc: + enter: '§aНажмите на NPC или напишите "cancel".' + choseStarter: '§aВыберите NPC который начинает квест.' + notStarter: '§cЭтот NPC не начинает квест.' + text: + argNotSupported: '§cАргумент {arg} не поддерживается.' + chooseLvlRequired: '§aНапишите необходимое количество уровней:' + chooseJobRequired: '§aНапишите имя нужной работы:' + choosePermissionRequired: '§aНапишите необходимое разрешение для запуска квеста:' + choosePermissionMessage: '§aВы можете выбрать сообщение об отказе игроку, если у него нет необходимого разрешения. (Чтобы пропустить этот шаг, напишите "null".)' + choosePlaceholderRequired: + identifier: '§aЗапишите имя необходимого плейсхолдера без процентов символов:' + value: '§aЗапишите необходимое значение для заполнителя §e%§e{placeholder}§e%§a:' + chooseSkillRequired: '§aНапишите название необходимого навыка:' + chooseMoneyRequired: '§aНапишите количество предметов:' + reward: + permissionName: '§aЗапишите имя разрешения.' + permissionWorld: '§aНапишите мир, в котором разрешение будет отредактировано, или "null", если вы хотите быть глобальным.' + money: '§aНапишите сумму полученных денег:' + wait: '§aНапишите количество игровых тактов для ожидания: (1 секунда = 20 игровых тактов)' + random: + min: '§aНапишите минимальную сумму вознаграждений, предоставляемых игроку (включительно).' + max: 'Напишите максимальную сумму вознаграждений, выданных игроку (включительно).' + chooseObjectiveRequired: '§aЗапишите название цели.' + chooseObjectiveTargetScore: '§aНапишите целевой показатель для цели.' + chooseRegionRequired: '§aВведите название нужного региона (вы должны быть в том же мире).' + chooseRequirementCustomReason: 'Напишите пользовательскую причину для этого требования. Если игрок не соответствует требованиям, но все равно пытается начать квест, это сообщение появится в чате.' + chooseRequirementCustomDescription: 'Напишите пользовательское описание для этого требования. Это появится в описании квеста в меню.' + chooseRewardCustomDescription: 'Напишите пользовательское описание для этой награды. Это появится в описании квеста в меню.' + selectWantedBlock: '§aНажмите с палкой на нужном блоке для сцены.' + itemCreator: + itemType: '§aНапишите название блока для добычи:' + itemAmount: '§aНапишите количество предметов:' + itemName: '§aВведите название предмета:' + itemLore: '§aИзмените описание предмета: (Напишите "help" для помощи)' + unknownItemType: '§cНеизвестный тип предмета.' + invalidItemType: '§cНедопустимый тип предмета. (Предмет не может быть блоком.)' + unknownBlockType: '§cНеизвестный тип блока.' + invalidBlockType: '§cНедопустимый тип блока.' dialog: - cleared: '§a{amount} удаленное(ых) сообщение(й).' + syntaxRemove: '§cCorrect syntax: удалить <id>' + player: '§aСообщение "§7{msg}§a" добавлено для игрока.' + npc: '§aСообщение "§7{msg}§a" добавлено для NPC.' + noSender: '§aСообщение "§7{msg}§a" добавлено без отправителя.' + messageRemoved: '§aСообщение "§7{msg}§a" удалено.' edited: '§aСообщение "§7{msg}§a" отредактировано.' + soundAdded: '§aЗвук "§7{sound}§a" добавлен для сообщения "§7{msg}§a".' + cleared: '§a{amount} удаленное(ых) сообщение(й).' help: - addSound: '§6Добавил звук <id> <sound>: §eДобавить звук к сообщению.' - clear: '§6clear: §eУдалить все сообщения.' - close: '§6close: §eПодтвердить все сообщения.' - edit: '§6редактировать <id> <message>: §eРедактировать сообщение.' header: '§6§lBeautyQuests — помощь редактора диалогов' - list: '§6close: §eПодтвердить все сообщения.' - nothing: '§6noSender <сообщение>: §eДобавить сообщение без отправителя.' - nothingInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' npc: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' - npcInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' - npcName: '§6npcName [настраиваемое имя NPC]: §eУстановить (или сбросить) пользовательское имя NPC в диалоговом окне' player: '§6player <сообщение>: §eДобавить сообщение, которое будет отправлено игроком.' - playerInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + nothing: '§6noSender <сообщение>: §eДобавить сообщение без отправителя.' remove: '§6remove <id>: §eУдалить сообщение.' + list: '§6close: §eПодтвердить все сообщения.' + npcInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + playerInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + nothingInsert: '§6npc <сообщение>: §eДобавить сообщение, которое будет отправлено NPC.' + edit: '§6редактировать <id> <message>: §eРедактировать сообщение.' + addSound: '§6Добавил звук <id> <sound>: §eДобавить звук к сообщению.' + clear: '§6clear: §eУдалить все сообщения.' + close: '§6close: §eПодтвердить все сообщения.' setTime: '§6setTime <id> <время>: §eУстановить время (в тактах) до того как следующее сообщение воспроизведется автоматически.' + npcName: '§6npcName [настраиваемое имя NPC]: §eУстановить (или сбросить) пользовательское имя NPC в диалоговом окне' skippable: '§6skippable [true|false]: §eУстановите, можно ли пропустить диалоговое окно или нет' - messageRemoved: '§aСообщение "§7{msg}§a" удалено.' - noSender: '§aСообщение "§7{msg}§a" добавлено без отправителя.' - npc: '§aСообщение "§7{msg}§a" добавлено для NPC.' + timeSet: '§aВремя отредактировано для сообщения {msg}: Теперь {time} тактов.' + timeRemoved: '§aВремя было удалено для сообщения {msg}.' npcName: set: '§aПользовательское имя NPC установлено на §7{new_name}§a (было §7{old_name}§a)' unset: '§aПользовательское имя NPC возвращено к стандартному (было §7{old_name}§a)' - player: '§aСообщение "§7{msg}§a" добавлено для игрока.' skippable: set: '§aСтатус пропуска диалогового окна теперь установлен на §7{new_state}§a (был §7{old_state}§a)' unset: '§aСтатус пропуска диалогового окна сбрасывается на значение по умолчанию (был §7{old_state}§a)' - soundAdded: '§aЗвук "§7{sound}§a" добавлен для сообщения "§7{msg}§a".' - syntaxRemove: '§cCorrect syntax: удалить <id>' - timeRemoved: '§aВремя было удалено для сообщения {msg}.' - timeSet: '§aВремя отредактировано для сообщения {msg}: Теперь {time} тактов.' - enter: - list: '§c⚠ §7Вы вошли в режим редактирования списка. Используйте "add" для добавления новых строк. Обратитесь к "help" (без слэша) для получения помощи. §e§lВведите "close" для выхода из редактора.' - subtitle: '§6Напишите "/quests exitEditor" чтобы принудительно закрыть редактор.' - title: '§6~ Режим редактирования ~' - firework: - edited: Отредактировал фейерверк квеста! - invalid: Этот предмет не является действительным фейерверком. - invalidHand: Вы должны держать фейерверк в своей основной руке. - removed: Удален фейерверк квеста! - goToLocation: '§aПерейдите в нужное место для этапа.' - invalidColor: Введенный вами цвет недействителен. Он должен быть либо шестнадцатеричным, либо RGB. - invalidPattern: '§cНедопустимый шаблон регулярного выражения §4{input}§c.' - itemCreator: - invalidBlockType: '§cНедопустимый тип блока.' - invalidItemType: '§cНедопустимый тип предмета. (Предмет не может быть блоком.)' - itemAmount: '§aНапишите количество предметов:' - itemLore: '§aИзмените описание предмета: (Напишите "help" для помощи)' - itemName: '§aВведите название предмета:' - itemType: '§aНапишите название блока для добычи:' - unknownBlockType: '§cНеизвестный тип блока.' - unknownItemType: '§cНеизвестный тип предмета.' mythicmobs: - disabled: '§cMythicMob отключен.' - isntMythicMob: '§cЭтот Mythic Mob не существует.' list: '§aСписок всех Mythic Mobs:' + isntMythicMob: '§cЭтот Mythic Mob не существует.' + disabled: '§cMythicMob отключен.' + advancedSpawnersMob: 'Напишите имя пользовательского моба-спавнера, которого нужно убить:' + textList: + syntax: '§cПравильный синтаксис: ' + added: '§aТекст "§7{msg}§a" добавлен.' + removed: '§aТекст "§7{msg}§a" удален.' + help: + header: '§6§lBeautyQuests — помощь редактора диалогов' + add: '§6add <сообщение>: §eДобавить текст.' + remove: '§6remove <id>: §eУдалить сообщение.' + list: '§6close: §eПодтвердить все сообщения.' + close: '§6close: §eПроверить добавленные тексты.' + availableElements: 'Доступные элементы: §e{available_elements}' noSuchElement: '§cНет такого элемента. Допустимые элементы: §e{available_elements}' - npc: - choseStarter: '§aВыберите NPC который начинает квест.' - enter: '§aНажмите на NPC или напишите "cancel".' - notStarter: '§cЭтот NPC не начинает квест.' + invalidPattern: '§cНедопустимый шаблон регулярного выражения §4{input}§c.' + comparisonTypeDefault: '§aВыберите нужный вам тип сравнения среди {available}. Сравнение по умолчанию: §e§l{default}§r§a. Введите §onull§r§a, чтобы использовать его.' + scoreboardObjectiveNotFound: '§cНеизвестный объект таблицы.' pool: - hologramText: Напишите пользовательский текст голограммы для этого бассейна (или напишите "null", если вы хотите использовать текст по умолчанию). - maxQuests: Напишите максимальное количество заданий, запускаемых из этого пула. - questsPerLaunch: Напишите количество заданий, которое игроки смогут получить, нажав на NPC. + hologramText: 'Напишите пользовательский текст голограммы для этого бассейна (или напишите "null", если вы хотите использовать текст по умолчанию).' + maxQuests: 'Напишите максимальное количество заданий, запускаемых из этого пула.' + questsPerLaunch: 'Напишите количество заданий, которое игроки смогут получить, нажав на NPC.' timeMsg: 'Укажите время, за которое игроки смогут выполнить новый квест. (единица измерения по умолчанию: дни)' - scoreboardObjectiveNotFound: '§cНеизвестный объект таблицы.' - selectWantedBlock: '§aНажмите с палкой на нужном блоке для сцены.' + title: + title: 'Напишите текст заголовка (или «null», если не хотите).' + subtitle: 'Напишите текст подзаголовка (или «null», если не хотите).' + fadeIn: 'Запишите продолжительность «постепенного появления» в тиках (20 тиков = 1 секунда).' + stay: 'Запишите продолжительность «пребывания» в тиках (20 тиков = 1 секунда).' + fadeOut: 'Запишите продолжительность «постепенного исчезновения» в тиках (20 тиков = 1 секунда).' + colorNamed: 'Введите название цвета.' + color: 'Введите цвет в шестнадцатеричном формате (#XXXXX) или формате RGB (RED GRE BLU).' + invalidColor: 'Введенный вами цвет недействителен. Он должен быть либо шестнадцатеричным, либо RGB.' + firework: + invalid: 'Этот предмет не является действительным фейерверком.' + invalidHand: 'Вы должны держать фейерверк в своей основной руке.' + edited: 'Отредактировал фейерверк квеста!' + removed: 'Удален фейерверк квеста!' + writeCommandDelay: '§aНапишите нужную задержку команд в галочках.' +advancement: + notStarted: Не начато +inv: + validate: '§b§lПодтвердить' + cancel: '§c§lОтменить' + search: '§e§lПоиск' + addObject: '§aДобавить объект' + confirm: + name: Вы уверены? + 'yes': '§aПодтвердить' + 'no': '§cОтменить' + create: + stageCreate: '§aСоздать новый этап' + stageRemove: '§cУдалить этот этап' + stageUp: Переместиться выше + stageDown: Переместить ниже + stageType: '§7Тип этапа: §e{stage_type}' + cantFinish: '§7Вы должны создать хотя бы один этап, чтобы закончить создание квеста!' + findNPC: '§aНайти NPC' + bringBack: '§aВернуть предметы' + findRegion: '§aНайти регион' + killMobs: '§aУбить мобов' + mineBlocks: '§aСломать блоки' + placeBlocks: '§aПоставить блоки' + talkChat: '§aНаписать в чат' + interact: '§aВзаимодействовать с блоком' + fish: '§aНаловить рыбы' + melt: '§6Плавка предметов' + enchant: '§dЗачаровываные предметы' + craft: '§aСкрафтить предмет' + bucket: '§aЗаполнить ведро' + location: '§aДойти до локации' + playTime: '§eВремя игры' + breedAnimals: '§aРазводите животных' + tameAnimals: '§aПриручите животных' + death: '§cСкончался' + dealDamage: '§cНаносить урон мобам' + eatDrink: '§aЕшьте или пейте пищу, зелья' + NPCText: '§eОтредактировать диалог' + NPCSelect: '§eВыберите или создайте NPC' + hideClues: Скрыть частицы и голограммы + editMobsKill: '§eСменить мобов, для убийства' + mobsKillFromAFar: Требует убийства снарядом + editBlocksMine: '§eСменить блоки для разрушения' + preventBlockPlace: Запретить игрокам ломать свои блоки + editBlocksPlace: '§eСменить блоки для размещения' + editMessageType: '§eРедактировать сообщение для записи' + cancelMessage: Отменить отправку + ignoreCase: Игнорировать регистр сообщения + selectItems: '§eОтредактировать требуемые предметы' + selectItemsMessage: '§eРедактировать запрашивающее сообщение' + selectItemsComparisons: '§eВыбор сравнения товаров (ADVANCED) (РАСШИРЕННЫЙ)' + selectRegion: '§7Выберите регион' + toggleRegionExit: При выходе + stageStartMsg: '§eОтредактировать стартовое сообщение' + selectBlockLocation: '§eВыберите местоположение блока' + selectBlockMaterial: '§eВыбрать материал блока' + leftClick: Щелчок должен быть левой кнопкой + editFishes: '§eРедактируйте рыбы, чтобы поймать' + editItemsToMelt: '§eОтредактируйте элементы, чтобы расплавить' + editItemsToEnchant: '§eРедактируйте предметы для зачарования' + editItem: '§eРедактировать предмет для создания' + editBucketType: '§eРедактировать тип ведра для заполнения' + editBucketAmount: '§aНапишите количество вёдер для заполнения' + editLocation: '§eРедактировать местоположение' + editRadius: '§eРедактировать расстояние от места' + currentRadius: '§eТекущее расстояние: §6{radius}' + changeTicksRequired: '§eТребуются изменения галочек игры' + changeEntityType: '§eИзменить тип объекта' stage: location: - typeWorldPattern: '§aНапишите регулярное выражение для мировых названий:' - text: - argNotSupported: '§cАргумент {arg} не поддерживается.' - chooseJobRequired: '§aНапишите имя нужной работы:' - chooseLvlRequired: '§aНапишите необходимое количество уровней:' - chooseMoneyRequired: '§aНапишите количество предметов:' - chooseObjectiveRequired: '§aЗапишите название цели.' - chooseObjectiveTargetScore: '§aНапишите целевой показатель для цели.' - choosePermissionMessage: '§aВы можете выбрать сообщение об отказе игроку, если у него нет необходимого разрешения. (Чтобы пропустить этот шаг, напишите "null".)' - choosePermissionRequired: '§aНапишите необходимое разрешение для запуска квеста:' - choosePlaceholderRequired: - identifier: '§aЗапишите имя необходимого плейсхолдера без процентов символов:' - value: '§aЗапишите необходимое значение для заполнителя §e%§e{placeholder}§e%§a:' - chooseRegionRequired: '§aВведите название нужного региона (вы должны быть в том же мире).' - chooseSkillRequired: '§aНапишите название необходимого навыка:' - reward: - money: '§aНапишите сумму полученных денег:' - permissionName: '§aЗапишите имя разрешения.' - permissionWorld: '§aНапишите мир, в котором разрешение будет отредактировано, или "null", если вы хотите быть глобальным.' - random: - max: Напишите максимальную сумму вознаграждений, выданных игроку (включительно). - min: '§aНапишите минимальную сумму вознаграждений, предоставляемых игроку (включительно).' - wait: '§aНапишите количество игровых тактов для ожидания: (1 секунда = 20 игровых тактов)' - textList: - added: '§aТекст "§7{msg}§a" добавлен.' - help: - add: '§6add <сообщение>: §eДобавить текст.' - close: '§6close: §eПроверить добавленные тексты.' - header: '§6§lBeautyQuests — помощь редактора диалогов' - list: '§6close: §eПодтвердить все сообщения.' - remove: '§6remove <id>: §eУдалить сообщение.' - removed: '§aТекст "§7{msg}§a" удален.' - syntax: '§cПравильный синтаксис: ' - title: - fadeIn: Запишите продолжительность «постепенного появления» в тиках (20 тиков = 1 секунда). - fadeOut: Запишите продолжительность «постепенного исчезновения» в тиках (20 тиков = 1 секунда). - stay: Запишите продолжительность «пребывания» в тиках (20 тиков = 1 секунда). - subtitle: Напишите текст подзаголовка (или «null», если не хотите). - title: Напишите текст заголовка (или «null», если не хотите). - typeBucketAmount: '§aНапишите количество вёдер для заполнения:' - typeDamageAmount: 'Напишите количество урона, который игрок должен нанести:' - typeGameTicks: '§aНапишите необходимое количество игровых тактов:' - typeLocationRadius: '§aЗапишите требуемое расстояние от локации:' - errorOccurred: '§cПроизошла ошибка, свяжитесь с администратором! §4§lКод ошибки: {error}' - experience: - edited: '§aВы изменили добычу опыта с {old_xp_amount} до {xp_amount} очков.' - indexOutOfBounds: '§cЧисло {index} за пределами! Оно должно между {min} и {max}.' - invalidBlockData: '§cДанные блока {block_data} недопустимы или несовместимы с блоком {block_material}.' - invalidBlockTag: '§cНедоступный блочный тег {block_tag}.' - inventoryFull: '§cВаш инвентарь переполнен, предмет выпал на землю.' - moveToTeleportPoint: '§aПерейдите к локации для телепорта.' - npcDoesntExist: '§cNPC с идентификатором {npc_id} не существует.' - number: - invalid: '§c{input} не допустимое число.' - negative: '§cВы должны ввести положительное число!' - notInBounds: Число должно быть между {min} и {max} - zero: '§cВы должны ввести число, отличное от 0!' - pools: - allCompleted: '§7Вы завершили все задания!' - maxQuests: '§cУ вас не может быть более {pool_max_quests} заданий одновременно...' - noAvailable: '§7Заданий больше не осталось...' - noTime: '§cВы должны подождать {time_left} перед выполнением другого задания.' - quest: - alreadyStarted: '§cВы уже начали квест!' - cancelling: '§cПроцесс создания квеста был прерван.' - createCancelled: '§cСоздание или редактирование было отменено другим плагином!' - created: '§aПоздравляем! Вы создали квест §е{quest}§a, в который входит {quest_branches} ответвление(я)!' - editCancelling: '§cПроцесс редактирования квеста был прерван.' - edited: '§aПоздравляем! Вы отредактировали квест §е{quest}§a, в который входит {quest_branches} ответвление(я)!' - finished: - base: '§aПоздравляем! Вы успешно выполнили квест §e{quest_name}§a!' - obtain: '§aВы получили {rewards}!' - invalidID: '§cКвест под номером {quest_id}, не найден.' - invalidPoolID: '§cВетка {pool_id} не существует.' - notStarted: '§cВ данный момент вы не выполняете этот квест.' - started: '§aВы начали квест §r§e{quest_name}§o§6!' - questItem: - craft: '§cВы не можете использовать предмет задания для крафта!' - drop: '§cВы не можете выбросить предмет из задания!' - eat: '§cВы не можете съесть это!' - quests: - checkpoint: '§7Квест достиг контрольной точки!' - failed: '§cВы провалили задание {quest_name}...' - maxLaunched: '§cВы не можете взять больше {quests_max_amount} задания(й) одновременно...' - updated: '§7Квест §e{quest_name}§7 был обновлён.' - regionDoesntExists: '§cЭтот регион не существует. (Вы должны быть в том же мире.)' - requirements: - combatLevel: '§cВаш уровень боя должен быть {long_level}!' - job: '§cВаш уровень для работы §e{job_name}должен быть {long_level}!' - level: '§cВаш уровень должен быть {long_level}!' - money: '§cВы должны иметь {money}!' - quest: '§cВы должны выполнить квест §e{quest_name}§c!' - skill: '§cВаш уровень навыка §e{skill_name}§c должен быть {long_level}!' - waitTime: '§o{time_left} минут(ы), прежде чем вы сможете перезапустить задание!' - restartServer: '§7Перезагрузите сервер, чтобы увидеть изменения.' - selectNPCToKill: '§aВыберите NPC для удаления.' - stageMobs: - listMobs: '§aВам нужно убить {mobs}.' - typeCancel: '§aНапишите "cancel", чтобы вернуться к прежнему тексту.' - versionRequired: 'Требуемая версия: §l{version}' - writeChatMessage: '§aНапишите требуемое сообщение: (Добавьте "{SLASH}" в начало если вы хотите выполнить команду.)' - writeCommand: '§aВведите нужную команду: (Команда без "/" и заполнения"{PLAYER} поддерживается. Оно будет заменено на имя исполнителя команды.)' - writeCommandDelay: '§aНапишите нужную задержку команд в галочках.' - writeConfirmMessage: '§aНапишите сообщение для подтверждения, которое будет показано когда игрок собирается начать задание: (Напишите "null", если вы хотите отправить сообщение по умолчанию.)' - writeDescriptionText: '§aНапишите текст, который описывает цель этапа:' - writeEndMsg: '§aНапишите сообщение, которое будет отправлено в конце квеста, "null", если вы хотите стандартное сообщение или "none", если вы не хотите никакое. Вы можете использовать "{rewards}", оно будет заменено на награду' - writeEndSound: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' - writeHologramText: '§aЗапишите текст голограммы: (Напишите "none", если вы не желаете добавлять голограмму и «null", если хотите текст по умолчанию.)' - writeMessage: '§aНапишите сообщение, которое будет отправлено игроку' - writeMobAmount: '§aНапишите количество мобов для убийства:' - writeMobName: '§aЗапишите Имя моба которого надо убить:' - writeNPCText: '§aНапишите диалог, который будет отправлен игроку от NPC: (Напишите "help" для помощи.)' - writeNpcName: '§aНапишите название NPC:' - writeNpcSkinName: '§aНапишите название скина NPC:' - writeQuestDescription: '§aНапишите описание квеста, которое будет отображаться в квестовом интерфейсе игрока.' - writeQuestMaterial: '§aНапишите материал квестового предмета.' - writeQuestName: '§aНапишите название вашего квеста:' - writeQuestTimer: '§aЗапишите необходимое время (в минутах), прежде чем вы сможете перезагрузить квест: (Напишите "null", если вы хотите установить время по умолчанию.)' - writeRegionName: '§aВведите название региона, необходимого для этапа:' - writeStageText: '§aНапишите текст, который будет отправлен игроку в начале этапа:' - writeStartMessage: '§aНапишите сообщение, которое будет отправлено в начале задания: «null», если вы хотите использовать значение по умолчанию, или «none», если вы не хотите:' - writeXPGain: '§aНапишите количество очков опыта, которые получит игрок: (Крайнее значение: {xp_amount})' + worldPattern: '§aУстановить шаблон имени мира §d(ДОПОЛНИТЕЛЬНО)' + worldPatternLore: 'Если вы хотите, чтобы этап был завершен для любого мира, соответствующего определенному шаблону, введите здесь regex (регулярное выражение).' + death: + causes: '§aУстановить причины смерти §d(ДОПОЛНИТЕЛЬНО)' + anyCause: Любая причина смерти + setCauses: '{causes_amount} причина(ы) смерти' + dealDamage: + damage: '§eНаносить урон' + targetMobs: '§cМобы, наносящие урон' + eatDrink: + items: '§eРедактировать предметы для еды или питья' + stages: + name: Создать этапы + nextPage: '§eСледующая страница' + laterPage: '§eПредыдущая страница' + endingItem: '§eРедактировать конечные награды' + descriptionTextItem: '§eРедактировать описание' + regularPage: '§aОбычные этапы' + branchesPage: '§dЭтапы ответвления' + previousBranch: '§eВернуться к предыдущему ответвлению' + newBranch: '§eПерейти к новому ответвлению' + validationRequirements: '§eТребования к валидации' + validationRequirementsLore: Все требования должны соответствовать игроку, который пытается завершить стадию. Если нет, стадия не может быть завершена. + details: + hologramLaunch: '§eРедактировать пункт "Launch" голограммы' + hologramLaunchLore: Когда игрок может начать квест, голограмма отображается над головой Стартового NPC. + hologramLaunchNo: '§eРедактировать голограмму "Запуск недоступен"' + hologramLaunchNoLore: Голограмма отображается над головой стартового NPC, когда игрок НЕ может начать задание. + customConfirmMessage: '§eОтредактировать сообщение для подтверждения квеста' + customConfirmMessageLore: Сообщение, отображаемое в интерфейсе подтверждения когда игрок собирается начать квест. + customDescription: '§eРедактировать описание' + customDescriptionLore: Описание, показанное под названием квеста в GUI. + name: Информация о последней ошибке + multipleTime: + itemName: Переключить повтор. + itemLore: Можно ли выполнить квест несколько раз? + cancellable: Отменяется игроком + cancellableLore: Позволяет игроку отменить квест через меню квестов. + startableFromGUI: Запускается из графического интерфейса + startableFromGUILore: Позволяет игроку начать квест из меню квестов. + scoreboardItem: Включить табло + scoreboardItemLore: Если этот параметр отключен, квест не будет отслеживаться на табло. + hideNoRequirementsItem: Скрыть когда требования не выполнены + hideNoRequirementsItemLore: Если включено, задание не будет отображаться в меню заданий, когда требования не выполняются. + bypassLimit: Не считайте лимит квестов + bypassLimitLore: Если этот параметр включен, квест будет запущен, даже если игрок достиг максимального количества начатых квестов. + auto: Запускать автоматически при первом подключении + autoLore: Если этот параметр включен, задание будет запускаться автоматически, когда игрок впервые присоединяется к серверу. + questName: '§a§lИзменить название квеста' + questNameLore: Для завершения создания квеста необходимо указать имя. + setItemsRewards: '§eРедактировать награды' + removeItemsReward: '§eУдалить предметы из инвентаря' + setXPRewards: '§eИзменить опыт вознаграждения' + setCheckpointReward: '§eИзменить награды контрольной точки' + setRewardStopQuest: '§cОстановить задание' + setRewardsWithRequirements: '§eНаграды с требованиями' + setRewardsRandom: '§dСлучайные награды' + setPermReward: '§eРедактировать разрешения' + setMoneyReward: '§eИзменить денежное вознаграждение' + setWaitReward: '§eИзменить награду "ждать"' + setTitleReward: '§eИзменить название награды' + selectStarterNPC: '§e§lВыберите NPC, который будет начинать квест ' + selectStarterNPCLore: Щелчок по выбранному NPC запустит квест. + selectStarterNPCPool: '§c⚠ Выбрана группа квестов' + createQuestName: '§lСоздать квест' + createQuestLore: Вы должны определить название квеста. + editQuestName: '§lИзменить квест' + endMessage: '§eИзменить конечное сообщение' + endMessageLore: Сообщение, которое будет отправлено игроку в конце квеста. + endSound: '§eРедактировать конечный звук' + endSoundLore: Звук, который будет воспроизведен в конце квеста. + startMessage: '§eИзменить стартовое сообщение' + startMessageLore: Сообщение, которое будет отправлено игроку в начале задания. + startDialog: '§eРедактировать стартовый диалог' + startDialogLore: Диалог, который будет воспроизведен перед началом квестов, когда игроки нажмут на стартового NPC. + editRequirements: '§eИзменить требования' + editRequirementsLore: Все требования должны применяться к игроку, прежде чем он сможет начать квест. + startRewards: '§6Начальные награды' + startRewardsLore: Действия, выполняемые при запуске квеста. + cancelRewards: '§cОтменить действия' + cancelRewardsLore: Действия, выполняемые, когда игроки отменяют это задание. + hologramText: '§eТекст голограммы' + hologramTextLore: Текст отображается на голограмме над головой стартового NPC. + timer: '§bПерезапустить таймер' + timerLore: Время до того, как игрок сможет снова начать квест. + requirements: '{amount} требование(я)' + rewards: '{amount} награда(ы)' + actions: '{amount} действие(s)' + rewardsLore: Действия, выполняемые по окончании квеста. + customMaterial: '§eРедактировать материал квестового предмета ' + customMaterialLore: Предмет этого квеста в меню квестов. + failOnDeath: Неудача при смерти + failOnDeathLore: Будет ли квест отменен после смерти игрока? + questPool: '§eБассейн заданий' + questPoolLore: Прикрепить это задание к бассейну заданий + firework: '§dЗавершение Фейерверка' + fireworkLore: Фейерверк запускается, когда игрок заканчивает задание + fireworkLoreDrop: Перетащите свой собственный фейерверк здесь + visibility: '§bВидимость задания' + visibilityLore: Выберите, на каких вкладках меню будет отображаться задание, и будет ли оно отображаться на динамических картах. + keepDatas: Сохранять данные игроков + keepDatasLore: |- + Заставить плагин сохранять данные игроков, даже если этапы были отредактированы. §c§lПРЕДУПРЕЖДЕНИЕ§c- включение этой опции может нарушить данные ваших игроков. + loreReset: '§e§lДостижения всех игроков будут сброшены' + optionValue: '§fЗначение: §7{value}' + defaultValue: '§f(значение по умолчанию)' + requiredParameter: '§7Необходимый параметр' + itemsSelect: + name: Редактировать предметы + none: |- + §aПереместите предмет здесь или кликните, чтобы открыть редактор предметов + itemSelect: + name: Выбрать предмет + npcCreate: + name: Создать NPC + setName: '§eРедактировать имя NPC' + setSkin: '§eРедактировать скин NPC' + setType: '§eРедактировать тип NPC' + move: + itemName: '§eПередвинуть' + itemLore: '§aИзменить местоположение NPC.' + moveItem: '§a§lПроверить место' + npcSelect: + name: Выбрать или создать? + selectStageNPC: '§eВыберите существующий NPC' + createStageNPC: '§eСоздать NPC' + entityType: + name: Выберите тип сущности + chooseQuest: + name: Какой квест? + menu: '§aМеню квестов' + menuLore: Приведет вас к меню ваших квестов. + mobs: + name: Выберите мобов + none: '§aНажмите, чтобы добавить моба.' + editAmount: Редактировать сумму + editMobName: Изменить название моба + setLevel: Установите минимальный уровень + mobSelect: + name: Установите тип моба + bukkitEntityType: '§eВыберите тип объекта' + mythicMob: '§6Выберите мифический моб' + epicBoss: '§6Выберите эпического босса' + boss: '§6Выберите босса' + stageEnding: + locationTeleport: '§eРедактировать местоположение телепорта' + command: '§eРедактировать выполненную команду' + requirements: + name: Требования + setReason: Установите пользовательскую причину + rewards: + name: Награды + commands: 'Команды: {amount}' + random: + rewards: Редактировать награды + minMax: Редактировать минимальное и максимальное значение + checkpointActions: + name: Значок контрольной точки + cancelActions: + name: Отменить действия + rewardsWithRequirements: + name: Награды с требованиями + listAllQuests: + name: Квесты + listPlayerQuests: + name: 'Задания {player_name}' + listQuests: + notStarted: Не начатые квесты + finished: Завершенные квесты + inProgress: Квесты в процессе выполнения + loreDialogsHistoryClick: '§7Просмотр диалоговых окон' + loreCancelClick: '§cОтменить квест' + loreStart: '§a§oНажмите, чтобы начать задание.' + loreStartUnavailable: '§c§oВы не соответствуете требованиям для начала задания.' + canRedo: '§3§oВы можете перевыполнить этот квест!' + itemCreator: + name: Создатель предмета + itemType: '§bТип предмета' + itemFlags: Вкл/выкл флаги элемента + itemName: '§bНазвание предмета' + itemLore: '§bЛор' + isQuestItem: '§bQuest предмет:' + command: + name: Команда + value: '§eКоманда' + console: Консоль + parse: Разбор заполнителей + delay: '§bЗадержка' + chooseAccount: + name: Какой аккаунт? + listBook: + questName: Имя + questStarter: Старт + questRewards: Награды + questMultiple: Несколько раз + requirements: Требования + questStages: Этапы + noQuests: Ранее заданий не создано. + commandsList: + name: Список команд + value: '§Команды: {command_label}' + console: '§eКонсоль: {command_console}' + block: + name: Выбрать блок + material: '§eМатериал: {block_type}' + blockData: '§dБлокировать данные (дополнительно)' + blocksList: + name: Выбрать блок + addBlock: '§aНажмите, чтобы добавить блок.' + blockAction: + name: Выберите действие блока + location: '§eВыберите точное место' + material: '§eВыберите материал блока' + buckets: + name: Тип ведра + permission: + name: Выберите разрешение + perm: '§aРазрешение' + world: '§aМир' + worldGlobal: '§b§lГлобальный' + remove: Удалить разрешение + removeLore: '§7Разрешение будет снято\n§7вместо данного.' + permissionList: + name: Список разрешений + removed: '§eСнятый: §6{permission_removed}' + world: '§eМир: §6{permission_world}' + classesRequired.name: Требуются классы + classesList.name: Список классов + factionsRequired.name: Требуются фракции + factionsList.name: Список фракций + poolsManage: + name: Объединенные задания + poolMaxQuests: '§8Максимум заданий: §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Количество заданий, выдаваемых за запуск: §7{pool_quests_per_launch}' + poolRedo: '§8Можно переделывать выполненные задания: §7{pool_redo}' + poolTime: '§8Время между заданиями: §7{pool_time}' + poolHologram: '§8Текст голограммы: §7{pool_hologram}' + poolAvoidDuplicates: '§8Избегайте дублирования: §7{pool_duplicates}' + poolQuestsList: '§7{pool_quests_amount} §8задание(й): §7{pool_quests}' + create: '§aСоздать Объединенные задания' + edit: '§e> §6§oРедактировать Объединенные... §e<' + choose: '§e> §6§oВыберите этот список §e<' + poolCreation: + name: Создание Объединенных заданий + hologramText: '§eПользовательское объединенние голограмм' + maxQuests: '§aМаксимум заданий' + questsPerLaunch: '§aКоличество заданий, выдаваемых за запуск' + time: '§bУстановить время между заданиями' + redoAllowed: Повтор разрешён + avoidDuplicates: Избегайте дублирования + avoidDuplicatesLore: '§8> §7Старайтесь не выполнять\n одно и то же задание снова и снова.' + requirements: '§bТребования для начала задания' + poolsList.name: Бассейны квестов + itemComparisons: + name: Сравнение предметов + bukkit: Bukkit родное сравнение + bukkitLore: "Использует систему сравнения товаров Bukkit по умолчанию.\nСравнивает материал, долговечность, NBT теги..." + customBukkit: Bukkit родное сравнение - NO NBT + customBukkitLore: "Использует систему сравнения товаров Bukkit по умолчанию, но стирает теги NBT.\nСравнивает материал, долговечность..." + material: Материал предмета + materialLore: 'Сравнивает материал предмета (например, камень, железный меч ...)' + itemName: Название предмета + itemNameLore: Сравнивает названия предметов + itemLore: Описание предмета + itemLoreLore: Сравнивает данные предметов + enchants: Чары предметов + enchantsLore: Сравнивает зачарованные предметы + repairCost: Стоимость ремонта + repairCostLore: Сравнивает стоимость ремонта доспехов и мечей. + editTitle: + name: Изменить заголовок + title: '§6Заголовок' + subtitle: '§eПодзаголовок' + fadeIn: '§aПродолжительность постепенного появления' + stay: '§bПродолжительность пребывания' + fadeOut: '§aПродолжительность затухания' + damageCause: + name: Причина повреждения + damageCausesList: + name: Список причин повреждений + visibility: + name: Видимость квеста + notStarted: 'Вкладка меню "Не запущено"' scoreboard: - asyncEnd: '§бывший' name: '§6§lЗАДАНИЯ' noLaunched: '§cНет заданий в процессе выполнения.' - noLaunchedDescription: '§c§oЗагрузка' noLaunchedName: '§c§lЗагрузка' + noLaunchedDescription: '§c§oЗагрузка' + textBetwteenBranch: '§e или' + asyncEnd: '§бывший' stage: - breed: '§eПорода §6{mobs}' - bucket: '§eЗаполнить §6{buckets}' + region: '§eНайти регион §6{region_id}' + npc: '§eПоговорить с NPC §6{dialog_npc_name}' + mobs: '§eУбить §6{mobs}' + mine: '§eДобыть {blocks}' + placeBlocks: '§eРазместить {blocks}' chat: '§eНаписать §6{text}' - craft: '§eСоздать §6{items}' - fish: '§eНаловить §6{items}' - interact: '§eНажмите на блок в §6{x}' interactMaterial: '§eКликните на §6{block}§e блок' - items: '§eВерните предметы:' + fish: '§eНаловить §6{items}' + craft: '§eСоздать §6{items}' + bucket: '§eЗаполнить §6{buckets}' location: '§eИди к §6{target_x}§e, §6{target_y}§e, §6{target_z}§e в §6{target_world}' - mine: '§eДобыть {blocks}' - mobs: '§eУбить §6{mobs}' - npc: '§eПоговорить с NPC §6{dialog_npc_name}' - placeBlocks: '§eРазместить {blocks}' - region: '§eНайти регион §6{region_id}' + breed: '§eПорода §6{mobs}' tame: '§eПриручить §6{mobs}' - textBetwteenBranch: '§e или' + die: '§cЭта' +indication: + startQuest: '§7Вы хотите начать квест {quest_name}?' + closeInventory: '§7Вы уверены, что хотите закрыть этот интерфейс?' + cancelQuest: '§7Вы уверены, что хотите отменить квест {quest_name}?' + removeQuest: '§7Вы уверены, что хотите удалить квест {quest}?' + removePool: '§7 Вы уверены, что хотите удалить пул {pool}?' +description: + requirement: + title: '§8§lТребования:' + level: 'Уровень {short_level}' + jobLevel: 'Уровень {short_level} для {job_name}' + combatLevel: 'Боевой уровень {short_level}' + skillLevel: 'Уровень {short_level} для {skill_name}' + class: 'Класс {class_name}' + faction: 'Фракция {faction_name}' + quest: 'Закончите квест §e{quest_name}' + reward: + title: '§8§lНаграды:' +misc: + format: + prefix: '§6<§e§lКвесты§r§6> §r' + time: + weeks: '{weeks_amount} недель' + days: '{days_amount} дней' + hours: '{hours_amount} часов' + minutes: '{minutes_amount} минут' + lessThanAMinute: 'меньше минуты' + stageType: + region: Найти регион + npc: Найти NPC + items: Вернуть предметы + mobs: Убивать мобов + mine: Сломать блоки + placeBlocks: Разместите блоки + chat: Пиши в чат + interact: Взаимодействовать с блоком + Fish: Ловить рыбу + Craft: Создать предмет + Bucket: Наполнить ведро + location: Найти место + playTime: Время игры + breedAnimals: Разводите животных + tameAnimals: Приручить животных + dealDamage: Наносит урон + comparison: + equals: равно {number} + different: отличается от {number} + less: строго меньше {number} + lessOrEquals: меньше чем {number} + greater: строго больше {number} + greaterOrEquals: больше чем {number} + requirement: + logicalOr: '§dЛогическое ИЛИ (требования)(requirements)' + skillAPILevel: '§bтребуемый уровень SkillAPI' + class: '§bТребуются классы' + faction: '§bТребуются фракции' + jobLevel: '§bТребуемый уровень должности' + combatLevel: '§bТребуется боевой уровень' + experienceLevel: '§bНеобходимый уровень опыта' + permissions: '§3Требуется разрешение(а)' + scoreboard: '§dТребуется оценка' + region: '§dТребуется регион' + placeholder: '§bТребуется значение placeholder' + quest: '§aТребуется квест' + mcMMOSkillLevel: '§dТребуемый уровень mcMMOSkillLevel' + money: '§dТребуются деньги' + bucket: + water: Ведро воды + lava: Ведро лавы + milk: Ведро молока + click: + right: ПКМ + left: ЛКМ + shift-right: Shift+щелчок правой + shift-left: Shift+щелчок левой + amounts: + comparisons: '{comparisons_amount} сравнение(ы)' + ticks: '{ticks} тиков' + questItemLore: '§e§oКвестовый предмет' + hologramText: '§8§lКвестовый NPC' + poolHologramText: '§eДоступно новое задание!' + entityType: '§eТип объекта: {entity_type}' + entityTypeAny: '§eЛюбая сущность' + enabled: Включено + disabled: Выключено + unknown: неизвестно + notSet: '§cне установлено' + reset: Перезагрузка + or: или + amount: '§eКоличество: {amount}' + 'yes': 'Да' + 'no': 'Нет' + and: и diff --git a/core/src/main/resources/locales/zh_CN.yml b/core/src/main/resources/locales/zh_CN.yml index 72baa334..2cd2d57d 100644 --- a/core/src/main/resources/locales/zh_CN.yml +++ b/core/src/main/resources/locales/zh_CN.yml @@ -1,801 +1,831 @@ --- -advancement: - finished: Finished - notStarted: Not started -description: - requirement: - class: '{class_name} 职业' - combatLevel: 战斗等级 {short_level} - faction: '{faction_name} 派系' - jobLevel: '{job_name} {short_level}级' - level: '{short_level}级' - quest: 完成任务 §e{quest_name} - skillLevel: '{skill_name} {short_level}级' - title: '§8§l要求:' - reward: - title: '§8§l奖励:' -indication: - cancelQuest: '§7您确定要取消任务 {quest_name}?' - closeInventory: '§7你确定要关闭该页面吗?' - removeQuest: '§7您确定要删除任务 {quest}?' - startQuest: '§7您是否想要接受任务 {quest_name}?' -inv: - addObject: '§a添加一个目标' - block: - blockData: '§d方块数据(高级)' - blockName: '§b自定义方块名称' - blockTag: '§d标签 (高级)' - blockTagLore: 选择描述可能方块列表的标签。可使用数据包自定义标签。你可以在Minecraft Wiki查询标签列表。 - material: '§e材料: {block_type}' - materialNotItemLore: 所选方块无法显示为物品。它仍正确地存储为{block_material}。 - name: 选择方块 - blockAction: - location: '§e选择精确位置' - material: '§e选择方块材料' - name: 选择方块行动 - blocksList: - addBlock: '§a点击添加一个方块.' - name: 选择方块 - buckets: - name: 桶的类型 - cancel: '§c§l取消' - cancelActions: - name: 取消行动 - checkpointActions: - name: 记录点行动 - chooseAccount: - name: '§5选择哪一个帐号?' - chooseQuest: - menu: '§a任务菜单' - menuLore: 前往任务菜单。 - name: '§5选择哪一个任务?' - classesList.name: 职业列表 - classesRequired.name: 所需职业 - command: - console: 控制台 - delay: '§b延迟' - name: '§8指令' - parse: 解析占位符 - value: '§b指令' - commandsList: - console: '§e控制台: {command_console}' - name: 指令列表 - value: '§e指令: {command_label}' - confirm: - name: '§8你确认?' - 'no': '§c让我再想想' - 'yes': '§a确认' - create: - NPCSelect: '§e选择或创建NPC' - NPCText: '§e编辑NPC的文本对话' - breedAnimals: '§a饲养动物' - bringBack: '§a带回物品' - bucket: '§a装满桶' - cancelMessage: 取消发送 - cantFinish: '§7你必须先创建至少一个任务阶段!' - changeEntityType: '§e更改实体类型' - changeTicksRequired: '§e需要更改游玩刻' - craft: '§a合成物品' - currentRadius: '§e当前距离: §6{radius}' - dealDamage: '§c对怪物造成伤害' - death: '§c死亡' - eatDrink: '§a食用食物或饮用药水' - editBlocksMine: '§e编辑要破坏的方块' - editBlocksPlace: '§e编辑要放置的方块' - editBucketAmount: '§e编辑要装满的桶数量' - editBucketType: '§e编辑要装满的桶类型' - editFishes: '§e编辑所需的鱼' - editItem: '§e编辑要合成的物品' - editItemsToEnchant: '§e编辑要附魔的物品' - editItemsToMelt: '§e编辑要熔炼的物品' - editLocation: '§e编辑位置' - editMessageType: '§e编辑要输入的消息' - editMobsKill: '§e编辑要击杀的怪物' - editRadius: '§e编辑离目的地的距离' - enchant: '§附魔物品' - findNPC: '§a寻找一个NPC' - findRegion: '§a找到一片区域' - fish: '§a钓鱼' - hideClues: 隐藏任务指示 (粒子效果和全息文字) - ignoreCase: 忽略消息大小写 - interact: '§a点击方块' - killMobs: '§a击杀怪物' - leftClick: 必须左击 - location: 前往指定位置 - melt: '§熔炼物品' - mineBlocks: '§a破坏方块' - mobsKillFromAFar: 需要远程击杀怪物 - placeBlocks: '§a放置方块' - playTime: '§e游戏时间' - preventBlockPlace: 防止玩家破坏方块 - replacePlaceholders: 使用PAPI替换{PLAYER}和占位符 - selectBlockLocation: '§6选择方块位置' - selectBlockMaterial: '§e选择方块材料' - selectItems: '§b选择所需的物品' - selectItemsComparisons: '§e选择物品比较式(高级)' - selectItemsMessage: '§e编辑询问消息' - selectRegion: '§7选择一片区域' - stage: - dealDamage: - damage: '§e要造成的伤害' - targetMobs: '§c要造成伤害的怪物对象' - death: - anyCause: 任何死因 - causes: '§a设置死因 §d(高级)' - setCauses: '{causes_amount} 死因' - eatDrink: - items: '§e编辑要食用或饮用的物品' - location: - worldPattern: '§a设置世界名称模式 §d(高级选项)' - worldPatternLore: 如果你想要匹配特定模式的任意世界都能完成任务阶段,请在此输入正则表达式。 - stageCreate: '§a创建新的阶段' - stageDown: 下移 - stageRemove: '§c删除这一阶段' - stageStartMsg: '§e编辑阶段开始的消息' - stageType: '§7阶段类型:§e{stage_type}' - stageUp: 上移 - talkChat: '§a在聊天框内输入' - tameAnimals: '§a驯服动物' - toggleRegionExit: 退出时 - damageCause: - name: 造成伤害 - damageCausesList: - name: 造成伤害列表 - details: - actions: '{amount}行动' - auto: 登录时自动开始任务 - autoLore: 如果启用,则玩家首次加入服务器时将自动开始该任务。 - bypassLimit: 忽略任务上限 - bypassLimitLore: 如果启用,即使玩家已经达到任务上限也能接受任务。 - cancelRewards: '§c取消行动' - cancelRewardsLore: 玩家取消该任务时触发的行动。 - cancellable: 玩家可取消任务 - cancellableLore: 允许玩家在任务菜单中取消任务。 - createQuestLore: 你必须设定任务名。 - createQuestName: '§l创建任务' - customConfirmMessage: '§e编辑确认接受任务的消息' - customConfirmMessageLore: 显示在确认菜单中的消息。 - customDescription: '§e编辑任务描述' - customDescriptionLore: 在GUI中显示在任务名下方的描述。 - customMaterial: '§a编辑任务物品材料名' - customMaterialLore: 在任务菜单中代表该任务的物品图标。 - defaultValue: '§8(默认值)' - editQuestName: '§l编辑任务' - editRequirements: '§e编辑需求' - editRequirementsLore: 接受任务所需前置。 - endMessage: '§a编辑任务结束消息' - endMessageLore: 将在任务结束时发送给玩家的消息。 - endSound: '§e编辑结束音效' - endSoundLore: 在任务结束时播放的音效。 - failOnDeath: 玩家死亡时任务失败 - failOnDeathLore: 当玩家死亡时是否取消任务? - firework: '§d任务结束烟花' - fireworkLore: 玩家完成任务时发射的烟花 - fireworkLoreDrop: 把你的自定义烟花放在这里 - hideNoRequirementsItem: 未满足需求时隐藏 - hideNoRequirementsItemLore: 如果启用,在未满足需求时任务将不会显示在任务菜单中。 - hologramLaunch: '§e编辑 “启动” 全息项' - hologramLaunchLore: 显示在接受任务的NPC头上的全息文字。 - hologramLaunchNo: '§e编辑 “启动不可用” 全息项' - hologramLaunchNoLore: 在玩家没有接受任务时显示在NPC头上的全息文字。 - hologramText: '§e全息文字' - hologramTextLore: 显示在可接受任务的NPC的头上的全息文字。 - keepDatas: 保留玩家数据 - keepDatasLore: '强制插件保存玩家数据,即使是已编辑阶段也会保存。 §c§l警告§c- 启用此选项可能会损坏你的玩家数据。' - loreReset: '§e§l所有玩家的进度将被重置' - multipleTime: - itemLore: 任务是否可以多次完成? - itemName: 切换是否可重复 - name: '§8最终任务详细设置' - optionValue: '§8数值:§7{value}' - questName: '§a§l编辑任务名' - questNameLore: 必须设置一个名称来创建任务。 - questPool: '§e任务池' - questPoolLore: 将该任务加到任务池中 - removeItemsReward: 从物品栏中移除物品 - requiredParameter: '§7所需参数' - requirements: '{amount} 个任务需求' - rewards: '{amount} 个奖励' - rewardsLore: 任务接受时执行的行动。 - scoreboardItem: 启用计分版 - scoreboardItemLore: 如果禁用,则该任务目标不会显示在计分板上。 - selectStarterNPC: '§6§l选择接受任务的NPC' - selectStarterNPCLore: 点击选中的NPC将开始任务。 - selectStarterNPCPool: '§c:⚠ 已选择一个任务池' - setCheckpointReward: '§e编辑记录点奖励' - setItemsRewards: '§7编辑获得的物品' - setMoneyReward: '§e编辑获得的金钱' - setPermReward: '§e编辑权限' - setRewardStopQuest: '§c停止任务' - setRewardsRandom: '§d随机奖励' - setRewardsWithRequirements: '§e需满足需求的奖励' - setTitleReward: '§e编辑标题奖励' - setWaitReward: '§e编辑“等待”奖励' - setXPRewards: '§e编辑获得的经验' - startDialog: '§e编辑任务开场白' - startDialogLore: 当玩家点击任务NPC时,在任务开始之前播放的对话框。 - startMessage: '§e编辑开始消息' - startMessageLore: 任务开始时发送给玩家的消息。 - startRewards: '§6开始任务的奖励' - startRewardsLore: 玩家接受任务时执行的行动。 - startableFromGUI: 可从GUI菜单中开始任务 - startableFromGUILore: 允许玩家在任务菜单中开始任务。 - timer: '§b重启计时器' - timerLore: 玩家可以再次开始任务的时间。 - visibility: '§b任务可见度' - visibilityLore: 选择在菜单栏何处显示任务,如果安装了卫星地图插件,则在地图上显示任务。 - editTitle: - fadeIn: '§a淡入持续时间' - fadeOut: '§a淡出持续时间' - name: 编辑标题 - stay: '§b停留持续时间' - subtitle: '§e副标题' - title: '§6标题' - entityType: - name: '§5选择生物类型' - equipmentSlots: - name: 装备栏位 - factionsList.name: 派系列表 - factionsRequired.name: 所需派系 - itemComparisons: - bukkit: Bukkit原生比较 - bukkitLore: 使用Bukkit默认项目的比较系统。 比较材料、耐久度、NBT标签…… - customBukkit: Bukkit原生比较 - 无NBT - customBukkitLore: 使用Bukkit默认物品比较系统,但除去NBT标签。 兼容材料名、耐久度等 - enchants: 物品附魔 - enchantsLore: 比较物品附魔 - itemLore: 物品描述 - itemLoreLore: 比较物品描述 - itemName: 物品名称 - itemNameLore: 比较物品名称 - itemsAdder: ItemsAdder - itemsAdderLore: 比较ItemsAdder ID - material: 物品材料 - materialLore: 比较物品材料(比如石头|stone、铁剑|iron sword) - name: 物品比较式 - repairCost: 修复花费 - repairCostLore: 比较盔甲和武器的修复花费 - itemCreator: - isQuestItem: '§b任务物品:' - itemFlags: 开关物品标志显示 - itemLore: '§b物品描述' - itemName: '§b物品名' - itemType: '§b物品类型' - name: '§8物品编辑器' - itemSelect: - name: 选择物品 - itemsSelect: - name: 编辑物品 - none: '§a把物品放到这里或点击打开物品编辑器.' - listAllQuests: - name: '§8任务' - listBook: - noQuests: 没有已创建的任务 - questMultiple: 可重复次数 - questName: 任务名 - questRewards: 任务奖励 - questStages: 任务阶段 - questStarter: 开始任务方式 - requirements: 任务需求 - listPlayerQuests: - name: '§8{player_name}的任务' - listQuests: - canRedo: '§3§o你可以再次接受这个任务!' - finished: 已完成的任务 - inProgress: 进行中的任务 - loreCancelClick: '§c取消任务' - loreDialogsHistoryClick: '§7查看对话' - loreStart: '§a§o点击开始任务。' - loreStartUnavailable: '§c§o你不满足任务需求,无法开始任务。' - notStarted: 没有已开始的任务 - timeToWaitRedo: '§3§o你可以在{time_left}后重启该任务。' - timesFinished: '§3该任务完成了{times_finished}次。' - mobSelect: - boss: '§6选择一个Boss' - bukkitEntityType: '§e选择一个生物类型' - epicBoss: '§6选择一个Epic Boss' - mythicMob: '§6选择一个MythicMob' - name: 选择怪物类型 - mobs: - name: 选择怪物 - none: '§a点击添加怪物' - setLevel: 设置最低等级 - npcCreate: - move: - itemLore: '§a更改NPC位置.' - itemName: '§6传送' - moveItem: '§a§l确认前往' - name: 创建NPC - setName: '§a编辑NPC名称' - setSkin: '§e编辑NPC皮肤' - setType: '§a编辑NPC类型' - npcSelect: - createStageNPC: '§e创建 NPC' - name: 选择还是创建NPC? - selectStageNPC: '§6选择 NPC' - particleEffect: - color: '§b粒子颜色' - name: 创建粒子特效 - shape: '§d粒子形状' - type: '§e粒子类型' - particleList: - colored: 彩色粒子 - name: 粒子列表 - permission: - name: 选择权限 - perm: '§a权限' - remove: 删除权限 - removeLore: '§7P将收回权限\n§7而非给予权限。' - world: '§a世界' - worldGlobal: '§b§l全局' - permissionList: - name: 权限列表 - removed: '§e已移除: §6{permission_removed}' - world: '§e世界:§6{permission_world}' - poolCreation: - avoidDuplicates: 避免重复 - avoidDuplicatesLore: '§8> §7尝试避免重复\n 同一任务' - hologramText: '§e自定义任务池全息显示' - maxQuests: '§a最大任务数' - name: 创建任务池 - questsPerLaunch: 每次启动时开始的任务 - redoAllowed: 是否可重复完成 - requirements: '§b开始任务所需前置' - time: '§b设置任务之间的间隔' - poolsList.name: 任务池 - poolsManage: - choose: '§e> §6§o选择该任务池 §e<' - create: '§a创建一个任务池' - edit: '§e> §6§o编辑任务池…… §e<' - itemName: '§a池#{pool}' - name: 任务池 - poolAvoidDuplicates: '§8避免重复:§7{pool_duplicates}' - poolHologram: '§8全息文本:§7{pool_hologram}' - poolMaxQuests: '§8最大任务数:§7{pool_max_quests}' - poolNPC: '§8NPC:§7{pool_npc_id}' - poolQuestsList: '§7{pool_quests_amount} §8任务:§7{pool_quests}' - poolQuestsPerLaunch: '§8每次给予的任务:§7{pool_quests_per_launch}' - poolRedo: '§8可以重新接受已完成的任务:§7{pool_redo}' - poolTime: '§8任务之间的间隔:§7{pool_time}' - requirements: - name: 任务需求 - rewards: - commands: '指令: {amount}' - name: 任务奖励 - random: - minMax: 编辑最小和最大值 - rewards: 编辑奖励 - rewardsWithRequirements: - name: 需满足需求的奖励 - search: '§e§l搜索' - stageEnding: - command: '§a编辑执行的指令' - locationTeleport: '§a编辑传送点' - stages: - branchesPage: '§d分支任务阶段' - descriptionTextItem: '§e编辑文本描述' - endingItem: '§e编辑阶段结束奖励' - laterPage: '§e上一页' - name: '§8创建任务阶段' - newBranch: '§e前往新的任务分支' - nextPage: '§e下一页' - previousBranch: '§e返回上一个分支' - regularPage: '§a普通任务阶段' - validationRequirements: '§e验证需求' - validationRequirementsLore: 所有需求必须匹配尝试完成阶段的玩家。否则该阶段无法完成。 - validate: '§b§l确认' - visibility: - finished: '“已完成”菜单栏' - inProgress: '“进行中”菜单栏' - maps: 地图(比如Dynmap或BlueMap) - name: 任务可见度 - notStarted: '“未开始”菜单栏' -misc: - amount: '§e数量: {amount}' - amounts: - comparisons: '{comparisons_amount}个对比' - dialogLines: '{lines_amount}行' - items: '{items_amount}件物品' - mobs: '{mobs_amount}个怪物' - permissions: '{permissions_amount}个权限' - and: 和 - bucket: - lava: 岩浆桶 - milk: 牛奶桶 - snow: 雪桶 - water: 水桶 - click: - left: 左击 - middle: 中键点击 - right: 右击 - shift-left: Shift+左击 - shift-right: Shift+右击 - comparison: - different: 不同于{number} - equals: 等于{number} - greater: 精确大于{number} - greaterOrEquals: 大于{number} - less: 精确小于 {number} - lessOrEquals: 小于{number} - disabled: 已关闭 - enabled: 已启用 - entityType: '§e生物类型: {entity_type}' - entityTypeAny: '§e任何实体' - format: - prefix: '§6<§e§l任务§r§6> §r' - hologramText: '§8§l任务NPC' - 'no': '否' - notSet: '§c未设置' - or: 或 - poolHologramText: '§e有可接受的新任务!' - questItemLore: '§e§o任务物品' - removeRaw: 移除 - requirement: - class: '§b所需职业' - combatLevel: '§b所需战斗等级' - equipment: '§e所需装备' - experienceLevel: '§b所需经验等级' - faction: '§b所需派系' - jobLevel: '§b所需工作等级' - logicalOr: '§d逻辑 或 (前置)' - mcMMOSkillLevel: '§d所需技能等级' - money: '§d所需金额' - permissions: '§3所需权限' - placeholder: '§b所需占位符数值' - quest: '§a所需前置任务' - region: '§d需要区域' - scoreboard: '§d所需分数' - skillAPILevel: '§d所需SkillAPI等级' - reset: 重置 - stageType: - Bucket: 装满桶 - Craft: 合成物品 - Enchant: 附魔物品 - Fish: 钓鱼 - Melt: 熔炼物品 - breedAnimals: 饲养动物 - chat: 在聊天框内说话 - dealDamage: 造成伤害 - die: 死亡 - eatDrink: 食用或饮用 - interact: 与方块交互 - items: 带回物品 - location: 寻找地点 - mine: 破坏方块 - mobs: 击杀怪物 - npc: 寻找 NPC - placeBlocks: 放置方块 - playTime: 游戏时间 - region: 寻找区域 - tameAnimals: 驯服动物 - ticks: '{ticks}刻' - time: - days: '{days_amount}天' - hours: '{hours_amount}小时' - lessThanAMinute: 少于一分钟 - minutes: '{minutes_amount}分钟' - weeks: '{weeks_amount}周' - unknown: 未知 - 'yes': '是' msg: + quest: + finished: + base: '§a恭喜你完成了任务 §o§6{quest_name}§r§a!' + obtain: '§a你获得了 {rewards}!' + started: '§a你接受了任务 §r§e{quest_name}§o§6!' + created: '§a你成功地创建了 "§e{quest}§a" 任务, 包含 {quest_branches} 个阶段!' + edited: '§a你成功地修改了 "§e{quest}§a", 包含 {quest_branches} 个阶段!' + createCancelled: '§c抱歉,任务创建/编辑已被其他插件取消...' + cancelling: '§c已取消创建任务.' + editCancelling: '§c已取消编辑任务.' + invalidID: '§cID为 {quest_id} 的任务不存在.' + invalidPoolID: '§c任务池{pool_id}不存在。' + alreadyStarted: '§c你已经接受了这个任务!' + notStarted: '§c你未执行这个任务。' + quests: + maxLaunched: '§c你不能同时进行多于{quests_max_amount}个任务……' + updated: '§7已更新任务 {quest_name} !' + checkpoint: '§7已到达任务记录点!' + failed: '§6任务{quest_name}失败……' + pools: + noTime: '§c你必须先等待一会儿才能执行其它任务。' + allCompleted: '§7你已完成所有任务!' + noAvailable: '§7没有更多可用的任务……' + maxQuests: '§c你不能同时进行多于 {pool_max_quests}个任务……' + questItem: + drop: '§c你不能丢弃任务物品!' + craft: '§c你不能用任务物品来合成物品!' + eat: '§c你不能吃下任务物品!' + stageMobs: + listMobs: '§a你需要杀死 {mobs}.' + writeNPCText: '输入玩家需要对NPC说的话. 输入 "help" 来获取帮助. (指令不需要输入 /)' + writeRegionName: '输入任务阶段所需前往的区域名.' + writeXPGain: '输入玩家获得的经验点. 最终获得: §a{xp_amount}' + writeMobAmount: '输入要击杀的怪物数.' + writeMobName: '§a请输入要击杀的自定义怪物名称:' + writeChatMessage: '§a输入需要发送的信息: (如果需要发送命令,请在开头添加 "\{SLASH}".)' + writeMessage: '§a输入发送给玩家的消息' + writeStartMessage: '§a输入在开始任务时发送给玩家的消息,输入“null”则发送默认消息,输入“none”则不发送消息:' + writeEndMsg: '§a输入任务结束时发送的消息,输入“null” 则发送默认消息,输入“none”则不发送。你可以使用 "\{rewards}"显示获得的奖励。' + writeEndSound: '§a输入在任务结束时播放给玩家的音效名,输入“null”则使用默认音效,输入“none”则不播放音效:' + writeDescriptionText: '任务阶段目标描述.' + writeStageText: '任务开始时发送的消息.' + moveToTeleportPoint: 前往指定的传送点. + writeNpcName: '§a请输入NPC名称:' + writeNpcSkinName: '§a请输入NPC皮肤名:' + writeQuestName: '§a输入任务名:' + writeCommand: '§a输入指令. (开头无需加上斜杠/) 你可以用 \{player}来代表玩家名.' + writeHologramText: '§a输入全息文字. (输入 "none" 则不显示, 输入 "null" 显示默认文本) ' + writeQuestTimer: '§a输入重新开始任务的冷却时间 (单位为分钟)(输入 "null" 则使用默认值)' + writeConfirmMessage: '§a请输入玩家确认加入任务的消息: (输入 "null" 则显示默认消息)' + writeQuestDescription: '§a请输入显示在玩家任务菜单内的任务描述。' + writeQuestMaterial: '§a请输入任务物品材料名。' + requirements: + quest: '§c你必须先完成任务§e "{quest_name}"§c!' + level: '§c你的等级必须是{long_level}!' + job: '§c你的职业等级§e{job_name}§c必须是{long_level}!' + skill: '§c你的技能等级§e{skill_name}§c必须是{long_level}!' + combatLevel: '§c你的战力等级必须是{long_level}!' + money: '§c你必须拥有{money}!' + waitTime: '§c你必须等待{time_left}才能重启该任务!' + experience: + edited: '已编辑获得的经验: {old_xp_amount}pts. 改为 {xp_amount}pts.' + selectNPCToKill: 选择要击杀的NPC. + regionDoesntExists: '§c这个区域不存在... (你必须在目标区域同一世界内)' + npcDoesntExist: '§cID为{npc_id}的NPC不存在.' + number: + negative: '§c你必须输入正数!' + zero: '§c你必须输入大于0的数!' + invalid: '§c"{input}" 不是有效的数字.' + notInBounds: '§c你的数字必须介于{min}和{max}之间。' + errorOccurred: '§c插件发生错误,请联系管理员!错误代码为: {error}' + indexOutOfBounds: '§c数字 ({index}) 超过了区间 [{min}, {max}].' + invalidBlockData: '§c方块数据{block_data} 无效或者不兼容方块{block_material}。' + invalidBlockTag: '§c无法使用方块标签{block_tag}。' bringBackObjects: 把 {items} 带回给我. + inventoryFull: '§c你的背包已满, 任务奖励已掉落在地上.' + versionRequired: '需要版本:§l{version}' + restartServer: '§7重启服务器查看修改。' + dialogs: + skipped: '§8§o已跳过对话。' + tooFar: '§7§o你离{npc_name}太远了...' command: - adminModeEntered: '§a你已进入管理员模式.' - adminModeLeft: '§a你退出了管理员模式.' - backupCreated: '§6你成功地创建了任务和玩家数据的备份文件.' - backupPlayersFailed: '§c创建玩家数据备份失败.' - backupQuestsFailed: '§c创建任务数据备份失败.' - cancelQuest: '§6你放弃了任务 {quest}.' - cancelQuestUnavailable: '§c无法取消任务 {quest} .' + downloadTranslations: + syntax: '§c你必须指定要下载的语言。例如:"/quests downloadTranslations en_US"。' + notFound: '§c找不到{version}版本的{lang}语言。' + exists: '§c文件 {file_name} 已存在。在你的指令后加上 "-overwrite" 覆盖文件。 (/quests downloadTranslations <lang> -overwrite)' + downloaded: '§a已下载语言{lang}!§7你现在必须打开文件"/plugins/BeautyQuests/config.yml",更改§ominecraftTranslationsFile§7的值为{lang},然后重启服务器。' checkpoint: noCheckpoint: '§c未找到任务{quest}的记录点。' questNotStarted: '§c你没有接受这个任务。' - downloadTranslations: - downloaded: '§a已下载语言{lang}!§7你现在必须打开文件"/plugins/BeautyQuests/config.yml",更改§ominecraftTranslationsFile§7的值为{lang},然后重启服务器。' - exists: '§c文件 {file_name} 已存在。在你的指令后加上 "-overwrite" 覆盖文件。 (/quests downloadTranslations <lang> -overwrite)' - notFound: '§c找不到{version}版本的{lang}语言。' - syntax: '§c你必须指定要下载的语言。例如:"/quests downloadTranslations en_US"。' - help: - adminMode: '§6/{label} adminMode : §e切换管理员模式 (显示消息)' - create: '§6/{label} create: §a创建任务' - downloadTranslations: '§6/{label} downloadTranslations <language>: §e下载翻译文件' - edit: '§6/{label} edit: §a编辑任务' - finishAll: '§6/{label} finishAll <玩家名>: §a结束一名玩家所有进行中的任务。' - header: '§6§lBeautyQuests - §6帮助§r' - list: '§e/{label} list: §a查看任务列表 (部分版本无效)' - reload: '§e/{label} reload: §a保存并重载配置和插件数据 - §c§o不推荐使用' - remove: '§6/{label} remove [id]: §a删除ID为 [id] 的任务或点击任务NPC来删除' - resetPlayer: '§6/{label} resetPlayer <玩家名>: §e删除一名玩家的所有任务数据。' - resetPlayerQuest: '§6/{label} resetPlayerQuest <玩家名> [id]: §e删除一名玩家的一个任务数据' - save: '§6/{label} save: §a手动保存数据.' - seePlayer: '§6/{label} seePlayer <玩家名>: §a查看玩家的任务数据。' - setFirework: '§6/{label} setFirework: §e编辑默认结束烟花。' - setItem: '§6/{label} setItem <talk|launch> : §e保存全息物品到数据文件内.' - setStage: '§6/{label} setStage <玩家名> <id> [新任务分支] [新任务阶段]: §e跳过玩家当前的任务阶段/开始任务分支/s为任务分支设置任务阶段。' - start: '§6/{label} start <玩家名> [id] : §e强制玩家接受任务.' - startDialog: '§6/{label} startDialog <player> <quest id>: §e播放NPC任务阶段的待定对话或任务起始对话。' - version: '§6/{label} version: §e查看插件版本.' + setStage: + branchDoesntExist: '§cid为{branch_id}的任务分支不存在。' + doesntExist: '§cID为{stage_id}的任务阶段不存在.' + next: '§a已跳过该任务阶段.' + nextUnavailable: '§c"skip"选项在玩家到达任务分支结尾时无法使用。' + set: '§a已进入任务阶段 {stage_id} .' + startDialog: + impossible: '§c现在无法开始对话。' + noDialog: '§c玩家没有待定对话。' + alreadyIn: '§c已对玩家播放对话。' + success: '§a已为玩家{player}播放任务{quest}的对话!' invalidCommand: simple: '§c指令不存在, 输入 §ehelp §c查看帮助(不需要 /)' itemChanged: '§a已编辑物品. 更改会在重启后生效.' itemRemoved: '§a已删除全息物品.' - leaveAll: '§e你强制结束了{success}个任务. §c出现{errors}个错误.' removed: '§a成功删除任务 {quest_name}。' + leaveAll: '§e你强制结束了{success}个任务. §c出现{errors}个错误.' resetPlayer: player: '§6你的所有任务数据 ({quest_amount}) 被 {deleter_name} 删除了.' remover: '§6已删除{player}的{quest_amount}任务信息(和{quest_pool}任务池)。' - resetPlayerPool: - full: '§a你重置了{pool}任务池的{player}数据。' - timer: '§a你已重置{pool}任务池计时器{player}。' resetPlayerQuest: player: '§6任务数据 {quest} 已被 {deleter_name} 删除.' remover: '§6{quest} 的 {player} 条任务信息已被删除.' resetQuest: '§6已移除{player_amount}的任务数据。' + startQuest: '§e你为{player}强制接收了任务{quest}.' + startQuestNoRequirements: '§c玩家不满足任务{quest}的需求……在指令结尾加上 "-overrideRequirements" 无视需求检测。' + cancelQuest: '§6你放弃了任务 {quest}.' + cancelQuestUnavailable: '§c无法取消任务 {quest} .' + backupCreated: '§6你成功地创建了任务和玩家数据的备份文件.' + backupPlayersFailed: '§c创建玩家数据备份失败.' + backupQuestsFailed: '§c创建任务数据备份失败.' + adminModeEntered: '§a你已进入管理员模式.' + adminModeLeft: '§a你退出了管理员模式.' + resetPlayerPool: + timer: '§a你已重置{pool}任务池计时器{player}。' + full: '§a你重置了{pool}任务池的{player}数据。' + startPlayerPool: + error: '为{player}开始任务池{pool}失败。' + success: '已开始任务池{pool}为{player}。结果:{result}' scoreboard: - hidden: '§6已隐藏{player_name}的计分版.' - lineInexistant: '§c第 {line_id} 行不存在.' - lineRemoved: '§6你成功地删除了第 {line_id} 行.' - lineReset: '§6你成功地重置了第 {line_id} 行.' lineSet: '§6你成功地编辑了第 {line_id} 行.' - own: - hidden: '§6已隐藏你的计分板。' - shown: '§6已显示你的计分板。' + lineReset: '§6你成功地重置了第 {line_id} 行.' + lineRemoved: '§6你成功地删除了第 {line_id} 行.' + lineInexistant: '§c第 {line_id} 行不存在.' resetAll: '§6你成功地清空了 {player_name} 的计分版.' - shown: '§6已重新显示{player_name}的计分版。' - setStage: - branchDoesntExist: '§cid为{branch_id}的任务分支不存在。' - doesntExist: '§cID为{stage_id}的任务阶段不存在.' - next: '§a已跳过该任务阶段.' - nextUnavailable: '§c"skip"选项在玩家到达任务分支结尾时无法使用。' - set: '§a已进入任务阶段 {stage_id} .' - startDialog: - alreadyIn: '§c已对玩家播放对话。' - impossible: '§c现在无法开始对话。' - noDialog: '§c玩家没有待定对话。' - success: '§a已为玩家{player}播放任务{quest}的对话!' - startPlayerPool: - error: 为{player}开始任务池{pool}失败。 - success: '已开始任务池{pool}为{player}。结果:{result}' - startQuest: '§6你接受了任务 {quest} (UUID: {player}).' - startQuestNoRequirements: '§c玩家不满足任务{quest}的需求……在指令结尾加上 "-overrideRequirements" 无视需求检测。' - dialogs: - skipped: '§8§o已跳过对话。' - tooFar: '§7§o你离{npc_name}太远了...' + hidden: '§6已隐藏{player_name}的计分版.' + shown: '§6已重新显示{player_name}的计分版。' + own: + hidden: '§6已隐藏你的计分板。' + shown: '§6已显示你的计分板。' + help: + header: '§6§lBeautyQuests - §6帮助§r' + create: '§6/{label} create: §a创建任务' + edit: '§6/{label} edit: §a编辑任务' + remove: '§6/{label} remove [id]: §a删除ID为 [id] 的任务或点击任务NPC来删除' + finishAll: '§6/{label} finishAll <玩家名>: §a结束一名玩家所有进行中的任务。' + setStage: '§6/{label} setStage <玩家名> <id> [新任务分支] [新任务阶段]: §e跳过玩家当前的任务阶段/开始任务分支/s为任务分支设置任务阶段。' + startDialog: '§6/{label} startDialog <player> <quest id>: §e播放NPC任务阶段的待定对话或任务起始对话。' + resetPlayer: '§6/{label} resetPlayer <玩家名>: §e删除一名玩家的所有任务数据。' + resetPlayerQuest: '§6/{label} resetPlayerQuest <玩家名> [id]: §e删除一名玩家的一个任务数据' + seePlayer: '§6/{label} seePlayer <玩家名>: §a查看玩家的任务数据。' + reload: '§e/{label} reload: §a保存并重载配置和插件数据 - §c§o不推荐使用' + start: '§6/{label} start <玩家名> [id] : §e强制玩家接受任务.' + setItem: '§6/{label} setItem <talk|launch> : §e保存全息物品到数据文件内.' + setFirework: '§6/{label} setFirework: §e编辑默认结束烟花。' + adminMode: '§6/{label} adminMode : §e切换管理员模式 (显示消息)' + version: '§6/{label} version: §e查看插件版本.' + downloadTranslations: '§6/{label} downloadTranslations <language>: §e下载翻译文件' + save: '§6/{label} save: §a手动保存数据.' + list: '§e/{label} list: §a查看任务列表 (部分版本无效)' + typeCancel: '§a输入 "cancel" 返回到上一条消息.' editor: - advancedSpawnersMob: '输入所需击杀的自定义刷怪笼怪物名称:' - already: '§c你已在编辑器中.' - availableElements: '可用元素:§e{available_elements}' blockAmount: '§e请输入所需方块数:' - blockData: '§a请输入方块数据 (可用的方块数据: {available_datas}):' blockName: '§a请输入方块名:' + blockData: '§a请输入方块数据 (可用的方块数据: {available_datas}):' blockTag: '§a请输入方块标签 (可用标签:§7{available_tags}§a):' - chat: '§6你已进入编辑器模式。输入"/quests exitEditor" 强制退出编辑器。(不推荐使用,最好使用 "close" 或 "cancel" 回到上一个菜单)' - color: '可以输入十六位格式(#XXXXX)或RGB格式(RED GRE BLU)的颜色。' - colorNamed: 输入颜色名称。 - comparisonTypeDefault: '§a请选择你想要在{available}中使用的比较类型。默认比较类型为:§e§l{default}§r§a。输入§onull§r§a使用。' - dialog: - cleared: '§a已删除{amount}条消息.' - edited: '§a已编辑消息 "§7{msg}§a"。' - help: - addSound: '§eaddsound <id> <音效名>: §b给一条消息添加音效.' - clear: '§eclear: §b删除所有消息.' - close: '§eclose: §b退出并保存所有消息.' - edit: '§6edit <id> <message>:§e编辑消息。' - header: '§e§lBeautyQuest - §6对话编辑器帮助' - list: '§elist: §b查看所有的消息.' - nothing: '§6noSender <消息>: §e添加一条没有发送者的消息.' - nothingInsert: '§enothinginsert <id> <消息>: §b插入一条没有任何前缀的消息.' - npc: '§npc <message>: §b添加一条由NPC说出的消息。' - npcInsert: '§enpcinsert <id> <消息>: §b插入一条由NPC说出的话.' - npcName: '§6npcname [自定义NPC名称]: §eSet (或重置为默认) 自定义NPC名称' - player: '§6player <message>: §b添加一条由玩家说出的消息。' - playerInsert: '§eplayerinsert <id> <消息>: §b插入一条由玩家说出的话.' - remove: '§6emove <id>: §e删除一条消息.' - setTime: '§6setTime <id> <时间>: §e设置自动播放下一条消息的时间(单位为刻) 。' - skippable: '§6skippable [true|false]: §e设置是否可跳过对话' - messageRemoved: '§a已删除消息 "§7{msg}§a"。' - noSender: '§a已添加无发送者的消息“{msg}”。' - npc: '§a已为NPC添加消息 "§7{msg}§a"。' - npcName: - set: '§a自定义NPC名称已设置为§7{new_name}§a (原为§7{old_name}§a)' - unset: '§a自定义NPC名称重置为默认值 (原为§7{old_name}§a)' - player: '§a已为玩家添加消息 "§7{msg}§a"。' - skippable: - set: '§a对话可跳过状态已设置为§7{new_state}§a (原为§7{old_state}§a)' - unset: '§a对话可跳过状态已重置为默认§7{1}§a (原为§7{old_state}§a)' - soundAdded: '§a已为消息 "§7{msg}§a"添加音效 "§7{sound}§a"。' - syntaxRemove: '§c正确用法: remove <id>' - timeRemoved: '§a已删除消息{msg}的时间。' - timeSet: '§a已编辑消息 {msg} 的时间: 现在是 {time} 刻。' + typeBucketAmount: '§a请输入要装满桶的数量:' + typeDamageAmount: '输入玩家需要造成的伤害:' + goToLocation: '§a前往该任务阶段指定地点。' + typeLocationRadius: '§a请输入距离指定位置所需的距离:' + typeGameTicks: '§a请输入所需的刻数:' + already: '§c你已在编辑器中.' + stage: + location: + typeWorldPattern: '§a输入世界名称的正则表达式:' enter: - list: '§c⚠ §7你已进入"list"编辑器。输入"add"添加一行。使用 "help" (无需斜杠) 查看帮助。§e§l输入"close"退出编辑器。' - subtitle: '§e输入 "/quests exitEditor" 强制退出任务编辑器。' title: '§6~ 进入编辑器模式 ~' - firework: - edited: 已编辑任务烟花! - invalid: 这件物品不是有效的烟花。 - invalidHand: 你必须在主手手持烟花。 - removed: 已移除任务烟花! - goToLocation: '§a前往该任务阶段指定地点。' - invalidColor: 你输入的颜色无效,必须是十六位或RGB颜色。 - invalidPattern: '§c无效的正则表达式§4{input}§c。' - itemCreator: - invalidBlockType: '§c无效的方块类型。' - invalidItemType: '§c无效的物品类型 (必须是物品而不能是方块).' - itemAmount: '§e请输入所需物品数:' - itemLore: '§e修改物品描述. 输入 "help" 查看帮助.' - itemName: '§a输入物品名:' - itemType: '§a输入物品类型名:' - unknownBlockType: '§c未知方块类型。' - unknownItemType: '§c未知的物品类型.' - mythicmobs: - disabled: '§cMythicMob已关闭.' - isntMythicMob: '§c这个MythicMob不存在.' - list: '§a所有的MythocMobs:' - noSuchElement: '§c没有这样的元素。可用元素:§e{available_elements}' + subtitle: '§e输入 "/quests exitEditor" 强制退出任务编辑器。' + list: '§c⚠ §7你已进入"list"编辑器。输入"add"添加一行。使用 "help" (无需斜杠) 查看帮助。§e§l输入"close"退出编辑器。' + chat: '§6你已进入编辑器模式。输入"/quests exitEditor" 强制退出编辑器。(不推荐使用,最好使用 "close" 或 "cancel" 回到上一个菜单)' npc: - choseStarter: '§a选择接受任务的NPC.' enter: '§a点击一个NPC,或输入"cancel"取消.' + choseStarter: '§a选择接受任务的NPC.' notStarter: '§c这个NPC没有可以接受的任务...' - pool: - hologramText: 请输入该池的自定义全息显示文本(输入“null”使用默认值)。 - maxQuests: 输入在该池中可运行的最大任务数。 - questsPerLaunch: 输入点击NPC时给予玩家的任务数。 - timeMsg: '请输入玩家可接取新任务的等候时间。(默认单位:天)' - scoreboardObjectiveNotFound: '§c未知的计分板目标。' - selectWantedBlock: '§a用木棍点击开始任务阶段的方块.' - stage: - location: - typeWorldPattern: '§a输入世界名称的正则表达式:' text: argNotSupported: '§c不支持 {arg} 参数.' - chooseJobRequired: '§a输入所需的工作名:' chooseLvlRequired: '§a输入所需等级:' - chooseMoneyRequired: '§e输入所需金额:' - chooseObjectiveRequired: '§a请输入目标名。' - chooseObjectiveTargetScore: '§a请输入完成任务目标所需目标数。' - choosePermissionMessage: '§e如果玩家没有所需权限则显示的拒绝消息. (输入 "null" 跳过这步)' + chooseJobRequired: '§a输入所需的工作名:' choosePermissionRequired: '§a输入开始任务所需权限:' + choosePermissionMessage: '§e如果玩家没有所需权限则显示的拒绝消息. (输入 "null" 跳过这步)' choosePlaceholderRequired: identifier: '§e输入所需的占位符名 (§l不用加上 %%§r§e).' value: '§a请输入所需的§e%§e{placeholder}§e%§a占位符值:' - chooseRegionRequired: '§a请输入所需区域名 (你必须与该区域在同一个世界中)。' chooseSkillRequired: '§a输入技能名:' + chooseMoneyRequired: '§e输入所需金额:' reward: - money: '§e输入获得的钱数:' permissionName: '§a请输入权限名称。' permissionWorld: '§a请输入可编辑权限的世界名,输入"null"则所有世界可编辑。' + money: '§e输入获得的钱数:' + wait: '§a输入所需等待游戏刻数(1秒=20刻)' random: - max: '§a输入给予玩家的最高奖励数量 (包括全部)。' min: '§a输入给予玩家的最低奖励数量 (包括全部)。' - wait: '§a输入所需等待游戏刻数(1秒=20刻)' + max: '§a输入给予玩家的最高奖励数量 (包括全部)。' + chooseObjectiveRequired: '§a请输入目标名。' + chooseObjectiveTargetScore: '§a请输入完成任务目标所需目标数。' + chooseRegionRequired: '§a请输入所需区域名 (你必须与该区域在同一个世界中)。' + chooseRequirementCustomReason: '输入此需求的自定义原因。如果玩家在达成此需求前尝试开启此任务,此消息将会被发送。' + chooseRequirementCustomDescription: '写下此需求的自定义描述。它将出现在菜单中的任务描述中。' + chooseRewardCustomDescription: '写下此奖励的自定义描述。它将出现在菜单中的任务描述中。' + selectWantedBlock: '§a用木棍点击开始任务阶段的方块.' + itemCreator: + itemType: '§a输入物品类型名:' + itemAmount: '§e请输入所需物品数:' + itemName: '§a输入物品名:' + itemLore: '§e修改物品描述. 输入 "help" 查看帮助.' + unknownItemType: '§c未知的物品类型.' + invalidItemType: '§c无效的物品类型 (必须是物品而不能是方块).' + unknownBlockType: '§c未知方块类型。' + invalidBlockType: '§c无效的方块类型。' + dialog: + syntaxMessage: '§c正确用法 : {command} <message>' + syntaxRemove: '§c正确用法: remove <id>' + player: '§a已为玩家添加消息 "§7{msg}§a"。' + npc: '§a已为NPC添加消息 "§7{msg}§a"。' + noSender: '§a已添加无发送者的消息“{msg}”。' + messageRemoved: '§a已删除消息 "§7{msg}§a"。' + edited: '§a已编辑消息 "§7{msg}§a"。' + soundAdded: '§a已为消息 "§7{msg}§a"添加音效 "§7{sound}§a"。' + cleared: '§a已删除{amount}条消息.' + help: + header: '§e§lBeautyQuest - §6对话编辑器帮助' + npc: '§npc <message>: §b添加一条由NPC说出的消息。' + player: '§6player <message>: §b添加一条由玩家说出的消息。' + nothing: '§6noSender <消息>: §e添加一条没有发送者的消息.' + remove: '§6emove <id>: §e删除一条消息.' + list: '§elist: §b查看所有的消息.' + npcInsert: '§enpcinsert <id> <消息>: §b插入一条由NPC说出的话.' + playerInsert: '§eplayerinsert <id> <消息>: §b插入一条由玩家说出的话.' + nothingInsert: '§enothinginsert <id> <消息>: §b插入一条没有任何前缀的消息.' + edit: '§6edit <id> <message>:§e编辑消息。' + addSound: '§eaddsound <id> <音效名>: §b给一条消息添加音效.' + clear: '§eclear: §b删除所有消息.' + close: '§eclose: §b退出并保存所有消息.' + setTime: '§6setTime <id> <时间>: §e设置自动播放下一条消息的时间(单位为刻) 。' + npcName: '§6npcname [自定义NPC名称]: §eSet (或重置为默认) 自定义NPC名称' + skippable: '§6skippable [true|false]: §e设置是否可跳过对话' + timeSet: '§a已编辑消息 {msg} 的时间: 现在是 {time} 刻。' + timeRemoved: '§a已删除消息{msg}的时间。' + npcName: + set: '§a自定义NPC名称已设置为§7{new_name}§a (原为§7{old_name}§a)' + unset: '§a自定义NPC名称重置为默认值 (原为§7{old_name}§a)' + skippable: + set: '§a对话可跳过状态已设置为§7{new_state}§a (原为§7{old_state}§a)' + unset: '§a对话可跳过状态已重置为默认§7{1}§a (原为§7{old_state}§a)' + mythicmobs: + list: '§a所有的MythocMobs:' + isntMythicMob: '§c这个MythicMob不存在.' + disabled: '§cMythicMob已关闭.' + advancedSpawnersMob: '输入所需击杀的自定义刷怪笼怪物名称:' textList: + syntax: '§c正确用法: ' added: '§a已添加文本 "§7{msg}§a"。' + removed: '§a已删除文本 "§7{msg}§a"。' help: - add: '§6add [消息]: §e添加一条文本.' - close: '6close: §e确认添加文本并退出编辑器.' header: '§6§lBeautyQuests — 编辑器列表帮助' - list: '§6list: §e查看所有已添加的文本.' + add: '§6add [消息]: §e添加一条文本.' remove: '§6remove [id]: §e删除一条文本.' - removed: '§a已删除文本 "§7{msg}§a"。' - syntax: '§c正确用法: ' + list: '§6list: §e查看所有已添加的文本.' + close: '6close: §e确认添加文本并退出编辑器.' + availableElements: '可用元素:§e{available_elements}' + noSuchElement: '§c没有这样的元素。可用元素:§e{available_elements}' + invalidPattern: '§c无效的正则表达式§4{input}§c。' + comparisonTypeDefault: '§a请选择你想要在{available}中使用的比较类型。默认比较类型为:§e§l{default}§r§a。输入§onull§r§a使用。' + scoreboardObjectiveNotFound: '§c未知的计分板目标。' + pool: + hologramText: '请输入该池的自定义全息显示文本(输入“null”使用默认值)。' + maxQuests: '输入在该池中可运行的最大任务数。' + questsPerLaunch: '输入点击NPC时给予玩家的任务数。' + timeMsg: '请输入玩家可接取新任务的等候时间。(默认单位:天)' title: - fadeIn: 输入淡入持续时间,单位为刻(20刻=1秒)。 - fadeOut: 输入淡出持续时间,单位为刻(20刻=1秒)。 - stay: 输入停留持续时间,单位为刻(20刻=1秒)。 - subtitle: 输入副标题文本(输入“null”则不显示文本)。 - title: 输入标题文本(输入“null”则不显示文本)。 - typeBucketAmount: '§a请输入要装满桶的数量:' - typeDamageAmount: '输入玩家需要造成的伤害:' - typeGameTicks: '§a请输入所需的刻数:' - typeLocationRadius: '§a请输入距离指定位置所需的距离:' - errorOccurred: '§c插件发生错误,请联系管理员!错误代码为: {error}' - experience: - edited: '已编辑获得的经验: {old_xp_amount}pts. 改为 {xp_amount}pts.' - indexOutOfBounds: '§c数字 ({index}) 超过了区间 [{min}, {max}].' - invalidBlockData: '§c方块数据{block_data} 无效或者不兼容方块{block_material}。' - invalidBlockTag: '§c无法使用方块标签{block_tag}。' - inventoryFull: '§c你的背包已满, 任务奖励已掉落在地上.' - moveToTeleportPoint: 前往指定的传送点. - npcDoesntExist: '§cID为{npc_id}的NPC不存在.' - number: - invalid: '§c"{input}" 不是有效的数字.' - negative: '§c你必须输入正数!' - notInBounds: '§c你的数字必须介于{min}和{max}之间。' - zero: '§c你必须输入大于0的数!' - pools: - allCompleted: '§7你已完成所有任务!' - maxQuests: '§c你不能同时进行多于 {pool_max_quests}个任务……' - noAvailable: '§7没有更多可用的任务……' - noTime: '§c你必须先等待一会儿才能执行其它任务。' - quest: - alreadyStarted: '§c你已经接受了这个任务!' - cancelling: '§c已取消创建任务.' - createCancelled: '§c抱歉,任务创建/编辑已被其他插件取消...' - created: '§a你成功地创建了 "§e{quest}§a" 任务, 包含 {quest_branches} 个阶段!' - editCancelling: '§c已取消编辑任务.' - edited: '§a你成功地修改了 "§e{quest}§a", 包含 {quest_branches} 个阶段!' - finished: - base: '§a恭喜你完成了任务 §o§6{quest_name}§r§a!' - obtain: '§a你获得了 {rewards}!' - invalidID: '§cID为 {quest_id} 的任务不存在.' - invalidPoolID: '§c任务池{pool_id}不存在。' - notStarted: '§c你未执行这个任务。' - started: '§a你接受了任务 §r§e{quest_name}§o§6!' - questItem: - craft: '§c你不能用任务物品来合成物品!' - drop: '§c你不能丢弃任务物品!' - eat: '§c你不能吃下任务物品!' - quests: - checkpoint: '§7已到达任务记录点!' - failed: '§6任务{quest_name}失败……' - maxLaunched: '§c你不能同时进行多于{quests_max_amount}个任务……' - updated: '§7已更新任务 {quest_name} !' - regionDoesntExists: '§c这个区域不存在... (你必须在目标区域同一世界内)' + title: '输入标题文本(输入“null”则不显示文本)。' + subtitle: '输入副标题文本(输入“null”则不显示文本)。' + fadeIn: '输入淡入持续时间,单位为刻(20刻=1秒)。' + stay: '输入停留持续时间,单位为刻(20刻=1秒)。' + fadeOut: '输入淡出持续时间,单位为刻(20刻=1秒)。' + colorNamed: '输入颜色名称。' + color: '可以输入十六位格式(#XXXXX)或RGB格式(RED GRE BLU)的颜色。' + invalidColor: '你输入的颜色无效,必须是十六位或RGB颜色。' + firework: + invalid: '这件物品不是有效的烟花。' + invalidHand: '你必须在主手手持烟花。' + edited: '已编辑任务烟花!' + removed: '已移除任务烟花!' + writeCommandDelay: '§a请输入指令延迟,单位为刻。' +advancement: + finished: 已完成{times_finished}次 + notStarted: 未开始 +inv: + validate: '§b§l确认' + cancel: '§c§l取消' + search: '§e§l搜索' + addObject: '§a添加一个目标' + confirm: + name: '§8你确认?' + 'yes': '§a确认' + 'no': '§c让我再想想' + create: + stageCreate: '§a创建新的阶段' + stageRemove: '§c删除这一阶段' + stageUp: 上移 + stageDown: 下移 + stageType: '§7阶段类型:§e{stage_type}' + cantFinish: '§7你必须先创建至少一个任务阶段!' + findNPC: '§a寻找一个NPC' + bringBack: '§a带回物品' + findRegion: '§a找到一片区域' + killMobs: '§a击杀怪物' + mineBlocks: '§a破坏方块' + placeBlocks: '§a放置方块' + talkChat: '§a在聊天框内输入' + interact: '§a点击方块' + interactLocation: '§a与目标地点的方块交互' + fish: '§a钓鱼' + melt: '§熔炼物品' + enchant: '§附魔物品' + craft: '§a合成物品' + bucket: '§a装满桶' + location: 前往指定位置 + playTime: '§e游戏时间' + breedAnimals: '§a饲养动物' + tameAnimals: '§a驯服动物' + death: '§c死亡' + dealDamage: '§c对怪物造成伤害' + eatDrink: '§a食用食物或饮用药水' + NPCText: '§e编辑NPC的文本对话' + NPCSelect: '§e选择或创建NPC' + hideClues: 隐藏任务指示 (粒子效果和全息文字) + editMobsKill: '§e编辑要击杀的怪物' + mobsKillFromAFar: 需要远程击杀怪物 + editBlocksMine: '§e编辑要破坏的方块' + preventBlockPlace: 防止玩家破坏方块 + editBlocksPlace: '§e编辑要放置的方块' + editMessageType: '§e编辑要输入的消息' + cancelMessage: 取消发送 + ignoreCase: 忽略消息大小写 + replacePlaceholders: '替换\{PLAYER}和PlaceholderAPI中的占位符' + selectItems: '§b选择所需的物品' + selectItemsMessage: '§e编辑询问消息' + selectItemsComparisons: '§e选择物品比较式(高级)' + selectRegion: '§7选择一片区域' + toggleRegionExit: 退出时 + stageStartMsg: '§e编辑阶段开始的消息' + selectBlockLocation: '§6选择方块位置' + selectBlockMaterial: '§e选择方块材料' + leftClick: 必须左击 + editFishes: '§e编辑所需的鱼' + editItemsToMelt: '§e编辑要熔炼的物品' + editItemsToEnchant: '§e编辑要附魔的物品' + editItem: '§e编辑要合成的物品' + editBucketType: '§e编辑要装满的桶类型' + editBucketAmount: '§e编辑要装满的桶数量' + editLocation: '§e编辑位置' + editRadius: '§e编辑离目的地的距离' + currentRadius: '§e当前距离: §6{radius}' + changeTicksRequired: '§e需要更改游玩刻' + changeEntityType: '§e更改实体类型' + stage: + location: + worldPattern: '§a设置世界名称模式 §d(高级选项)' + worldPatternLore: '如果你想要匹配特定模式的任意世界都能完成任务阶段,请在此输入正则表达式。' + death: + causes: '§a设置死因 §d(高级)' + anyCause: 任何死因 + setCauses: '{causes_amount} 死因' + dealDamage: + damage: '§e要造成的伤害' + targetMobs: '§c要造成伤害的怪物对象' + eatDrink: + items: '§e编辑要食用或饮用的物品' + stages: + name: '§8创建任务阶段' + nextPage: '§e下一页' + laterPage: '§e上一页' + endingItem: '§e编辑阶段结束奖励' + descriptionTextItem: '§e编辑文本描述' + regularPage: '§a普通任务阶段' + branchesPage: '§d分支任务阶段' + previousBranch: '§e返回上一个分支' + newBranch: '§e前往新的任务分支' + validationRequirements: '§e验证需求' + validationRequirementsLore: 所有需求必须匹配尝试完成阶段的玩家。否则该阶段无法完成。 + details: + hologramLaunch: '§e编辑 “启动” 全息项' + hologramLaunchLore: 显示在接受任务的NPC头上的全息文字。 + hologramLaunchNo: '§e编辑 “启动不可用” 全息项' + hologramLaunchNoLore: 在玩家没有接受任务时显示在NPC头上的全息文字。 + customConfirmMessage: '§e编辑确认接受任务的消息' + customConfirmMessageLore: 显示在确认菜单中的消息。 + customDescription: '§e编辑任务描述' + customDescriptionLore: 在GUI中显示在任务名下方的描述。 + name: '§8最终任务详细设置' + multipleTime: + itemName: 切换是否可重复 + itemLore: 任务是否可以多次完成? + cancellable: 玩家可取消任务 + cancellableLore: 允许玩家在任务菜单中取消任务。 + startableFromGUI: 可从GUI菜单中开始任务 + startableFromGUILore: 允许玩家在任务菜单中开始任务。 + scoreboardItem: 启用计分版 + scoreboardItemLore: 如果禁用,则该任务目标不会显示在计分板上。 + hideNoRequirementsItem: 未满足需求时隐藏 + hideNoRequirementsItemLore: 如果启用,在未满足需求时任务将不会显示在任务菜单中。 + bypassLimit: 忽略任务上限 + bypassLimitLore: 如果启用,即使玩家已经达到任务上限也能接受任务。 + auto: 登录时自动开始任务 + autoLore: 如果启用,则玩家首次加入服务器时将自动开始该任务。 + questName: '§a§l编辑任务名' + questNameLore: 必须设置一个名称来创建任务。 + setItemsRewards: '§7编辑获得的物品' + removeItemsReward: 从物品栏中移除物品 + setXPRewards: '§e编辑获得的经验' + setCheckpointReward: '§e编辑记录点奖励' + setRewardStopQuest: '§c停止任务' + setRewardsWithRequirements: '§e需满足需求的奖励' + setRewardsRandom: '§d随机奖励' + setPermReward: '§e编辑权限' + setMoneyReward: '§e编辑获得的金钱' + setWaitReward: '§e编辑“等待”奖励' + setTitleReward: '§e编辑标题奖励' + selectStarterNPC: '§6§l选择接受任务的NPC' + selectStarterNPCLore: 点击选中的NPC将开始任务。 + selectStarterNPCPool: '§c:⚠ 已选择一个任务池' + createQuestName: '§l创建任务' + createQuestLore: 你必须设定任务名。 + editQuestName: '§l编辑任务' + endMessage: '§a编辑任务结束消息' + endMessageLore: 将在任务结束时发送给玩家的消息。 + endSound: '§e编辑结束音效' + endSoundLore: 在任务结束时播放的音效。 + startMessage: '§e编辑开始消息' + startMessageLore: 任务开始时发送给玩家的消息。 + startDialog: '§e编辑任务开场白' + startDialogLore: 当玩家点击任务NPC时,在任务开始之前播放的对话框。 + editRequirements: '§e编辑需求' + editRequirementsLore: 接受任务所需前置。 + startRewards: '§6开始任务的奖励' + startRewardsLore: 玩家接受任务时执行的行动。 + cancelRewards: '§c取消行动' + cancelRewardsLore: 玩家取消该任务时触发的行动。 + hologramText: '§e全息文字' + hologramTextLore: 显示在可接受任务的NPC的头上的全息文字。 + timer: '§b重启计时器' + timerLore: 玩家可以再次开始任务的时间。 + requirements: '{amount} 个任务需求' + rewards: '{amount} 个奖励' + actions: '{amount}行动' + rewardsLore: 任务接受时执行的行动。 + customMaterial: '§a编辑任务物品材料名' + customMaterialLore: 在任务菜单中代表该任务的物品图标。 + failOnDeath: 玩家死亡时任务失败 + failOnDeathLore: 当玩家死亡时是否取消任务? + questPool: '§e任务池' + questPoolLore: 将该任务加到任务池中 + firework: '§d任务结束烟花' + fireworkLore: 玩家完成任务时发射的烟花 + fireworkLoreDrop: 把你的自定义烟花放在这里 + visibility: '§b任务可见度' + visibilityLore: 选择在菜单栏何处显示任务,如果安装了卫星地图插件,则在地图上显示任务。 + keepDatas: 保留玩家数据 + keepDatasLore: |- + 强制插件保存玩家数据,即使是已编辑阶段也会保存。 §c§l警告§c- 启用此选项可能会损坏你的玩家数据。 + loreReset: '§e§l所有玩家的进度将被重置' + optionValue: '§8数值:§7{value}' + defaultValue: '§8(默认值)' + requiredParameter: '§7所需参数' + itemsSelect: + name: 编辑物品 + none: |- + §a把物品放到这里或点击打开物品编辑器. + itemSelect: + name: 选择物品 + npcCreate: + name: 创建NPC + setName: '§a编辑NPC名称' + setSkin: '§e编辑NPC皮肤' + setType: '§a编辑NPC类型' + move: + itemName: '§6传送' + itemLore: '§a更改NPC位置.' + moveItem: '§a§l确认前往' + npcSelect: + name: 选择还是创建NPC? + selectStageNPC: '§6选择 NPC' + createStageNPC: '§e创建 NPC' + entityType: + name: '§5选择生物类型' + chooseQuest: + name: '§5选择哪一个任务?' + menu: '§a任务菜单' + menuLore: 前往任务菜单。 + mobs: + name: 选择怪物 + none: '§a点击添加怪物' + editAmount: 编辑数量 + editMobName: 编辑生物名称 + setLevel: 设置最低等级 + mobSelect: + name: 选择怪物类型 + bukkitEntityType: '§e选择一个生物类型' + mythicMob: '§6选择一个MythicMob' + epicBoss: '§6选择一个Epic Boss' + boss: '§6选择一个Boss' + advancedSpawners: '§6选择一个 AdvancedSpawners 的生物' + stageEnding: + locationTeleport: '§a编辑传送点' + command: '§a编辑执行的指令' requirements: - combatLevel: '§c你的战力等级必须是{long_level}!' - job: '§c你的职业等级§e{job_name}§c必须是{long_level}!' - level: '§c你的等级必须是{long_level}!' - money: '§c你必须拥有{money}!' - quest: '§c你必须先完成任务§e "{quest_name}"§c!' - skill: '§c你的技能等级§e{skill_name}§c必须是{long_level}!' - waitTime: '§c你必须等待{time_left}才能重启该任务!' - restartServer: '§7重启服务器查看修改。' - selectNPCToKill: 选择要击杀的NPC. - stageMobs: - listMobs: '§a你需要杀死 {mobs}.' - typeCancel: '§a输入 "cancel" 返回到上一条消息.' - versionRequired: '需要版本:§l{version}' - writeChatMessage: '要玩家输入的消息 (在开头加上 {SLASH} 来让玩家输入指令).' - writeCommand: '§a输入指令. (开头无需加上斜杠/) 你可以用 {PLAYER}来代表玩家名.' - writeCommandDelay: '§a请输入指令延迟,单位为刻。' - writeConfirmMessage: '§a请输入玩家确认加入任务的消息: (输入 "null" 则显示默认消息)' - writeDescriptionText: '任务阶段目标描述.' - writeEndMsg: '§a输入任务结束时发送的消息,输入“null” 则发送默认消息,输入“none”则不发送。你可以使用 "{rewards}"显示获得的奖励。' - writeEndSound: '§a输入在任务结束时播放给玩家的音效名,输入“null”则使用默认音效,输入“none”则不播放音效:' - writeHologramText: '§a输入全息文字. (输入 "none" 则不显示, 输入 "null" 显示默认文本) ' - writeMessage: '§a输入发送给玩家的消息' - writeMobAmount: '输入要击杀的怪物数.' - writeMobName: '§a请输入要击杀的自定义怪物名称:' - writeNPCText: '输入玩家需要对NPC说的话. 输入 "help" 来获取帮助. (指令不需要输入 /)' - writeNpcName: '§a请输入NPC名称:' - writeNpcSkinName: '§a请输入NPC皮肤名:' - writeQuestDescription: '§a请输入显示在玩家任务菜单内的任务描述。' - writeQuestMaterial: '§a请输入任务物品材料名。' - writeQuestName: '§a输入任务名:' - writeQuestTimer: '§a输入重新开始任务的冷却时间 (单位为分钟)(输入 "null" 则使用默认值)' - writeRegionName: '输入任务阶段所需前往的区域名.' - writeStageText: '任务开始时发送的消息.' - writeStartMessage: '§a输入在开始任务时发送给玩家的消息,输入“null”则发送默认消息,输入“none”则不发送消息:' - writeXPGain: '输入玩家获得的经验点. 最终获得: §a{xp_amount}' + name: 任务需求 + setReason: 设置自定义原因 + reason: '§8自定义原因: §7{reason}' + rewards: + name: 任务奖励 + commands: '指令: {amount}' + random: + rewards: 编辑奖励 + minMax: 编辑最小和最大值 + checkpointActions: + name: 记录点行动 + cancelActions: + name: 取消行动 + rewardsWithRequirements: + name: 需满足需求的奖励 + listAllQuests: + name: '§8任务' + listPlayerQuests: + name: '§8{player_name}的任务' + listQuests: + notStarted: 没有已开始的任务 + finished: 已完成的任务 + inProgress: 进行中的任务 + loreDialogsHistoryClick: '§7查看对话' + loreCancelClick: '§c取消任务' + loreStart: '§a§o点击开始任务。' + loreStartUnavailable: '§c§o你不满足任务需求,无法开始任务。' + timeToWaitRedo: '§7§o你可以在{time_left}后重做该任务。' + canRedo: '§3§o你可以再次接受这个任务!' + timesFinished: '§e已完成 §6{times_finished} §e次.' + format: + normal: '§6§l§o{quest_name}' + withId: '§6§l§o{quest_name}§r §e#{quest_id}' + itemCreator: + name: '§8物品编辑器' + itemType: '§b物品类型' + itemFlags: 开关物品标志显示 + itemName: '§b物品名' + itemLore: '§b物品描述' + isQuestItem: '§b任务物品:' + command: + name: '§8指令' + value: '§b指令' + console: 控制台 + parse: 解析占位符 + delay: '§b延迟' + chooseAccount: + name: '§5选择哪一个帐号?' + listBook: + questName: 任务名 + questStarter: 开始任务方式 + questRewards: 任务奖励 + questMultiple: 可重复次数 + requirements: 任务需求 + questStages: 任务阶段 + noQuests: 没有已创建的任务 + commandsList: + name: 指令列表 + value: '§e指令: {command_label}' + console: '§e控制台: {command_console}' + block: + name: 选择方块 + material: '§e材料: {block_type}' + materialNotItemLore: '所选方块无法显示为物品。它仍正确地存储为{block_material}。' + blockName: '§b自定义方块名称' + blockData: '§d方块数据(高级)' + blockTag: '§d标签 (高级)' + blockTagLore: '选择描述可能方块列表的标签。可使用数据包自定义标签。你可以在Minecraft Wiki查询标签列表。' + blocksList: + name: 选择方块 + addBlock: '§a点击添加一个方块.' + blockAction: + name: 选择方块行动 + location: '§e选择精确位置' + material: '§e选择方块材料' + buckets: + name: 桶的类型 + permission: + name: 选择权限 + perm: '§a权限' + world: '§a世界' + worldGlobal: '§b§l全局' + remove: 删除权限 + removeLore: '§7P将收回权限\n§7而非给予权限。' + permissionList: + name: 权限列表 + removed: '§e已移除: §6{permission_removed}' + world: '§e世界:§6{permission_world}' + classesRequired.name: 所需职业 + classesList.name: 职业列表 + factionsRequired.name: 所需派系 + factionsList.name: 派系列表 + poolsManage: + name: 任务池 + itemName: '§a任务池 {pool}' + poolNPC: '§8NPC:§7{pool_npc_id}' + poolMaxQuests: '§8最大任务数:§7{pool_max_quests}' + poolQuestsPerLaunch: '§8每次给予的任务:§7{pool_quests_per_launch}' + poolRedo: '§8可以重新接受已完成的任务:§7{pool_redo}' + poolTime: '§8任务之间的间隔:§7{pool_time}' + poolHologram: '§8全息文本:§7{pool_hologram}' + poolAvoidDuplicates: '§8避免重复:§7{pool_duplicates}' + poolQuestsList: '§7{pool_quests_amount} §8任务:§7{pool_quests}' + create: '§a创建一个任务池' + edit: '§e> §6§o编辑任务池…… §e<' + choose: '§e> §6§o选择该任务池 §e<' + poolCreation: + name: 创建任务池 + hologramText: '§e自定义任务池全息显示' + maxQuests: '§a最大任务数' + questsPerLaunch: 每次启动时开始的任务 + time: '§b设置任务之间的间隔' + redoAllowed: 是否可重复完成 + avoidDuplicates: 避免重复 + avoidDuplicatesLore: '§8> §7尝试避免重复\n 同一任务' + requirements: '§b开始任务所需前置' + poolsList.name: 任务池 + itemComparisons: + name: 物品比较式 + bukkit: Bukkit原生比较 + bukkitLore: "使用Bukkit的默认物品比较系统。\n将会检查材料、耐久度、NBT标签等是否一致" + customBukkit: Bukkit原生比较 - 无NBT + customBukkitLore: "使用Bukkit的默认物品比较系统,NBT标签除外。\n这将会检查材质、耐久等是否相等" + material: 物品材料 + materialLore: '比较物品材料(比如石头|stone、铁剑|iron sword)' + itemName: 物品名称 + itemNameLore: 比较物品名称 + itemLore: 物品描述 + itemLoreLore: 比较物品描述 + enchants: 物品附魔 + enchantsLore: 比较物品附魔 + repairCost: 修复花费 + repairCostLore: 比较盔甲和武器的修复花费 + itemsAdder: ItemsAdder + itemsAdderLore: 比较ItemsAdder ID + mmoItems: MMOitems 物品 + mmoItemsLore: 比较 MMOItems 的物品类型和ID + editTitle: + name: 编辑标题 + title: '§6标题' + subtitle: '§e副标题' + fadeIn: '§a淡入持续时间' + stay: '§b停留持续时间' + fadeOut: '§a淡出持续时间' + particleEffect: + name: 创建粒子特效 + shape: '§d粒子形状' + type: '§e粒子类型' + color: '§b粒子颜色' + particleList: + name: 粒子列表 + colored: 彩色粒子 + damageCause: + name: 造成伤害 + damageCausesList: + name: 造成伤害列表 + visibility: + name: 任务可见度 + notStarted: '“未开始”菜单栏' + inProgress: '“进行中”菜单栏' + finished: '“已完成”菜单栏' + maps: '地图(比如Dynmap或BlueMap)' + equipmentSlots: + name: 装备栏位 + questObjects: + setCustomDescription: '设置自定义描述' + description: '§8描述: §7{description}' scoreboard: - asyncEnd: '§ex' name: '§6§l任务' noLaunched: '§c你没有进行中的任务.' - noLaunchedDescription: '§c§o载入中' noLaunchedName: '§c§l载入中' + noLaunchedDescription: '§c§o载入中' + textBetwteenBranch: '§e或' + asyncEnd: '§ex' stage: - breed: '§e饲养§6{mobs}' - bucket: '§e装满 §6{buckets}' + region: '§e找到区域 §6{region_id}' + npc: '§e和NPC谈话 §6{dialog_npc_name}' + items: '§e将以下物品带给§6{dialog_npc_name}§e: {items}' + mobs: '§e击杀 §6{mobs}' + mine: '§e挖掘 {blocks}' + placeBlocks: '§e放置{blocks}' chat: '§e输入 §6{text}' + interact: '§e点击位于§6{x} {y} {z}的方块' + interactMaterial: '§e点击§6{block}§e方块' + fish: '§e钓鱼 §6{items}' + melt: '§e熔炼 §6{items}' + enchant: '§e附魔 §6{items}' craft: '§e合成 §6{items}' + bucket: '§e装满 §6{buckets}' + location: '§e前往位于 §6{target_world}的坐标§6{target_x}§e, §6{target_y}§e, §6{target_z}§e ' + playTimeFormatted: '§e游玩 §6{time_remaining_human}' + breed: '§e饲养§6{mobs}' + tame: '§e驯服§6{mobs}' + die: '§c死亡' dealDamage: any: '§c造成{damage_remaining}点伤害' mobs: '§c对{target_mobs}造成{damage_remaining}点伤害' - die: '§c死亡' eatDrink: '§e消耗§6{items}' - enchant: '§e附魔 §6{items}' - fish: '§e钓鱼 §6{items}' - interact: '§e点击在§6{x}的方块' - interactMaterial: '§e点击§6{block}§e方块' - items: '§e将物品带给§6{dialog_npc_name}§e:' - location: '§e前往位于 §6{target_world}的坐标§6{target_x}§e, §6{target_y}§e, §6{target_z}§e ' - melt: '§e熔炼 §6{items}' - mine: '§e挖掘 {blocks}' - mobs: '§e击杀 §6{mobs}' - npc: '§e和NPC谈话 §6{dialog_npc_name}' - placeBlocks: '§e放置{blocks}' - playTimeFormatted: '§e游玩 §6{time_remaining_human}' - region: '§e找到区域 §6{region_id}' - tame: '§e驯服§6{mobs}' - textBetwteenBranch: '§e或' +indication: + startQuest: '§7您是否想要接受任务 {quest_name}?' + closeInventory: '§7你确定要关闭该页面吗?' + cancelQuest: '§7您确定要取消任务 {quest_name}?' + removeQuest: '§7您确定要删除任务 {quest}?' + removePool: '§7您确定要删除任务池 {pool}?' +description: + requirement: + title: '§8§l要求:' + level: '{short_level}级' + jobLevel: '{job_name} {short_level}级' + combatLevel: '战斗等级 {short_level}' + skillLevel: '{skill_name} {short_level}级' + class: '{class_name} 职业' + faction: '{faction_name} 派系' + quest: '完成任务 §e{quest_name}' + reward: + title: '§8§l奖励:' +misc: + format: + prefix: '§6<§e§l任务§r§6> §r' + npcText: '§6[{message_id}/{message_count}] §e§l{npc_name_message}:§r§e {text}' + selfText: '§6[{message_id}/{message_count}] §e§l{player_name}:§r§e {text}' + time: + weeks: '{weeks_amount}周' + days: '{days_amount}天' + hours: '{hours_amount}小时' + minutes: '{minutes_amount}分钟' + lessThanAMinute: '少于一分钟' + stageType: + region: 寻找区域 + npc: 寻找 NPC + items: 带回物品 + mobs: 击杀怪物 + mine: 破坏方块 + placeBlocks: 放置方块 + chat: 在聊天框内说话 + interact: 与方块交互 + interactLocation: 与目标地点的方块交互 + Fish: 钓鱼 + Melt: 熔炼物品 + Enchant: 附魔物品 + Craft: 合成物品 + Bucket: 装满桶 + location: 寻找地点 + playTime: 游戏时间 + breedAnimals: 饲养动物 + tameAnimals: 驯服动物 + die: 死亡 + dealDamage: 造成伤害 + eatDrink: 食用或饮用 + comparison: + equals: 等于{number} + different: 不同于{number} + less: 精确小于 {number} + lessOrEquals: 小于{number} + greater: 精确大于{number} + greaterOrEquals: 大于{number} + requirement: + logicalOr: '§d逻辑 或 (前置)' + skillAPILevel: '§d所需SkillAPI等级' + class: '§b所需职业' + faction: '§b所需派系' + jobLevel: '§b所需工作等级' + combatLevel: '§b所需战斗等级' + experienceLevel: '§b所需经验等级' + permissions: '§3所需权限' + scoreboard: '§d所需分数' + region: '§d需要区域' + placeholder: '§b所需占位符数值' + quest: '§a所需前置任务' + mcMMOSkillLevel: '§d所需技能等级' + money: '§d所需金额' + equipment: '§e所需装备' + reward: + skillApiXp: SkillAPI 经验奖励 + bucket: + water: 水桶 + lava: 岩浆桶 + milk: 牛奶桶 + snow: 雪桶 + click: + right: 右击 + left: 左击 + shift-right: Shift+右击 + shift-left: Shift+左击 + middle: 中键点击 + amounts: + items: '{items_amount}件物品' + comparisons: '{comparisons_amount} 个比较' + dialogLines: '{lines_amount}行' + permissions: '{permissions_amount}个权限' + mobs: '{mobs_amount}个怪物' + xp: '{xp_amount} 经验点' + ticks: '{ticks}刻' + location: |- + 位置: {x} {y} {z} + 世界: {world} + questItemLore: '§e§o任务物品' + hologramText: '§8§l任务NPC' + poolHologramText: '§e有可接受的新任务!' + entityType: '§e生物类型: {entity_type}' + entityTypeAny: '§e任何实体' + enabled: 已启用 + disabled: 已关闭 + unknown: 未知 + notSet: '§c未设置' + removeRaw: 移除 + reset: 重置 + or: 或 + amount: '§e数量: {amount}' + 'yes': '是' + 'no': '否' + and: 和 From c85ad8ccf7a1d3e75e0099f1c39eaf5f26fcc316 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sun, 5 Nov 2023 17:59:13 +0100 Subject: [PATCH 78/95] :loud_sound: Added log for wrong inventory catching --- .../quests/gui/GuiManagerImplementation.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index 017e9993..45cf9cc1 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -6,6 +6,7 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.*; import org.bukkit.inventory.Inventory; @@ -186,20 +187,23 @@ public void onDrag(InventoryDragEvent event) { event.setCancelled(true); } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) public void onOpen(InventoryOpenEvent event) { - if (!event.isCancelled()) - return; - if (players.containsKey(event.getPlayer())) { + if (event.isCancelled() && players.containsKey(event.getPlayer())) { QuestsPlugin.getPlugin().getLoggerExpanded().warning("The opening of a BeautyQuests menu for player " + event.getPlayer().getName() + " has been cancelled by another plugin."); } } private void ensureSameInventory(Gui gui, Inventory inventory) { - if (gui.getInventory() != inventory) + if (gui.getInventory() != inventory) { + String expectedName = gui.getInventory().getType().name() + " (" + gui.getClass().getSimpleName() + ")"; + String foundName = inventory == null ? "null" : inventory.getType().name(); + QuestsPlugin.getPlugin().getLoggerExpanded() + .debug("Player shall have a " + expectedName + " inventory but had a " + foundName + " inventory."); throw new IllegalStateException( "The inventory opened by the player is not the same as the one registered by the plugin"); + } } } From 9e26fee974d86c605212a568f60e95d9c05fc790 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 9 Nov 2023 22:33:54 +0100 Subject: [PATCH 79/95] :bug: Fixed custom mob name and minimum level not appearing in GUI --- .../java/fr/skytasul/quests/mobs/Mob.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/mobs/Mob.java b/core/src/main/java/fr/skytasul/quests/mobs/Mob.java index c5ddce46..471b579f 100644 --- a/core/src/main/java/fr/skytasul/quests/mobs/Mob.java +++ b/core/src/main/java/fr/skytasul/quests/mobs/Mob.java @@ -32,15 +32,15 @@ public Mob(@NotNull MobFactory<D> factory, @NotNull D data) { this.factory = factory; this.data = data; } - + public @NotNull MobFactory<D> getFactory() { return factory; } - + public @NotNull D getData() { return data; } - + public @NotNull String getName() { if (formattedName == null) { if (customName != null) { @@ -54,13 +54,14 @@ public Mob(@NotNull MobFactory<D> factory, @NotNull D data) { } return formattedName; } - + public @NotNull List<@Nullable String> getDescriptiveLore() { return factory.getDescriptiveLore(data); } public void setCustomName(@Nullable String customName) { this.customName = customName; + formattedName = null; } public @Nullable Double getMinLevel() { @@ -69,6 +70,7 @@ public void setCustomName(@Nullable String customName) { public void setMinLevel(@Nullable Double minLevel) { this.minLevel = minLevel; + formattedName = null; } public @NotNull XMaterial getMobItem() { @@ -79,15 +81,15 @@ public void setMinLevel(@Nullable Double minLevel) { return XMaterial.SPONGE; } } - + public boolean applies(@Nullable Object data) { return factory.mobApplies(this.data, data); } - + public boolean appliesEntity(@NotNull Entity entity) { return factory.bukkitMobApplies(data, entity); } - + public double getLevel(@NotNull Entity entity) { if (!(factory instanceof LeveledMobFactory)) throw new UnsupportedOperationException( @@ -132,15 +134,15 @@ public Map<String, Object> serialize(){ map.put("name", customName); if (minLevel != null) map.put("minLevel", minLevel); - + return map; } - + @SuppressWarnings ("rawtypes") public static Mob<?> deserialize(Map<String, Object> map) { String factoryName = (String) map.get("factoryName"); String value = (String) map.get("value"); - + MobFactory<?> factory = MobFactory.getMobFactory(factoryName); if (factory == null) throw new IllegalArgumentException("The factory " + factoryName + " is not installed in BeautyQuests."); Object object = factory.fromValue(value); From da58d969b96052e6819ee08d861040429cf0f2d3 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 11 Nov 2023 22:01:29 +0100 Subject: [PATCH 80/95] :white_check_mark: Added unit testing for ChatColorUtils --- api/pom.xml | 17 ++++ .../quests/api/utils/ChatColorUtils.java | 86 ++++++------------- .../quests/api/utils/ChatColorUtilsTest.java | 34 ++++++++ api/src/test/resources/word_wrap.csv | 17 ++++ 4 files changed, 95 insertions(+), 59 deletions(-) create mode 100755 api/src/test/java/fr/skytasul/quests/api/utils/ChatColorUtilsTest.java create mode 100755 api/src/test/resources/word_wrap.csv diff --git a/api/pom.xml b/api/pom.xml index 85d178b1..d8b7188e 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -10,6 +10,10 @@ <artifactId>beautyquests-parent</artifactId> <version>1.0-SNAPSHOT</version> </parent> + + <properties> + <junit.version>5.10.1</junit.version> + </properties> <build> <plugins> @@ -142,5 +146,18 @@ <version>9.4.0</version> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java b/api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java index f8a9160d..1a6ac793 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/ChatColorUtils.java @@ -1,6 +1,5 @@ package fr.skytasul.quests.api.utils; -import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; @@ -11,51 +10,20 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class ChatColorUtils { - - // For testing purposes - public static void main(String[] args) { - //test("Hello there, it's me", 12, 15, "Hello there,", "it's me"); - //test("§aHello there, it's me", 12, 15, "§aHello there,", "§ait's me"); - //test("§aHello §cthere, it's me", 12, 16, "§aHello §cthere,", "§cit's me"); - //test("§aHello §cthere, it's me", 13, 17, "§aHello §cthere,", "§cit's me"); - //test("§aHello §lthere, it's me", 12, 16, "§aHello §lthere,", "§a§lit's me"); - //test("§aHello §c§lthere, it's me", 12, 16, "§aHello", "§c§lthere, it's", "§c§lme"); - //test("§aHello §c§a§o§c§lthere, it's me", 12, 16, "§aHello", "§c§lthere, it's", "§c§lme"); - //test("§aHello §x§1§1§1§1§1§2there, it's me", 12, 30, "§aHello §x§1§1§1§1§1§2there,", "§x§1§1§1§1§1§2it's me"); - //test("§aHello §x§1§1§1§1§1§2there, it's me", 12, 14, "§aHello there,", "it's me"); - //test("§aHello §x§1§1§1§1§1§2there, it's me", 12, 12, "§aHello", "§athere,", "it's me"); - //test("§aHello §x§1§1§1§1§1§2§lthere, it's me", 12, 30, "§aHello §x§1§1§1§1§1§2§lthere,", "§x§1§1§1§1§1§2§lit's me"); - //test("§aHello §x§1§1§1§1§1§2the§lre, it's me", 12, 30, "§aHello §x§1§1§1§1§1§2the§lre,", "§x§1§1§1§1§1§2§lit's me"); - //test("§aHello §x§1§1§1§1§1§2there, §lit's me, owo §ofellas §nowo", 26, 100, "§aHello §x§1§1§1§1§1§2there, §lit's me, owo", "§x§1§1§1§1§1§2§l§ofellas §nowo"); - //test("1 §x§B§B§E§E§D§DHello there, §lhow are you, fellow §ostranger§x§B§B§E§E§D§D?", 40, 100, "1 §x§B§B§E§E§D§DHello there, §lhow are you, fellow", "§x§B§B§E§E§D§D§l§ostranger§x§B§B§E§E§D§D?"); - //test("§aHello, thisisaverylongword and thisisa§lverylongword", 10, 25, "§aHello,", "§athisisaver", "§aylongword", "§aand"); - //test("§bVery_much_§along_word_§dwith_colors_§cinside_and_useless_words_after", 20, 50); - } - - private static int testID = 0; +/** + * Various utility methods for handling Minecraft colors in strings. + * + * @author SkytAsul + */ +public final class ChatColorUtils { + + private ChatColorUtils() {} + private static final Pattern START_WITH_COLORS = Pattern.compile("(?i)^(" + ChatColor.COLOR_CHAR + "[0-9A-FK-ORX])+"); private static final Pattern COLOR = Pattern.compile("(?i)" + ChatColor.COLOR_CHAR + "[0-9A-FK-ORX]"); private static final Pattern HEX_COLOR = Pattern.compile("(?i)[&§]#([A-F0-9]{6})"); private static final Pattern NEWLINE_PATTERN = Pattern.compile("\\\\n|\\{nl\\}"); - - private static void test(String string, int line, int critical, String... expected) { - testID++; - List<String> wrapped = wordWrap(string, line, critical); - PrintStream stream; - if (Arrays.asList(expected).equals(wrapped)) { - stream = System.out; - stream.println("Test " + testID + " successful."); - }else { - stream = System.err; - stream.println("Test " + testID + " not successful."); - stream.println("Got:\n" + String.join("\n", wrapped)); - stream.println("Expected:\n" + String.join("\n", expected)); - } - stream.println(); - stream.println("------------"); - } - + /** * Breaks a raw string up into a series of lines. Words are wrapped using * spaces as decimeters and the newline character is respected. @@ -67,7 +35,7 @@ private static void test(String string, int line, int critical, String... expect public static @NotNull List<@NotNull String> wordWrap(@Nullable String rawString, int lineLength) { return wordWrap(rawString, lineLength, lineLength); } - + public static @NotNull List<@NotNull String> wordWrap(@Nullable String rawString, int maxLineLength, int criticalLineLength) { if (maxLineLength > criticalLineLength) maxLineLength = criticalLineLength; @@ -75,14 +43,14 @@ private static void test(String string, int line, int critical, String... expect if (rawString == null) { return Arrays.asList(""); } - + rawString = NEWLINE_PATTERN.matcher(rawString).replaceAll("\n"); - + // A string shorter than the lineWidth is a single line if (rawString.length() <= maxLineLength && !rawString.contains("\n")) { return Arrays.asList(rawString); } - + try { char[] rawChars = (rawString + ' ').toCharArray(); // add a trailing space to trigger pagination StringBuilder word = new StringBuilder(); @@ -93,10 +61,10 @@ private static void test(String string, int line, int critical, String... expect List<String> lines = new LinkedList<>(); int wordLength = 0; int lineLength = 0; - + for (int i = 0; i < rawChars.length; i++) { char c = rawChars[i]; - + // skip chat color modifiers if (c == ChatColor.COLOR_CHAR) { Matcher matcher = START_WITH_COLORS.matcher(rawString.substring(i)); @@ -106,7 +74,7 @@ private static void test(String string, int line, int critical, String... expect colors = appendRawColorString(colors, rawColors); String toAdd = getColorDifference(oldColors, colors); //System.out.println("new colors: " + colors + " | to add: " + toAdd); - + if (colors.length() >= criticalLineLength) { // weird case : the formatting and word is longer than a line colors = ""; }else { @@ -165,7 +133,7 @@ private static void test(String string, int line, int critical, String... expect colorsWord = colors; word = lineLength == 0 ? new StringBuilder(colors) : new StringBuilder(); wordLength = 0; - + if (c == '\n') { // Newline forces the line to flush ////System.out.println(lastColors.replace('§', '&') + " LINE " + line.toString()); lines.add(line.toString()); @@ -179,11 +147,11 @@ private static void test(String string, int line, int critical, String... expect wordLength++; } } - + if (line.length() > 0) { // Only add the last line if there is anything to add lines.add(line.toString()); } - + return lines; }catch (Exception ex) { new RuntimeException("An exception occurred while trying to split the string " + rawString + " with max length " + maxLineLength + " and critical length " + criticalLineLength, ex).printStackTrace(); @@ -191,7 +159,7 @@ private static void test(String string, int line, int critical, String... expect return Arrays.asList(rawString.split("(?<=\\G.{4})")); } } - + public static @NotNull String appendRawColorString(@NotNull String original, @NotNull String appended) { StringBuilder builder = new StringBuilder(original); StringBuilder hexBuilder = null; @@ -222,11 +190,11 @@ private static void test(String string, int line, int critical, String... expect } return builder.toString(); } - + private static @NotNull String getColorDifference(@NotNull String oldColors, @NotNull String newColors) { return newColors.startsWith(oldColors) ? newColors.substring(oldColors.length()) : newColors; } - + private static @NotNull List<@NotNull String> splitColoredWord(@NotNull String string, int stringLength, int maxLength, int criticalLength, @NotNull String startColors) { final String original = string; @@ -286,7 +254,7 @@ private static void test(String string, int line, int critical, String... expect split.add(string); return split; } - + private static int getFirstTextIndex(@NotNull String string) { for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); @@ -298,7 +266,7 @@ private static int getFirstTextIndex(@NotNull String string) { } return string.length(); } - + public static @NotNull String translateHexColorCodes(@NotNull String message) { Matcher matcher = HEX_COLOR.matcher(message); StringBuffer buffer = new StringBuffer(message.length() + 4 * 8); @@ -311,7 +279,7 @@ private static int getFirstTextIndex(@NotNull String string) { } return matcher.appendTail(buffer).toString(); } - + public static @NotNull String getLastColors(@NotNull String originalColors, @Nullable String appended) { if (appended == null || appended.length() == 0) return originalColors; StringBuilder builder = originalColors == null ? new StringBuilder() : new StringBuilder(originalColors); @@ -355,5 +323,5 @@ private static int getFirstTextIndex(@NotNull String string) { } return builder.toString(); } - + } diff --git a/api/src/test/java/fr/skytasul/quests/api/utils/ChatColorUtilsTest.java b/api/src/test/java/fr/skytasul/quests/api/utils/ChatColorUtilsTest.java new file mode 100755 index 00000000..ddb2237b --- /dev/null +++ b/api/src/test/java/fr/skytasul/quests/api/utils/ChatColorUtilsTest.java @@ -0,0 +1,34 @@ +package fr.skytasul.quests.api.utils; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.aggregator.AggregateWith; +import org.junit.jupiter.params.aggregator.ArgumentsAccessor; +import org.junit.jupiter.params.aggregator.ArgumentsAggregationException; +import org.junit.jupiter.params.aggregator.ArgumentsAggregator; +import org.junit.jupiter.params.provider.CsvFileSource; + +class ChatColorUtilsTest { + + @ParameterizedTest + @CsvFileSource(resources = "/word_wrap.csv", numLinesToSkip = 1) + void test(String string, int line, int critical, @AggregateWith(VarargsAggregator.class) String... expected) { + List<@NotNull String> wrapped = ChatColorUtils.wordWrap(string, line, critical); + assertArrayEquals(expected, wrapped.toArray(new String[0])); + } + + static class VarargsAggregator implements ArgumentsAggregator { + @Override + public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) + throws ArgumentsAggregationException { + return accessor.toList().stream() + .skip(context.getIndex()) + .map(String::valueOf) + .toArray(String[]::new); + } + } + +} diff --git a/api/src/test/resources/word_wrap.csv b/api/src/test/resources/word_wrap.csv new file mode 100755 index 00000000..b3cf91f6 --- /dev/null +++ b/api/src/test/resources/word_wrap.csv @@ -0,0 +1,17 @@ +string,line,critical,expected, +"Hello there, it's me",12,15,"Hello there,",it's me +"§aHello there, it's me", 12, 15, "§aHello there,", "§ait's me" +"§aHello §cthere, it's me", 12, 16, "§aHello §cthere,", "§cit's me" +"§aHello §cthere, it's me", 13, 17, "§aHello §cthere,", "§cit's me" +"§aHello §lthere, it's me", 12, 16, "§aHello §lthere,", "§a§lit's me" +"§aHello §c§lthere, it's me", 12, 16, "§aHello", "§c§lthere, it's", "§c§lme" +"§aHello §c§a§o§c§lthere, it's me", 12, 16, "§aHello", "§c§lthere, it's", "§c§lme" +"§aHello §x§1§1§1§1§1§2there, it's me", 12, 30, "§aHello §x§1§1§1§1§1§2there,", "§x§1§1§1§1§1§2it's me" +"§aHello §x§1§1§1§1§1§2there, it's me", 12, 14, "§aHello there,", "it's me" +"§aHello §x§1§1§1§1§1§2there, it's me", 12, 12, "§aHello", "§athere,", "it's me" +"§aHello §x§1§1§1§1§1§2§lthere, it's me", 12, 30, "§aHello §x§1§1§1§1§1§2§lthere,", "§x§1§1§1§1§1§2§lit's me" +"§aHello §x§1§1§1§1§1§2the§lre, it's me", 12, 30, "§aHello §x§1§1§1§1§1§2the§lre,", "§x§1§1§1§1§1§2§lit's me" +"§aHello §x§1§1§1§1§1§2there, §lit's me, owo §ofellas §nowo", 26, 100, "§aHello §x§1§1§1§1§1§2there, §lit's me, owo", "§x§1§1§1§1§1§2§l§ofellas §nowo" +"1 §x§B§B§E§E§D§DHello there, §lhow are you, fellow §ostranger§x§B§B§E§E§D§D?", 40, 100, "1 §x§B§B§E§E§D§DHello there, §lhow are you, fellow", "§x§B§B§E§E§D§D§l§ostranger§x§B§B§E§E§D§D?" +"§aHello, thisisaverylongword and thisisa§lverylongword", 10, 25, "§aHello,", "§athisisaver", "§aylongword", "§aand", "§athisisa§lv", "§a§lerylongwor", "§a§ld" +"§bVery_much_§along_word_§dwith_colors_§cinside_and_useless_words_after", 20, 50, "idk" From ff8360a8e6beb4924863d6362b51d2aa41cb6519 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 13 Nov 2023 10:13:56 +0100 Subject: [PATCH 81/95] :children_crossing: Hide requirements button for "play time" stage --- api/dependency-reduced-pom.xml | 42 ++++++++++++++ api/pom.xml | 8 +++ .../api/stages/creation/StageCreation.java | 47 +++++++++------- .../skytasul/quests/stages/StagePlayTime.java | 56 +++++++++++-------- 4 files changed, 110 insertions(+), 43 deletions(-) diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml index eeca2f22..55adc0d4 100755 --- a/api/dependency-reduced-pom.xml +++ b/api/dependency-reduced-pom.xml @@ -84,6 +84,13 @@ <skipSource>false</skipSource> </configuration> </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.2.2</version> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> </plugins> </build> <repositories> @@ -193,5 +200,40 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>5.10.1</version> + <scope>test</scope> + <exclusions> + <exclusion> + <artifactId>opentest4j</artifactId> + <groupId>org.opentest4j</groupId> + </exclusion> + <exclusion> + <artifactId>junit-platform-commons</artifactId> + <groupId>org.junit.platform</groupId> + </exclusion> + <exclusion> + <artifactId>apiguardian-api</artifactId> + <groupId>org.apiguardian</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <version>5.10.1</version> + <scope>test</scope> + <exclusions> + <exclusion> + <artifactId>apiguardian-api</artifactId> + <groupId>org.apiguardian</groupId> + </exclusion> + </exclusions> + </dependency> </dependencies> + <properties> + <junit.version>5.10.1</junit.version> + </properties> </project> diff --git a/api/pom.xml b/api/pom.xml index d8b7188e..7efae76d 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -95,6 +95,14 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.2.2</version> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> </plugins> </build> diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java index 66f055cd..06aa448f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/creation/StageCreation.java @@ -24,6 +24,11 @@ public abstract class StageCreation<T extends AbstractStage> { + protected static final int SLOT_REWARDS = 1; + protected static final int SLOT_DESCRIPTION = 2; + protected static final int SLOT_MESSAGE = 3; + protected static final int SLOT_REQUIREMENTS = 4; + private static final ItemStack ENDING_ITEM = ItemUtils.item(XMaterial.BAKED_POTATO, Lang.ending.toString()); private static final ItemStack DESCRITPION_MESSAGE_ITEM = ItemUtils.item(XMaterial.OAK_SIGN, Lang.descMessage.toString()); @@ -33,14 +38,14 @@ public abstract class StageCreation<T extends AbstractStage> { QuestOption.formatDescription(Lang.validationRequirementsLore.toString())); protected final @NotNull StageCreationContext<T> context; - + private List<AbstractReward> rewards; private List<AbstractRequirement> requirements; - + private List<StageOption<T>> options; - + private String customDescription, startMessage; - + protected StageCreation(@NotNull StageCreationContext<T> context) { this.context = context; } @@ -48,55 +53,55 @@ protected StageCreation(@NotNull StageCreationContext<T> context) { public @NotNull StageCreationContext<T> getCreationContext() { return context; } - + public @NotNull StageGuiLine getLine() { return context.getLine(); } - + public List<AbstractReward> getRewards() { return rewards; } - + public void setRewards(List<AbstractReward> rewards) { this.rewards = rewards; getLine().refreshItemLore(1, QuestOption.formatDescription(RewardList.getSizeString(rewards.size()))); } - + public List<AbstractRequirement> getRequirements() { return requirements; } - + public void setRequirements(List<AbstractRequirement> requirements) { getLine().refreshItemLore(4, QuestOption.formatDescription(RequirementList.getSizeString(requirements.size()))); this.requirements = requirements; } - + public String getCustomDescription() { return customDescription; } - + public void setCustomDescription(String customDescription) { this.customDescription = customDescription; getLine().refreshItemLore(2, QuestOption.formatNullableValue(customDescription)); } - + public String getStartMessage() { return startMessage; } - + public void setStartMessage(String startMessage) { this.startMessage = startMessage; getLine().refreshItemLore(3, QuestOption.formatNullableValue(startMessage)); } - + public void setupLine(@NotNull StageGuiLine line) { - line.setItem(1, ENDING_ITEM.clone(), + line.setItem(SLOT_REWARDS, ENDING_ITEM.clone(), event -> QuestsAPI.getAPI().getRewards().createGUI(QuestObjectLocation.STAGE, rewards -> { setRewards(rewards); event.reopen(); }, rewards).open(event.getPlayer())); - line.setItem(2, DESCRITPION_MESSAGE_ITEM.clone(), event -> { + line.setItem(SLOT_DESCRIPTION, DESCRITPION_MESSAGE_ITEM.clone(), event -> { Lang.DESC_MESSAGE.send(event.getPlayer()); new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { setCustomDescription(obj); @@ -104,7 +109,7 @@ public void setupLine(@NotNull StageGuiLine line) { }).passNullIntoEndConsumer().start(); }); - line.setItem(3, START_MESSAGE_ITEM.clone(), event -> { + line.setItem(SLOT_MESSAGE, START_MESSAGE_ITEM.clone(), event -> { Lang.START_TEXT.send(event.getPlayer()); new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { setStartMessage(obj); @@ -112,7 +117,7 @@ public void setupLine(@NotNull StageGuiLine line) { }).passNullIntoEndConsumer().start(); }); - line.setItem(4, VALIDATION_REQUIREMENTS_ITEM.clone(), event -> { + line.setItem(SLOT_REQUIREMENTS, VALIDATION_REQUIREMENTS_ITEM.clone(), event -> { QuestsAPI.getAPI().getRequirements().createGUI(QuestObjectLocation.STAGE, requirements -> { setRequirements(requirements); event.reopen(); @@ -129,7 +134,7 @@ public void start(@NotNull Player p) { setRequirements(new ArrayList<>()); setCustomDescription(null); setStartMessage(null); - + options = context.getType().getOptionsRegistry().getCreators().stream().map(SerializableCreator::newObject) .collect(Collectors.toList()); options.forEach(option -> option.startEdition(this)); @@ -144,7 +149,7 @@ public void edit(@NotNull T stage) { setRequirements(stage.getValidationRequirements()); setStartMessage(stage.getStartMessage()); setCustomDescription(stage.getCustomText()); - + options = stage.getOptions().stream().map(StageOption::clone).map(x -> (StageOption<T>) x).collect(Collectors.toList()); options.forEach(option -> option.startEdition(this)); } @@ -166,5 +171,5 @@ public void edit(@NotNull T stage) { * @return AsbtractStage created */ protected abstract @NotNull T finishStage(@NotNull StageController branch); - + } diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index 4b239e07..8e633625 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -15,6 +15,7 @@ import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; +import fr.skytasul.quests.api.requirements.RequirementList; import fr.skytasul.quests.api.stages.AbstractStage; import fr.skytasul.quests.api.stages.StageController; import fr.skytasul.quests.api.stages.StageDescriptionPlaceholdersContext; @@ -31,23 +32,23 @@ public class StagePlayTime extends AbstractStage implements HasProgress { private final long playTicks; - + private Map<Player, BukkitTask> tasks = new HashMap<>(); - + public StagePlayTime(StageController controller, long ticks) { super(controller); this.playTicks = ticks; } - + public long getTicksToPlay() { return playTicks; } - + @Override public @NotNull String getDefaultDescription(@NotNull StageDescriptionPlaceholdersContext context) { return Lang.SCOREBOARD_PLAY_TIME.toString(); } - + @Override protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placeholders) { super.createdPlaceholdersRegistry(placeholders); @@ -55,19 +56,19 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol context -> Utils.millisToHumanString(getPlayerAmount(context.getPlayerAccount()))); ProgressPlaceholders.registerProgress(placeholders, "time", this); } - + private long getRemaining(PlayerAccount acc) { long remaining = Utils.parseLong(getData(acc, "remainingTime")); long lastJoin = Utils.parseLong(getData(acc, "lastJoin")); long playedTicks = (System.currentTimeMillis() - lastJoin) / 50; return remaining - playedTicks; } - + private void launchTask(Player p, long remaining) { tasks.put(p, Bukkit.getScheduler().runTaskLater(BeautyQuests.getInstance(), () -> finishStage(p), remaining < 0 ? 0 : remaining)); } - + @Override public int getPlayerAmount(@NotNull PlayerAccount account) { return (int) (getRemaining(account) * 50L); @@ -84,7 +85,7 @@ public void joined(Player p) { updateObjective(p, "lastJoin", System.currentTimeMillis()); launchTask(p, Utils.parseLong(getData(p, "remainingTime"))); } - + @Override public void left(Player p) { super.left(p); @@ -101,7 +102,7 @@ private void cancelTask(Player p, BukkitTask task) { task.cancel(); updateObjective(p, "remainingTime", getRemaining(PlayersManager.getPlayerAccount(p))); } - + @Override public void started(PlayerAccount acc) { super.started(acc); @@ -109,7 +110,7 @@ public void started(PlayerAccount acc) { if (acc.isCurrent()) launchTask(acc.getPlayer(), playTicks); } - + @Override public void ended(PlayerAccount acc) { super.ended(acc); @@ -124,7 +125,7 @@ public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { datas.put("remainingTime", playTicks); datas.put("lastJoin", System.currentTimeMillis()); } - + @Override public void unload() { super.unload(); @@ -132,17 +133,26 @@ public void unload() { tasks.clear(); } + @Override + public void setValidationRequirements(@NotNull RequirementList validationRequirements) { + super.setValidationRequirements(validationRequirements); + if (!validationRequirements.isEmpty()) + QuestsPlugin.getPlugin().getLogger().warning(validationRequirements.size() + + " requirements are set for a \"play time\" stage, but requirements are unsupported for this stage type.\n" + + controller.toString()); + } + @Override protected void serialize(ConfigurationSection section) { section.set("playTicks", playTicks); } - + public static StagePlayTime deserialize(ConfigurationSection section, StageController controller) { return new StagePlayTime(controller, section.getLong("playTicks")); } - + public static class Creator extends StageCreation<StagePlayTime> { - + private long ticks; public Creator(@NotNull StageCreationContext<StagePlayTime> context) { @@ -152,7 +162,9 @@ public Creator(@NotNull StageCreationContext<StagePlayTime> context) { @Override public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - + + line.removeItem(SLOT_REQUIREMENTS); + line.setItem(7, ItemUtils.item(XMaterial.CLOCK, Lang.changeTicksRequired.toString()), event -> { Lang.GAME_TICKS.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { @@ -161,12 +173,12 @@ public void setupLine(@NotNull StageGuiLine line) { }, MinecraftTimeUnit.TICK.getParser()).start(); }); } - + public void setTicks(long ticks) { this.ticks = ticks; getLine().refreshItemLoreOptionValue(7, Lang.Ticks.quickFormat("ticks", ticks + " ticks")); } - + @Override public void start(Player p) { super.start(p); @@ -176,18 +188,18 @@ public void start(Player p) { context.reopenGui(); }, MinecraftTimeUnit.TICK.getParser()).start(); } - + @Override public void edit(StagePlayTime stage) { super.edit(stage); setTicks(stage.playTicks); } - + @Override public StagePlayTime finishStage(StageController controller) { return new StagePlayTime(controller, ticks); } - + } - + } From 720aa860b25640ec9e7d05020952bee6480da406 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 13 Nov 2023 10:15:50 +0100 Subject: [PATCH 82/95] :bug: Fixed NPC selection editor not working for kill NPC * fixes #294 --- .../integrations/mobs/CitizensFactory.java | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java index 3d7c9dc8..9bc09a8d 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/mobs/CitizensFactory.java @@ -41,24 +41,7 @@ public void itemClick(Player p, Consumer<NPC> run) { Lang.SELECT_KILL_NPC.send(p); // we cannot use the SelectNPC editor as it uses the BQNPCManager // and if it is registered to another NPC plugin it wouldn't work - new InventoryClear(p, () -> run.accept(null)) { - - @EventHandler(priority = EventPriority.LOW) - private void onNPCClick(NPCRightClickEvent e) { - if (e.getClicker() != player) - return; - e.setCancelled(true); - stop(); - run.accept(e.getNPC()); - } - - @Override - public void begin() { - super.begin(); - Lang.NPC_EDITOR_ENTER.send(p); - } - - }.start(); + new CitizensNpcClickEditor(p, () -> run.accept(null), p, run).start(); } @Override @@ -98,4 +81,30 @@ public void onNPCKilled(NPCDeathEvent e) { callEvent(e, e.getNPC(), en, en.getKiller()); } + private class CitizensNpcClickEditor extends InventoryClear implements Listener { + private final Player p; + private final Consumer<NPC> run; + + private CitizensNpcClickEditor(Player p, Runnable cancel, Player p2, Consumer<NPC> run) { + super(p, cancel); + this.p = p2; + this.run = run; + } + + @EventHandler(priority = EventPriority.LOW) + private void onNPCClick(NPCRightClickEvent e) { + if (e.getClicker() != player) + return; + e.setCancelled(true); + stop(); + run.accept(e.getNPC()); + } + + @Override + public void begin() { + super.begin(); + Lang.NPC_EDITOR_ENTER.send(p); + } + } + } From 3949ef1803d2fea47cc62511b019becf0d0a8fb2 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Mon, 13 Nov 2023 10:47:51 +0100 Subject: [PATCH 83/95] :bug: Fixed play time no longer working --- .../src/main/java/fr/skytasul/quests/stages/StagePlayTime.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index 8e633625..7232f63a 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -163,7 +163,8 @@ public Creator(@NotNull StageCreationContext<StagePlayTime> context) { public void setupLine(@NotNull StageGuiLine line) { super.setupLine(line); - line.removeItem(SLOT_REQUIREMENTS); + line.refreshItemName(SLOT_REQUIREMENTS, + "§n" + Lang.validationRequirements + "§c " + Lang.Disabled.toString().toUpperCase()); line.setItem(7, ItemUtils.item(XMaterial.CLOCK, Lang.changeTicksRequired.toString()), event -> { Lang.GAME_TICKS.send(event.getPlayer()); From fb375e83ca0eb3a89912bb7e14f27b435b5c0a9c Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 18 Nov 2023 12:54:12 +0100 Subject: [PATCH 84/95] :bug: Fixed some bugs * fixed error popping in console when scoreboards failed to enable * made plugin resilient to lack of data for a stage --- .../quests/scoreboards/ScoreboardManager.java | 78 +++++++++---------- .../StageControllerImplementation.java | 9 ++- integrations/pom.xml | 2 +- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java index 2125b6bb..b4282a7c 100644 --- a/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java +++ b/core/src/main/java/fr/skytasul/quests/scoreboards/ScoreboardManager.java @@ -1,11 +1,7 @@ package fr.skytasul.quests.scoreboards; import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.function.Consumer; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; @@ -31,38 +27,38 @@ public class ScoreboardManager implements Listener, QuestsHandler { private final File file; private Map<Player, Scoreboard> scoreboards; private Map<UUID, Boolean> forceHiddenState; - + // Parameters private final List<ScoreboardLine> lines = new ArrayList<>(); - + private int changeTime; private boolean hide; private boolean refreshLines; private boolean hideUnknownQuestPlaceholders; - + private List<String> worldsFilter; private boolean isWorldAllowList; - + public ScoreboardManager(File file) { this.file = file; } - + public List<ScoreboardLine> getScoreboardLines(){ return lines; } - + public int getQuestChangeTime(){ return changeTime; } - + public boolean hideEmtptyScoreboard(){ return hide; } - + public boolean refreshLines(){ return refreshLines; } - + public boolean hideUnknownQuestPlaceholders() { return hideUnknownQuestPlaceholders; } @@ -70,19 +66,19 @@ public boolean hideUnknownQuestPlaceholders() { public List<String> getWorldsFilter() { return worldsFilter; } - + public boolean isWorldAllowList() { return isWorldAllowList; } - + public boolean isWorldAllowed(String worldName) { return isWorldAllowList() ? getWorldsFilter().contains(worldName) : !getWorldsFilter().contains(worldName); } - + public Scoreboard getPlayerScoreboard(Player p){ return scoreboards.get(p); } - + public void removePlayerScoreboard(Player p){ Scoreboard scoreboard = scoreboards.remove(p); if (scoreboard != null) { @@ -90,32 +86,32 @@ public void removePlayerScoreboard(Player p){ forceHiddenState.put(p.getUniqueId(), scoreboard.isForceHidden()); } } - + public void create(Player p){ if (!QuestsConfiguration.getConfig().getQuestsConfig().scoreboards()) return; removePlayerScoreboard(p); - + Scoreboard scoreboard = new Scoreboard(p, this); scoreboards.put(p, scoreboard); - + Boolean forceHidden = forceHiddenState.remove(p.getUniqueId()); if (forceHidden != null && forceHidden.booleanValue()) scoreboard.hide(true); } - + @Override public void load() { if (!QuestsConfiguration.getConfig().getQuestsConfig().scoreboards()) return; - + try { new FastBoard(null); // trigger class initialization }catch (ExceptionInInitializerError ex) { throw new IllegalStateException("The Scoreboard util cannot load, probably due to an incompatible server version.", ex); }catch (NullPointerException ex) {} // as we pass a null player to initialize, it will throw NPE - + YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - + ConfigurationSection questsSection = config.getConfigurationSection("quests"); changeTime = questsSection.getInt("changeTime", 11); hide = questsSection.getBoolean("hideIfEmpty", true); @@ -124,7 +120,7 @@ public void load() { worldsFilter = config.getStringList("worlds.filterList"); isWorldAllowList = config.getBoolean("worlds.isAllowList"); - + lines.clear(); for (Map<?, ?> map : config.getMapList("lines")) { if (lines.size() == 15) { @@ -138,14 +134,16 @@ public void load() { } } QuestsPlugin.getPlugin().getLoggerExpanded().debug("Registered " + lines.size() + " lines in scoreboard"); - + scoreboards = new HashMap<>(); forceHiddenState = new HashMap<>(); Bukkit.getPluginManager().registerEvents(this, BeautyQuests.getInstance()); } - + @Override public void unload(){ + if (scoreboards == null) + return; HandlerList.unregisterAll(this); for (Scoreboard s : scoreboards.values()) s.cancel(); if (!scoreboards.isEmpty()) QuestsPlugin.getPlugin().getLoggerExpanded().info(scoreboards.size() + " scoreboards deleted."); @@ -154,26 +152,26 @@ public void unload(){ forceHiddenState.clear(); forceHiddenState = null; } - + @EventHandler public void onAccountJoin(PlayerAccountJoinEvent e) { create(e.getPlayer()); } - + @EventHandler (priority = EventPriority.LOW) public void onAccountLeave(PlayerAccountLeaveEvent e) { removePlayerScoreboard(e.getPlayer()); } - + @EventHandler public void onChangeWorld(PlayerChangedWorldEvent e) { Scoreboard scoreboard = getPlayerScoreboard(e.getPlayer()); if (scoreboard == null) return; scoreboard.worldChange(isWorldAllowed(e.getPlayer().getWorld().getName())); } - + /* Quests events */ - + @Override public void questEdit(Quest newQuest, Quest oldQuest, boolean keepDatas) { scoreboards.forEach((p, scoreboard) -> { @@ -184,42 +182,42 @@ public void questEdit(Quest newQuest, Quest oldQuest, boolean keepDatas) { } }); } - + @Override public void questRemove(Quest quest) { if (!quest.isScoreboardEnabled()) return; scoreboards.forEach((p, scoreboard) -> scoreboard.questRemove(quest)); } - + @Override public void questFinish(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; questEvent(acc, x -> x.questRemove(quest)); } - + @Override public void questReset(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; questEvent(acc, x -> x.questRemove(quest)); } - + @Override public void questUpdated(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; questEvent(acc, x -> x.setShownQuest(quest, true)); } - + @Override public void questStart(PlayerAccount acc, Quest quest) { if (!quest.isScoreboardEnabled()) return; questEvent(acc, x -> x.questAdd(quest)); } - + private void questEvent(PlayerAccount acc, Consumer<Scoreboard> consumer) { if (acc.isCurrent()) { Scoreboard scoreboard = scoreboards.get(acc.getPlayer()); if (scoreboard != null) consumer.accept(scoreboard); } } - + } diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index 9b29ce10..4ff30fc9 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -5,7 +5,6 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; -import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -82,7 +81,13 @@ public boolean hasStarted(@NotNull PlayerAccount acc) { public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nullable Object dataValue) { PlayerAccount acc = PlayersManager.getPlayerAccount(player); Map<String, Object> datas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); - Validate.notNull(datas, "Account " + acc.debugName() + " does not have datas for " + toString()); + if (datas == null) { + QuestsPlugin.getPlugin().getLogger() + .severe("Account " + acc.debugName() + " did not have data for " + toString() + ". Creating some."); + datas = new HashMap<>(); + stage.initPlayerDatas(acc, datas); + } + datas.put(dataKey, dataValue); acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); diff --git a/integrations/pom.xml b/integrations/pom.xml index cb5917cb..5f1b5e5b 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -198,7 +198,7 @@ <dependency> <groupId>com.github.decentsoftware-eu</groupId> <artifactId>decentholograms</artifactId> - <version>2.8.1</version> + <version>2.8.5</version> <scope>provided</scope> </dependency> <dependency> From d22a10aef66292e61db5e553afe40c9d91423d20 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 24 Nov 2023 10:54:35 +0100 Subject: [PATCH 85/95] :sparkles: Added player selector support for pool start command --- .../quests/commands/CommandsPools.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java index 6c51a592..47b92ab8 100644 --- a/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java +++ b/core/src/main/java/fr/skytasul/quests/commands/CommandsPools.java @@ -6,6 +6,7 @@ import fr.skytasul.quests.api.commands.revxrsal.annotation.Subcommand; import fr.skytasul.quests.api.commands.revxrsal.annotation.Switch; 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.orphan.OrphanCommand; import fr.skytasul.quests.api.localization.Lang; @@ -40,15 +41,17 @@ public void resetPlayerPool(BukkitCommandActor actor, Player player, QuestPool p @Subcommand("start") @CommandPermission("beautyquests.command.pools.start") - public void start(BukkitCommandActor actor, Player player, QuestPool pool) { - PlayerAccount acc = PlayersManager.getPlayerAccount(player); - if (!pool.canGive(player)) { - Lang.POOL_START_ERROR.send(player, pool, acc); - return; - } + public void start(BukkitCommandActor actor, EntitySelector<Player> players, QuestPool pool) { + for (Player player : players) { + PlayerAccount acc = PlayersManager.getPlayerAccount(player); + if (!pool.canGive(player)) { + Lang.POOL_START_ERROR.send(player, pool, acc); + return; + } - pool.give(player).thenAccept( - result -> Lang.POOL_START_SUCCESS.send(player, pool, acc, PlaceholderRegistry.of("result", result))); + pool.give(player).thenAccept( + result -> Lang.POOL_START_SUCCESS.send(player, pool, acc, PlaceholderRegistry.of("result", result))); + } } } From c8f763e623ffab6dcbe18debb3408174df48f948 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 24 Nov 2023 10:58:50 +0100 Subject: [PATCH 86/95] :goal_net: Made plugin more robust in case of missing stage datas --- .../stages/types/AbstractCountableStage.java | 5 ++--- .../StageControllerImplementation.java | 20 ++++++++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java index 177316ce..46cd296a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractCountableStage.java @@ -57,7 +57,7 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { Map<?, Integer> remaining = getData(acc, "remaining"); if (warnNull && remaining == null) { QuestsPlugin.getPlugin().getLoggerExpanded().warning( - "Cannot retrieve stage datas for " + acc.getNameAndID() + " on " + super.toString(), + "Cannot retrieve remaining amounts for " + acc.getNameAndID() + " on " + controller.toString(), "datas" + acc.getNameAndID() + controller.toString(), 10); } @@ -91,7 +91,7 @@ public Map<Integer, Entry<T, Integer>> cloneObjects() { @Override public @NotNull Map<CountableObject<T>, Integer> getPlayerAmounts(@NotNull PlayerAccount account) { - return getPlayerRemainings(account, true) + return getPlayerRemainings(account, false) .entrySet().stream() .map(entry -> new AbstractMap.SimpleEntry<>(getObject(entry.getKey()).orElse(null), entry.getValue())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); @@ -161,7 +161,6 @@ public boolean event(@NotNull Player p, @UnknownNullability Object object, int a for (CountableObject<T> countableObject : objects) { if (objectApplies(countableObject.getObject(), object)) { Map<UUID, Integer> playerAmounts = getPlayerRemainings(acc, true); - if (playerAmounts == null) return true; if (playerAmounts.containsKey(countableObject.getUUID())) { int playerAmount = playerAmounts.remove(countableObject.getUUID()); if (playerAmount <= amount) { diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index 4ff30fc9..b0a6d36e 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -20,6 +20,7 @@ import fr.skytasul.quests.api.events.accounts.PlayerAccountLeaveEvent; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.players.PlayerAccount; +import fr.skytasul.quests.api.players.PlayerQuestDatas; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.stages.*; import fr.skytasul.quests.api.utils.messaging.MessageType; @@ -83,7 +84,7 @@ public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nu Map<String, Object> datas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); if (datas == null) { QuestsPlugin.getPlugin().getLogger() - .severe("Account " + acc.debugName() + " did not have data for " + toString() + ". Creating some."); + .severe("Account " + acc.getNameAndID() + " did not have data for " + toString() + ". Creating some."); datas = new HashMap<>(); stage.initPlayerDatas(acc, datas); } @@ -97,8 +98,21 @@ public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nu @Override public <D> @Nullable D getData(@NotNull PlayerAccount acc, @NotNull String dataKey) { - Map<String, Object> stageDatas = acc.getQuestDatas(branch.getQuest()).getStageDatas(getStorageId()); - return stageDatas == null ? null : (D) stageDatas.get(dataKey); + PlayerQuestDatas playerDatas = acc.getQuestDatas(branch.getQuest()); + Map<String, Object> datas = playerDatas.getStageDatas(getStorageId()); + + if (datas == null) { + if (!hasStarted(acc)) + throw new IllegalStateException("Trying to fetch data of not launched stage"); + + QuestsPlugin.getPlugin().getLogger() + .severe("Account " + acc.getNameAndID() + " did not have data for " + toString() + ". Creating some."); + datas = new HashMap<>(); + stage.initPlayerDatas(acc, datas); + acc.getQuestDatas(branch.getQuest()).setStageDatas(getStorageId(), datas); + } + + return (D) datas.get(dataKey); } @Override From b64bb8dcebf838b0c2ee6ae3d9d24166db07c341 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 24 Nov 2023 11:04:11 +0100 Subject: [PATCH 87/95] :bug: Fixed dynmap integration not working * fixes #298 --- core/src/main/java/fr/skytasul/quests/BeautyQuests.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 95388748..89b647db 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -495,6 +495,9 @@ private void loadAllDatas() throws Throwable { logger.severe("Error while loading player datas.", ex); } + pools = new QuestPoolsManagerImplementation(new File(getDataFolder(), "questPools.yml")); + quests = new QuestsManagerImplementation(this, data.getInt("lastID"), saveFolder); + getAPI().getQuestsHandlers().forEach(handler -> { try { handler.load(); @@ -503,9 +506,6 @@ private void loadAllDatas() throws Throwable { } }); - pools = new QuestPoolsManagerImplementation(new File(getDataFolder(), "questPools.yml")); - quests = new QuestsManagerImplementation(this, data.getInt("lastID"), saveFolder); - if (config.firstQuestID != -1) { logger.warning("The config option \"firstQuest\" is present in your config.yml but is now unsupported. Please remove it."); QuestImplementation quest = quests.getQuest(config.firstQuestID); From 785ea78da0b27d6ab2675b697a7166c3596539d2 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Tue, 28 Nov 2023 18:54:20 +0100 Subject: [PATCH 88/95] :sparkles: Added offline modes to "play time" stage --- .../quests/api/localization/Lang.java | 5 + .../skytasul/quests/stages/StagePlayTime.java | 117 +++++++++++++++--- core/src/main/resources/locales/en_US.yml | 6 + 3 files changed, 114 insertions(+), 14 deletions(-) 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 8de0233b..5131f2f0 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 @@ -401,6 +401,11 @@ public enum Lang implements Locale { stageEatDrinkItems("inv.create.stage.eatDrink.items"), + stagePlayTimeChangeTimeMode("inv.create.stage.playTime.changeTimeMode"), + stagePlayTimeModeOnline("inv.create.stage.playTime.modes.online"), + stagePlayTimeModeOffline("inv.create.stage.playTime.modes.offline"), + stagePlayTimeModeRealtime("inv.create.stage.playTime.modes.realtime"), + INVENTORY_STAGES("inv.stages.name"), nextPage("inv.stages.nextPage"), laterPage("inv.stages.laterPage"), diff --git a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java index 7232f63a..e915acbc 100644 --- a/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java +++ b/core/src/main/java/fr/skytasul/quests/stages/StagePlayTime.java @@ -2,7 +2,9 @@ import java.util.HashMap; import java.util.Map; +import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; @@ -13,6 +15,7 @@ import fr.skytasul.quests.api.editors.parsers.DurationParser.MinecraftTimeUnit; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.players.PlayerAccount; import fr.skytasul.quests.api.players.PlayersManager; import fr.skytasul.quests.api.requirements.RequirementList; @@ -22,6 +25,7 @@ import fr.skytasul.quests.api.stages.creation.StageCreation; import fr.skytasul.quests.api.stages.creation.StageCreationContext; import fr.skytasul.quests.api.stages.creation.StageGuiLine; +import fr.skytasul.quests.api.utils.MinecraftVersion; import fr.skytasul.quests.api.utils.Utils; import fr.skytasul.quests.api.utils.XMaterial; import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; @@ -32,12 +36,14 @@ public class StagePlayTime extends AbstractStage implements HasProgress { private final long playTicks; + private final TimeMode timeMode; private Map<Player, BukkitTask> tasks = new HashMap<>(); - public StagePlayTime(StageController controller, long ticks) { + public StagePlayTime(StageController controller, long ticks, TimeMode timeMode) { super(controller); this.playTicks = ticks; + this.timeMode = timeMode; } public long getTicksToPlay() { @@ -58,10 +64,31 @@ protected void createdPlaceholdersRegistry(@NotNull PlaceholderRegistry placehol } private long getRemaining(PlayerAccount acc) { - long remaining = Utils.parseLong(getData(acc, "remainingTime")); - long lastJoin = Utils.parseLong(getData(acc, "lastJoin")); - long playedTicks = (System.currentTimeMillis() - lastJoin) / 50; - return remaining - playedTicks; + switch (timeMode) { + case ONLINE: + long remaining = Utils.parseLong(getData(acc, "remainingTime")); + long lastJoin = Utils.parseLong(getData(acc, "lastJoin")); + long playedTicks = (System.currentTimeMillis() - lastJoin) / 50; + return remaining - playedTicks; + case OFFLINE: + World world = Bukkit.getWorld(UUID.fromString(getData(acc, "worldUuid"))); + if (world == null) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot get remaining time of " + acc.getNameAndID() + + " for " + controller + " because the world has changed.", + acc.getNameAndID() + hashCode() + "time", + 15); + return -1; + } + + long startTime = Utils.parseLong(getData(acc, "worldStartTime")); + long elapsedTicks = world.getGameTime() - startTime; + return playTicks - elapsedTicks; + case REALTIME: + startTime = Utils.parseLong(getData(acc, "startTime")); + elapsedTicks = (System.currentTimeMillis() - startTime) / 50; + return playTicks - elapsedTicks; + } + throw new UnsupportedOperationException(); } private void launchTask(Player p, long remaining) { @@ -82,8 +109,9 @@ public int getTotalAmount() { @Override public void joined(Player p) { super.joined(p); - updateObjective(p, "lastJoin", System.currentTimeMillis()); - launchTask(p, Utils.parseLong(getData(p, "remainingTime"))); + if (timeMode == TimeMode.ONLINE) + updateObjective(p, "lastJoin", System.currentTimeMillis()); + launchTask(p, getRemaining(PlayersManager.getPlayerAccount(p))); } @Override @@ -100,7 +128,8 @@ public void left(Player p) { private void cancelTask(Player p, BukkitTask task) { task.cancel(); - updateObjective(p, "remainingTime", getRemaining(PlayersManager.getPlayerAccount(p))); + if (timeMode == TimeMode.ONLINE) + updateObjective(p, "remainingTime", getRemaining(PlayersManager.getPlayerAccount(p))); } @Override @@ -122,8 +151,20 @@ public void ended(PlayerAccount acc) { @Override public void initPlayerDatas(PlayerAccount acc, Map<String, Object> datas) { super.initPlayerDatas(acc, datas); - datas.put("remainingTime", playTicks); - datas.put("lastJoin", System.currentTimeMillis()); + switch (timeMode) { + case ONLINE: + datas.put("remainingTime", playTicks); + datas.put("lastJoin", System.currentTimeMillis()); + break; + case OFFLINE: + World world = Bukkit.getWorlds().get(0); + datas.put("worldStartTime", world.getGameTime()); + datas.put("worldUuid", world.getUID().toString()); + break; + case REALTIME: + datas.put("startTime", System.currentTimeMillis()); + break; + } } @Override @@ -145,15 +186,43 @@ public void setValidationRequirements(@NotNull RequirementList validationRequire @Override protected void serialize(ConfigurationSection section) { section.set("playTicks", playTicks); + section.set("timeMode", timeMode.name()); } public static StagePlayTime deserialize(ConfigurationSection section, StageController controller) { - return new StagePlayTime(controller, section.getLong("playTicks")); + return new StagePlayTime(controller, section.getLong("playTicks"), + TimeMode.valueOf(section.getString("timeMode", "ONLINE").toUpperCase())); + } + + public enum TimeMode { + ONLINE(Lang.stagePlayTimeModeOnline.toString()), + OFFLINE(Lang.stagePlayTimeModeOffline.toString()) { + @Override + public boolean isActive() { + // no way to get full world time before 1.16.5 + return MinecraftVersion.MAJOR > 16 || (MinecraftVersion.MAJOR == 16 && MinecraftVersion.MINOR == 5); + } + }, + REALTIME(Lang.stagePlayTimeModeRealtime.toString()); + + private final String description; + + private TimeMode(String description) { + this.description = description; + } + + public boolean isActive() { + return true; + } } public static class Creator extends StageCreation<StagePlayTime> { private long ticks; + private TimeMode timeMode = TimeMode.ONLINE; + + private int slotTicks; + private int slotTimeMode; public Creator(@NotNull StageCreationContext<StagePlayTime> context) { super(context); @@ -166,18 +235,37 @@ public void setupLine(@NotNull StageGuiLine line) { line.refreshItemName(SLOT_REQUIREMENTS, "§n" + Lang.validationRequirements + "§c " + Lang.Disabled.toString().toUpperCase()); - line.setItem(7, ItemUtils.item(XMaterial.CLOCK, Lang.changeTicksRequired.toString()), event -> { + slotTicks = line.setItem(7, ItemUtils.item(XMaterial.CLOCK, Lang.changeTicksRequired.toString()), event -> { Lang.GAME_TICKS.send(event.getPlayer()); new TextEditor<>(event.getPlayer(), event::reopen, obj -> { setTicks(obj); event.reopen(); }, MinecraftTimeUnit.TICK.getParser()).start(); }); + + slotTimeMode = line.setItem(8, + ItemUtils.item(XMaterial.COMMAND_BLOCK, Lang.stagePlayTimeChangeTimeMode.toString(), + QuestOption.formatNullableValue(timeMode.description, timeMode == TimeMode.ONLINE)), + event -> { + TimeMode next = timeMode; + do { + next = TimeMode.values()[(next.ordinal() + 1) % TimeMode.values().length]; + } while (!next.isActive()); + setTimeMode(next); + }); } public void setTicks(long ticks) { this.ticks = ticks; - getLine().refreshItemLoreOptionValue(7, Lang.Ticks.quickFormat("ticks", ticks + " ticks")); + getLine().refreshItemLoreOptionValue(slotTicks, Lang.Ticks.quickFormat("ticks", ticks)); + } + + public void setTimeMode(TimeMode timeMode) { + if (this.timeMode != timeMode) { + this.timeMode = timeMode; + getLine().refreshItemLore(slotTimeMode, + QuestOption.formatNullableValue(timeMode.description, timeMode == TimeMode.ONLINE)); + } } @Override @@ -194,11 +282,12 @@ public void start(Player p) { public void edit(StagePlayTime stage) { super.edit(stage); setTicks(stage.playTicks); + setTimeMode(stage.timeMode); } @Override public StagePlayTime finishStage(StageController controller) { - return new StagePlayTime(controller, ticks); + return new StagePlayTime(controller, ticks, timeMode); } } diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 22016ff1..6015bdda 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -413,6 +413,12 @@ inv: targetMobs: '§cMobs to damage' eatDrink: items: '§eEdit items to eat or drink' + playTime: + changeTimeMode: 'Change time counting strategy' + modes: + online: 'Player has to be connected to the server' + offline: 'Player can be offline, but server has to be running for the time to be counted' + realtime: 'Time is counted even if the player and the server are offline' stages: name: Create stages nextPage: §eNext page From ec5e62d62b05aa210e7e8fb79d0008a1680cf8b0 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Thu, 30 Nov 2023 21:53:24 +0100 Subject: [PATCH 89/95] :sparkles: Made next/prev page item more customizable + option to remove vertical separator --- .../quests/api/QuestsConfiguration.java | 16 +- .../api/comparison/ItemComparisonMap.java | 7 +- .../quests/api/data/SQLDataSaver.java | 6 +- .../quests/api/editors/WaitBlockClick.java | 7 +- .../quests/api/editors/WaitClick.java | 7 +- .../skytasul/quests/api/gui/GuiManager.java | 4 + .../quests/api/gui/ImmutableItemStack.java | 78 ----- .../skytasul/quests/api/gui/ItemFactory.java | 20 ++ .../fr/skytasul/quests/api/gui/ItemUtils.java | 40 --- .../skytasul/quests/api/gui/LoreBuilder.java | 7 +- .../quests/api/gui/templates/PagedGUI.java | 96 +++--- .../skytasul/quests/api/mobs/MobFactory.java | 6 +- .../api/options/UpdatableOptionSet.java | 6 +- .../api/stages/types/AbstractEntityStage.java | 8 +- .../quests/api/stages/types/Locatable.java | 1 + .../quests/api/utils/NumberedList.java | 6 +- .../quests/api/utils/PlayerListCategory.java | 26 +- .../QuestsConfigurationImplementation.java | 81 ++++- .../quests/gui/DefaultItemFactory.java | 49 ++++ .../quests/gui/GuiManagerImplementation.java | 17 +- .../quests/gui/blocks/SelectBlockGUI.java | 2 +- .../quest/QuestCreationGuiImplementation.java | 2 +- .../stages/StageLineImplementation.java | 6 +- .../quests/gui/creation/stages/StagesGUI.java | 15 +- .../quests/gui/items/ItemCreatorGUI.java | 4 +- .../skytasul/quests/gui/items/ItemsGUI.java | 2 +- .../skytasul/quests/gui/misc/CommandGUI.java | 11 +- .../fr/skytasul/quests/gui/misc/TitleGUI.java | 5 +- .../skytasul/quests/gui/npc/NpcCreateGUI.java | 4 +- .../skytasul/quests/gui/npc/NpcSelectGUI.java | 2 +- .../gui/particles/ParticleEffectGUI.java | 5 +- .../quests/gui/pools/PoolEditGUI.java | 4 +- .../quests/gui/quests/PlayerListGUI.java | 277 ++++++++---------- .../gui/quests/PlayerListGUIBackup.java | 272 +++++++++++++++++ .../quests/options/OptionVisibility.java | 3 +- .../players/AbstractPlayersManager.java | 7 +- .../rewards/RequirementDependentReward.java | 4 +- core/src/main/resources/config.yml | 12 +- .../vault/permission/PermissionGUI.java | 7 +- 39 files changed, 701 insertions(+), 431 deletions(-) delete mode 100644 api/src/main/java/fr/skytasul/quests/api/gui/ImmutableItemStack.java create mode 100755 api/src/main/java/fr/skytasul/quests/api/gui/ItemFactory.java create mode 100755 core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java create mode 100755 core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java diff --git a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java index d251d9ec..2f6ba381 100644 --- a/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -4,7 +4,6 @@ import java.util.Set; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import com.cryptomorin.xseries.XMaterial; import fr.skytasul.quests.api.npcs.NpcClickType; import fr.skytasul.quests.api.options.description.QuestDescription; import fr.skytasul.quests.api.utils.PlayerListCategory; @@ -20,6 +19,9 @@ public interface QuestsConfiguration { @NotNull Quests getQuestsConfig(); + @NotNull + Gui getGuiConfig(); + @NotNull Dialogs getDialogsConfig(); @@ -61,8 +63,6 @@ interface Quests { ItemStack getDefaultQuestItem(); - XMaterial getPageMaterial(); - double startParticleDistance(); int requirementUpdateTime(); @@ -73,6 +73,16 @@ interface Quests { } + interface Gui { + + ItemStack getPreviousPageItem(); + + ItemStack getNextPageItem(); + + boolean showVerticalSeparator(); + + } + interface Dialogs { boolean sendInActionBar(); diff --git a/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java b/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java index 39df09d8..fef13466 100644 --- a/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java +++ b/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java @@ -1,11 +1,6 @@ package fr.skytasul.quests.api.comparison; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.Inventory; diff --git a/api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java b/api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java index 01c2c21c..504a13bd 100644 --- a/api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java +++ b/api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.api.data; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.sql.Types; +import java.sql.*; import java.util.Date; import java.util.HashMap; import java.util.Map; diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java b/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java index b5d76804..41b22525 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/WaitBlockClick.java @@ -8,7 +8,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.QuestsPlugin; public class WaitBlockClick extends InventoryClear implements Listener { @@ -24,7 +24,7 @@ public WaitBlockClick(Player p, Runnable cancel, Consumer<Location> end, ItemSta @EventHandler public void onClick(PlayerInteractEvent e){ if (e.getPlayer() != player) return; - if (ItemUtils.itemCancel.equals(e.getItem())) { + if (QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel().equals(e.getItem())) { cancel(); return; } @@ -41,7 +41,8 @@ public void begin(){ super.begin(); player.getInventory().setItem(4, item); player.getInventory().setHeldItemSlot(4); - if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); + if (cancel != null) + player.getInventory().setItem(8, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel()); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java b/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java index 21777dbc..02f5f48f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java +++ b/api/src/main/java/fr/skytasul/quests/api/editors/WaitClick.java @@ -7,7 +7,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.QuestsPlugin; public class WaitClick extends InventoryClear implements Listener { @@ -38,7 +38,7 @@ public void onInteract(PlayerInteractEvent e) { run = validate; }else if (e.getItem().equals(noneItem)){ run = none; - }else if (ItemUtils.itemCancel.equals(e.getItem())) { + } else if (QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel().equals(e.getItem())) { run = cancel; }else return; e.setCancelled(true); @@ -57,7 +57,8 @@ public void begin(){ player.getInventory().setHeldItemSlot(3); player.getInventory().setItem(5, noneItem); } - if (cancel != null) player.getInventory().setItem(8, ItemUtils.itemCancel); + if (cancel != null) + player.getInventory().setItem(8, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel()); } } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java index e6759867..e2ad6f99 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/GuiManager.java @@ -23,4 +23,8 @@ public interface GuiManager { public void setFactory(@NotNull GuiFactory factory); + public @NotNull ItemFactory getItemFactory(); + + public void setItemFactory(@NotNull ItemFactory factory); + } diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/ImmutableItemStack.java b/api/src/main/java/fr/skytasul/quests/api/gui/ImmutableItemStack.java deleted file mode 100644 index 74c391a4..00000000 --- a/api/src/main/java/fr/skytasul/quests/api/gui/ImmutableItemStack.java +++ /dev/null @@ -1,78 +0,0 @@ -package fr.skytasul.quests.api.gui; - -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.MaterialData; - -public class ImmutableItemStack extends ItemStack { - - private ItemStack realItemStack; - - public ImmutableItemStack(ItemStack item){ - super(item); - } - - @Override - public void setAmount(int amount){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public void setData(MaterialData data){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public void setDurability(short durability){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public boolean setItemMeta(ItemMeta itemMeta){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public void setType(Material type){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public void addEnchantment(Enchantment ench, int level){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public void addUnsafeEnchantment(Enchantment ench, int level){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public int removeEnchantment(Enchantment ench){ - throw new UnsupportedOperationException("This ItemStack instance is immutable"); - } - - @Override - public boolean isSimilar(ItemStack stack) { - if (realItemStack == null) realItemStack = toMutableStack(); - return realItemStack.isSimilar(stack); - } - - @Override - public ItemStack clone() { - return new ItemStack(this); - } - - public ItemStack toMutableStack() { - return new ItemStack(this); - } - - public ItemStack toMutableStack(int amount) { - ItemStack item = new ItemStack(this); - item.setAmount(amount); - return item; - } - -} diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/ItemFactory.java b/api/src/main/java/fr/skytasul/quests/api/gui/ItemFactory.java new file mode 100755 index 00000000..ea2dc739 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/gui/ItemFactory.java @@ -0,0 +1,20 @@ +package fr.skytasul.quests.api.gui; + +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +public interface ItemFactory { + + public @NotNull ItemStack getPreviousPage(); + + public @NotNull ItemStack getNextPage(); + + public @NotNull ItemStack getCancel(); + + public @NotNull ItemStack getDone(); + + public @NotNull ItemStack getNotDone(); + + public @NotNull ItemStack getNone(); + +} 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 2598780e..3f2486c5 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 @@ -12,14 +12,11 @@ import org.bukkit.inventory.meta.*; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; -import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.QuestOption; import fr.skytasul.quests.api.utils.ChatColorUtils; import fr.skytasul.quests.api.utils.MinecraftNames; import fr.skytasul.quests.api.utils.MinecraftVersion; -import net.md_5.bungee.api.ChatColor; public final class ItemUtils { @@ -317,43 +314,6 @@ public static ItemStack removeEnchant(ItemStack is, Enchantment en){ return is; } - - /** - * Immutable ItemStack instance with lore : <i>inv.stages.laterPage</i> and material : <i>pageItem</i> - * @see #itemNextPage - */ - public static final ImmutableItemStack itemLaterPage = new ImmutableItemStack( - item(QuestsConfiguration.getConfig().getQuestsConfig().getPageMaterial(), Lang.laterPage.toString())); - - /** - * Immutable ItemStack instance with lore : <i>inv.stages.nextPage</i> and material : <i>pageItem</i> - * @see #itemLaterPage - */ - public static final ImmutableItemStack itemNextPage = new ImmutableItemStack( - item(QuestsConfiguration.getConfig().getQuestsConfig().getPageMaterial(), Lang.nextPage.toString())); - - /** - * Immutable ItemStack instance with name : <i>inv.cancel</i> and material : barrier - */ - public static final ImmutableItemStack itemCancel = new ImmutableItemStack(item(XMaterial.BARRIER, Lang.cancel.toString())); - - /** - * Immutable ItemStack instance with name : <i>"§cNone"</i> and material : barrier - */ - public static final ImmutableItemStack itemNone = new ImmutableItemStack(item(XMaterial.BARRIER, "§cNone")); - - /** - * Immutable ItemStack instance with name : <i>inv.done</i> and material : diamond - * @see #itemNotDone - */ - public static final ImmutableItemStack itemDone = new ImmutableItemStack(addEnchant(item(XMaterial.DIAMOND, Lang.done.toString()), Enchantment.DURABILITY, 0)); - - /** - * Immutable ItemStack instance with name: <i>inv.done</i> but red and strikethrough, material: charcoal - * @see #itemDone - */ - public static final ImmutableItemStack itemNotDone = new ImmutableItemStack(item(XMaterial.CHARCOAL, "§c§l§m" + ChatColor.stripColor(Lang.done.toString()))); - /** * Get a glass pane ItemStack instance with the color wanted * @param color DyeColor wanted diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/LoreBuilder.java b/api/src/main/java/fr/skytasul/quests/api/gui/LoreBuilder.java index 9cfdbfac..c3b38eec 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/LoreBuilder.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/LoreBuilder.java @@ -1,12 +1,7 @@ package fr.skytasul.quests.api.gui; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.TreeMap; import org.bukkit.event.inventory.ClickType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java index f407ed42..29329b4b 100644 --- a/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java +++ b/api/src/main/java/fr/skytasul/quests/api/gui/templates/PagedGUI.java @@ -14,7 +14,10 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; @@ -36,23 +39,30 @@ public abstract class PagedGUI<T> extends AbstractGui { protected int page = 0; protected int maxPage; + private final int columns; + private final int dataSlots; + private String name; private DyeColor color; protected List<T> objects; protected Consumer<List<T>> validate; - private ItemStack validationItem = ItemUtils.itemDone; + private ItemStack validationItem = QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone(); protected LevenshteinComparator<T> comparator; - protected PagedGUI(String name, DyeColor color, Collection<T> objects) { + protected PagedGUI(@NotNull String name, @Nullable DyeColor color, @NotNull Collection<T> objects) { this(name, color, objects, null, null); } - protected PagedGUI(String name, DyeColor color, Collection<T> objects, Consumer<List<T>> validate, Function<T, String> searchName) { + protected PagedGUI(@NotNull String name, @Nullable DyeColor color, @NotNull Collection<T> objects, + @Nullable Consumer<List<T>> validate, @Nullable Function<T, String> searchName) { this.name = name; this.color = color; this.objects = new ArrayList<>(objects); this.validate = validate; if (searchName != null) this.comparator = new LevenshteinComparator<>(searchName); + + columns = QuestsConfiguration.getConfig().getGuiConfig().showVerticalSeparator() ? 7 : 8; + dataSlots = columns * 5; } @Override @@ -65,17 +75,23 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { this.player = player; calcMaxPages(); - setBarItem(0, ItemUtils.itemLaterPage); - setBarItem(4, ItemUtils.itemNextPage); + setBarItem(0, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getPreviousPage()); + setBarItem(4, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNextPage()); if (validate != null) setBarItem(2, validationItem); if (comparator != null) setBarItem(3, itemSearch); - for (int i = 0; i < 5; i++) - inventory.setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); + displaySeparator(); setItems(); } + private void displaySeparator() { + if (color != null && QuestsConfiguration.getConfig().getGuiConfig().showVerticalSeparator()) { + for (int i = 0; i < 5; i++) + getInventory().setItem(i * 9 + columns, ItemUtils.itemSeparator(color)); + } + } + public PagedGUI<T> setValidate(Consumer<List<T>> validate, ItemStack validationItem) { if (this.validate != null) throw new IllegalStateException("A validation has already be added."); if (this.getInventory() != null) @@ -103,28 +119,43 @@ public <C extends Comparable<C>> PagedGUI<T> sortValues(Function<T, C> mapper) { return this; } + public void setSeparatorColor(@Nullable DyeColor color) { + this.color = color; + if (getInventory() != null) + displaySeparator(); + } + + public void setObjects(@NotNull Collection<T> objects) { + this.objects = new ArrayList<>(objects); + page = 0; + calcMaxPages(); + setItems(); + } + protected void calcMaxPages() { this.maxPage = objects.isEmpty() ? 1 : (int) Math.ceil(objects.size() * 1D / 35D); } protected void setItems() { - for (int i = 0; i < 35; i++) setMainItem(i, null); - for (int i = page * 35; i < objects.size(); i++){ - if (i == (page + 1) * 35) break; + for (int i = 0; i < dataSlots; i++) + setMainItem(i, null); + for (int i = page * dataSlots; i < objects.size(); i++) { + if (i == (page + 1) * dataSlots) + break; T obj = objects.get(i); - setMainItem(i - page * 35, getItemStack(obj)); + setMainItem(i - page * dataSlots, getItemStack(obj)); } } private int setMainItem(int mainSlot, ItemStack is){ - int line = (int) Math.floor(mainSlot * 1.0 / 7.0); - int slot = mainSlot + (2 * line); + int line = (int) Math.floor(mainSlot * 1.0 / columns); + int slot = mainSlot + ((9 - columns) * line); setItem(is, slot); return slot; } - private int setBarItem(int barSlot, ItemStack is){ - int slot = barSlot * 9 + 8; + protected int setBarItem(int barSlot, ItemStack is) { + int slot = barSlot * 9 + 8; // always at last column so +8 setItem(is, slot); return slot; } @@ -150,19 +181,30 @@ private void setItem(ItemStack is, int rawSlot) { */ public int getObjectSlot(T object){ int index = objects.indexOf(object); - if (index < page*35 || index > (page + 1)*35) return -1; + if (index < page * dataSlots || index > (page + 1) * dataSlots) + return -1; - int line = (int) Math.floor(index * 1.0 / 7.0); - return index + (2 * line) - page * 35; + int line = (int) Math.floor(index * 1.0 / columns); + return index + ((9 - columns) * line) - page * dataSlots; } @Override public void onClick(GuiClickEvent event) { - switch (event.getSlot() % 9) { - case 8: + int column = event.getSlot() % 9; + if (column == 8) { int barSlot = (event.getSlot() - 8) / 9; - switch (barSlot){ + barClick(event, barSlot); + } else if (!QuestsConfiguration.getConfig().getGuiConfig().showVerticalSeparator() || column != 7) { + int line = (int) Math.floor(event.getSlot() * 1D / 9D); + int objectSlot = event.getSlot() - line * (9 - columns) + page * dataSlots; + click(objects.get(objectSlot), event.getClicked(), event.getClick()); + // inv.setItem(slot, getItemStack(objects.get(objectSlot))); + } + } + + protected void barClick(GuiClickEvent event, int barSlot) { + switch (barSlot) { case 0: if (page == 0) break; page--; @@ -180,7 +222,6 @@ public void onClick(GuiClickEvent event) { case 3: new TextEditor<String>(player, this::reopen, obj -> { - //objects.stream().filter(x -> getName(x).contains((String) obj)); objects.sort(comparator.setReference(obj)); page = 0; setItems(); @@ -188,17 +229,6 @@ public void onClick(GuiClickEvent event) { }).start(); break; } - break; - - case 7: - break; - - default: - int line = (int) Math.floor(event.getSlot() * 1D / 9D); - int objectSlot = event.getSlot() - line * 2 + page * 35; - click(objects.get(objectSlot), event.getClicked(), event.getClick()); - //inv.setItem(slot, getItemStack(objects.get(objectSlot))); - } } public final void reopen() { diff --git a/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java b/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java index 0950e5a1..f9d0b45f 100644 --- a/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java +++ b/api/src/main/java/fr/skytasul/quests/api/mobs/MobFactory.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.api.mobs; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.OptionalInt; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import org.apache.commons.lang.Validate; diff --git a/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java b/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java index f56e6f99..b4eb44bd 100644 --- a/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java +++ b/api/src/main/java/fr/skytasul/quests/api/options/UpdatableOptionSet.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.api.options; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; @SuppressWarnings ("rawtypes") public class UpdatableOptionSet implements OptionSet { diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java index 534c10bf..0b66090a 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/AbstractEntityStage.java @@ -1,13 +1,7 @@ package fr.skytasul.quests.api.stages.types; -import java.util.AbstractMap; -import java.util.Comparator; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; -import java.util.OptionalInt; -import java.util.Spliterator; -import java.util.Spliterators; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java index a78fb585..02148d43 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/types/Locatable.java @@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.stages.types.Locatable.MultipleLocatable; /** * This interface indicates that an object can provide some locations on demand. diff --git a/api/src/main/java/fr/skytasul/quests/api/utils/NumberedList.java b/api/src/main/java/fr/skytasul/quests/api/utils/NumberedList.java index 14e5e067..80bdcf2c 100644 --- a/api/src/main/java/fr/skytasul/quests/api/utils/NumberedList.java +++ b/api/src/main/java/fr/skytasul/quests/api/utils/NumberedList.java @@ -1,10 +1,6 @@ package fr.skytasul.quests.api.utils; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; public class NumberedList<T> implements Iterable<T>, Cloneable{ 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 2e6c1747..b38f958d 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 @@ -1,5 +1,6 @@ package fr.skytasul.quests.api.utils; +import org.bukkit.DyeColor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.cryptomorin.xseries.XMaterial; @@ -11,26 +12,31 @@ public enum PlayerListCategory { FINISHED( 1, XMaterial.WRITTEN_BOOK, - Lang.finisheds.toString()), + Lang.finisheds.toString(), + DyeColor.GREEN), IN_PROGRESS( 2, XMaterial.BOOK, - Lang.inProgress.toString()), + Lang.inProgress.toString(), + DyeColor.YELLOW), NOT_STARTED( 3, XMaterial.WRITABLE_BOOK, - Lang.notStarteds.toString()); + Lang.notStarteds.toString(), + DyeColor.RED); private final int slot; private final @NotNull XMaterial material; private final @NotNull String name; - - private PlayerListCategory(int slot, @NotNull XMaterial material, @NotNull String name) { + private final @Nullable DyeColor color; + + private PlayerListCategory(int slot, @NotNull XMaterial material, @NotNull String name, @Nullable DyeColor color) { this.slot = slot; this.material = material; this.name = name; + this.color = color; } - + public int getSlot() { return slot; } @@ -42,7 +48,11 @@ public int getSlot() { public @NotNull String getName() { return name; } - + + public @Nullable DyeColor getColor() { + return color; + } + public boolean isEnabled() { return QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs().contains(this); } @@ -53,5 +63,5 @@ public boolean isEnabled() { }catch (IllegalArgumentException ex) {} return null; } - + } \ No newline at end of file diff --git a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java index a5b5d2ac..d2c6a071 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsConfigurationImplementation.java @@ -52,6 +52,7 @@ public static QuestsConfigurationImplementation getConfiguration() { private final FileConfiguration config; private QuestsConfig quests; + private GuiConfig gui; private DialogsConfig dialogs; private QuestsSelectionConfig selection; private QuestsMenuConfig menu; @@ -62,6 +63,7 @@ public static QuestsConfigurationImplementation getConfiguration() { this.config = config; quests = new QuestsConfig(); + gui = new GuiConfig(config.getConfigurationSection("gui")); dialogs = new DialogsConfig(config.getConfigurationSection("dialogs")); selection = new QuestsSelectionConfig(config.getConfigurationSection("questsSelection")); menu = new QuestsMenuConfig(config.getConfigurationSection("questsMenu")); @@ -71,6 +73,7 @@ public static QuestsConfigurationImplementation getConfiguration() { boolean update() { boolean result = false; + result |= gui.update(); result |= dialogs.update(); result |= selection.update(); result |= menu.update(); @@ -86,6 +89,7 @@ void init() { if (isMinecraftTranslationsEnabled()) initializeTranslations(); quests.init(); + gui.init(); dialogs.init(); selection.init(); menu.init(); @@ -172,6 +176,15 @@ private ItemStack loadHologram(String name) { return null; } + private static ItemStack loadItem(ConfigurationSection config, String key, ItemStack def) { + if (config.isItemStack(key)) + return config.getItemStack(key); + if (config.isString(key)) + return XMaterial.matchXMaterial(config.getString(key)).map(XMaterial::parseItem).orElse(def); + QuestsPlugin.getPlugin().getLogger().warning("Cannot load item " + key + " from config"); + return def; + } + private String loadSound(String key) { String sound = config.getString(key); try { @@ -202,6 +215,11 @@ public FileConfiguration getConfig() { return quests; } + @Override + public @NotNull Gui getGuiConfig() { + return gui; + } + @Override public @NotNull DialogsConfig getDialogsConfig() { return dialogs; @@ -309,7 +327,6 @@ public class QuestsConfig implements QuestsConfiguration.Quests { private String finishSound = "ENTITY_PLAYER_LEVELUP"; private String nextStageSound = "ITEM_FIRECHARGE_USE"; private ItemStack defaultQuestItem = XMaterial.BOOK.parseItem(); - private XMaterial pageItem = XMaterial.ARROW; private int startParticleDistance; private int requirementUpdateTime; private boolean sendUpdate = true; @@ -328,16 +345,7 @@ private void init() { questConfirmGUI = config.getBoolean("questConfirmGUI"); sounds = config.getBoolean("sounds"); fireworks = config.getBoolean("fireworks"); - if (config.contains("pageItem")) - pageItem = XMaterial.matchXMaterial(config.getString("pageItem")).orElse(XMaterial.ARROW); - if (pageItem == null) - pageItem = XMaterial.ARROW; - if (config.isItemStack("item")) { - defaultQuestItem = config.getItemStack("item"); - } else if (config.isString("item")) { - defaultQuestItem = XMaterial.matchXMaterial(config.getString("item")).orElse(XMaterial.BOOK).parseItem(); - } else - defaultQuestItem = XMaterial.BOOK.parseItem(); + defaultQuestItem = loadItem(config, "item", XMaterial.BOOK.parseItem()); defaultQuestItem = ItemUtils.clearVisibleAttributes(defaultQuestItem); startParticleDistance = config.getInt("startParticleDistance"); requirementUpdateTime = config.getInt("requirementUpdateTime"); @@ -423,11 +431,6 @@ public ItemStack getDefaultQuestItem() { return defaultQuestItem; } - @Override - public XMaterial getPageMaterial() { - return pageItem; - } - @Override public double startParticleDistance() { return startParticleDistance; @@ -546,6 +549,52 @@ public String getDefaultNPCSound() { } + public class GuiConfig implements QuestsConfiguration.Gui { + + private ItemStack previousPageItem; + private ItemStack nextPageItem; + private boolean verticalSeparator; + + private final ConfigurationSection config; + + private GuiConfig(ConfigurationSection config) { + this.config = config; + } + + private boolean update() { + boolean result = false; + if (config.getParent() != null) { + result |= migrateEntry(config.getParent(), "pageItem", config, "previous page item"); + + if (!config.contains("next page item", true)) + config.set("next page item", config.get("previous page item")); + } + return result; + } + + private void init() { + previousPageItem = loadItem(config, "previous page item", XMaterial.ARROW.parseItem()); + nextPageItem = loadItem(config, "next page item", XMaterial.ARROW.parseItem()); + verticalSeparator = config.getBoolean("vertical separator"); + } + + @Override + public ItemStack getPreviousPageItem() { + return previousPageItem; + } + + @Override + public ItemStack getNextPageItem() { + return nextPageItem; + } + + @Override + public boolean showVerticalSeparator() { + return verticalSeparator; + } + + } + public class QuestsSelectionConfig implements QuestsConfiguration.QuestsSelection { private boolean skipGuiIfOnlyOneQuest = true; diff --git a/core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java b/core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java new file mode 100755 index 00000000..5f1e907a --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/DefaultItemFactory.java @@ -0,0 +1,49 @@ +package fr.skytasul.quests.gui; + +import static fr.skytasul.quests.api.gui.ItemUtils.addEnchant; +import static fr.skytasul.quests.api.gui.ItemUtils.item; +import static fr.skytasul.quests.api.gui.ItemUtils.name; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.gui.ItemFactory; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.utils.XMaterial; +import net.md_5.bungee.api.ChatColor; + +public class DefaultItemFactory implements ItemFactory { + + @Override + public @NotNull ItemStack getPreviousPage() { + return name(QuestsConfiguration.getConfig().getGuiConfig().getPreviousPageItem().clone(), + Lang.laterPage.toString()); + } + + @Override + public @NotNull ItemStack getNextPage() { + return name(QuestsConfiguration.getConfig().getGuiConfig().getNextPageItem().clone(), + Lang.nextPage.toString()); + } + + @Override + public @NotNull ItemStack getCancel() { + return item(XMaterial.BARRIER, Lang.cancel.toString()); + } + + @Override + public @NotNull ItemStack getDone() { + return addEnchant(item(XMaterial.DIAMOND, Lang.done.toString()), Enchantment.DURABILITY, 0); + } + + @Override + public @NotNull ItemStack getNotDone() { + return item(XMaterial.CHARCOAL, "§c§l§m" + ChatColor.stripColor(Lang.done.toString())); + } + + @Override + public @NotNull ItemStack getNone() { + return item(XMaterial.BARRIER, "§cNone"); + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java index 45cf9cc1..de10516e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/GuiManagerImplementation.java @@ -13,10 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.Gui; -import fr.skytasul.quests.api.gui.GuiClickEvent; -import fr.skytasul.quests.api.gui.GuiFactory; -import fr.skytasul.quests.api.gui.GuiManager; +import fr.skytasul.quests.api.gui.*; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.DelayCloseBehavior; import fr.skytasul.quests.api.gui.close.OpenCloseBehavior; @@ -30,9 +27,11 @@ public class GuiManagerImplementation implements GuiManager, Listener { private Map<Player, Gui> players = new HashMap<>(); private boolean dismissClose = false; private GuiFactory factory; + private ItemFactory itemFactory; public GuiManagerImplementation() { setFactory(new DefaultGuiFactory()); + setItemFactory(new DefaultItemFactory()); } @Override @@ -92,6 +91,16 @@ public void setFactory(@NotNull GuiFactory factory) { this.factory = factory; } + @Override + public @NotNull ItemFactory getItemFactory() { + return itemFactory; + } + + @Override + public void setItemFactory(@NotNull ItemFactory factory) { + this.itemFactory = factory; + } + @EventHandler public void onClose(InventoryCloseEvent event) { if (dismissClose) { 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 330ef1c7..2d8f1a19 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 @@ -89,7 +89,7 @@ public void place(@NotNull Inventory inventory, int slot) { }, this::tagClick)); } - buttons.put(8, LayoutedButton.create(ItemUtils.itemDone, this::doneClick)); + buttons.put(8, LayoutedButton.create(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone(), this::doneClick)); } private void amountClick(LayoutedClickEvent event) { 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 d0e80143..0b5d85d5 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 @@ -97,7 +97,7 @@ public boolean isValid() { options.calculateDependencies(); buttons.put(QuestOptionCreator.calculateSlot(3), - LayoutedButton.create(ItemUtils.itemLaterPage, event -> session.openStagesGUI(event.getPlayer()))); + LayoutedButton.create(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getPreviousPage(), event -> session.openStagesGUI(event.getPlayer()))); doneButtonSlot = QuestOptionCreator.calculateSlot(5); buttons.put(doneButtonSlot, LayoutedButton.create(() -> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java index 5ebc5df0..c135fcbe 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StageLineImplementation.java @@ -5,7 +5,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.stages.creation.StageGuiClickHandler; import fr.skytasul.quests.api.stages.creation.StageGuiLine; @@ -104,9 +104,9 @@ public void setPage(int page) { } if (page > 0) - setRawItem(0, ItemUtils.itemLaterPage); + setRawItem(0, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getPreviousPage()); if (page < maxPage) - setRawItem(8, ItemUtils.itemNextPage); + setRawItem(8, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNextPage()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java index ac01f7a9..12d742d7 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/creation/stages/StagesGUI.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -33,7 +34,7 @@ public class StagesGUI extends AbstractGui { private static final int SLOT_FINISH = 52; private static final ItemStack stageCreate = ItemUtils.item(XMaterial.SLIME_BALL, Lang.stageCreate.toString()); - private static final ItemStack notDone = ItemUtils.lore(ItemUtils.itemNotDone.clone(), Lang.cantFinish.toString()); + private static final ItemStack notDone = ItemUtils.lore(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNotDone().clone(), Lang.cantFinish.toString()); private List<Line> lines = new ArrayList<>(); @@ -65,17 +66,17 @@ protected void populate(@NotNull Player player, @NotNull Inventory inv) { lines.get(0).setCreationState(); lines.get(15).setCreationState(); - inv.setItem(45, ItemUtils.itemLaterPage); - inv.setItem(50, ItemUtils.itemNextPage); + inv.setItem(45, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getPreviousPage()); + inv.setItem(50, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNextPage()); - inv.setItem(SLOT_FINISH, isEmpty() ? notDone : ItemUtils.itemDone); - inv.setItem(53, previousBranch == null ? ItemUtils.itemCancel + inv.setItem(SLOT_FINISH, isEmpty() ? notDone : QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); + inv.setItem(53, previousBranch == null ? QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel() : ItemUtils.item(XMaterial.FILLED_MAP, Lang.previousBranch.toString())); refresh(); if (session.isEdition() && this == session.getStagesGUI()) { editBranch(session.getQuestEdited().getBranchesManager().getBranch(0)); - inv.setItem(SLOT_FINISH, ItemUtils.itemDone); + inv.setItem(SLOT_FINISH, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); } } @@ -234,7 +235,7 @@ <T extends AbstractStage> StageCreation<T> setStageCreation(StageType<T> type) { context.setCreation((StageCreation) creation); creation.setupLine(lineObj); - getInventory().setItem(SLOT_FINISH, ItemUtils.itemDone); + getInventory().setItem(SLOT_FINISH, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); int maxStages = ending ? 20 : 15; ItemStack manageItem = ItemUtils.item(XMaterial.BARRIER, Lang.stageType.format(type), getLineManageLore(lineId)); diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java index d022d64a..3d92830d 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java @@ -52,8 +52,8 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { inventory.setItem(4, ItemUtils.item(XMaterial.FEATHER, Lang.itemLore.toString())); inventory.setItem(6, ItemUtils.item(XMaterial.BOOK, Lang.itemQuest.toString() + " §c" + Lang.No.toString())); if (allowCancel) - inventory.setItem(8, ItemUtils.itemCancel); - inventory.setItem(17, ItemUtils.itemDone); + inventory.setItem(8, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel()); + inventory.setItem(17, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); inventory.getItem(17).setType(Material.COAL); } diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java index 6b25ea23..21980e2e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemsGUI.java @@ -42,7 +42,7 @@ protected Inventory instanciate(@NotNull Player player) { @Override protected void populate(@NotNull Player player, @NotNull Inventory inv) { - inv.setItem(size - 1, ItemUtils.itemDone); + inv.setItem(size - 1, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); for (int i = 0; i < size - 1; i++) { if (i < items.size()) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java index e2a78eff..ecae845b 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/CommandGUI.java @@ -4,6 +4,7 @@ import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.ItemUtils; @@ -16,14 +17,14 @@ import fr.skytasul.quests.utils.types.Command; public class CommandGUI extends LayoutedGUI.LayoutedRowsGUI { - + private Consumer<Command> end; - + private String cmd; private boolean console = false; private boolean parse = false; private int delay = 0; - + private final @NotNull LayoutedButton doneButton; public CommandGUI(Consumer<Command> end, Runnable cancel) { @@ -40,7 +41,7 @@ public CommandGUI(Consumer<Command> end, Runnable cancel) { buttons.put(5, LayoutedButton.createLoreValue(XMaterial.CLOCK, Lang.commandDelay.toString(), () -> delay, this::delayClick)); buttons.put(8, - LayoutedButton.create(() -> cmd == null ? ItemUtils.itemNotDone : ItemUtils.itemDone, this::doneClick)); + LayoutedButton.create(() -> cmd == null ? QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNotDone() : QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone(), this::doneClick)); } public CommandGUI setFromExistingCommand(@Nullable Command cmd) { @@ -54,7 +55,7 @@ public CommandGUI setFromExistingCommand(@Nullable Command cmd) { } return this; } - + private void commandClick(LayoutedClickEvent event) { Lang.COMMAND.send(event.getPlayer()); new TextEditor<String>(event.getPlayer(), event::reopen, cmd -> { diff --git a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java index 92b25f86..b5637f5f 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/misc/TitleGUI.java @@ -7,6 +7,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.NumberParser; import fr.skytasul.quests.api.gui.AbstractGui; @@ -100,8 +101,8 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { inventory.setItem(SLOT_STAY, ItemUtils.item(XMaterial.CLOCK, Lang.title_stay.toString())); inventory.setItem(SLOT_FADE_OUT, ItemUtils.item(XMaterial.CLOCK, Lang.title_fadeOut.toString())); - inventory.setItem(7, ItemUtils.itemCancel); - inventory.setItem(8, ItemUtils.itemDone.toMutableStack()); + inventory.setItem(7, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel()); + inventory.setItem(8, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); // updating lores setTitle(title); diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java index f4bcbc3f..ce84c48c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcCreateGUI.java @@ -56,8 +56,8 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { setName("§cno name selected"); setSkin("Knight"); setType(EntityType.PLAYER); - inventory.setItem(7, ItemUtils.itemCancel); - inventory.setItem(8, ItemUtils.itemDone); + inventory.setItem(7, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel()); + inventory.setItem(8, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); } private void setName(String name) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java index 75f6b5d4..fb47b81e 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/npc/NpcSelectGUI.java @@ -44,7 +44,7 @@ public static AbstractGui select(@NotNull Runnable cancel, @NotNull Consumer<BqN .createNpcSelection(event.getPlayer(), event::reopen, end).start(); })); if (nullable) - builder.addButton(2, LayoutedButton.create(ItemUtils.itemNone, event -> { + builder.addButton(2, LayoutedButton.create(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNone(), event -> { event.close(); end.accept(null); })); diff --git a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java index c8b49443..c26e209a 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/particles/ParticleEffectGUI.java @@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.ColorParser; import fr.skytasul.quests.api.gui.ItemUtils; @@ -79,8 +80,8 @@ public boolean isValid() { return ParticleEffect.canHaveColor(particle); } }); - buttons.put(7, LayoutedButton.create(ItemUtils.itemCancel, this::cancelClick)); - buttons.put(8, LayoutedButton.create(ItemUtils.itemDone, this::doneClick)); + buttons.put(7, LayoutedButton.create(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel(), this::cancelClick)); + buttons.put(8, LayoutedButton.create(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone(), this::doneClick)); } private void shapeClick(LayoutedClickEvent event) { diff --git a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java index 438da325..4bccefe1 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/pools/PoolEditGUI.java @@ -107,8 +107,8 @@ protected void populate(@NotNull Player player, @NotNull Inventory inv) { inv.setItem(SLOT_DUPLICATE, ItemUtils.itemSwitch(Lang.poolAvoidDuplicates.toString(), avoidDuplicates, Lang.poolAvoidDuplicatesLore.toString())); inv.setItem(SLOT_REQUIREMENTS, ItemUtils.item(XMaterial.NETHER_STAR, Lang.poolRequirements.toString(), getRequirementsLore())); - inv.setItem(SLOT_CANCEL, ItemUtils.itemCancel); - inv.setItem(SLOT_CREATE, ItemUtils.itemDone); + inv.setItem(SLOT_CANCEL, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getCancel()); + inv.setItem(SLOT_CREATE, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); } @Override 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 a48252fd..a1ee995d 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 @@ -1,13 +1,15 @@ package fr.skytasul.quests.gui.quests; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; -import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -16,11 +18,11 @@ import fr.skytasul.quests.api.QuestsAPI; import fr.skytasul.quests.api.QuestsConfiguration; import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; import fr.skytasul.quests.api.gui.close.CloseBehavior; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.gui.templates.PagedGUI; import fr.skytasul.quests.api.localization.Lang; import fr.skytasul.quests.api.options.description.DescriptionSource; import fr.skytasul.quests.api.options.description.QuestDescriptionContext; @@ -31,39 +33,29 @@ import fr.skytasul.quests.players.PlayerAccountImplementation; import fr.skytasul.quests.utils.QuestUtils; -public class PlayerListGUI extends AbstractGui { +public class PlayerListGUI extends PagedGUI<Quest> { static final String UNSELECTED_PREFIX = "§7○ "; private static final String SELECTED_PREFIX = "§b§l● "; - private Player open; private PlayerAccountImplementation acc; private boolean hide; - private int page = 0; private @Nullable PlayerListCategory cat = null; - private List<Quest> quests; public PlayerListGUI(PlayerAccountImplementation acc) { this(acc, true); } public PlayerListGUI(PlayerAccountImplementation acc, boolean hide) { + super(Lang.INVENTORY_PLAYER_LIST.format(acc), DyeColor.GRAY, Collections.emptyList()); this.acc = acc; this.hide = hide; } - @Override - protected Inventory instanciate(@NotNull Player player) { - return Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc)); - } - @Override protected void populate(@NotNull Player player, @NotNull Inventory inventory) { - open = player; - - setBarItem(0, ItemUtils.itemLaterPage); - setBarItem(4, ItemUtils.itemNextPage); + super.populate(player, inventory); for (PlayerListCategory enabledCat : QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs()) { setBarItem(enabledCat.getSlot(), @@ -72,7 +64,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { if (PlayerListCategory.IN_PROGRESS.isEnabled()) { setCategory(PlayerListCategory.IN_PROGRESS); - if (quests.isEmpty() && QuestsConfiguration.getConfig().getQuestsMenuConfig().isNotStartedTabOpenedWhenEmpty() + if (objects.isEmpty() && QuestsConfiguration.getConfig().getQuestsMenuConfig().isNotStartedTabOpenedWhenEmpty() && PlayerListCategory.NOT_STARTED.isEnabled()) setCategory(PlayerListCategory.NOT_STARTED); }else if (PlayerListCategory.NOT_STARTED.isEnabled()) { @@ -80,107 +72,136 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { }else setCategory(PlayerListCategory.FINISHED); } - private void setQuests(List<Quest> quests) { - this.quests = quests; - quests.sort(null); - } - private void setCategory(PlayerListCategory category){ if (cat == category) return; if (cat != null) toggleCategorySelected(); cat = category; - page = 0; - toggleCategorySelected(); - setItems(); + setSeparatorColor(cat.getColor()); DyeColor color = cat == PlayerListCategory.FINISHED ? DyeColor.GREEN: (cat == PlayerListCategory.IN_PROGRESS ? DyeColor.YELLOW : DyeColor.RED); for (int i = 0; i < 5; i++) getInventory().setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); - } - private void setItems(){ - for (int i = 0; i < 35; i++) setMainItem(i, null); - switch (cat){ - - case FINISHED: - displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), - qu, acc, cat, DescriptionSource.MENU).formatDescription(); - if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() - && acc.getQuestDatas(qu).hasFlowDialogs()) { - if (!lore.isEmpty()) lore.add(null); - lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); - } - return createQuestItem(qu, lore); - }); - break; - - case IN_PROGRESS: - displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), - qu, acc, cat, DescriptionSource.MENU).formatDescription(); + List<Quest> quests; + switch (cat) { + case FINISHED: + quests = QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide); + break; - boolean hasDialogs = QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() - && acc.getQuestDatas(qu).hasFlowDialogs(); - boolean cancellable = - QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); - if (cancellable || hasDialogs) { - if (!lore.isEmpty()) lore.add(null); - if (cancellable) lore.add("§8" + Lang.ClickLeft + " §8> " + Lang.cancelLore); - if (hasDialogs) lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); - } - return createQuestItem(qu, lore); - }); - break; + case IN_PROGRESS: + quests = QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false); + break; - case NOT_STARTED: - displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() - .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) - .collect(Collectors.toList()), qu -> { - return createQuestItem(qu, - new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), qu, - acc, cat, DescriptionSource.MENU).formatDescription()); - }); - break; + case NOT_STARTED: + quests = QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() + .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) + .collect(Collectors.toList()); + break; - default: - break; + default: + throw new UnsupportedOperationException(); } + + setObjects(quests); + sortValues(Function.identity()); } - private void displayQuests(List<Quest> quests, Function<Quest, ItemStack> itemProvider) { - setQuests(quests); - for (int i = page * 35; i < quests.size(); i++) { - if (i == (page + 1) * 35) break; - Quest qu = quests.get(i); - ItemStack item; - try { - item = itemProvider.apply(qu); - }catch (Exception ex) { - item = ItemUtils.item(XMaterial.BARRIER, "§cError - Quest #" + qu.getId()); - QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred when creating item of quest " + qu.getId() + " for account " + acc.abstractAcc.getIdentifier(), ex); + @Override + public @NotNull ItemStack getItemStack(@NotNull Quest qu) { + ItemStack item; + try { + List<String> lore; + switch (cat) { + case FINISHED: + lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), + qu, acc, cat, DescriptionSource.MENU).formatDescription(); + if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs()) { + if (!lore.isEmpty()) + lore.add(null); + lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); + } + break; + + case IN_PROGRESS: + lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), + qu, acc, cat, DescriptionSource.MENU).formatDescription(); + + boolean hasDialogs = QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs(); + boolean cancellable = + QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() + && qu.isCancellable(); + if (cancellable || hasDialogs) { + if (!lore.isEmpty()) + lore.add(null); + if (cancellable) + lore.add("§8" + Lang.ClickLeft + " §8> " + Lang.cancelLore); + if (hasDialogs) + lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); + } + break; + + case NOT_STARTED: + lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), qu, + acc, cat, DescriptionSource.MENU).formatDescription(); + break; + + default: + throw new UnsupportedOperationException(); + } - setMainItem(i - page * 35, item); + item = ItemUtils.nameAndLore(qu.getQuestItem().clone(), + player.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu) : Lang.formatNormal.format(qu), + lore); + } catch (Exception ex) { + item = ItemUtils.item(XMaterial.BARRIER, "§cError - Quest #" + qu.getId()); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred when creating item of quest " + qu.getId() + + " for account " + acc.abstractAcc.getIdentifier(), ex); } + return item; } - private int setMainItem(int mainSlot, ItemStack is){ - int line = (int) Math.floor(mainSlot * 1.0 / 7.0); - int slot = mainSlot + (2 * line); - getInventory().setItem(slot, is); - return slot; - } - - private int setBarItem(int barSlot, ItemStack is){ - int slot = barSlot * 9 + 8; - getInventory().setItem(slot, is); - return slot; + @Override + protected void barClick(GuiClickEvent event, int barSlot) { + Optional<PlayerListCategory> clickedCat = + Arrays.stream(PlayerListCategory.values()).filter(cat -> cat.getSlot() == barSlot).findAny(); + if (clickedCat.isPresent()) { + if (clickedCat.get().isEnabled()) + setCategory(clickedCat.get()); + } else + super.barClick(event, barSlot); } - private ItemStack createQuestItem(Quest qu, List<String> lore) { - return ItemUtils.nameAndLore(qu.getQuestItem().clone(), - open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu) : Lang.formatNormal.format(qu), lore); + @Override + public void click(@NotNull Quest qu, @NotNull ItemStack item, @NotNull ClickType clickType) { + if (cat == PlayerListCategory.NOT_STARTED) { + if (!qu.getOptionValueOrDef(OptionStartable.class)) + return; + if (!acc.isCurrent()) + return; + Player target = acc.getPlayer(); + if (qu.canStart(target, true)) { + close(); + qu.attemptStart(target); + } + } else { + if (clickType.isRightClick()) { + if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs()) { + QuestUtils.playPluginSound(player, "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); + new DialogHistoryGUI(acc, qu, this::reopen).open(player); + } + } else if (clickType.isLeftClick()) { + if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() + && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { + QuestsPlugin.getPlugin().getGuiManager().getFactory() + .createConfirmation(() -> qu.cancelPlayer(acc), this::reopen, Lang.INDICATION_CANCEL.format(qu)) + .open(player); + } + } + } } private void toggleCategorySelected() { @@ -198,72 +219,6 @@ private void toggleCategorySelected() { is.setItemMeta(im); } - - @Override - public void onClick(GuiClickEvent event) { - switch (event.getSlot() % 9) { - case 8: - int barSlot = (event.getSlot() - 8) / 9; - switch (barSlot) { - case 0: - if (page == 0) - break; - page--; - setItems(); - break; - case 4: - page++; - setItems(); - break; - - case 1: - case 2: - case 3: - Arrays.stream(PlayerListCategory.values()).filter(cat -> cat.getSlot() == barSlot).findAny() - .filter(cat -> cat.isEnabled()).ifPresent(this::setCategory); - break; - - } - break; - - case 7: - break; - - default: - int id = (int) (event.getSlot() - (Math.floor(event.getSlot() * 1D / 9D) * 2) + page * 35); - Quest qu = quests.get(id); - if (cat == PlayerListCategory.NOT_STARTED) { - if (!qu.getOptionValueOrDef(OptionStartable.class)) - break; - if (!acc.isCurrent()) - break; - Player target = acc.getPlayer(); - if (qu.canStart(target, true)) { - event.close(); - qu.attemptStart(target); - } - } else { - if (event.getClick().isRightClick()) { - if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() - && acc.getQuestDatas(qu).hasFlowDialogs()) { - QuestUtils.playPluginSound(event.getPlayer(), "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); - new DialogHistoryGUI(acc, qu, event::reopen).open(event.getPlayer()); - } - } else if (event.getClick().isLeftClick()) { - if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() - && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { - QuestsPlugin.getPlugin().getGuiManager().getFactory() - .createConfirmation(() -> qu.cancelPlayer(acc), event::reopen, - Lang.INDICATION_CANCEL.format(qu)) - .open(event.getPlayer()); - } - } - } - break; - - } - } - @Override public CloseBehavior onClose(Player p) { return StandardCloseBehavior.REMOVE; diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java b/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java new file mode 100755 index 00000000..cd7c33b2 --- /dev/null +++ b/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java @@ -0,0 +1,272 @@ +package fr.skytasul.quests.gui.quests; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import fr.skytasul.quests.api.QuestsAPI; +import fr.skytasul.quests.api.QuestsConfiguration; +import fr.skytasul.quests.api.QuestsPlugin; +import fr.skytasul.quests.api.gui.AbstractGui; +import fr.skytasul.quests.api.gui.GuiClickEvent; +import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.gui.close.CloseBehavior; +import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; +import fr.skytasul.quests.api.localization.Lang; +import fr.skytasul.quests.api.options.description.DescriptionSource; +import fr.skytasul.quests.api.options.description.QuestDescriptionContext; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.PlayerListCategory; +import fr.skytasul.quests.api.utils.XMaterial; +import fr.skytasul.quests.options.OptionStartable; +import fr.skytasul.quests.players.PlayerAccountImplementation; +import fr.skytasul.quests.utils.QuestUtils; + +public class PlayerListGUIBackup extends AbstractGui { + + static final String UNSELECTED_PREFIX = "§7○ "; + private static final String SELECTED_PREFIX = "§b§l● "; + + private Player open; + private PlayerAccountImplementation acc; + private boolean hide; + + private int page = 0; + private @Nullable PlayerListCategory cat = null; + private List<Quest> quests; + + public PlayerListGUIBackup(PlayerAccountImplementation acc) { + this(acc, true); + } + + public PlayerListGUIBackup(PlayerAccountImplementation acc, boolean hide) { + this.acc = acc; + this.hide = hide; + } + + @Override + protected Inventory instanciate(@NotNull Player player) { + return Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc)); + } + + @Override + protected void populate(@NotNull Player player, @NotNull Inventory inventory) { + open = player; + + setBarItem(0, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getPreviousPage()); + setBarItem(4, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNextPage()); + + for (PlayerListCategory enabledCat : QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs()) { + setBarItem(enabledCat.getSlot(), + ItemUtils.item(enabledCat.getMaterial(), UNSELECTED_PREFIX + enabledCat.getName())); + } + + if (PlayerListCategory.IN_PROGRESS.isEnabled()) { + setCategory(PlayerListCategory.IN_PROGRESS); + if (quests.isEmpty() && QuestsConfiguration.getConfig().getQuestsMenuConfig().isNotStartedTabOpenedWhenEmpty() + && PlayerListCategory.NOT_STARTED.isEnabled()) + setCategory(PlayerListCategory.NOT_STARTED); + }else if (PlayerListCategory.NOT_STARTED.isEnabled()) { + setCategory(PlayerListCategory.NOT_STARTED); + }else setCategory(PlayerListCategory.FINISHED); + } + + private void setQuests(List<Quest> quests) { + this.quests = quests; + quests.sort(null); + } + + private void setCategory(PlayerListCategory category){ + if (cat == category) return; + if (cat != null) + toggleCategorySelected(); + cat = category; + page = 0; + toggleCategorySelected(); + setItems(); + + DyeColor color = cat == PlayerListCategory.FINISHED ? DyeColor.GREEN: (cat == PlayerListCategory.IN_PROGRESS ? DyeColor.YELLOW : DyeColor.RED); + for (int i = 0; i < 5; i++) + getInventory().setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); + } + + private void setItems(){ + for (int i = 0; i < 35; i++) setMainItem(i, null); + switch (cat){ + + case FINISHED: + displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide), qu -> { + List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), + qu, acc, cat, DescriptionSource.MENU).formatDescription(); + if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs()) { + if (!lore.isEmpty()) lore.add(null); + lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); + } + return createQuestItem(qu, lore); + }); + break; + + case IN_PROGRESS: + displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false), qu -> { + List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), + qu, acc, cat, DescriptionSource.MENU).formatDescription(); + + boolean hasDialogs = QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs(); + boolean cancellable = + QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); + if (cancellable || hasDialogs) { + if (!lore.isEmpty()) lore.add(null); + if (cancellable) lore.add("§8" + Lang.ClickLeft + " §8> " + Lang.cancelLore); + if (hasDialogs) lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); + } + return createQuestItem(qu, lore); + }); + break; + + case NOT_STARTED: + displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() + .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) + .collect(Collectors.toList()), qu -> { + return createQuestItem(qu, + new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), qu, + acc, cat, DescriptionSource.MENU).formatDescription()); + }); + break; + + default: + break; + } + } + + private void displayQuests(List<Quest> quests, Function<Quest, ItemStack> itemProvider) { + setQuests(quests); + for (int i = page * 35; i < quests.size(); i++) { + if (i == (page + 1) * 35) break; + Quest qu = quests.get(i); + ItemStack item; + try { + item = itemProvider.apply(qu); + }catch (Exception ex) { + item = ItemUtils.item(XMaterial.BARRIER, "§cError - Quest #" + qu.getId()); + QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred when creating item of quest " + qu.getId() + " for account " + acc.abstractAcc.getIdentifier(), ex); + } + setMainItem(i - page * 35, item); + } + } + + private int setMainItem(int mainSlot, ItemStack is){ + int line = (int) Math.floor(mainSlot * 1.0 / 7.0); + int slot = mainSlot + (2 * line); + getInventory().setItem(slot, is); + return slot; + } + + private int setBarItem(int barSlot, ItemStack is){ + int slot = barSlot * 9 + 8; + getInventory().setItem(slot, is); + return slot; + } + + private ItemStack createQuestItem(Quest qu, List<String> lore) { + return ItemUtils.nameAndLore(qu.getQuestItem().clone(), + open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu) : Lang.formatNormal.format(qu), lore); + } + + private void toggleCategorySelected() { + ItemStack is = getInventory().getItem(cat.getSlot() * 9 + 8); + ItemMeta im = is.getItemMeta(); + String name = im.getDisplayName(); + if (!im.hasEnchant(Enchantment.DURABILITY)) { + im.addEnchant(Enchantment.DURABILITY, 0, true); + name = SELECTED_PREFIX + name.substring(UNSELECTED_PREFIX.length()); + }else{ + im.removeEnchant(Enchantment.DURABILITY); + name = UNSELECTED_PREFIX + name.substring(SELECTED_PREFIX.length()); + } + im.setDisplayName(name); + is.setItemMeta(im); + } + + + @Override + public void onClick(GuiClickEvent event) { + switch (event.getSlot() % 9) { + case 8: + int barSlot = (event.getSlot() - 8) / 9; + switch (barSlot) { + case 0: + if (page == 0) + break; + page--; + setItems(); + break; + case 4: + page++; + setItems(); + break; + + case 1: + case 2: + case 3: + Arrays.stream(PlayerListCategory.values()).filter(cat -> cat.getSlot() == barSlot).findAny() + .filter(cat -> cat.isEnabled()).ifPresent(this::setCategory); + break; + + } + break; + + case 7: + break; + + default: + int id = (int) (event.getSlot() - (Math.floor(event.getSlot() * 1D / 9D) * 2) + page * 35); + Quest qu = quests.get(id); + if (cat == PlayerListCategory.NOT_STARTED) { + if (!qu.getOptionValueOrDef(OptionStartable.class)) + break; + if (!acc.isCurrent()) + break; + Player target = acc.getPlayer(); + if (qu.canStart(target, true)) { + event.close(); + qu.attemptStart(target); + } + } else { + if (event.getClick().isRightClick()) { + if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() + && acc.getQuestDatas(qu).hasFlowDialogs()) { + QuestUtils.playPluginSound(event.getPlayer(), "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); + new DialogHistoryGUI(acc, qu, event::reopen).open(event.getPlayer()); + } + } else if (event.getClick().isLeftClick()) { + if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() + && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { + QuestsPlugin.getPlugin().getGuiManager().getFactory() + .createConfirmation(() -> qu.cancelPlayer(acc), event::reopen, + Lang.INDICATION_CANCEL.format(qu)) + .open(event.getPlayer()); + } + } + } + break; + + } + } + + @Override + public CloseBehavior onClose(Player p) { + return StandardCloseBehavior.REMOVE; + } + +} diff --git a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java index 2d5968db..80c0d783 100644 --- a/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java +++ b/core/src/main/java/fr/skytasul/quests/options/OptionVisibility.java @@ -13,6 +13,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.AbstractGui; import fr.skytasul.quests.api.gui.GuiClickEvent; import fr.skytasul.quests.api.gui.ItemUtils; @@ -85,7 +86,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { locations.put(loc, visible); inventory.setItem(i, ItemUtils.itemSwitch(loc.getName(), visible)); } - inventory.setItem(4, ItemUtils.itemDone); + inventory.setItem(4, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone()); } @Override 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 72765d50..73d34974 100644 --- a/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java +++ b/core/src/main/java/fr/skytasul/quests/players/AbstractPlayersManager.java @@ -4,12 +4,7 @@ import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; diff --git a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java index accbf4ae..49141bf5 100644 --- a/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java +++ b/core/src/main/java/fr/skytasul/quests/rewards/RequirementDependentReward.java @@ -7,7 +7,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.gui.ItemUtils; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.gui.LoreBuilder; import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; import fr.skytasul.quests.api.gui.layout.LayoutedButton; @@ -99,7 +99,7 @@ public void itemClick(QuestObjectClickEvent event) { .addButton(1, LayoutedButton.create(XMaterial.CHEST, () -> "§a" + rewards.getSizeString(), Collections.emptyList(), this::editRewards)) - .addButton(4, LayoutedButton.create(ItemUtils.itemDone, __ -> event.reopenGUI())) + .addButton(4, LayoutedButton.create(QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone(), __ -> event.reopenGUI())) .setName(Lang.INVENTORY_REWARDS_WITH_REQUIREMENTS.toString()) .setCloseBehavior(StandardCloseBehavior.REOPEN) .build() diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 5832c9dd..dc6b9222 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -54,8 +54,6 @@ fireworks: true npcClick: [RIGHT, SHIFT_RIGHT] # Default item shown for a quest in the menus item: BOOK -# Page item material -pageItem: ARROW # Maxmium distance where starting particles are shown startParticleDistance: 20 # Number of seconds before the plugin checks every requirements for the player to show the starting particle @@ -65,6 +63,16 @@ requirementReasonOnMultipleQuests: true # Enables the sending of the "you obtain xxx" when a player terminates a stage with end rewards stageEndRewardsMessage: true +# - GUIs- +# Some options related to graphical user interfaces +gui: + # Previous page item + previous page item: ARROW + # Next page item + next page item: ARROW + # Show a vertical separator made of glass pane between the items pane and the arrow buttons + vertical separator: true + # - Dialogs - # Various options related to dialogs dialogs: diff --git a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java index 2912e068..7aa7f872 100644 --- a/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java +++ b/integrations/src/main/java/fr/skytasul/quests/integrations/vault/permission/PermissionGUI.java @@ -8,6 +8,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import fr.skytasul.quests.api.QuestsPlugin; import fr.skytasul.quests.api.editors.TextEditor; import fr.skytasul.quests.api.editors.parsers.WorldParser; import fr.skytasul.quests.api.gui.AbstractGui; @@ -45,7 +46,7 @@ protected void populate(@NotNull Player player, @NotNull Inventory inventory) { world == null ? Lang.worldGlobal.toString() : "§b" + world)); inventory.setItem(2, ItemUtils.itemSwitch(Lang.permRemove.toString(), take, Lang.permRemoveLore.toString())); - ItemStack done = ItemUtils.itemDone.toMutableStack(); + ItemStack done = QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getDone(); if (perm == null) done.setType(Material.COAL); inventory.setItem(4, done); } @@ -81,7 +82,7 @@ public void onClick(GuiClickEvent event) { break; } } - + private void updatePerm(Player p, String perm) { this.perm = perm; ItemUtils.lore(getInventory().getItem(0), perm == null ? Lang.NotSet.toString() : "§b" + perm); @@ -98,5 +99,5 @@ private void updateWorld(Player p, String name) { public CloseBehavior onClose(Player p) { return StandardCloseBehavior.REOPEN; } - + } From 290c26bcfa456e8235d1a54e4b21df6dae583e5f Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 1 Dec 2023 10:27:54 +0100 Subject: [PATCH 90/95] :bug: Fixed wrong order of quests in GUI --- .../quests/gui/quests/PlayerListGUI.java | 3 +- .../gui/quests/PlayerListGUIBackup.java | 272 ------------------ 2 files changed, 1 insertion(+), 274 deletions(-) delete mode 100755 core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java 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 a1ee995d..08876cab 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 @@ -4,7 +4,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.function.Function; import java.util.stream.Collectors; import org.bukkit.DyeColor; import org.bukkit.enchantments.Enchantment; @@ -102,9 +101,9 @@ private void setCategory(PlayerListCategory category){ default: throw new UnsupportedOperationException(); } + quests.sort(null); setObjects(quests); - sortValues(Function.identity()); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java b/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java deleted file mode 100755 index cd7c33b2..00000000 --- a/core/src/main/java/fr/skytasul/quests/gui/quests/PlayerListGUIBackup.java +++ /dev/null @@ -1,272 +0,0 @@ -package fr.skytasul.quests.gui.quests; - -import java.util.Arrays; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.bukkit.Bukkit; -import org.bukkit.DyeColor; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import fr.skytasul.quests.api.QuestsAPI; -import fr.skytasul.quests.api.QuestsConfiguration; -import fr.skytasul.quests.api.QuestsPlugin; -import fr.skytasul.quests.api.gui.AbstractGui; -import fr.skytasul.quests.api.gui.GuiClickEvent; -import fr.skytasul.quests.api.gui.ItemUtils; -import fr.skytasul.quests.api.gui.close.CloseBehavior; -import fr.skytasul.quests.api.gui.close.StandardCloseBehavior; -import fr.skytasul.quests.api.localization.Lang; -import fr.skytasul.quests.api.options.description.DescriptionSource; -import fr.skytasul.quests.api.options.description.QuestDescriptionContext; -import fr.skytasul.quests.api.quests.Quest; -import fr.skytasul.quests.api.utils.PlayerListCategory; -import fr.skytasul.quests.api.utils.XMaterial; -import fr.skytasul.quests.options.OptionStartable; -import fr.skytasul.quests.players.PlayerAccountImplementation; -import fr.skytasul.quests.utils.QuestUtils; - -public class PlayerListGUIBackup extends AbstractGui { - - static final String UNSELECTED_PREFIX = "§7○ "; - private static final String SELECTED_PREFIX = "§b§l● "; - - private Player open; - private PlayerAccountImplementation acc; - private boolean hide; - - private int page = 0; - private @Nullable PlayerListCategory cat = null; - private List<Quest> quests; - - public PlayerListGUIBackup(PlayerAccountImplementation acc) { - this(acc, true); - } - - public PlayerListGUIBackup(PlayerAccountImplementation acc, boolean hide) { - this.acc = acc; - this.hide = hide; - } - - @Override - protected Inventory instanciate(@NotNull Player player) { - return Bukkit.createInventory(null, 45, Lang.INVENTORY_PLAYER_LIST.format(acc)); - } - - @Override - protected void populate(@NotNull Player player, @NotNull Inventory inventory) { - open = player; - - setBarItem(0, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getPreviousPage()); - setBarItem(4, QuestsPlugin.getPlugin().getGuiManager().getItemFactory().getNextPage()); - - for (PlayerListCategory enabledCat : QuestsConfiguration.getConfig().getQuestsMenuConfig().getEnabledTabs()) { - setBarItem(enabledCat.getSlot(), - ItemUtils.item(enabledCat.getMaterial(), UNSELECTED_PREFIX + enabledCat.getName())); - } - - if (PlayerListCategory.IN_PROGRESS.isEnabled()) { - setCategory(PlayerListCategory.IN_PROGRESS); - if (quests.isEmpty() && QuestsConfiguration.getConfig().getQuestsMenuConfig().isNotStartedTabOpenedWhenEmpty() - && PlayerListCategory.NOT_STARTED.isEnabled()) - setCategory(PlayerListCategory.NOT_STARTED); - }else if (PlayerListCategory.NOT_STARTED.isEnabled()) { - setCategory(PlayerListCategory.NOT_STARTED); - }else setCategory(PlayerListCategory.FINISHED); - } - - private void setQuests(List<Quest> quests) { - this.quests = quests; - quests.sort(null); - } - - private void setCategory(PlayerListCategory category){ - if (cat == category) return; - if (cat != null) - toggleCategorySelected(); - cat = category; - page = 0; - toggleCategorySelected(); - setItems(); - - DyeColor color = cat == PlayerListCategory.FINISHED ? DyeColor.GREEN: (cat == PlayerListCategory.IN_PROGRESS ? DyeColor.YELLOW : DyeColor.RED); - for (int i = 0; i < 5; i++) - getInventory().setItem(i * 9 + 7, ItemUtils.itemSeparator(color)); - } - - private void setItems(){ - for (int i = 0; i < 35; i++) setMainItem(i, null); - switch (cat){ - - case FINISHED: - displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsFinished(acc, hide), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), - qu, acc, cat, DescriptionSource.MENU).formatDescription(); - if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() - && acc.getQuestDatas(qu).hasFlowDialogs()) { - if (!lore.isEmpty()) lore.add(null); - lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); - } - return createQuestItem(qu, lore); - }); - break; - - case IN_PROGRESS: - displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsStarted(acc, true, false), qu -> { - List<String> lore = new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), - qu, acc, cat, DescriptionSource.MENU).formatDescription(); - - boolean hasDialogs = QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() - && acc.getQuestDatas(qu).hasFlowDialogs(); - boolean cancellable = - QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() && qu.isCancellable(); - if (cancellable || hasDialogs) { - if (!lore.isEmpty()) lore.add(null); - if (cancellable) lore.add("§8" + Lang.ClickLeft + " §8> " + Lang.cancelLore); - if (hasDialogs) lore.add("§8" + Lang.ClickRight + " §8> " + Lang.dialogsHistoryLore); - } - return createQuestItem(qu, lore); - }); - break; - - case NOT_STARTED: - displayQuests(QuestsAPI.getAPI().getQuestsManager().getQuestsNotStarted(acc, hide, true).stream() - .filter(quest -> !quest.isHiddenWhenRequirementsNotMet() || quest.canStart(acc.getPlayer(), false)) - .collect(Collectors.toList()), qu -> { - return createQuestItem(qu, - new QuestDescriptionContext(QuestsConfiguration.getConfig().getQuestDescriptionConfig(), qu, - acc, cat, DescriptionSource.MENU).formatDescription()); - }); - break; - - default: - break; - } - } - - private void displayQuests(List<Quest> quests, Function<Quest, ItemStack> itemProvider) { - setQuests(quests); - for (int i = page * 35; i < quests.size(); i++) { - if (i == (page + 1) * 35) break; - Quest qu = quests.get(i); - ItemStack item; - try { - item = itemProvider.apply(qu); - }catch (Exception ex) { - item = ItemUtils.item(XMaterial.BARRIER, "§cError - Quest #" + qu.getId()); - QuestsPlugin.getPlugin().getLoggerExpanded().severe("An error ocurred when creating item of quest " + qu.getId() + " for account " + acc.abstractAcc.getIdentifier(), ex); - } - setMainItem(i - page * 35, item); - } - } - - private int setMainItem(int mainSlot, ItemStack is){ - int line = (int) Math.floor(mainSlot * 1.0 / 7.0); - int slot = mainSlot + (2 * line); - getInventory().setItem(slot, is); - return slot; - } - - private int setBarItem(int barSlot, ItemStack is){ - int slot = barSlot * 9 + 8; - getInventory().setItem(slot, is); - return slot; - } - - private ItemStack createQuestItem(Quest qu, List<String> lore) { - return ItemUtils.nameAndLore(qu.getQuestItem().clone(), - open.hasPermission("beautyquests.seeId") ? Lang.formatId.format(qu) : Lang.formatNormal.format(qu), lore); - } - - private void toggleCategorySelected() { - ItemStack is = getInventory().getItem(cat.getSlot() * 9 + 8); - ItemMeta im = is.getItemMeta(); - String name = im.getDisplayName(); - if (!im.hasEnchant(Enchantment.DURABILITY)) { - im.addEnchant(Enchantment.DURABILITY, 0, true); - name = SELECTED_PREFIX + name.substring(UNSELECTED_PREFIX.length()); - }else{ - im.removeEnchant(Enchantment.DURABILITY); - name = UNSELECTED_PREFIX + name.substring(SELECTED_PREFIX.length()); - } - im.setDisplayName(name); - is.setItemMeta(im); - } - - - @Override - public void onClick(GuiClickEvent event) { - switch (event.getSlot() % 9) { - case 8: - int barSlot = (event.getSlot() - 8) / 9; - switch (barSlot) { - case 0: - if (page == 0) - break; - page--; - setItems(); - break; - case 4: - page++; - setItems(); - break; - - case 1: - case 2: - case 3: - Arrays.stream(PlayerListCategory.values()).filter(cat -> cat.getSlot() == barSlot).findAny() - .filter(cat -> cat.isEnabled()).ifPresent(this::setCategory); - break; - - } - break; - - case 7: - break; - - default: - int id = (int) (event.getSlot() - (Math.floor(event.getSlot() * 1D / 9D) * 2) + page * 35); - Quest qu = quests.get(id); - if (cat == PlayerListCategory.NOT_STARTED) { - if (!qu.getOptionValueOrDef(OptionStartable.class)) - break; - if (!acc.isCurrent()) - break; - Player target = acc.getPlayer(); - if (qu.canStart(target, true)) { - event.close(); - qu.attemptStart(target); - } - } else { - if (event.getClick().isRightClick()) { - if (QuestsConfiguration.getConfig().getDialogsConfig().isHistoryEnabled() - && acc.getQuestDatas(qu).hasFlowDialogs()) { - QuestUtils.playPluginSound(event.getPlayer(), "ITEM_BOOK_PAGE_TURN", 0.5f, 1.4f); - new DialogHistoryGUI(acc, qu, event::reopen).open(event.getPlayer()); - } - } else if (event.getClick().isLeftClick()) { - if (QuestsConfiguration.getConfig().getQuestsMenuConfig().allowPlayerCancelQuest() - && cat == PlayerListCategory.IN_PROGRESS && qu.isCancellable()) { - QuestsPlugin.getPlugin().getGuiManager().getFactory() - .createConfirmation(() -> qu.cancelPlayer(acc), event::reopen, - Lang.INDICATION_CANCEL.format(qu)) - .open(event.getPlayer()); - } - } - } - break; - - } - } - - @Override - public CloseBehavior onClose(Player p) { - return StandardCloseBehavior.REMOVE; - } - -} From 318c83c486da3b7682f35e53820bf0ba559ea89d Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Fri, 1 Dec 2023 10:34:21 +0100 Subject: [PATCH 91/95] :globe_with_meridians: Updated i18n for french and german --- core/src/main/resources/locales/de_DE.yml | 1424 +++++++++++---------- core/src/main/resources/locales/fr_FR.yml | 6 + 2 files changed, 719 insertions(+), 711 deletions(-) diff --git a/core/src/main/resources/locales/de_DE.yml b/core/src/main/resources/locales/de_DE.yml index c2f34aaa..f96cd390 100644 --- a/core/src/main/resources/locales/de_DE.yml +++ b/core/src/main/resources/locales/de_DE.yml @@ -1,519 +1,92 @@ --- -advancement: - finished: Abgeschlossen - notStarted: Nicht gestartet -description: - requirement: - class: Klasse {class_name} - combatLevel: Kampflevel {short_level} - faction: Fraktion {faction_name} - jobLevel: Level {short_level} für {job_name} - quest: Quest beenden §e{quest_name} - skillLevel: Level {short_level} für {skill_name} - title: '§8§lAnforderungen:' - reward: - title: '§8§lBelohnungen:' -indication: - cancelQuest: '§7Bist du sicher, dass du die Quest {quest_name} abbrechen möchtest?' - closeInventory: '§7Bist du sicher, dass du die GUI schließen möchtest?' - removeQuest: '§7Bist du sicher, dass du die Quest {quest} entfernen möchtest?' - startQuest: '§7Möchtest du die Quest {quest_name} starten?' -inv: - addObject: '§aFüge ein Ziel hinzu' - block: - blockData: '§dBlockdaten (fortgeschritten)' - blockName: '§bEigener Blockname' - blockTag: '§dTag (Erweitert)' - blockTagLore: Wähle einen Tag, welcher eine Liste von möglichen Blöcken beschreibt. Tags können durch Datapacks angepasst werden. Du kannst eine Liste von Tags im Minecraft Wiki finden. - materialNotItemLore: Dieser Block kann momentan nicht als Item angezeigt werden. Er wird immer noch korrekt als {block_material} gespeichert. - name: Block auswählen - blockAction: - location: '§eWähle einen genauen Ort aus' - material: '§eWähle ein Blockmaterial' - name: Blockaktion auswählen - blocksList: - addBlock: '§aKlicke, um einen Block hinzuzufügen.' - name: Blöcke auswählen - buckets: - name: Eimertyp - cancel: '§c§lAbbrechen' - cancelActions: - name: Aktionen abbrechen - checkpointActions: - name: Checkpoint-Aktionen - chooseAccount: - name: Welcher Account? - chooseQuest: - menu: '§aQuests Menu' - menuLore: Ruft dich zu deinem Quest-Menü zurück. - name: Welche Quest? - classesList.name: Klassenliste - classesRequired.name: Klassen erforderlich - command: - console: Konsole - delay: '§bVerzögerung' - name: Befehl - parse: Platzhalter analysieren - value: '§eBefehl' - commandsList: - console: '§eKonsole: {command_console}' - name: Befehlliste - value: '§eBefehl: {command_label}' - confirm: - name: Bist du sicher? - 'no': '§cAbbrechen' - 'yes': '§aBestätigen' - create: - NPCSelect: '§eNPC auswählen oder erstellen' - NPCText: '§eDialog bearbeiten' - breedAnimals: '§aZüchte Tiere' - bringBack: '§aItems zurückbringen' - bucket: '§aEimer befüllen' - cancelMessage: Senden abbrechen - cantFinish: '§7Du musst mindestens eine Stufe erstellen, bevor du die Questerstellung fertigstellen kannst!' - changeEntityType: '§eObjekttyp ändern' - changeTicksRequired: '§eÄndere die erforderlichen gespielten Ticks' - craft: '§aItem herstellen' - currentRadius: '§eAktuelle Entfernung: §6{radius}' - dealDamage: '§cSchaden an Mobs zufügen' - death: '§csterben' - eatDrink: '§aEssen oder trinken Sie Essen oder Tränke' - editBlocksMine: '§eDie zu zerstörenden Blöcke bearbeiten' - editBlocksPlace: '§eDie zu plazierenden Blöcke bearbeiten' - editBucketAmount: '§eAnzahl an zu befüllenden Eimern bearbeiten' - editBucketType: '§eTyp des zu befüllenden Eimers bearbeiten' - editFishes: '§eDie zu fangenden Fische bearbeiten' - editItem: '§eHerzustellendes Item bearbeiten' - editItemsToEnchant: '§eBearbeite Items zum Verzaubern' - editItemsToMelt: '§eBearbeite Items zum Schmelzen' - editLocation: '§ePosition bearbeiten' - editMessageType: '§eDie zu schreibende Nachricht bearbeiten' - editMobsKill: '§eDie zu tötenden Mobs bearbeiten' - editRadius: '§eEntfernung von Position bearbeiten' - enchant: '§dVerzauberte Gegenstände' - findNPC: '§aNPC finden' - findRegion: '§aRegion finden' - fish: '§aFische fangen' - hideClues: Partikel und Hologramme verstecken - ignoreCase: Fall der Nachricht ignorieren - interact: '§aMit Block interagieren' - killMobs: '§aMobs töten' - leftClick: Muss Linksklick sein - location: '§aZu Position gehen' - melt: '§6Schmelze Elemente' - mineBlocks: '§aBlöcke zerstören' - mobsKillFromAFar: Muss mit Projektil getötet werden - placeBlocks: '§aPlatziere Blöcke' - playTime: '§eSpielzeit' - preventBlockPlace: Spieler daran hindern, ihre eigenen Blöcke zu zerstören - replacePlaceholders: Ersetze {PLAYER} und Platzhalter von PAPI - selectBlockLocation: '§eBlockposition auswählen' - selectBlockMaterial: '§eWähle Blockmaterial' - selectItems: '§eBenötigte Items auswählen' - selectItemsComparisons: '§eWähle Gegenstandsvergleiche (ERWEITERT)' - selectItemsMessage: '§eFragenachricht bearbeiten' - selectRegion: '§7Region auswählen' - stage: - dealDamage: - damage: '§eSchaden zu erledigen' - targetMobs: '§cMobs zu Schaden' - death: - anyCause: Jede Todesursache - causes: '§aSetze Todesursache §d(FORTGESCHRITTEN)' - setCauses: '{causes_amount} Todesursache(n)' - eatDrink: - items: '§eBearbeite Items um zu essen oder zu trinken' - location: - worldPattern: '§aSetze Weltennamenmuster §d(FORTGESCHRITTEN)' - worldPatternLore: Wenn du möchtest, dass die Stage für eine Welt, die einem bestimmten Muster entspricht, abgeschlossen wird, gib hier einen Regex (regulärer Ausdruck) ein. - stageCreate: '§aNeuen Schritt erstellen' - stageDown: Eins runter - stageRemove: '§cDiesen Schritt löschen' - stageStartMsg: '§eStartnachricht bearbeiten' - stageType: '§7Stufentyp: §e{stage_type}' - stageUp: Eins höher - talkChat: '§aIm Chat schreiben' - tameAnimals: '§aZähme Tiere' - toggleRegionExit: Beim Verlassen - details: - actions: '{amount} Aktion(en)' - auto: Beim ersten Beitritt automatisch starten - autoLore: Wenn aktiviert, wird die Quest automatisch gestartet, wenn der Spieler zum ersten Mal den Server betritt. - bypassLimit: Questlimit nicht zählen - bypassLimitLore: Wenn aktiviert, ist die Quest startbar, auch wenn der Spieler seine maximale Anzahl an begonnenen Quests erreicht hat. - cancelRewards: '§cAbbrechen von Aktionen' - cancelRewardsLore: Aktionen wenn Spieler diese Quest abbrechen. - cancellable: Vom Spieler abbrechbar - cancellableLore: Ermöglicht dem Spieler, die Quest durch das Quest-Menü abzubrechen. - createQuestLore: Du musst einen Questnamen definieren. - createQuestName: '§lQuest erstellen' - customConfirmMessage: '§eQuestbestätigungsnachricht bearbeiten' - customConfirmMessageLore: Meldung, die in der Bestätigungs-GUI angezeigt wird, wenn ein Spieler die Quest startet. - customDescription: '§eBearbeite Quest Beschreibung' - customDescriptionLore: Beschreibung, die unter dem Namen der Quest in GUIs steht. - customMaterial: '§eBearbeite das Material des Questgegenstandes' - customMaterialLore: Angezeigter Gegenstand dieser Quest im Questmenü. - defaultValue: '§8(Standardwert)' - editQuestName: '§lQuest bearbeiten' - editRequirements: '§eAnforderungen bearbeiten' - editRequirementsLore: Alle Anforderungen müssen auf den Spieler zutreffen, bevor er mit der Quest beginnen kann. - endMessage: '§eAbschlussnachricht bearbeiten' - endMessageLore: Nachricht, die am Ende der Quest an den Spieler gesendet wird. - endSound: '§eBearbeite den end sound' - endSoundLore: Ton, der am Ende einer Quest abgespielt wird. - failOnDeath: Im Todesfall fehlschlagen - failOnDeathLore: Wird die Quest abgebrochen, wenn der Spieler stirbt? - firework: '§dEnding Feuerwerk' - fireworkLore: Feuerwerk startet, wenn der Spieler die Quest beendet hat - fireworkLoreDrop: Lege dein eigenes Feuerwerk hierher - hideNoRequirementsItem: Verstecken, wenn die Anforderungen nicht erfüllt sind - hideNoRequirementsItemLore: Wenn aktiviert, wird die Quest nicht im Questmenü angezeigt, wenn die Anforderungen nicht erfüllt sind. - hologramLaunch: '§e„Starten“‐Hologramm‐Item bearbeiten' - hologramLaunchLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest starten kann. - hologramLaunchNo: '§e„Starten nicht verfügbar“‐Hologramm‐Item bearbeiten' - hologramLaunchNoLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest NICHT starten kann. - hologramText: '§eHologrammtext' - hologramTextLore: Text, der auf dem Hologramm über dem Kopf des Starter NPCs angezeigt wird. - keepDatas: Spielerdaten beibehalten - keepDatasLore: 'Erzwinge das Plugin die Daten der Spieler zu speichern, obwohl Stufen bearbeitet wurden. §c§lWARNUNG §c- Aktivieren dieser Option kann die Daten deiner Spieler zerstören.' - loreReset: '§e§lDer Fortschritt aller Spieler wird zurückgesetzt' - multipleTime: - itemLore: Kann die Quest mehrmals abgeschlossen werden? - itemName: Wiederholbar ein-/ausschalten - name: Letzte Questdetails - optionValue: '§8Wert: §7{value}' - questName: '§a§lQuestname bearbeiten' - questNameLore: Ein Name muss gesetzt werden, um die Questerstellung abzuschließen. - questPool: '§eQuestgruppe' - questPoolLore: Füge diese Quest einer Questgruppe hinzu - removeItemsReward: '§eEntferne Items vom Inventar' - requiredParameter: '§7Benötigter Parameter' - requirements: '{amount} Anforderung(en)' - rewards: '{amount} Belohnung(en)' - rewardsLore: Aktionen die durchgeführt werden wenn die Quest endet. - scoreboardItem: Scoreboard aktivieren - scoreboardItemLore: Wenn deaktiviert, wird die Quest nicht über das Scoreboard verfolgt. - selectStarterNPC: '§e§lNPC‐Starter auswählen' - selectStarterNPCLore: Ein Klick auf den ausgewählten NPC startet die Quest - selectStarterNPCPool: '§c⚠: Eine Questgruppe ist ausgewählt' - setCheckpointReward: '§eBearbeite Checkpoint Belohnungen' - setItemsRewards: '§eBelohnungs‐Items bearbeiten' - setMoneyReward: '§eGeldbelohnung bearbeiten' - setPermReward: '§eBerechtigungen bearbeiten' - setRewardStopQuest: '§cQuest stoppen' - setRewardsRandom: '§dZufällige Belohnungen' - setRewardsWithRequirements: '§eBelohnungen mit Voraussetzungen' - setTitleReward: '§eTitelbelohnung bearbeiten' - setWaitReward: '§e"Warte"-Belohnung bearbeiten' - setXPRewards: '§eBelohnungserfahrungspunkte bearbeiten' - startDialog: '§eStart‐Dialog bearbeiten' - startDialogLore: Dialog, der vor dem Start der Quests angezeigt wird, wenn Spieler auf den Starter NPC klicken. - startMessage: '§eStartnachricht bearbeiten' - startMessageLore: Nachricht, die am Anfang der Quest an den Spieler gesendet wird. - startRewards: '§6Startbelohnungen' - startRewardsLore: Aktionen die durchgeführt werden wenn die Quest startet. - startableFromGUI: Über GUI startbar - startableFromGUILore: Ermöglicht dem Spieler, die Quest aus dem Quest-Menü zu starten. - timer: '§bNeustart Timer' - timerLore: Zeit, bis der Spieler die Quest wieder starten kann. - visibility: '§bQuest Sichtbarkeit' - visibilityLore: Legen Sie fest, in welchen Tabs des Menüs die Quest angezeigt wird und ob die Quest auf dynamischen Karten sichtbar ist. - editTitle: - fadeIn: '§aEinblendedauer' - fadeOut: '§aAusblendedauer' - name: Titel bearbeiten - stay: '§bEinblendedauer' - subtitle: '§eUntertitel' - title: '§6Titel' - entityType: - name: Objekttyp auswählen - factionsList.name: Fraktionsliste - factionsRequired.name: Fraktionen benötigt - itemComparisons: - bukkit: Bukkit nativer Vergleich - bukkitLore: Nutzt das Standard Bukkit Gegenstandsvergleichsystem. Vergleicht Material, Haltbarkeit, NBT Tags... - customBukkit: Bukkit nativer Vergleich - KEIN NBT - customBukkitLore: Nutzt das Standard Bukkit Gegenstandsvergleichsystem, aber löscht NBT Tags. Vergleicht Material, Haltbarkeit... - enchants: Gegenstände verzaubert - enchantsLore: Vergleicht Gegenstandsverzauberungen - itemLore: Gegenstands-Beschreibung - itemLoreLore: Vergleicht Gegenstands-Beschreibungen - itemName: Gegenstandsname - itemNameLore: Vergleicht Gegenstandsnamen - itemsAdder: ItemsAdder - itemsAdderLore: Vergleicht ItemsAdder-IDs - material: Gegenstandsmaterial - materialLore: Vergleicht Gegenstandsmaterial (z.B Stein, Eisenschwert...) - name: Itemvergleiche - repairCost: Reparaturkosten - repairCostLore: Vergleicht Reparaturkosten für Rüstungen und Schwerter - itemCreator: - isQuestItem: '§bQuest‐Item:' - itemFlags: Item‐Flags umschalten - itemLore: '§bItem‐Beschreibung' - itemName: '§bItem‐Name' - itemType: '§bItem‐Typ' - name: Item‐Ersteller - itemSelect: - name: Item auswählen - itemsSelect: - name: Items bearbeiten - none: '§aBewege ein Item hierher oder klicke, um den Item‐Editor zu öffnen.' - listAllQuests: - name: Quests - listBook: - noQuests: Es wurden zuvor keine Quests erstellt. - questMultiple: Mehrfachverwendung - questName: Name - questRewards: Belohnungen - questStages: Schritte - questStarter: Starter - requirements: Vorraussetzungen - listPlayerQuests: - name: 'Quests von {player_name}' - listQuests: - canRedo: '§3§oDu kannst diese Quest erneut starten!' - finished: Abgeschlossene Quests - inProgress: Laufende Quests - loreCancelClick: '§cQuest abbrechen' - loreDialogsHistoryClick: '§7Dialoge anzeigen' - loreStart: '§a§oKlicke, um die Quest zu starten.' - loreStartUnavailable: '§c§oDu erfüllst nicht die Anforderungen, um die Quest zu starten.' - notStarted: Nicht gestartete Quests - timeToWaitRedo: '§3§oDu kannst diese Quest in {time_left} erneut starten.' - timesFinished: '§3Quest {times_finished} mal(e) erledigt.' - mobSelect: - boss: '§6Wähle einen Boss' - bukkitEntityType: '§eObjekttyp auswählen' - epicBoss: '§6Wähle einen Epic Boss' - mythicMob: '§6Mythic Mob auswählen' - name: Wähle den Mobtyp - mobs: - name: Mobs auswählen - none: '§aKlicke, um ein Mob hinzuzufügen.' - setLevel: Mindestlevel festlegen - npcCreate: - move: - itemLore: '§aDie NPC‐Position ändern.' - itemName: '§eBewegen' - moveItem: '§a§lPosition bestätigen' - name: NPC erstellen - setName: '§eNPC‐Name bearbeiten' - setSkin: '§eNPC‐Skin bearbeiten' - setType: '§eNPC‐Typ bearbeiten' - npcSelect: - createStageNPC: '§eNPC erstellen' - name: Auswählen oder erstellen? - selectStageNPC: '§eExistierenden NPC auswählen' - particleEffect: - color: '§bPartikelfarbe' - name: Erstelle einen Partikeleffekt - shape: '§dPartikel Muster' - type: '§ePartikel Typ' - particleList: - colored: Farbige Partikel - name: Partikel Liste - permission: - name: Berechtigung auswählen - perm: '§aBerechtigung' - remove: Berechtigung entfernen - removeLore: '§7Berechtigung wird genommen\n§7statt zu geben.' - world: '§aWelt' - worldGlobal: '§b§lGlobal' - permissionList: - name: Berechtigungsliste - removed: '§eGenommen: §6{permission_removed}' - world: '§eWelt: §6{permission_world}' - poolCreation: - avoidDuplicates: Duplikate vermeiden - avoidDuplicatesLore: '§8> §7Versuche es zu vermeiden,\n immer wieder die gleiche Quest zu absolvieren' - hologramText: '§eBenutzerdefiniertes Hologramm der Gruppe' - maxQuests: '§aMax. Quests' - name: Questgruppen Erstellung - questsPerLaunch: '§aPro Start gestartete Quests' - redoAllowed: Ist Wiederholen erlaubt - requirements: '§bAnforderungen, um eine Quest zu starten' - time: '§bLege die Zeit zwischen Quests fest' - poolsList.name: Questgruppen - poolsManage: - choose: '§e> §6§oWähle diese Gruppe §e<' - create: '§aErstelle eine Questgruppe' - edit: '§e> §6§oBearbeite die Gruppe... §e<' - itemName: '§aGruppe #{pool}' - name: Questgruppen - poolAvoidDuplicates: '§8Duplikate vermeiden: §7{pool_duplicates}' - poolHologram: '§8Hologramm-Text: §7{pool_hologram}' - poolMaxQuests: '§8Max. Quests: §7{pool_max_quests}' - poolQuestsList: '§7{pool_quests_amount} §8Quest(s): §7{pool_quests}' - poolQuestsPerLaunch: '§8Quests pro Start vergeben: §7{pool_quests_per_launch}' - poolRedo: '§8Kann abgeschlossene Quests wiederholen: §7{pool_redo}' - poolTime: '§8Zeit zwischen Quests: §7{pool_time}' - requirements: - name: Anforderungen - rewards: - commands: 'Befehle: {amount}' - name: Belohnungen - random: - minMax: Bearbeite das min und max - rewards: Belohnungen bearbeiten - rewardsWithRequirements: - name: Belohnungen mit Voraussetzungen - search: '§e§lSuche' - stageEnding: - command: '§eAuszuführenden Befehl bearbeiten' - locationTeleport: '§eTeleportationsposition bearbeiten' - stages: - branchesPage: '§dZweig‐Schritte' - descriptionTextItem: '§eBeschreibung bearbeiten' - endingItem: '§eAbschlussbelohnung bearbeiten' - laterPage: '§eVorherige Seite' - name: Schritte erstellen - newBranch: '§eZum neuen Zweig gehen' - nextPage: '§eNächste Seite' - previousBranch: '§eZurück zum vorherigen Zweig' - regularPage: '§aReguläre Schritte' - validationRequirements: '§eValidierungsanforderungen' - validationRequirementsLore: Alle Anforderungen müssen dem Spieler entsprechen, der versucht, den Schritt zu beenden. Ist dies nicht der Fall, kann der Schritt nicht beendet werden. - validate: '§b§lBestätigen' -misc: - amount: '§eAnzahl: {amount}' - and: und - bucket: - lava: Lavaeimer - milk: Milcheimer - water: Wassereimer - click: - left: Linksklick - middle: Mittelklick - right: Rechtsklick - shift-left: Shift-Linksklick - shift-right: Shift-Rechtsklick - comparison: - different: anders als {number} - equals: gleich wie {number} - greater: strikt größer als {number} - greaterOrEquals: größer als {number} - less: strikt weniger als {number} - lessOrEquals: weniger als {number} - disabled: Deaktiviert - enabled: Aktiviert - entityType: '§eObjekttyp: {entity_type}' - entityTypeAny: '§eJedes Objekt' - format: - editorPrefix: '§a' - prefix: '§6<§e§lQuests§r§6> §r' - hologramText: '§8§lQuest‐NPC' - 'no': 'Nein' - notSet: '§cnicht gesetzt' - or: oder - poolHologramText: '§eNeue Quest verfügbar!' - questItemLore: '§e§oQuest‐Item' - removeRaw: Entfernen - requirement: - class: '§bBenötigte Klasse(n)' - combatLevel: '§bKampflevel benötigt' - experienceLevel: '§bErfahrungslevel benötigt' - faction: '§bBenötigte Fraktion(en)' - jobLevel: '§bJob‐Level benötigt' - logicalOr: '§dLogisch ODER (Voraussetzungen)' - mcMMOSkillLevel: '§dBenötigtes Fertigkeitslevel' - money: '§dGeld benötigt' - permissions: '§3Benötigte Berechtigung(en)' - placeholder: '§bPlatzhalter‐Wert benötigt' - quest: '§aQuest benötigt' - region: '§dRegion erforderlich' - scoreboard: '§dPunktestand erforderlich' - skillAPILevel: '§bAPI-Level benötigt' - stageType: - Bucket: Eimer befüllen - Craft: Item herstellen - Fish: Fische fangen - breedAnimals: Züchte Tiere - chat: Im Chat schreiben - interact: Mit Block interagieren - items: Items zurückbringen - location: Position finden - mine: Blöcke zerstören - mobs: Mobs töten - npc: NPC finden - placeBlocks: Blöcke platzieren - playTime: Spielzeit - region: Region finden - tameAnimals: Zähme Tiere - ticks: '{ticks} Ticks' - time: - days: '{days_amount} Tage' - hours: '{hours_amount} Stunden' - lessThanAMinute: weniger als eine Minute - minutes: '{minutes_amount} Minuten' - weeks: '{weeks_amount} Wochen' - unknown: unbekannt - 'yes': 'Ja' msg: + quest: + finished: + base: '§aGlückwunsch! Du hast die Quest §e{quest_name}§a abgeschlossen!' + obtain: '§aDu erhälst {rewards}!' + started: '§aDu hast die Quest §r§e{quest_name}§o§6 gestartet!' + created: '§aGlückwunsch! Du hast die Quest §e{quest}§a mit {quest_branches} Zweig(en) erstellt!' + edited: '§aGlückwunsch! Du hast die Quest §e{quest}§a bearbeitet, die jetzt {quest_branches} Zweig(e) enthält!' + createCancelled: '§cDie Erstellung oder Bearbeitung wurde von einem anderen Plugin abgebrochen!' + cancelling: '§cErstellung der Quest abgebrochen.' + editCancelling: '§cBearbeitung der Quest abgebrochen.' + invalidID: '§cDie Quest mit der ID {quest_id} existiert nicht.' + invalidPoolID: '§cDie Gruppe {pool_id} existiert nicht.' + alreadyStarted: '§cDu hast die Quest bereits gestartet!' + notStarted: '§cDu machst diese Quest momentan nicht.' + quests: + maxLaunched: '§cDu kannst nicht mehr als {quests_max_amount} Quest(s) gleichzeitig haben...' + updated: '§7Quest §e{quest_name}§7 aktualisiert.' + checkpoint: '§7Quest-Checkpoint erreicht!' + failed: '§cDu hast die Quest {quest_name} fehlgeschlagen...' + pools: + noTime: '§cDu musst warten, bevor du eine andere Quest absolvieren kannst.' + allCompleted: '§7Du hast alle Quests abgeschlossen!' + noAvailable: '§7Es ist keine Quest mehr verfügbar...' + maxQuests: '§cDu kannst nicht mehr als {pool_max_quests} Quest(s) gleichzeitig haben...' + questItem: + drop: '§cDu kannst einen Questgegenstand nicht fallen lassen!' + craft: '§cDu kannst keinen Questgegenstand zum Craften verwenden!' + eat: Du kannst Quest Items nicht Essen! + stageMobs: + listMobs: '§aDu musst {mobs} töten.' + writeNPCText: '§aSchreibe den Dialog, den der NPC mit dem Spieler führt: (Schreibe „help”, um Hilfe zu erhalten.)' + writeRegionName: '§aSchreibe den für den Schritt benötigten Namen der Region:' + writeXPGain: '§aSchreibe die Menge an Erfahrungspunkten, die der Spieler erhalten wird: (Letzter Wert: {xp_amount})' + writeMobAmount: '§aSchreibe die zu tötende Mob‐Menge:' + writeMobName: '§aSchreibe den benutzerdefinierten Namen des zu tötenden Mobs:' + writeMessage: '§aSchreibe die Nachricht die an den Spieler gesendet wird' + writeStartMessage: '§aSchreibe die Nachricht, die zu Beginn der Quest gesendet wird, "null", wenn du die Standardnachricht wünschst, oder "none", wenn du dir keine Nachricht wünschst:' + writeEndSound: '§aSchreibe den Tonnamen, der am Ende der Quest dem Spieler abgespielt wird, "null" wenn Sie die Standardeinstellung oder "keine" wollen, wenn Sie keine wollen:' + writeDescriptionText: '§aSchreibe einen Text, der das Ziel des Schrittes beschreibt:' + writeStageText: '§aSchreibe den am Anfang des Schrittes zum Spieler gesendete Text:' + moveToTeleportPoint: '§aGehe zur gewünschten Teleportationsposition.' + writeNpcName: '§aSchreibe den Namen des NPCs:' + writeNpcSkinName: '§aSchreibe den Namen des NPC‐Skins:' + writeQuestName: '§a Schreibe den Namen der Quest:' + writeHologramText: '§aSchreibe den Text des Hologramms: (Schreibe „none”, wenn du kein Hologramm haben möchtest und „null”, wenn du den Standard‐Text verwenden willst.)' + writeQuestTimer: '§aSchreibe die benötigte Zeit (in Minuten), bevor ein Spieler die Quest erneut starten kann: (Schreibe „null“, wenn der Standard‐Timer verwendet werden soll.)' + writeConfirmMessage: '§aSchreibe die Bestätigungsnachricht, die beim Startversuch der Quest dem Spieler gezeigt wird: (Schreibe „null“, wenn die Standard‐Nachricht verwendet werden soll.)' + writeQuestDescription: '§aGebe die Beschreibung der Quest ein, welche in der Quest-GUI des Spielers angezeigt werden soll.' + writeQuestMaterial: '§aSchreibe das Material des Questgegenstandes.' + requirements: + quest: '§cDu musst die Quest §e{quest_name}§c abgeschlossen haben!' + level: '§cDein Level muss {long_level} sein!' + job: '§cDein Level für den Job §e{job_name}§c muss {long_level} sein!' + skill: '§cDein Level für die Fertigkeit §e{skill_name}§c muss {long_level} sein!' + combatLevel: '§cDein Kampflevel muss {long_level} sein!' + money: '§cDu benötigst {money}!' + waitTime: '§cDu musst {time_left} warten, bevor du die Quest erneut starten kannst!' + experience: + edited: '§aDu hast die Erfahrungsgewinnung von {old_xp_amount} auf {xp_amount} Punkt(e) gesetzt.' + selectNPCToKill: '§aWähle den zu tötenden NPC.' + regionDoesntExists: '§cDie Region existiert nicht. (Du musst dich in der selben Welt befinden.)' + npcDoesntExist: '§cDer NPC mit der ID {npc_id} existiert nicht.' + number: + negative: '§cDu musst eine positive Zahl eingeben!' + zero: '§cDie Zahl darf nicht 0 sein!' + invalid: '§c{input} ist keine gültige Zahl.' + notInBounds: '§cDeine Zahl muss zwischen {min} und {max} liegen.' + errorOccurred: '§cEin Fehler ist aufgetreten; kontaktiere einen Administrator! §4§lFehlercode: {error}' + indexOutOfBounds: '§cDie Zahl {index} ist außerhalb der Grenze! Sie muss zwischen {min} und {max} liegen.' + invalidBlockData: '§cDie Blockdaten {block_data} sind ungültig oder inkompatibel mit dem Block {block_material}.' + invalidBlockTag: '§cNicht verfügbarer Blocktag {block_tag}.' bringBackObjects: Bring mir {items} zurück. + inventoryFull: '§cDein Inventar ist voll, das Item wurde auf den Boden gelegt.' + versionRequired: 'Benötigte Version: §l{version}' + restartServer: '§7Starte deinen Server neu, um die Änderungen zu sehen.' + dialogs: + skipped: 'Dialog übersprungen.' + tooFar: '§7§oDu bist zu weit von {npc_name}...' command: - adminModeEntered: '§aDu hast den Admin‐Modus betreten.' - adminModeLeft: '§aDu hast den Admin‐Modus verlassen.' - backupCreated: '§6Du hast erfolgreich Sicherungen aller Quests und Spielerinformationen erstellt.' - backupPlayersFailed: '§cDas Sichern von allen Spielerinformationen ist fehlgeschlagen.' - backupQuestsFailed: '§cDas Sichern von allen Quests ist fehlgeschlagen.' - cancelQuest: '§6Du hast die Quest {quest} abgebrochen.' - cancelQuestUnavailable: '§cDie Quest {quest} kann nicht abgebrochen werden.' - checkpoint: - noCheckpoint: '§cKein Checkpoint für die Quest {quest} gefunden.' - questNotStarted: '§cDu machst diese Quest nicht.' downloadTranslations: - downloaded: '§aSprache {lang} wurde heruntergeladen! §7Du musst nun die Datei "/plugins/BeautyQuests/config.yml" bearbeiten, um den Wert von §ominecraftTranslationsFile§7 mit {lang} zu ändern. Der Server muss anschliessend neu gestartet werden.' - exists: '§cDie Datei {file_name} existiert bereits. Füge "-Overwrite "true" an deinen Befehl an, um ihn zu überschreiben. (/quests downloadTranslations <lang> -overwrite true)' - notFound: '§cSprache {lang} nicht gefunden für die Version {version}.' syntax: '§cDu musst eine Sprache auswählen zum downloaden. Beispiel: "/quests downloadTranslations en_US".' - help: - adminMode: '§6/{label} adminMode: §eSchalte den Admin‐Modus (für die Anzeige von Protokollnachrichten) für dich um.' - create: '§6/{label} create: §eErstelle eine Quest.' - downloadTranslations: '§6/{label} heruntergeladene Übersetzung <language>: §eDownloads einer Vanille-Übersetzungsdatei' - edit: '§6/{label} edit: §eBearbeite eine Quest.' - finishAll: '§6/{label} finishAll <Spieler>: §eBeende alle Quests eines Spielers.' - header: '§6§lBeautyQuests — Hilfe' - list: '§6/{label} list: §eSieh dir die Questliste an. (Funktioniert nur bei unterstützten Versionen.)' - reload: '§6/{label} reload: §eSpeichere und und lade alle Konfigurationen und Dateien neu. (§cveraltet§e)' - remove: '§6/{label} remove <ID>: §eLösche eine Quest mit der angegebenen ID oder klicke auf den NPC, wenn nicht definiert.' - resetPlayer: '§6/{label} resetPlayer <Spieler>: §eEntferne alle Informationen eines Spielers.' - resetPlayerQuest: '§6/{label} resetPlayerQuest <Spieler> [ID]: §eLösche Informationen einer Quest für einen Spieler.' - save: '§6/{label} save: §eFühre eine manuelle Plugin‐Speicherung durch.' - seePlayer: '§6/{label} seePlayer <Spieler>: §eSieh dir die Informationen eines Spielers an.' - setFirework: '§6/{label} SetFeuerwerk: §eBearbeite das standardmäßig end Feuerwerk.' - setItem: '§6/{label} setItem <talk|launch>: §eSpeichere das Hologramm‐Item.' - setStage: '§6/{label} setStage <Spieler> <ID> [neuer Zweig] [neuer Schritt]: §eÜberspringe den aktuellen Schritt/starte einen Zweig/setze einen Schritt für einen Zweig.' - start: '§6/{label} start <Spieler> [ID]: §eErzwinge das Starten einer Quest.' - startDialog: '§6/{label} startDialog <player> <quest id>: §eStartet den ausstehenden Dialog für eine NPC-Stufe oder den Startdialog für eine Quest.' - version: '§6/{label} version: §eLass dir die aktuelle Plugin‐Version anzeigen.' - invalidCommand: - simple: '§cDieser Befehl existiert nicht, schreibe §ehelp§c.' - itemChanged: '§aDas Item wurde bearbeitet. Die Änderungen werden nach einem Neustart angewendet.' - itemRemoved: '§aDas Hologramm‐Item wurde entfernt.' - leaveAll: '§aDu hast das Ende von {success} Quest(s) erzwungen. Fehler: {errors}' - removed: '§aDie Quest {quest_name} wurde erfolgreich entfernt.' - resetPlayer: - player: '§6Alle Informationen deiner {quest_amount} Quest(s) wurde/wurden von {deleter_name} gelöscht.' - remover: '§6{quest_amount} Questinformation(en) (und {quest_pool} Gruppen) von {player} wurde(n) gelöscht.' - resetPlayerPool: - full: '§aDu hast die {pool} Gruppendaten auf {player} zurückgesetzt.' - timer: '§aDu hast den {pool} Gruppentimer auf {player} zurückgesetzt.' - resetPlayerQuest: - player: '§6Alle Informationen über die Quest {quest} wurden von {deleter_name} gelöscht.' - remover: '§6{player} Questinformation(en) von {quest} wurde(n) gelöscht.' - resetQuest: '§6Quest Daten wurden für {player_amount} Spieler entfernt.' - scoreboard: - hidden: '§6Das Scoreboard des Spielers {player_name} wurde versteckt.' - lineInexistant: '§cDie Zeile {line_id} existiert nicht.' - lineRemoved: '§6Du hast die Zeile {line_id} erfolgreich entfernt.' - lineReset: '§6Du hast die Zeile {line_id} erfolgreich zurückgesetzt.' - lineSet: '§6Du hast die Zeile {line_id} erfolgreich bearbeitet.' - own: - hidden: '§6Dein Scoreboard ist jetzt versteckt.' - shown: Dein Scoreboard wird wieder angezeigt. - resetAll: '§6Du hast das Scoreboard des Spielers {player_name} erfolgreich zurückgesetzt.' - shown: '§6Das Scoreboard des Spielers {player_name} wurde angezeigt.' + notFound: '§cSprache {lang} nicht gefunden für die Version {version}.' + exists: '§cDie Datei {file_name} existiert bereits. Füge "-Overwrite "true" an deinen Befehl an, um ihn zu überschreiben. (/quests downloadTranslations <lang> -overwrite true)' + downloaded: '§aSprache {lang} wurde heruntergeladen! §7Du musst nun die Datei "/plugins/BeautyQuests/config.yml" bearbeiten, um den Wert von §ominecraftTranslationsFile§7 mit {lang} zu ändern. Der Server muss anschliessend neu gestartet werden.' + checkpoint: + noCheckpoint: '§cKein Checkpoint für die Quest {quest} gefunden.' + questNotStarted: '§cDu machst diese Quest nicht.' setStage: branchDoesntExist: '§cDer Zweig mit der ID {branch_id} existiert nicht.' doesntExist: '§cDer Schritt mit der ID {stage_id} existiert nicht.' @@ -521,245 +94,674 @@ msg: nextUnavailable: '§cDie „Überspringen“‐Option ist nicht verfügbar, wenn der Spieler am Ende eines Zweiges ist.' set: '§aSchritt {stage_id} gestartet.' startDialog: - alreadyIn: '§cDer Spieler spielt bereits einen Dialog.' impossible: '§cKann den Dialog jetzt nicht starten.' noDialog: '§cDer Spieler hat keinen ausstehenden Dialog.' + alreadyIn: '§cDer Spieler spielt bereits einen Dialog.' success: '§aStartete Dialog für Spieler {player} in Quest {quest}!' + invalidCommand: + simple: '§cDieser Befehl existiert nicht, schreibe §ehelp§c.' + itemChanged: '§aDas Item wurde bearbeitet. Die Änderungen werden nach einem Neustart angewendet.' + itemRemoved: '§aDas Hologramm‐Item wurde entfernt.' + removed: '§aDie Quest {quest_name} wurde erfolgreich entfernt.' + leaveAll: '§aDu hast das Ende von {success} Quest(s) erzwungen. Fehler: {errors}' + resetPlayer: + player: '§6Alle Informationen deiner {quest_amount} Quest(s) wurde/wurden von {deleter_name} gelöscht.' + remover: '§6{quest_amount} Questinformation(en) (und {quest_pool} Gruppen) von {player} wurde(n) gelöscht.' + resetPlayerQuest: + player: '§6Alle Informationen über die Quest {quest} wurden von {deleter_name} gelöscht.' + remover: '§6{player} Questinformation(en) von {quest} wurde(n) gelöscht.' + resetQuest: '§6Quest Daten wurden für {player_amount} Spieler entfernt.' + startQuestNoRequirements: '§cDer Spieler erfüllt nicht die Anforderungen für die Quest {quest}... Füge "-OverrideRequirements am Ende deines Befehls hinzu, um die Anforderungsüberprüfung zu umgehen.' + cancelQuest: '§6Du hast die Quest {quest} abgebrochen.' + cancelQuestUnavailable: '§cDie Quest {quest} kann nicht abgebrochen werden.' + backupCreated: '§6Du hast erfolgreich Sicherungen aller Quests und Spielerinformationen erstellt.' + backupPlayersFailed: '§cDas Sichern von allen Spielerinformationen ist fehlgeschlagen.' + backupQuestsFailed: '§cDas Sichern von allen Quests ist fehlgeschlagen.' + adminModeEntered: '§aDu hast den Admin‐Modus betreten.' + adminModeLeft: '§aDu hast den Admin‐Modus verlassen.' + resetPlayerPool: + timer: '§aDu hast den {pool} Gruppentimer auf {player} zurückgesetzt.' + full: '§aDu hast die {pool} Gruppendaten auf {player} zurückgesetzt.' startPlayerPool: - error: Der Pool {pool} für {player} konnte nicht gestartet werden. + error: 'Der Pool {pool} für {player} konnte nicht gestartet werden.' success: 'Pool {pool} bis {player}gestartet. Ergebnis: {result}' - startQuest: '§6Du hast den Start der Quest {quest} erzwungen. (Spieler‐UUID: {player})' - startQuestNoRequirements: '§cDer Spieler erfüllt nicht die Anforderungen für die Quest {quest}... Füge "-OverrideRequirements am Ende deines Befehls hinzu, um die Anforderungsüberprüfung zu umgehen.' - dialogs: - skipped: Dialog übersprungen. - tooFar: '§7§oDu bist zu weit von {npc_name}...' + scoreboard: + lineSet: '§6Du hast die Zeile {line_id} erfolgreich bearbeitet.' + lineReset: '§6Du hast die Zeile {line_id} erfolgreich zurückgesetzt.' + lineRemoved: '§6Du hast die Zeile {line_id} erfolgreich entfernt.' + lineInexistant: '§cDie Zeile {line_id} existiert nicht.' + resetAll: '§6Du hast das Scoreboard des Spielers {player_name} erfolgreich zurückgesetzt.' + hidden: '§6Das Scoreboard des Spielers {player_name} wurde versteckt.' + shown: '§6Das Scoreboard des Spielers {player_name} wurde angezeigt.' + own: + hidden: '§6Dein Scoreboard ist jetzt versteckt.' + shown: Dein Scoreboard wird wieder angezeigt. + help: + header: '§6§lBeautyQuests — Hilfe' + create: '§6/{label} create: §eErstelle eine Quest.' + edit: '§6/{label} edit: §eBearbeite eine Quest.' + remove: '§6/{label} remove <ID>: §eLösche eine Quest mit der angegebenen ID oder klicke auf den NPC, wenn nicht definiert.' + finishAll: '§6/{label} finishAll <Spieler>: §eBeende alle Quests eines Spielers.' + setStage: '§6/{label} setStage <Spieler> <ID> [neuer Zweig] [neuer Schritt]: §eÜberspringe den aktuellen Schritt/starte einen Zweig/setze einen Schritt für einen Zweig.' + startDialog: '§6/{label} startDialog <player> <quest id>: §eStartet den ausstehenden Dialog für eine NPC-Stufe oder den Startdialog für eine Quest.' + resetPlayer: '§6/{label} resetPlayer <Spieler>: §eEntferne alle Informationen eines Spielers.' + resetPlayerQuest: '§6/{label} resetPlayerQuest <Spieler> [ID]: §eLösche Informationen einer Quest für einen Spieler.' + seePlayer: '§6/{label} seePlayer <Spieler>: §eSieh dir die Informationen eines Spielers an.' + reload: '§6/{label} reload: §eSpeichere und und lade alle Konfigurationen und Dateien neu. (§cveraltet§e)' + start: '§6/{label} start <Spieler> [ID]: §eErzwinge das Starten einer Quest.' + setItem: '§6/{label} setItem <talk|launch>: §eSpeichere das Hologramm‐Item.' + setFirework: '§6/{label} SetFeuerwerk: §eBearbeite das standardmäßig end Feuerwerk.' + adminMode: '§6/{label} adminMode: §eSchalte den Admin‐Modus (für die Anzeige von Protokollnachrichten) für dich um.' + version: '§6/{label} version: §eLass dir die aktuelle Plugin‐Version anzeigen.' + downloadTranslations: '§6/{label} heruntergeladene Übersetzung <language>: §eDownloads einer Vanille-Übersetzungsdatei' + save: '§6/{label} save: §eFühre eine manuelle Plugin‐Speicherung durch.' + list: '§6/{label} list: §eSieh dir die Questliste an. (Funktioniert nur bei unterstützten Versionen.)' + typeCancel: '§aSchreibe „cancel“, um zum letzten Text zurückzukehren.' editor: - advancedSpawnersMob: 'Schreibe den Namen des benutzerdefinierten Spawnermob zum Töten:' - already: '§cDu befindest dich bereits im Editor.' - availableElements: 'Verfügbare Elemente: §e{available_elements}' blockAmount: '§aSchreibe die Anzahl der Blöcke:' - blockData: '§aSchreibe die Blockdaten (verfügbare Blockdaten: {available_datas}):' blockName: '§aSchreibe den Namen des Blocks:' + blockData: '§aSchreibe die Blockdaten (verfügbare Blockdaten: {available_datas}):' blockTag: '§aSchreibe den Blocktag (verfügbare Blocktags: §7{available_tags}§a):' + typeBucketAmount: '§aSchreibe die Anzahl an zu füllenden Eimern:' + typeDamageAmount: 'Schreibe die Menge an Schaden, die der Spieler zufügen muss:' + goToLocation: '§aGehe zur gewünschten Position für den Schritt.' + typeLocationRadius: '§aSchreibe die benötigte Distanz von der Position:' + typeGameTicks: '§aSchreibe die benötigten Spiel-Ticks:' + already: '§cDu befindest dich bereits im Editor.' + stage: + location: + typeWorldPattern: '§aSchreibe einen Regex für Weltnamen:' + enter: + title: '§6~ Editor‐Modus ~' + subtitle: '§6Schreibe „/quests exitEditor”, um das Verlassen zu erzwingen.' + list: '§c⚠ §7Du befindest dich in einem "Listen"-Editor. Verwende "add", um Zeilen hinzuzufügen. Siehe "help" (ohne Schrägstrich) für Hilfe. §e§lTippe "close", um den Editor zu verlassen.' chat: '§6Du bist zurzeit im Editor‐Modus. Schreibe „/quests exitEditor“, um das Verlassen des Editors zu erzwingen. (Nicht empfohlen, erwäge die Verwendung von Befehlen wie „close“ oder „cancel“, um zum vorherigen Inventar zurückzukehren.)' - color: 'Geben Sie eine Farbe im Hexadezimalformat (#XXXXX) oder RGB Format (RED GRE BLU) ein.' - colorNamed: Geben Sie den Namen einer Farbe ein. - comparisonTypeDefault: '§aWählen Sie den Vergleichstyp unter {available}aus. Der Standardvergleich ist: §e§l{default}§r§a. Geben Sie §onull§r§a ein, um ihn zu verwenden.' + npc: + enter: '§aKlicke auf einen NPC oder schreibe „cancel”.' + choseStarter: '§aWähle den NPC, der die Quest startet.' + notStarter: '§cDieser NPC ist kein Queststarter.' + text: + argNotSupported: '§cDas Argument {arg} wird nicht unterstützt.' + chooseLvlRequired: '§aSchreibe die Anzahl der benötigten Level:' + chooseJobRequired: '§aSchreibe den Namen des gewünschten Jobs:' + choosePermissionRequired: '§aSchreibe die benötigte Berechtigung, um die Quest zu starten:' + choosePermissionMessage: '§aDu kannst eine Verweigerungs‐Nachricht für Spieler ohne ausreichende Berechtigungen festlegen. (Um diesen Schritt zu überspringen, schreibe „null”.)' + choosePlaceholderRequired: + identifier: '§aSchreibe den Namen des benötigten Platzhalters ohne die Prozentzeichen:' + value: '§aSchreibe den erforderlichen Wert für den Platzhalter §e%§e{placeholder}§e%§a:' + chooseSkillRequired: '§aSchreibe den Namen der benötigten Fähigkeit:' + chooseMoneyRequired: '§aSchreibe die Menge an benötigtem Geld:' + reward: + permissionName: '§aGebe den Namen der Berechtigung ein.' + permissionWorld: '§aGebe die Welt an, in welcher die Berechtigung bearbeitet werden soll, oder "null" wenn es Global gelten soll.' + money: '§aSchreibe die zu bekommende Menge an Geld:' + wait: '§aSchreibe die Anzahl von Game Ticks, zum warten: (1 Sekunde = 20 Game Ticks)' + random: + min: '§aSchreibe die minimale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' + max: '§aSchreibe die maximale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' + chooseObjectiveRequired: '§aGebe den Namen des Ziels an.' + chooseObjectiveTargetScore: '§aGebe den benötigten Punktestand für das Ziel an.' + chooseRegionRequired: '§aSchreibe den Namen der benötigten Region (du musst in der gleichen Welt sein).' + selectWantedBlock: '§aKlicke mit dem Stock auf den gewünschten Block für diesen Schritt.' + itemCreator: + itemType: '§aSchreibe den Namen des gewünschten Items:' + itemAmount: '§aSchreibe die Menge des/der Item(s):' + itemName: '§aSchreibe den Item‐Namen:' + itemLore: '§aÄndere die Item‐Beschreibung: (Schreibe „help“ für Hilfe.)' + unknownItemType: '§cUnbekanntes Item.' + invalidItemType: '§cUngültiges Item. (Das Item darf kein Block sein.)' + unknownBlockType: '§cUnbekannter Blocktyp.' + invalidBlockType: '§cUngültiger Blocktyp.' dialog: - cleared: '§a{amount} entfernte Nachricht(en).' + syntaxRemove: '§cKorrekte Syntax: remove <ID>' + player: '§aNachricht "§7{msg}§a" für den Spieler hinzugefügt.' + npc: '§aNachricht "§7{msg}§a" für den NPC hinzugefügt.' + noSender: '§aNachricht "§7{msg}§a" ohne einen Absender hinzugefügt.' + messageRemoved: '§aNachricht "§7{msg}§a" entfernt.' edited: '§aNachricht "§7{msg}§a" bearbeitet.' + soundAdded: '§aTon "§7{sound}§a" für die Nachricht "§7{msg}§a" hinzugefügt.' + cleared: '§a{amount} entfernte Nachricht(en).' help: - addSound: '§6addSound <ID> <Geräusch>: §eFüge ein Geräusch einer Nachricht hinzu.' - clear: '§6clear: §eEntferne alle Nachrichten.' - close: '§6close: §eBestätige alle Nachrichten.' - edit: '§6edit <id> <message>: §eBearbeite eine Nachricht.' header: '§6§lBeautyQuests — Dialogbearbeitungs‐Hilfe' - list: '§6list: §eSchaue dir alle Nachrichten an.' - nothing: '§6noSender <Nachricht>: §eFüge eine Nachricht ohne Absender hinzu.' - nothingInsert: '§6nothingInsert <ID> <Nachricht>: §eFüge eine Nachricht ohne Präfix ein.' npc: '§6npc <Nachricht>: §eFüge eine vom NPC gesagte Nachricht hinzu.' - npcInsert: '§6npcInsert <ID> <Nachricht>: §eFüge eine vom NPC gesagte Nachricht ein.' - npcName: '§6npcName [benutzerdefinierter NPC-Name]: §eSetze (oder zurücksetzen auf Standard) des benutzerdefinierten Namens des NPCs im Dialog' player: '§6player <Nachricht>: §eFüge eine vom Spieler gesagte Nachricht hinzu.' - playerInsert: '§6playerInsert <ID> <Nachricht>: §eFüge eine vom Spieler gesagte Nachricht ein.' + nothing: '§6noSender <Nachricht>: §eFüge eine Nachricht ohne Absender hinzu.' remove: '§6remove <ID>: §eEntferne eine Nachricht.' + list: '§6list: §eSchaue dir alle Nachrichten an.' + npcInsert: '§6npcInsert <ID> <Nachricht>: §eFüge eine vom NPC gesagte Nachricht ein.' + playerInsert: '§6playerInsert <ID> <Nachricht>: §eFüge eine vom Spieler gesagte Nachricht ein.' + nothingInsert: '§6nothingInsert <ID> <Nachricht>: §eFüge eine Nachricht ohne Präfix ein.' + edit: '§6edit <id> <message>: §eBearbeite eine Nachricht.' + addSound: '§6addSound <ID> <Geräusch>: §eFüge ein Geräusch einer Nachricht hinzu.' + clear: '§6clear: §eEntferne alle Nachrichten.' + close: '§6close: §eBestätige alle Nachrichten.' setTime: '§6setTime <id> <time>: §eSetze die Zeit (in Ticks) bevor die nächste automatische Nachricht gesendet wird.' + npcName: '§6npcName [benutzerdefinierter NPC-Name]: §eSetze (oder zurücksetzen auf Standard) des benutzerdefinierten Namens des NPCs im Dialog' skippable: '§6Überspringbar [true|falsch]: §eLegen Sie fest, ob der Dialog übersprungen werden kann oder nicht' - messageRemoved: '§aNachricht "§7{msg}§a" entfernt.' - noSender: '§aNachricht "§7{msg}§a" ohne einen Absender hinzugefügt.' - npc: '§aNachricht "§7{msg}§a" für den NPC hinzugefügt.' + timeSet: '§aDie Zeit für die Nachricht {msg} wurde bearbeitet: jetzt {time} Ticks.' + timeRemoved: '§aDie Zeit wurde für die Nachricht {msg} entfernt.' npcName: set: '§aBenutzerdefinierter NPC-Name wurde zu §7{new_name}§a gesetzt (alter Name war §7{old_name}§a)' unset: '§aBenutzerdefinierter NPC-Name wurde auf Standard gesetzt (alter Name war §7{old_name}§a)' - player: '§aNachricht "§7{msg}§a" für den Spieler hinzugefügt.' skippable: set: '§aDer dialogbare Status ist nun auf §7{new_state}§a gesetzt (war §7{old_state}§a)' unset: '§aDer überspringbare Status wird auf Standard zurückgesetzt (war §7{old_state}§a)' - soundAdded: '§aTon "§7{sound}§a" für die Nachricht "§7{msg}§a" hinzugefügt.' - syntaxRemove: '§cKorrekte Syntax: remove <ID>' - timeRemoved: '§aDie Zeit wurde für die Nachricht {msg} entfernt.' - timeSet: '§aDie Zeit für die Nachricht {msg} wurde bearbeitet: jetzt {time} Ticks.' - enter: - list: '§c⚠ §7Du befindest dich in einem "Listen"-Editor. Verwende "add", um Zeilen hinzuzufügen. Siehe "help" (ohne Schrägstrich) für Hilfe. §e§lTippe "close", um den Editor zu verlassen.' - subtitle: '§6Schreibe „/quests exitEditor”, um das Verlassen zu erzwingen.' - title: '§6~ Editor‐Modus ~' - firework: - edited: Feuerwerk Quest bearbeitet! - invalid: Dieser Gegenstand ist kein gültiges Feuerwerk. - invalidHand: Du musst ein Feuerwerk in deiner Main Hand halten. - removed: Das Questfeuerwerk entfernt! - goToLocation: '§aGehe zur gewünschten Position für den Schritt.' - invalidColor: Die eingegebene Farbe ist ungültig. Sie muss entweder Hexadezimal- oder RGB sein. - invalidPattern: '§cUngültiges regex-Muster §4{input}§c.' - itemCreator: - invalidBlockType: '§cUngültiger Blocktyp.' - invalidItemType: '§cUngültiges Item. (Das Item darf kein Block sein.)' - itemAmount: '§aSchreibe die Menge des/der Item(s):' - itemLore: '§aÄndere die Item‐Beschreibung: (Schreibe „help“ für Hilfe.)' - itemName: '§aSchreibe den Item‐Namen:' - itemType: '§aSchreibe den Namen des gewünschten Items:' - unknownBlockType: '§cUnbekannter Blocktyp.' - unknownItemType: '§cUnbekanntes Item.' mythicmobs: - disabled: '§cMythicMob ist deaktiviert.' - isntMythicMob: '§cDieser Mythic Mob existiert nicht.' list: '§aEine Liste aller Mythic Mobs:' + isntMythicMob: '§cDieser Mythic Mob existiert nicht.' + disabled: '§cMythicMob ist deaktiviert.' + advancedSpawnersMob: 'Schreibe den Namen des benutzerdefinierten Spawnermob zum Töten:' + textList: + syntax: '§cKorrekte Syntax: ' + added: '§aText "§7{msg}§a" hinzugefügt.' + removed: '§aText "§7{msg}§a" entfernt.' + help: + header: '§6§lBeautyQuests — Listen‐Editor‐Hilfe' + add: '§6add <message>: §eFüge einen Text hinzu.' + remove: '§6remove <ID>: §eEntferne einen Text.' + list: '§6list: §eSieh dir alle hinzugefügten Texte an.' + close: '§6close: §eBestätige die hinzugefügten Texte.' + availableElements: 'Verfügbare Elemente: §e{available_elements}' noSuchElement: '§cDieses Element existiert nicht. Erlaubte Elemente sind: §e{available_elements}' - npc: - choseStarter: '§aWähle den NPC, der die Quest startet.' - enter: '§aKlicke auf einen NPC oder schreibe „cancel”.' - notStarter: '§cDieser NPC ist kein Queststarter.' + invalidPattern: '§cUngültiges regex-Muster §4{input}§c.' + comparisonTypeDefault: '§aWählen Sie den Vergleichstyp unter {available}aus. Der Standardvergleich ist: §e§l{default}§r§a. Geben Sie §onull§r§a ein, um ihn zu verwenden.' + scoreboardObjectiveNotFound: '§cUnbekanntes Scoreboard Ziel.' pool: - hologramText: Schreibe den benutzerdefinierten Hologramm-Text für diese Gruppe (oder "null", wenn du den Standardtext möchtest). - maxQuests: Lege die maximale Anzahl an Quests fest, die aus dieser Gruppe gestartet werden können. - questsPerLaunch: Schreibe die Anzahl der Quests, die du bei einem Klick auf den NPC erhalten hast. + hologramText: 'Schreibe den benutzerdefinierten Hologramm-Text für diese Gruppe (oder "null", wenn du den Standardtext möchtest).' + maxQuests: 'Lege die maximale Anzahl an Quests fest, die aus dieser Gruppe gestartet werden können.' + questsPerLaunch: 'Schreibe die Anzahl der Quests, die du bei einem Klick auf den NPC erhalten hast.' timeMsg: 'Schreibe die Zeit, bevor Spieler eine neue Quest annehmen können (Standardeinheit: Tage).' - scoreboardObjectiveNotFound: '§cUnbekanntes Scoreboard Ziel.' - selectWantedBlock: '§aKlicke mit dem Stock auf den gewünschten Block für diesen Schritt.' + title: + title: 'Schreibe den Titeltext (oder "null", wenn du keinen möchtest).' + subtitle: 'Schreibe den Untertiteltext (oder "null", wenn du keinen möchtest).' + fadeIn: 'Schreibe die "Einblende"-Dauer, in Ticks (20 ticks = 1 Sekunde).' + stay: 'Schreibe die "Bleibe"-Dauer, in Ticks (20 Ticks = 1 Sekunde).' + fadeOut: 'Schreibe die "Ausblende"-Dauer, in Ticks (20 ticks = 1 Sekunde).' + colorNamed: 'Geben Sie den Namen einer Farbe ein.' + color: 'Geben Sie eine Farbe im Hexadezimalformat (#XXXXX) oder RGB Format (RED GRE BLU) ein.' + invalidColor: 'Die eingegebene Farbe ist ungültig. Sie muss entweder Hexadezimal- oder RGB sein.' + firework: + invalid: 'Dieser Gegenstand ist kein gültiges Feuerwerk.' + invalidHand: 'Du musst ein Feuerwerk in deiner Main Hand halten.' + edited: 'Feuerwerk Quest bearbeitet!' + removed: 'Das Questfeuerwerk entfernt!' + writeCommandDelay: '§aGebe die gewünschte Befehl Verzögerung in Ticks an.' +advancement: + notStarted: Nicht gestartet +inv: + validate: '§b§lBestätigen' + cancel: '§c§lAbbrechen' + search: '§e§lSuche' + addObject: '§aFüge ein Ziel hinzu' + confirm: + name: Bist du sicher? + 'yes': '§aBestätigen' + 'no': '§cAbbrechen' + create: + stageCreate: '§aNeuen Schritt erstellen' + stageRemove: '§cDiesen Schritt löschen' + stageUp: Eins höher + stageDown: Eins runter + stageType: '§7Stufentyp: §e{stage_type}' + cantFinish: '§7Du musst mindestens eine Stufe erstellen, bevor du die Questerstellung fertigstellen kannst!' + findNPC: '§aNPC finden' + bringBack: '§aItems zurückbringen' + findRegion: '§aRegion finden' + killMobs: '§aMobs töten' + mineBlocks: '§aBlöcke zerstören' + placeBlocks: '§aPlatziere Blöcke' + talkChat: '§aIm Chat schreiben' + interact: '§aMit Block interagieren' + fish: '§aFische fangen' + melt: '§6Schmelze Elemente' + enchant: '§dVerzauberte Gegenstände' + craft: '§aItem herstellen' + bucket: '§aEimer befüllen' + location: '§aZu Position gehen' + playTime: '§eSpielzeit' + breedAnimals: '§aZüchte Tiere' + tameAnimals: '§aZähme Tiere' + death: '§csterben' + dealDamage: '§cSchaden an Mobs zufügen' + eatDrink: '§aEssen oder trinken Sie Essen oder Tränke' + NPCText: '§eDialog bearbeiten' + NPCSelect: '§eNPC auswählen oder erstellen' + hideClues: Partikel und Hologramme verstecken + editMobsKill: '§eDie zu tötenden Mobs bearbeiten' + mobsKillFromAFar: Muss mit Projektil getötet werden + editBlocksMine: '§eDie zu zerstörenden Blöcke bearbeiten' + preventBlockPlace: Spieler daran hindern, ihre eigenen Blöcke zu zerstören + editBlocksPlace: '§eDie zu plazierenden Blöcke bearbeiten' + editMessageType: '§eDie zu schreibende Nachricht bearbeiten' + cancelMessage: Senden abbrechen + ignoreCase: Fall der Nachricht ignorieren + selectItems: '§eBenötigte Items auswählen' + selectItemsMessage: '§eFragenachricht bearbeiten' + selectItemsComparisons: '§eWähle Gegenstandsvergleiche (ERWEITERT)' + selectRegion: '§7Region auswählen' + toggleRegionExit: Beim Verlassen + stageStartMsg: '§eStartnachricht bearbeiten' + selectBlockLocation: '§eBlockposition auswählen' + selectBlockMaterial: '§eWähle Blockmaterial' + leftClick: Muss Linksklick sein + editFishes: '§eDie zu fangenden Fische bearbeiten' + editItemsToMelt: '§eBearbeite Items zum Schmelzen' + editItemsToEnchant: '§eBearbeite Items zum Verzaubern' + editItem: '§eHerzustellendes Item bearbeiten' + editBucketType: '§eTyp des zu befüllenden Eimers bearbeiten' + editBucketAmount: '§eAnzahl an zu befüllenden Eimern bearbeiten' + editLocation: '§ePosition bearbeiten' + editRadius: '§eEntfernung von Position bearbeiten' + currentRadius: '§eAktuelle Entfernung: §6{radius}' + changeTicksRequired: '§eÄndere die erforderlichen gespielten Ticks' + changeEntityType: '§eObjekttyp ändern' stage: location: - typeWorldPattern: '§aSchreibe einen Regex für Weltnamen:' - text: - argNotSupported: '§cDas Argument {arg} wird nicht unterstützt.' - chooseJobRequired: '§aSchreibe den Namen des gewünschten Jobs:' - chooseLvlRequired: '§aSchreibe die Anzahl der benötigten Level:' - chooseMoneyRequired: '§aSchreibe die Menge an benötigtem Geld:' - chooseObjectiveRequired: '§aGebe den Namen des Ziels an.' - chooseObjectiveTargetScore: '§aGebe den benötigten Punktestand für das Ziel an.' - choosePermissionMessage: '§aDu kannst eine Verweigerungs‐Nachricht für Spieler ohne ausreichende Berechtigungen festlegen. (Um diesen Schritt zu überspringen, schreibe „null”.)' - choosePermissionRequired: '§aSchreibe die benötigte Berechtigung, um die Quest zu starten:' - choosePlaceholderRequired: - identifier: '§aSchreibe den Namen des benötigten Platzhalters ohne die Prozentzeichen:' - value: '§aSchreibe den erforderlichen Wert für den Platzhalter §e%§e{placeholder}§e%§a:' - chooseRegionRequired: '§aSchreibe den Namen der benötigten Region (du musst in der gleichen Welt sein).' - chooseSkillRequired: '§aSchreibe den Namen der benötigten Fähigkeit:' - reward: - money: '§aSchreibe die zu bekommende Menge an Geld:' - permissionName: '§aGebe den Namen der Berechtigung ein.' - permissionWorld: '§aGebe die Welt an, in welcher die Berechtigung bearbeitet werden soll, oder "null" wenn es Global gelten soll.' - random: - max: '§aSchreibe die maximale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' - min: '§aSchreibe die minimale Anzahl an Belohungen, die an einem Spieler gegeben werden (inklusive).' - wait: '§aSchreibe die Anzahl von Game Ticks, zum warten: (1 Sekunde = 20 Game Ticks)' - textList: - added: '§aText "§7{msg}§a" hinzugefügt.' - help: - add: '§6add <message>: §eFüge einen Text hinzu.' - close: '§6close: §eBestätige die hinzugefügten Texte.' - header: '§6§lBeautyQuests — Listen‐Editor‐Hilfe' - list: '§6list: §eSieh dir alle hinzugefügten Texte an.' - remove: '§6remove <ID>: §eEntferne einen Text.' - removed: '§aText "§7{msg}§a" entfernt.' - syntax: '§cKorrekte Syntax: ' - title: - fadeIn: Schreibe die "Einblende"-Dauer, in Ticks (20 ticks = 1 Sekunde). - fadeOut: Schreibe die "Ausblende"-Dauer, in Ticks (20 ticks = 1 Sekunde). - stay: Schreibe die "Bleibe"-Dauer, in Ticks (20 Ticks = 1 Sekunde). - subtitle: Schreibe den Untertiteltext (oder "null", wenn du keinen möchtest). - title: Schreibe den Titeltext (oder "null", wenn du keinen möchtest). - typeBucketAmount: '§aSchreibe die Anzahl an zu füllenden Eimern:' - typeDamageAmount: 'Schreibe die Menge an Schaden, die der Spieler zufügen muss:' - typeGameTicks: '§aSchreibe die benötigten Spiel-Ticks:' - typeLocationRadius: '§aSchreibe die benötigte Distanz von der Position:' - errorOccurred: '§cEin Fehler ist aufgetreten; kontaktiere einen Administrator! §4§lFehlercode: {error}' - experience: - edited: '§aDu hast die Erfahrungsgewinnung von {old_xp_amount} auf {xp_amount} Punkt(e) gesetzt.' - indexOutOfBounds: '§cDie Zahl {index} ist außerhalb der Grenze! Sie muss zwischen {min} und {max} liegen.' - invalidBlockData: '§cDie Blockdaten {block_data} sind ungültig oder inkompatibel mit dem Block {block_material}.' - invalidBlockTag: '§cNicht verfügbarer Blocktag {block_tag}.' - inventoryFull: '§cDein Inventar ist voll, das Item wurde auf den Boden gelegt.' - moveToTeleportPoint: '§aGehe zur gewünschten Teleportationsposition.' - npcDoesntExist: '§cDer NPC mit der ID {npc_id} existiert nicht.' - number: - invalid: '§c{input} ist keine gültige Zahl.' - negative: '§cDu musst eine positive Zahl eingeben!' - notInBounds: '§cDeine Zahl muss zwischen {min} und {max} liegen.' - zero: '§cDie Zahl darf nicht 0 sein!' - pools: - allCompleted: '§7Du hast alle Quests abgeschlossen!' - maxQuests: '§cDu kannst nicht mehr als {pool_max_quests} Quest(s) gleichzeitig haben...' - noAvailable: '§7Es ist keine Quest mehr verfügbar...' - noTime: '§cDu musst warten, bevor du eine andere Quest absolvieren kannst.' - quest: - alreadyStarted: '§cDu hast die Quest bereits gestartet!' - cancelling: '§cErstellung der Quest abgebrochen.' - createCancelled: '§cDie Erstellung oder Bearbeitung wurde von einem anderen Plugin abgebrochen!' - created: '§aGlückwunsch! Du hast die Quest §e{quest}§a mit {quest_branches} Zweig(en) erstellt!' - editCancelling: '§cBearbeitung der Quest abgebrochen.' - edited: '§aGlückwunsch! Du hast die Quest §e{quest}§a bearbeitet, die jetzt {quest_branches} Zweig(e) enthält!' - finished: - base: '§aGlückwunsch! Du hast die Quest §e{quest_name}§a abgeschlossen!' - obtain: '§aDu erhälst {rewards}!' - invalidID: '§cDie Quest mit der ID {quest_id} existiert nicht.' - invalidPoolID: '§cDie Gruppe {pool_id} existiert nicht.' - notStarted: '§cDu machst diese Quest momentan nicht.' - started: '§aDu hast die Quest §r§e{quest_name}§o§6 gestartet!' - questItem: - craft: '§cDu kannst keinen Questgegenstand zum Craften verwenden!' - drop: '§cDu kannst einen Questgegenstand nicht fallen lassen!' - eat: Du kannst Quest Items nicht Essen! - quests: - checkpoint: '§7Quest-Checkpoint erreicht!' - failed: '§cDu hast die Quest {quest_name} fehlgeschlagen...' - maxLaunched: '§cDu kannst nicht mehr als {quests_max_amount} Quest(s) gleichzeitig haben...' - updated: '§7Quest §e{quest_name}§7 aktualisiert.' - regionDoesntExists: '§cDie Region existiert nicht. (Du musst dich in der selben Welt befinden.)' - requirements: - combatLevel: '§cDein Kampflevel muss {long_level} sein!' - job: '§cDein Level für den Job §e{job_name}§c muss {long_level} sein!' - level: '§cDein Level muss {long_level} sein!' - money: '§cDu benötigst {money}!' - quest: '§cDu musst die Quest §e{quest_name}§c abgeschlossen haben!' - skill: '§cDein Level für die Fertigkeit §e{skill_name}§c muss {long_level} sein!' - waitTime: '§cDu musst {time_left} warten, bevor du die Quest erneut starten kannst!' - restartServer: '§7Starte deinen Server neu, um die Änderungen zu sehen.' - selectNPCToKill: '§aWähle den zu tötenden NPC.' - stageMobs: - listMobs: '§aDu musst {mobs} töten.' - typeCancel: '§aSchreibe „cancel“, um zum letzten Text zurückzukehren.' - versionRequired: 'Benötigte Version: §l{version}' - writeChatMessage: '§aSchreibe die benötigte Nachricht: (Füge „{SLASH}” zum Anfang hinzu, wenn du einen Befehl ausdrücken möchtest.)' - writeCommand: '§aSchreibe den gewünschten Befehl: (Den Befehl ohne den Schrägstrich schreiben. Unterstützter Platzhalter: „{PLAYER}“; welcher mit dem Namen des Spielers, der den Befehl ausgeführt hat, ersetzt wird.)' - writeCommandDelay: '§aGebe die gewünschte Befehl Verzögerung in Ticks an.' - writeConfirmMessage: '§aSchreibe die Bestätigungsnachricht, die beim Startversuch der Quest dem Spieler gezeigt wird: (Schreibe „null“, wenn die Standard‐Nachricht verwendet werden soll.)' - writeDescriptionText: '§aSchreibe einen Text, der das Ziel des Schrittes beschreibt:' - writeEndMsg: '§aSchreibe die Nachricht, die am Ende der Quest gesendet wird, "null", wenn du die Standardnachricht wünschst, oder "none", wenn du dir keine Nachricht wünschst. Du kannst "{rewards}" verwenden, das dann durch die erhaltenen Belohnungen ersetzt wird.' - writeEndSound: '§aSchreibe den Tonnamen, der am Ende der Quest dem Spieler abgespielt wird, "null" wenn Sie die Standardeinstellung oder "keine" wollen, wenn Sie keine wollen:' - writeHologramText: '§aSchreibe den Text des Hologramms: (Schreibe „none”, wenn du kein Hologramm haben möchtest und „null”, wenn du den Standard‐Text verwenden willst.)' - writeMessage: '§aSchreibe die Nachricht die an den Spieler gesendet wird' - writeMobAmount: '§aSchreibe die zu tötende Mob‐Menge:' - writeMobName: '§aSchreibe den benutzerdefinierten Namen des zu tötenden Mobs:' - writeNPCText: '§aSchreibe den Dialog, den der NPC mit dem Spieler führt: (Schreibe „help”, um Hilfe zu erhalten.)' - writeNpcName: '§aSchreibe den Namen des NPCs:' - writeNpcSkinName: '§aSchreibe den Namen des NPC‐Skins:' - writeQuestDescription: '§aGebe die Beschreibung der Quest ein, welche in der Quest-GUI des Spielers angezeigt werden soll.' - writeQuestMaterial: '§aSchreibe das Material des Questgegenstandes.' - writeQuestName: '§a Schreibe den Namen der Quest:' - writeQuestTimer: '§aSchreibe die benötigte Zeit (in Minuten), bevor ein Spieler die Quest erneut starten kann: (Schreibe „null“, wenn der Standard‐Timer verwendet werden soll.)' - writeRegionName: '§aSchreibe den für den Schritt benötigten Namen der Region:' - writeStageText: '§aSchreibe den am Anfang des Schrittes zum Spieler gesendete Text:' - writeStartMessage: '§aSchreibe die Nachricht, die zu Beginn der Quest gesendet wird, "null", wenn du die Standardnachricht wünschst, oder "none", wenn du dir keine Nachricht wünschst:' - writeXPGain: '§aSchreibe die Menge an Erfahrungspunkten, die der Spieler erhalten wird: (Letzter Wert: {xp_amount})' + worldPattern: '§aSetze Weltennamenmuster §d(FORTGESCHRITTEN)' + worldPatternLore: 'Wenn du möchtest, dass die Stage für eine Welt, die einem bestimmten Muster entspricht, abgeschlossen wird, gib hier einen Regex (regulärer Ausdruck) ein.' + death: + causes: '§aSetze Todesursache §d(FORTGESCHRITTEN)' + anyCause: Jede Todesursache + setCauses: '{causes_amount} Todesursache(n)' + dealDamage: + damage: '§eSchaden zu erledigen' + targetMobs: '§cMobs zu Schaden' + eatDrink: + items: '§eBearbeite Items um zu essen oder zu trinken' + stages: + name: Schritte erstellen + nextPage: '§eNächste Seite' + laterPage: '§eVorherige Seite' + endingItem: '§eAbschlussbelohnung bearbeiten' + descriptionTextItem: '§eBeschreibung bearbeiten' + regularPage: '§aReguläre Schritte' + branchesPage: '§dZweig‐Schritte' + previousBranch: '§eZurück zum vorherigen Zweig' + newBranch: '§eZum neuen Zweig gehen' + validationRequirements: '§eValidierungsanforderungen' + validationRequirementsLore: Alle Anforderungen müssen dem Spieler entsprechen, der versucht, den Schritt zu beenden. Ist dies nicht der Fall, kann der Schritt nicht beendet werden. + details: + hologramLaunch: '§e„Starten“‐Hologramm‐Item bearbeiten' + hologramLaunchLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest starten kann. + hologramLaunchNo: '§e„Starten nicht verfügbar“‐Hologramm‐Item bearbeiten' + hologramLaunchNoLore: Hologramm, das über dem Kopf des Starter NPCs angezeigt wird, wenn der Spieler die Quest NICHT starten kann. + customConfirmMessage: '§eQuestbestätigungsnachricht bearbeiten' + customConfirmMessageLore: Meldung, die in der Bestätigungs-GUI angezeigt wird, wenn ein Spieler die Quest startet. + customDescription: '§eBearbeite Quest Beschreibung' + customDescriptionLore: Beschreibung, die unter dem Namen der Quest in GUIs steht. + name: Letzte Questdetails + multipleTime: + itemName: Wiederholbar ein-/ausschalten + itemLore: Kann die Quest mehrmals abgeschlossen werden? + cancellable: Vom Spieler abbrechbar + cancellableLore: Ermöglicht dem Spieler, die Quest durch das Quest-Menü abzubrechen. + startableFromGUI: Über GUI startbar + startableFromGUILore: Ermöglicht dem Spieler, die Quest aus dem Quest-Menü zu starten. + scoreboardItem: Scoreboard aktivieren + scoreboardItemLore: Wenn deaktiviert, wird die Quest nicht über das Scoreboard verfolgt. + hideNoRequirementsItem: Verstecken, wenn die Anforderungen nicht erfüllt sind + hideNoRequirementsItemLore: Wenn aktiviert, wird die Quest nicht im Questmenü angezeigt, wenn die Anforderungen nicht erfüllt sind. + bypassLimit: Questlimit nicht zählen + bypassLimitLore: Wenn aktiviert, ist die Quest startbar, auch wenn der Spieler seine maximale Anzahl an begonnenen Quests erreicht hat. + auto: Beim ersten Beitritt automatisch starten + autoLore: Wenn aktiviert, wird die Quest automatisch gestartet, wenn der Spieler zum ersten Mal den Server betritt. + questName: '§a§lQuestname bearbeiten' + questNameLore: Ein Name muss gesetzt werden, um die Questerstellung abzuschließen. + setItemsRewards: '§eBelohnungs‐Items bearbeiten' + removeItemsReward: '§eEntferne Items vom Inventar' + setXPRewards: '§eBelohnungserfahrungspunkte bearbeiten' + setCheckpointReward: '§eBearbeite Checkpoint Belohnungen' + setRewardStopQuest: '§cQuest stoppen' + setRewardsWithRequirements: '§eBelohnungen mit Voraussetzungen' + setRewardsRandom: '§dZufällige Belohnungen' + setPermReward: '§eBerechtigungen bearbeiten' + setMoneyReward: '§eGeldbelohnung bearbeiten' + setWaitReward: '§e"Warte"-Belohnung bearbeiten' + setTitleReward: '§eTitelbelohnung bearbeiten' + selectStarterNPC: '§e§lNPC‐Starter auswählen' + selectStarterNPCLore: Ein Klick auf den ausgewählten NPC startet die Quest + selectStarterNPCPool: '§c⚠: Eine Questgruppe ist ausgewählt' + createQuestName: '§lQuest erstellen' + createQuestLore: Du musst einen Questnamen definieren. + editQuestName: '§lQuest bearbeiten' + endMessage: '§eAbschlussnachricht bearbeiten' + endMessageLore: Nachricht, die am Ende der Quest an den Spieler gesendet wird. + endSound: '§eBearbeite den end sound' + endSoundLore: Ton, der am Ende einer Quest abgespielt wird. + startMessage: '§eStartnachricht bearbeiten' + startMessageLore: Nachricht, die am Anfang der Quest an den Spieler gesendet wird. + startDialog: '§eStart‐Dialog bearbeiten' + startDialogLore: Dialog, der vor dem Start der Quests angezeigt wird, wenn Spieler auf den Starter NPC klicken. + editRequirements: '§eAnforderungen bearbeiten' + editRequirementsLore: Alle Anforderungen müssen auf den Spieler zutreffen, bevor er mit der Quest beginnen kann. + startRewards: '§6Startbelohnungen' + startRewardsLore: Aktionen die durchgeführt werden wenn die Quest startet. + cancelRewards: '§cAbbrechen von Aktionen' + cancelRewardsLore: Aktionen wenn Spieler diese Quest abbrechen. + hologramText: '§eHologrammtext' + hologramTextLore: Text, der auf dem Hologramm über dem Kopf des Starter NPCs angezeigt wird. + timer: '§bNeustart Timer' + timerLore: Zeit, bis der Spieler die Quest wieder starten kann. + requirements: '{amount} Anforderung(en)' + rewards: '{amount} Belohnung(en)' + actions: '{amount} Aktion(en)' + rewardsLore: Aktionen die durchgeführt werden wenn die Quest endet. + customMaterial: '§eBearbeite das Material des Questgegenstandes' + customMaterialLore: Angezeigter Gegenstand dieser Quest im Questmenü. + failOnDeath: Im Todesfall fehlschlagen + failOnDeathLore: Wird die Quest abgebrochen, wenn der Spieler stirbt? + questPool: '§eQuestgruppe' + questPoolLore: Füge diese Quest einer Questgruppe hinzu + firework: '§dEnding Feuerwerk' + fireworkLore: Feuerwerk startet, wenn der Spieler die Quest beendet hat + fireworkLoreDrop: Lege dein eigenes Feuerwerk hierher + visibility: '§bQuest Sichtbarkeit' + visibilityLore: Legen Sie fest, in welchen Tabs des Menüs die Quest angezeigt wird und ob die Quest auf dynamischen Karten sichtbar ist. + keepDatas: Spielerdaten beibehalten + keepDatasLore: |- + Erzwinge das Plugin die Daten der Spieler zu speichern, obwohl Stufen bearbeitet wurden. §c§lWARNUNG §c- Aktivieren dieser Option kann die Daten deiner Spieler zerstören. + loreReset: '§e§lDer Fortschritt aller Spieler wird zurückgesetzt' + optionValue: '§8Wert: §7{value}' + defaultValue: '§8(Standardwert)' + requiredParameter: '§7Benötigter Parameter' + itemsSelect: + name: Items bearbeiten + none: |- + §aBewege ein Item hierher oder klicke, um den Item‐Editor zu öffnen. + itemSelect: + name: Item auswählen + npcCreate: + name: NPC erstellen + setName: '§eNPC‐Name bearbeiten' + setSkin: '§eNPC‐Skin bearbeiten' + setType: '§eNPC‐Typ bearbeiten' + move: + itemName: '§eBewegen' + itemLore: '§aDie NPC‐Position ändern.' + moveItem: '§a§lPosition bestätigen' + npcSelect: + name: Auswählen oder erstellen? + selectStageNPC: '§eExistierenden NPC auswählen' + createStageNPC: '§eNPC erstellen' + entityType: + name: Objekttyp auswählen + chooseQuest: + name: Welche Quest? + menu: '§aQuests Menu' + menuLore: Ruft dich zu deinem Quest-Menü zurück. + mobs: + name: Mobs auswählen + none: '§aKlicke, um ein Mob hinzuzufügen.' + editAmount: Betrag bearbeiten + editMobName: Mob-Namen bearbeiten + setLevel: Mindestlevel festlegen + mobSelect: + name: Wähle den Mobtyp + bukkitEntityType: '§eObjekttyp auswählen' + mythicMob: '§6Mythic Mob auswählen' + epicBoss: '§6Wähle einen Epic Boss' + boss: '§6Wähle einen Boss' + stageEnding: + locationTeleport: '§eTeleportationsposition bearbeiten' + command: '§eAuszuführenden Befehl bearbeiten' + requirements: + name: Anforderungen + rewards: + name: Belohnungen + commands: 'Befehle: {amount}' + random: + rewards: Belohnungen bearbeiten + minMax: Bearbeite das min und max + checkpointActions: + name: Checkpoint-Aktionen + cancelActions: + name: Aktionen abbrechen + rewardsWithRequirements: + name: Belohnungen mit Voraussetzungen + listAllQuests: + name: Quests + listPlayerQuests: + name: 'Quests von {player_name}' + listQuests: + notStarted: Nicht gestartete Quests + finished: Abgeschlossene Quests + inProgress: Laufende Quests + loreDialogsHistoryClick: '§7Dialoge anzeigen' + loreCancelClick: '§cQuest abbrechen' + loreStart: '§a§oKlicke, um die Quest zu starten.' + loreStartUnavailable: '§c§oDu erfüllst nicht die Anforderungen, um die Quest zu starten.' + canRedo: '§3§oDu kannst diese Quest erneut starten!' + itemCreator: + name: Item‐Ersteller + itemType: '§bItem‐Typ' + itemFlags: Item‐Flags umschalten + itemName: '§bItem‐Name' + itemLore: '§bItem‐Beschreibung' + isQuestItem: '§bQuest‐Item:' + command: + name: Befehl + value: '§eBefehl' + console: Konsole + parse: Platzhalter analysieren + delay: '§bVerzögerung' + chooseAccount: + name: Welcher Account? + listBook: + questName: Name + questStarter: Starter + questRewards: Belohnungen + questMultiple: Mehrfachverwendung + requirements: Vorraussetzungen + questStages: Schritte + noQuests: Es wurden zuvor keine Quests erstellt. + commandsList: + name: Befehlliste + value: '§eBefehl: {command_label}' + console: '§eKonsole: {command_console}' + block: + name: Block auswählen + materialNotItemLore: 'Dieser Block kann momentan nicht als Item angezeigt werden. Er wird immer noch korrekt als {block_material} gespeichert.' + blockName: '§bEigener Blockname' + blockData: '§dBlockdaten (fortgeschritten)' + blockTag: '§dTag (Erweitert)' + blockTagLore: 'Wähle einen Tag, welcher eine Liste von möglichen Blöcken beschreibt. Tags können durch Datapacks angepasst werden. Du kannst eine Liste von Tags im Minecraft Wiki finden.' + blocksList: + name: Blöcke auswählen + addBlock: '§aKlicke, um einen Block hinzuzufügen.' + blockAction: + name: Blockaktion auswählen + location: '§eWähle einen genauen Ort aus' + material: '§eWähle ein Blockmaterial' + buckets: + name: Eimertyp + permission: + name: Berechtigung auswählen + perm: '§aBerechtigung' + world: '§aWelt' + worldGlobal: '§b§lGlobal' + remove: Berechtigung entfernen + removeLore: '§7Berechtigung wird genommen\n§7statt zu geben.' + permissionList: + name: Berechtigungsliste + removed: '§eGenommen: §6{permission_removed}' + world: '§eWelt: §6{permission_world}' + classesRequired.name: Klassen erforderlich + classesList.name: Klassenliste + factionsRequired.name: Fraktionen benötigt + factionsList.name: Fraktionsliste + poolsManage: + name: Questgruppen + poolMaxQuests: '§8Max. Quests: §7{pool_max_quests}' + poolQuestsPerLaunch: '§8Quests pro Start vergeben: §7{pool_quests_per_launch}' + poolRedo: '§8Kann abgeschlossene Quests wiederholen: §7{pool_redo}' + poolTime: '§8Zeit zwischen Quests: §7{pool_time}' + poolHologram: '§8Hologramm-Text: §7{pool_hologram}' + poolAvoidDuplicates: '§8Duplikate vermeiden: §7{pool_duplicates}' + poolQuestsList: '§7{pool_quests_amount} §8Quest(s): §7{pool_quests}' + create: '§aErstelle eine Questgruppe' + edit: '§e> §6§oBearbeite die Gruppe... §e<' + choose: '§e> §6§oWähle diese Gruppe §e<' + poolCreation: + name: Questgruppen Erstellung + hologramText: '§eBenutzerdefiniertes Hologramm der Gruppe' + maxQuests: '§aMax. Quests' + questsPerLaunch: '§aPro Start gestartete Quests' + time: '§bLege die Zeit zwischen Quests fest' + redoAllowed: Ist Wiederholen erlaubt + avoidDuplicates: Duplikate vermeiden + avoidDuplicatesLore: '§8> §7Versuche es zu vermeiden,\n immer wieder die gleiche Quest zu absolvieren' + requirements: '§bAnforderungen, um eine Quest zu starten' + poolsList.name: Questgruppen + itemComparisons: + name: Itemvergleiche + bukkit: Bukkit nativer Vergleich + customBukkit: Bukkit nativer Vergleich - KEIN NBT + material: Gegenstandsmaterial + materialLore: 'Vergleicht Gegenstandsmaterial (z.B Stein, Eisenschwert...)' + itemName: Gegenstandsname + itemNameLore: Vergleicht Gegenstandsnamen + itemLore: Gegenstands-Beschreibung + itemLoreLore: Vergleicht Gegenstands-Beschreibungen + enchants: Gegenstände verzaubert + enchantsLore: Vergleicht Gegenstandsverzauberungen + repairCost: Reparaturkosten + repairCostLore: Vergleicht Reparaturkosten für Rüstungen und Schwerter + itemsAdder: ItemsAdder + itemsAdderLore: Vergleicht ItemsAdder-IDs + editTitle: + name: Titel bearbeiten + title: '§6Titel' + subtitle: '§eUntertitel' + fadeIn: '§aEinblendedauer' + stay: '§bEinblendedauer' + fadeOut: '§aAusblendedauer' + particleEffect: + name: Erstelle einen Partikeleffekt + shape: '§dPartikel Muster' + type: '§ePartikel Typ' + color: '§bPartikelfarbe' + particleList: + name: Partikel Liste + colored: Farbige Partikel + damageCause: + name: Schadensursache + damageCausesList: + name: Schadensverursachungsliste + questObjects: + setCustomDescription: 'Eigene Beschreibung festlegen' scoreboard: - asyncEnd: '§ex' name: '§6§lQuests' noLaunched: '§cKeine laufenden Quests.' - noLaunchedDescription: '§c§oLaden' noLaunchedName: '&c&lLaden' + noLaunchedDescription: '§c§oLaden' + textBetwteenBranch: '§e oder' + asyncEnd: '§ex' stage: - breed: '§eZüchte §6{mobs}' - bucket: '§eBefülle §6{buckets}' + region: '§eFinde Region §6{region_id}' + npc: '§eSprich mit dem NPC §6{dialog_npc_name}' + mobs: '§eTöte §6{mobs}' + mine: '§eBaue {blocks} ab' + placeBlocks: '§ePlatziere {blocks}' chat: '§eSchreibe §6{text}' - craft: '§eStelle §6{items} §eher' - fish: '§eAngle §6{items}' - interact: '§eKlicke auf den Block bei §6{x}' interactMaterial: '§eKlicke auf einen §6{block}§e Block' - items: '§eBringe Items zu §6{dialog_npc_name}§e:' + fish: '§eAngle §6{items}' + melt: '§6{items} §eschmelzen' + enchant: '§6{items} §everzaubern' + craft: '§eStelle §6{items} §eher' + bucket: '§eBefülle §6{buckets}' location: '§eGehe zu: §6{target_x}§e, §6{target_y}§e, §6{target_z}§e in §6{target_world}' - mine: '§eBaue {blocks} ab' - mobs: '§eTöte §6{mobs}' - npc: '§eSprich mit dem NPC §6{dialog_npc_name}' - placeBlocks: '§ePlatziere {blocks}' - region: '§eFinde Region §6{region_id}' + breed: '§eZüchte §6{mobs}' tame: '§eZähme §6{mobs}' - textBetwteenBranch: '§e oder' + die: '§csterben' +indication: + startQuest: '§7Möchtest du die Quest {quest_name} starten?' + closeInventory: '§7Bist du sicher, dass du die GUI schließen möchtest?' + cancelQuest: '§7Bist du sicher, dass du die Quest {quest_name} abbrechen möchtest?' + removeQuest: '§7Bist du sicher, dass du die Quest {quest} entfernen möchtest?' +description: + requirement: + title: '§8§lAnforderungen:' + jobLevel: 'Level {short_level} für {job_name}' + combatLevel: 'Kampflevel {short_level}' + skillLevel: 'Level {short_level} für {skill_name}' + class: 'Klasse {class_name}' + faction: 'Fraktion {faction_name}' + quest: 'Quest beenden §e{quest_name}' + reward: + title: '§8§lBelohnungen:' +misc: + format: + prefix: '§6<§e§lQuests§r§6> §r' + editorPrefix: '§a' + time: + weeks: '{weeks_amount} Wochen' + days: '{days_amount} Tage' + hours: '{hours_amount} Stunden' + minutes: '{minutes_amount} Minuten' + lessThanAMinute: 'weniger als eine Minute' + stageType: + region: Region finden + npc: NPC finden + items: Items zurückbringen + mobs: Mobs töten + mine: Blöcke zerstören + placeBlocks: Blöcke platzieren + chat: Im Chat schreiben + interact: Mit Block interagieren + Fish: Fische fangen + Craft: Item herstellen + Bucket: Eimer befüllen + location: Position finden + playTime: Spielzeit + breedAnimals: Züchte Tiere + tameAnimals: Zähme Tiere + comparison: + equals: gleich wie {number} + different: anders als {number} + less: strikt weniger als {number} + lessOrEquals: weniger als {number} + greater: strikt größer als {number} + greaterOrEquals: größer als {number} + requirement: + logicalOr: '§dLogisch ODER (Voraussetzungen)' + skillAPILevel: '§bAPI-Level benötigt' + class: '§bBenötigte Klasse(n)' + faction: '§bBenötigte Fraktion(en)' + jobLevel: '§bJob‐Level benötigt' + combatLevel: '§bKampflevel benötigt' + experienceLevel: '§bErfahrungslevel benötigt' + permissions: '§3Benötigte Berechtigung(en)' + scoreboard: '§dPunktestand erforderlich' + region: '§dRegion erforderlich' + placeholder: '§bPlatzhalter‐Wert benötigt' + quest: '§aQuest benötigt' + mcMMOSkillLevel: '§dBenötigtes Fertigkeitslevel' + money: '§dGeld benötigt' + bucket: + water: Wassereimer + lava: Lavaeimer + milk: Milcheimer + snow: Schnee-Eimer + click: + right: Rechtsklick + left: Linksklick + shift-right: Shift-Rechtsklick + shift-left: Shift-Linksklick + middle: Mittelklick + ticks: '{ticks} Ticks' + questItemLore: '§e§oQuest‐Item' + hologramText: '§8§lQuest‐NPC' + poolHologramText: '§eNeue Quest verfügbar!' + entityType: '§eObjekttyp: {entity_type}' + entityTypeAny: '§eJedes Objekt' + enabled: Aktiviert + disabled: Deaktiviert + unknown: unbekannt + notSet: '§cnicht gesetzt' + removeRaw: Entfernen + reset: Zurücksetzen + or: oder + amount: '§eAnzahl: {amount}' + 'yes': 'Ja' + 'no': 'Nein' + and: und diff --git a/core/src/main/resources/locales/fr_FR.yml b/core/src/main/resources/locales/fr_FR.yml index 1d951a1e..1f15a9ea 100644 --- a/core/src/main/resources/locales/fr_FR.yml +++ b/core/src/main/resources/locales/fr_FR.yml @@ -379,6 +379,12 @@ inv: targetMobs: '§cMobs à heurter' eatDrink: items: '§eModifier les objets à manger ou à boire' + playTime: + changeTimeMode: 'Changer le mode de comptage du temps' + modes: + online: 'Le joueur doit être connecté sur le serveur' + offline: 'Le joueur peut être hors ligne, mais le serveur doit être lancé pour que le temps soit décompté.' + realtime: 'Le temps est décompté même si le joueur et le serveur sont hors ligne.' stages: name: Créer les étapes nextPage: '§ePage suivante' From 062136d299a3814ead1ae95428ee26cdb4abd678 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 2 Dec 2023 15:20:50 +0100 Subject: [PATCH 92/95] :bug: Fixed item creator GUI not refreshing properly --- .../java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java index 3d92830d..ccdce05c 100644 --- a/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java +++ b/core/src/main/java/fr/skytasul/quests/gui/items/ItemCreatorGUI.java @@ -73,6 +73,7 @@ public void onClick(GuiClickEvent event) { new TextEditor<>(event.getPlayer(), event::reopen, obj -> { type = obj; event.reopen(); + refresh(); }, QuestsPlugin.getPlugin().getEditorManager().getFactory().getMaterialParser(true, false)).start(); break; @@ -82,6 +83,7 @@ public void onClick(GuiClickEvent event) { amount = /* Math.min(obj, 64) */ obj; ItemUtils.name(event.getClicked(), Lang.Amount.quickFormat("amount", amount)); event.reopen(); + refresh(); }, NumberParser.INTEGER_PARSER_STRICT_POSITIVE).start(); break; @@ -95,6 +97,7 @@ public void onClick(GuiClickEvent event) { new TextEditor<String>(event.getPlayer(), event::reopen, obj -> { name = obj; event.reopen(); + refresh(); }).start(); break; @@ -103,6 +106,7 @@ public void onClick(GuiClickEvent event) { new TextListEditor(event.getPlayer(), list -> { lore = list; event.reopen(); + refresh(); }, lore).start(); break; From 718d193810d49dff3b44a3bb0317f936c3474c55 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 2 Dec 2023 15:21:54 +0100 Subject: [PATCH 93/95] :bug: Players cannot place quest items as blocks anymore --- .../java/fr/skytasul/quests/api/localization/Lang.java | 1 + .../src/main/java/fr/skytasul/quests/QuestsListener.java | 9 +++++++++ core/src/main/resources/locales/en_US.yml | 5 +++-- 3 files changed, 13 insertions(+), 2 deletions(-) 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 5131f2f0..c2aee23a 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 @@ -51,6 +51,7 @@ public enum Lang implements Locale { QUEST_ITEM_DROP("msg.questItem.drop"), QUEST_ITEM_CRAFT("msg.questItem.craft"), QUEST_ITEM_EAT("msg.questItem.eat"), + QUEST_ITEM_PLACE("msg.questItem.place"), STAGE_MOBSLIST("msg.stageMobs.listMobs"), diff --git a/core/src/main/java/fr/skytasul/quests/QuestsListener.java b/core/src/main/java/fr/skytasul/quests/QuestsListener.java index 944baf79..865915d4 100644 --- a/core/src/main/java/fr/skytasul/quests/QuestsListener.java +++ b/core/src/main/java/fr/skytasul/quests/QuestsListener.java @@ -9,6 +9,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.CraftItemEvent; @@ -195,6 +196,14 @@ public void onDeath(PlayerDeathEvent e) { if (BeautyQuests.getInstance().isRunningPaper()) Paper.handleDeathItems(e, Utils::isQuestItem); } + @EventHandler + public void onPlace(BlockPlaceEvent e) { + if (Utils.isQuestItem(e.getItemInHand())) { + e.setCancelled(true); + Lang.QUEST_ITEM_PLACE.send(e.getPlayer()); + } + } + @EventHandler(priority = EventPriority.HIGHEST) public void onBreak(BlockBreakEvent e) { if (e.isCancelled()) return; diff --git a/core/src/main/resources/locales/en_US.yml b/core/src/main/resources/locales/en_US.yml index 6015bdda..0de2c421 100644 --- a/core/src/main/resources/locales/en_US.yml +++ b/core/src/main/resources/locales/en_US.yml @@ -26,9 +26,10 @@ msg: noAvailable: §7There is no more quest available... maxQuests: §cYou cannot have more than {pool_max_quests} quest(s) at the same time... questItem: - drop: §cYou can't drop a quest item! - craft: §cYou can't use a quest item to craft! + drop: §cYou cannot drop a quest item! + craft: §cYou cannot use a quest item to craft! eat: §cYou cannot eat a quest item! + place: §cYou cannot place a quest item! stageMobs: listMobs: §aYou must kill {mobs}. writeNPCText: '§aWrite the dialog that will be said to the player by the NPC: (Write From a426872053d11879e8583b8a07476298ca82a9f8 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 9 Dec 2023 14:12:29 +0100 Subject: [PATCH 94/95] :sparkles: added "none" to hide stage from quest description --- .../quests/api/stages/StageController.java | 2 +- .../java/fr/skytasul/quests/BeautyQuests.java | 15 ++++++++++-- .../structure/QuestBranchImplementation.java | 24 ++++++------------- .../StageControllerImplementation.java | 14 ++++++++--- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java b/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java index c38e3738..5ee40504 100644 --- a/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java +++ b/api/src/main/java/fr/skytasul/quests/api/stages/StageController.java @@ -21,7 +21,7 @@ public interface StageController { public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nullable Object dataValue); - public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); + public @Nullable String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source); public <T> @Nullable T getData(@NotNull PlayerAccount acc, @NotNull String dataKey); diff --git a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java index 89b647db..d0685e33 100644 --- a/core/src/main/java/fr/skytasul/quests/BeautyQuests.java +++ b/core/src/main/java/fr/skytasul/quests/BeautyQuests.java @@ -436,10 +436,21 @@ private void loadDefaultIntegrations() { InternalIntegrations.AccountsHook.isEnabled(); // to initialize the class } - private YamlConfiguration loadLang() throws LoadingException { + private void loadLang() throws LoadingException { try { loadedLanguage = config.getConfig().getString("lang", "en_US"); - return Locale.loadLang(this, Lang.values(), loadedLanguage); + Locale.loadLang(this, Lang.values(), loadedLanguage); + + Pattern oldPlaceholders = Pattern.compile("\\{\\d\\}"); + for (Lang l : Lang.values()) { + if (oldPlaceholders.matcher(l.getValue()).find()) { + logger.warning( + "Found old placeholder format in /plugins/BeautyQuests/locales/" + loadedLanguage + ".yml."); + logger.warning( + "This means you probably have not deleted the locales folder after upgrading from a pre-1.0 version." + + " Expect some bugs with message formatting."); + } + } }catch (Exception ex) { throw new LoadingException("Couldn't load language file.", ex); } diff --git a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java index a43e445b..4fe2ed87 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/QuestBranchImplementation.java @@ -1,9 +1,6 @@ package fr.skytasul.quests.structure; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; @@ -125,26 +122,19 @@ public boolean isEndingStage(StageController stage) { throw new IllegalArgumentException("Account does not have this branch launched"); if (asyncReward.contains(acc)) return Lang.SCOREBOARD_ASYNC_END.toString(); if (datas.isInEndingStages()) { - StringBuilder stb = new StringBuilder(); - int i = 0; - for (EndingStage ending : endStages) { - i++; - stb.append(ending.getStage().getDescriptionLine(acc, source)); - if (i != endStages.size()){ - stb.append("{nl}"); - stb.append(Lang.SCOREBOARD_BETWEEN_BRANCHES.toString()); - stb.append("{nl}"); - } - } - return stb.toString(); + return endStages.stream() + .map(stage -> stage.getStage().getDescriptionLine(acc, source)) + .filter(Objects::nonNull) + .collect(Collectors.joining("{nl}" + Lang.SCOREBOARD_BETWEEN_BRANCHES + " {nl}")); } if (datas.getStage() < 0) return "§cerror: no stage set for branch " + getId(); if (datas.getStage() >= regularStages.size()) return "§cerror: datas do not match"; + String descriptionLine = regularStages.get(datas.getStage()).getDescriptionLine(acc, source); return MessageUtils.format(QuestsConfiguration.getConfig().getStageDescriptionConfig().getStageDescriptionFormat(), PlaceholderRegistry.of("stage_index", datas.getStage() + 1, "stage_amount", regularStages.size(), - "stage_description", regularStages.get(datas.getStage()).getDescriptionLine(acc, source))); + "stage_description", descriptionLine == null ? "" : descriptionLine)); } @Override diff --git a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java index b0a6d36e..03d047c1 100644 --- a/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java +++ b/core/src/main/java/fr/skytasul/quests/structure/StageControllerImplementation.java @@ -116,11 +116,19 @@ public void updateObjective(@NotNull Player player, @NotNull String dataKey, @Nu } @Override - public @NotNull String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { + public @Nullable String getDescriptionLine(@NotNull PlayerAccount acc, @NotNull DescriptionSource source) { try { + String description = stage.getCustomText(); + if (description != null) { + if (description.equals("none")) + return null; + description = "§e" + description; + } + StageDescriptionPlaceholdersContext context = StageDescriptionPlaceholdersContext.of(true, acc, source, null); - String description = - stage.getCustomText() == null ? stage.getDefaultDescription(context) : ("§e" + stage.getCustomText()); + if (description == null) + description = stage.getDefaultDescription(context); + return MessageUtils.finalFormat(description, stage.getPlaceholdersRegistry(), context); } catch (Exception ex) { QuestsPlugin.getPlugin().getLoggerExpanded().severe( From 026fb9d8c0421fbe1e842ab686c938384d5cad64 Mon Sep 17 00:00:00 2001 From: SkytAsul <skytasul@gmail.com> Date: Sat, 9 Dec 2023 14:19:26 +0100 Subject: [PATCH 95/95] :bookmark: 1.0 --- api/dependency-reduced-pom.xml | 2 +- api/pom.xml | 2 +- core/pom.xml | 2 +- core/src/main/resources/plugin.yml | 4 ++-- dist/pom.xml | 2 +- integrations/pom.xml | 2 +- pom.xml | 2 +- v1_12_R1/pom.xml | 2 +- v1_15_R1/pom.xml | 2 +- v1_16_R1/pom.xml | 2 +- v1_16_R2/pom.xml | 2 +- v1_16_R3/pom.xml | 2 +- v1_17_R1/pom.xml | 2 +- v1_18_R1/pom.xml | 2 +- v1_18_R2/pom.xml | 2 +- v1_19_R1/pom.xml | 2 +- v1_19_R2/pom.xml | 2 +- v1_19_R3/pom.xml | 2 +- v1_20_R1/pom.xml | 2 +- v1_20_R2/pom.xml | 2 +- v1_9_R1/pom.xml | 2 +- v1_9_R2/pom.xml | 2 +- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml index 55adc0d4..cf7a0a43 100755 --- a/api/dependency-reduced-pom.xml +++ b/api/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ <parent> <artifactId>beautyquests-parent</artifactId> <groupId>fr.skytasul</groupId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>beautyquests-api</artifactId> diff --git a/api/pom.xml b/api/pom.xml index 7efae76d..0618e860 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/core/pom.xml b/core/pom.xml index 81ed84ad..658e2cca 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <build> diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index 1e5f7f73..3ef14df2 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: BeautyQuests author: SkytAsul -version: "${human.version}_BUILD${build.number}" -#version: "${human.version}" +#version: "${human.version}_BUILD${build.number}" +version: "${human.version}" description: Quests system with a simple graphical interface. website: https://www.spigotmc.org/resources/beautyquests.39255/ api-version: 1.13 diff --git a/dist/pom.xml b/dist/pom.xml index f31f79bc..bce9ddf3 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <build> diff --git a/integrations/pom.xml b/integrations/pom.xml index 5f1b5e5b..2cb77a43 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <repositories> diff --git a/pom.xml b/pom.xml index cd670fc6..c7cee395 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> <packaging>pom</packaging> <name>BeautyQuests</name> diff --git a/v1_12_R1/pom.xml b/v1_12_R1/pom.xml index ff9bd2e9..354d84ff 100644 --- a/v1_12_R1/pom.xml +++ b/v1_12_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_15_R1/pom.xml b/v1_15_R1/pom.xml index a546f759..dde94862 100644 --- a/v1_15_R1/pom.xml +++ b/v1_15_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R1/pom.xml b/v1_16_R1/pom.xml index 9fc470b9..37301ed1 100644 --- a/v1_16_R1/pom.xml +++ b/v1_16_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R2/pom.xml b/v1_16_R2/pom.xml index 165aff1a..082961a2 100644 --- a/v1_16_R2/pom.xml +++ b/v1_16_R2/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_16_R3/pom.xml b/v1_16_R3/pom.xml index 3a8e768d..33fc68a3 100644 --- a/v1_16_R3/pom.xml +++ b/v1_16_R3/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml index 65b80b38..c6343c77 100644 --- a/v1_17_R1/pom.xml +++ b/v1_17_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_18_R1/pom.xml b/v1_18_R1/pom.xml index c23bcd03..565b2cba 100644 --- a/v1_18_R1/pom.xml +++ b/v1_18_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_18_R2/pom.xml b/v1_18_R2/pom.xml index f8e03ddc..9d1d0e60 100644 --- a/v1_18_R2/pom.xml +++ b/v1_18_R2/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_19_R1/pom.xml b/v1_19_R1/pom.xml index 5c7e455a..9da8b31b 100644 --- a/v1_19_R1/pom.xml +++ b/v1_19_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_19_R2/pom.xml b/v1_19_R2/pom.xml index a0d3ccdc..9cc5ac69 100644 --- a/v1_19_R2/pom.xml +++ b/v1_19_R2/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_19_R3/pom.xml b/v1_19_R3/pom.xml index 80b84a18..a4d7dce4 100644 --- a/v1_19_R3/pom.xml +++ b/v1_19_R3/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_20_R1/pom.xml b/v1_20_R1/pom.xml index 2ee2ca1f..8656c6d7 100644 --- a/v1_20_R1/pom.xml +++ b/v1_20_R1/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_20_R2/pom.xml b/v1_20_R2/pom.xml index 5a33ad14..0a0b6344 100755 --- a/v1_20_R2/pom.xml +++ b/v1_20_R2/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties> diff --git a/v1_9_R1/pom.xml b/v1_9_R1/pom.xml index f2e6a56f..481f6121 100644 --- a/v1_9_R1/pom.xml +++ b/v1_9_R1/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties> diff --git a/v1_9_R2/pom.xml b/v1_9_R2/pom.xml index 7d3fa0ff..25441477 100644 --- a/v1_9_R2/pom.xml +++ b/v1_9_R2/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>fr.skytasul</groupId> <artifactId>beautyquests-parent</artifactId> - <version>1.0-SNAPSHOT</version> + <version>1.0</version> </parent> <properties><maven.deploy.skip>true</maven.deploy.skip></properties>