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: https://repo.codemc.org/repository/maven-public ``` -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 fr.skytasul - beautyquests-core + beautyquests-api VERSION provided diff --git a/api/dependency-reduced-pom.xml b/api/dependency-reduced-pom.xml new file mode 100755 index 00000000..cf7a0a43 --- /dev/null +++ b/api/dependency-reduced-pom.xml @@ -0,0 +1,239 @@ + + + + beautyquests-parent + fr.skytasul + 1.0 + + 4.0.0 + beautyquests-api + + + + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + + + revxrsal.commands + fr.skytasul.quests.api.commands.revxrsal + + + com.cryptomorin.xseries + fr.skytasul.quests.api.utils + + + + + com.github.cryptomorin:XSeries + + com/cryptomorin/xseries/XMaterial* + com/cryptomorin/xseries/XBlock* + com/cryptomorin/xseries/XPotion* + + + + true + + + + maven-compiler-plugin + 3.8.0 + + true + + + + maven-javadoc-plugin + 3.4.1 + + + attach-javadocs + verify + + jar + + + + + false + none + + + + maven-source-plugin + 3.2.1 + + + attach-sources + verify + + jar-no-fork + + + + + false + + + + maven-surefire-plugin + 3.2.2 + + true + + + + + + + papermc + https://repo.papermc.io/repository/maven-public/ + + + jitpack.io + https://jitpack.io + + + + + org.jetbrains + annotations + 24.0.0 + provided + + + commons-lang + commons-lang + 2.6 + provided + + + io.papermc.paper + paper-api + 1.20.1-R0.1-SNAPSHOT + provided + + + guava + com.google.guava + + + gson + com.google.code.gson + + + bungeecord-chat + net.md-5 + + + snakeyaml + org.yaml + + + joml + org.joml + + + json-simple + com.googlecode.json-simple + + + fastutil + it.unimi.dsi + + + log4j-api + org.apache.logging.log4j + + + slf4j-api + org.slf4j + + + maven-resolver-provider + org.apache.maven + + + adventure-api + net.kyori + + + adventure-text-minimessage + net.kyori + + + adventure-text-serializer-gson + net.kyori + + + adventure-text-serializer-legacy + net.kyori + + + adventure-text-serializer-plain + net.kyori + + + adventure-text-logger-slf4j + net.kyori + + + checker-qual + org.checkerframework + + + asm + org.ow2.asm + + + asm-commons + org.ow2.asm + + + + + org.junit.jupiter + junit-jupiter-api + 5.10.1 + test + + + opentest4j + org.opentest4j + + + junit-platform-commons + org.junit.platform + + + apiguardian-api + org.apiguardian + + + + + org.junit.jupiter + junit-jupiter-params + 5.10.1 + test + + + apiguardian-api + org.apiguardian + + + + + + 5.10.1 + + diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 00000000..0618e860 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,171 @@ + + + 4.0.0 + jar + beautyquests-api + + fr.skytasul + beautyquests-parent + 1.0 + + + + 5.10.1 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + + revxrsal.commands + + fr.skytasul.quests.api.commands.revxrsal + + + com.cryptomorin.xseries + fr.skytasul.quests.api.utils + + + + + com.github.cryptomorin:XSeries + + com/cryptomorin/xseries/XMaterial* + com/cryptomorin/xseries/XBlock* + com/cryptomorin/xseries/XPotion* + + + + true + + + + package + + shade + + + + + + maven-compiler-plugin + 3.8.0 + + true + + + + maven-javadoc-plugin + 3.4.1 + + false + none + + + + attach-javadocs + verify + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + false + + + + attach-sources + verify + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.2 + + true + + + + + + + + papermc + https://repo.papermc.io/repository/maven-public/ + + + jitpack.io + https://jitpack.io + + + + + + org.jetbrains + annotations + 24.0.0 + provided + + + commons-lang + commons-lang + 2.6 + provided + + + + io.papermc.paper + paper-api + 1.20.1-R0.1-SNAPSHOT + provided + + + + com.github.Revxrsal.Lamp + bukkit + 3.1.1 + + + com.github.Revxrsal.Lamp + common + 3.1.1 + + + com.github.cryptomorin + XSeries + 9.4.0 + + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + test + + + + diff --git a/api/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java b/api/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java new file mode 100644 index 00000000..f69c9171 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/AbstractHolograms.java @@ -0,0 +1,44 @@ +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 { + + public abstract boolean supportPerPlayerVisibility(); + + public abstract boolean supportItems(); + + public abstract @NotNull BQHologram createHologram(@NotNull Location lc, boolean defaultVisible); + + public abstract class BQHologram { + protected @NotNull T hologram; + + protected BQHologram(@NotNull T hologram) { + this.hologram = hologram; + } + + public void setPlayersVisible(@NotNull List players) { + players.forEach(p -> setPlayerVisibility(p, true)); + } + + public void setPlayerVisibility(@NotNull Player p, boolean visible) { + throw new UnsupportedOperationException(); + } + + public void appendItem(@NotNull ItemStack item) { + throw new UnsupportedOperationException(); + } + + public abstract void appendTextLine(@Nullable String text); + + public abstract void teleport(@NotNull Location lc); + + public abstract void delete(); + } + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/AbstractMapIntegration.java b/api/src/main/java/fr/skytasul/quests/api/AbstractMapIntegration.java new file mode 100644 index 00000000..0928483a --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/AbstractMapIntegration.java @@ -0,0 +1,55 @@ +package fr.skytasul.quests.api; + +import org.bukkit.Location; +import fr.skytasul.quests.api.npcs.BqNpc; +import fr.skytasul.quests.api.quests.Quest; +import fr.skytasul.quests.api.utils.QuestVisibilityLocation; + +public abstract class AbstractMapIntegration implements QuestsHandler { + + @Override + public final void load() { + if (isEnabled()) + initializeMarkers(this::initializeQuests); + } + + private void initializeQuests() { + QuestsAPI.getAPI().getQuestsManager().getQuests().forEach(this::questLoaded); + } + + @Override + public void questLoaded(Quest quest) { + if (!isEnabled()) + return; + + 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 = starter.getLocation(); + if (lc == null) { + QuestsPlugin.getPlugin().getLoggerExpanded().warning("Cannot create map marker for quest #" + quest.getId() + " (" + quest.getName() + ")"); + }else { + addMarker(quest, lc); + } + } + + @Override + public void questUnload(Quest quest) { + if (!quest.isHidden(QuestVisibilityLocation.MAPS) && quest.getStarterNpc() != null) + removeMarker(quest); + } + + public abstract boolean isEnabled(); + + protected abstract void initializeMarkers(Runnable initializeQuests); + + protected abstract void addMarker(Quest quest, Location lc); + + protected abstract void removeMarker(Quest quest); + +} diff --git a/api/src/main/java/fr/skytasul/quests/api/BossBarManager.java b/api/src/main/java/fr/skytasul/quests/api/BossBarManager.java new file mode 100644 index 00000000..0451c272 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/BossBarManager.java @@ -0,0 +1,33 @@ +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 BossBarManager { + + @NotNull + BQBossBar buildBossBar(@NotNull String name, @NotNull BarColor color, @NotNull BarStyle 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(@NotNull String name); + + void setProgress(double progress); + + void setStyle(@NotNull BarStyle style); + + void addPlayer(@NotNull Player player); + + void removePlayer(@NotNull Player player); + + void removeAll(); + + } + +} 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..72e975ba --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsAPI.java @@ -0,0 +1,261 @@ +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.blocks.BQBlocksManager; +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.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; +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; +import fr.skytasul.quests.api.utils.messaging.MessageProcessor; + +/** + * This class contains most of the useful accessors to fetch data from BeautyQuests and methods to + * implement custom behaviors. + */ +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(); + + /** + * 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 getRequirements(); + + /** + * Gets the rewards registry, which provides methods to register and get rewards. + * + * @return the rewards registry + */ + @NotNull + QuestObjectsRegistry 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); + + /** + * Checks if there is an hologram manager registered. + * + * @return true if {@link #getHologramsManager()} will not return null, + * false 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.
+ * If there is already an holograms manager registered, this one will replace it. + * + * @param newHologramsManager holograms manager to register + */ + void setHologramsManager(@NotNull AbstractHolograms newHologramsManager); + + /** + * Checks if there is a boss bar manager registered. + * + * @return true if {@link #getBossBarManager()} will not return null, + * false 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.
+ * 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 getMessageProcessors(); + + /** + * Registers a custom message processor into the pipeline.
+ * If a processor with the same key and priority already exists, it will get replaced by this + * one.
+ * 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); + + /** + * 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/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/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..2f6ba381 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsConfiguration.java @@ -0,0 +1,134 @@ +package fr.skytasul.quests.api; + +import java.util.Collection; +import java.util.Set; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +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.progress.ProgressBarConfig; +import fr.skytasul.quests.api.utils.progress.itemdescription.ItemsDescriptionConfiguration; + +public interface QuestsConfiguration { + + static @NotNull QuestsConfiguration getConfig() { + return QuestsPlugin.getPlugin().getConfiguration(); + } + + @NotNull + Quests getQuestsConfig(); + + @NotNull + Gui getGuiConfig(); + + @NotNull + Dialogs getDialogsConfig(); + + @NotNull + QuestsSelection getQuestsSelectionConfig(); + + @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(); + + Collection getNpcClicks(); + + ItemStack getDefaultQuestItem(); + + double startParticleDistance(); + + int requirementUpdateTime(); + + boolean requirementReasonOnMultipleQuests(); + + boolean stageEndRewardsMessage(); + + } + + interface Gui { + + ItemStack getPreviousPageItem(); + + ItemStack getNextPageItem(); + + boolean showVerticalSeparator(); + + } + + interface Dialogs { + + boolean sendInActionBar(); + + int getDefaultTime(); + + boolean isSkippableByDefault(); + + boolean isClickDisabled(); + + boolean isHistoryEnabled(); + + int getMaxMessagesPerHistoryPage(); + + int getMaxDistance(); + + int getMaxDistanceSquared(); + + String getDefaultPlayerSound(); + + String getDefaultNPCSound(); + + } + + interface QuestsSelection { + + boolean skipGuiIfOnlyOneQuest(); + + boolean hideNoRequirements(); + + } + + interface QuestsMenu { + + boolean isNotStartedTabOpenedWhenEmpty(); + + boolean allowPlayerCancelQuest(); + + Set getEnabledTabs(); + + } + + interface StageDescription extends ItemsDescriptionConfiguration, ProgressBarConfig { + + String getStageDescriptionFormat(); + + } + +} 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 4d89d34b..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,10 +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 { @@ -22,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..d0a8b40f --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/QuestsPlugin.java @@ -0,0 +1,51 @@ +package fr.skytasul.quests.api; + +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +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.IntegrationManager; +import fr.skytasul.quests.api.utils.logger.LoggerExpanded; + +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(); + + public @NotNull BqNpcManager getNpcManager(); + + public @NotNull IntegrationManager getIntegrationManager(); + + public void notifyLoadingFailure(); + + 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/blocks/BQBlock.java b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java new file mode 100644 index 00000000..0f77b719 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/blocks/BQBlock.java @@ -0,0 +1,78 @@ +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; +import fr.skytasul.quests.api.utils.messaging.HasPlaceholders; +import fr.skytasul.quests.api.utils.messaging.PlaceholderRegistry; + +public abstract class BQBlock implements HasPlaceholders { + + private final @NotNull BQBlockType type; + private final @Nullable String customName; + + 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(); + } + + 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() + "}"; + } + + @Override + public @NotNull PlaceholderRegistry getPlaceholdersRegistry() { + if (placeholders == null) { + placeholders = new PlaceholderRegistry() + .registerIndexed("block_type", getAsString()) + .register("block_material", getMaterial().name()) + .register("block", getName()); + } + return placeholders; + } + +} 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 getNearbyBlocks( + @NotNull Locatable.MultipleLocatable.NearbyFetcher fetcher, + @NotNull Collection types); + + public @NotNull BQBlock createSimple(@NotNull XMaterial material, @Nullable String customName); + +} 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 d8e8f7fc..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,8 +1,7 @@ -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; - import java.lang.annotation.Retention; import java.lang.annotation.Target; 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 71% 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 index d449855c..78140c70 100644 --- a/core/src/main/java/fr/skytasul/quests/api/comparison/ItemComparison.java +++ b/api/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 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 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 not 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/api/src/main/java/fr/skytasul/quests/api/comparison/ItemComparisonMap.java similarity index 77% 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 ac6d81b4..fef13466 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 @@ -1,15 +1,11 @@ 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; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import fr.skytasul.quests.api.QuestsAPI; public class ItemComparisonMap implements Cloneable { @@ -21,30 +17,30 @@ public ItemComparisonMap() { this(new HashMap<>()); } - public ItemComparisonMap(ConfigurationSection notDefault) { + public ItemComparisonMap(@NotNull ConfigurationSection notDefault) { setNotDefaultComparisons(notDefault); } - public ItemComparisonMap(Map notDefault) { + public ItemComparisonMap(@NotNull Map notDefault) { setNotDefaultComparisons(notDefault); } - public void setNotDefaultComparisons(ConfigurationSection section) { + 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); } updated(); } - public void setNotDefaultComparisons(Map comparisons) { + public void setNotDefaultComparisons(@NotNull Map 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; @@ -53,7 +49,7 @@ public void setNotDefaultComparisons(Map comparisons) { updated(); } - public Map getNotDefault() { + public @NotNull Map getNotDefault() { return notDefault; } @@ -61,15 +57,15 @@ public boolean isDefault() { return notDefault.isEmpty(); } - public List 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 +90,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 +125,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 +142,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 +166,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/data/SQLDataSaver.java b/api/src/main/java/fr/skytasul/quests/api/data/SQLDataSaver.java similarity index 96% 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 aa121302..504a13bd 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 @@ -1,18 +1,12 @@ 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; 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 { 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/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..de60c584 --- /dev/null +++ b/api/src/main/java/fr/skytasul/quests/api/editors/DialogEditor.java @@ -0,0 +1,201 @@ +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; +import fr.skytasul.quests.api.npcs.dialogs.Message; +import fr.skytasul.quests.api.npcs.dialogs.Message.Sender; +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{ + + 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 = Arrays.stream(argsColored).skip(1).collect(Collectors.joining(" ")); + hasMsg = true; + } + switch (cmd) { + + case NOSENDER: + case NPC: + case PLAYER: + if (!hasMsg){ + Lang.DIALOG_MESSAGE_SYNTAX.send(player, PlaceholderRegistry.of("command", cmd)); + break; + } + d.add(msg, Sender.valueOf(cmd.name())); + Lang.valueOf("DIALOG_MSG_ADDED_" + cmd.name()).send(player, PlaceholderRegistry.of("msg", msg)); + break; + + case REMOVE: + if (!hasMsg){ + Lang.DIALOG_REMOVE_SYNTAX.send(player); + break; + } + try{ + int index = Integer.parseInt(args[1]); + Message removed = d.getMessages().remove(index); + if (removed != null){ + Lang.DIALOG_MSG_REMOVED.send(player, PlaceholderRegistry.of("msg", removed.text)); + } else + DefaultErrors.sendOutOfBounds(player, index, 0, d.getMessages().size()); + }catch (IllegalArgumentException ex){ + 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{index}: §7\"{msg}§7\"§e by §l{sender}", + PlaceholderRegistry.of("index", i, "msg", dmsg.text, "sender", dmsg.sender.name().toLowerCase()), + PlaceholdersContext.DEFAULT_CONTEXT); + } + break; + + case NOSENDERINSERT: + case NPCINSERT: + case PLAYERINSERT: + if (args.length < 3){ + Lang.DIALOG_MESSAGE_SYNTAX.send(player, PlaceholderRegistry.of("command", cmd + " ")); + break; + } + try{ + 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)); + }catch (NumberFormatException ex){ + DefaultErrors.sendInvalidNumber(player, args[1]); + } + break; + + case EDIT: + if (args.length < 3){ + Lang.DIALOG_MESSAGE_SYNTAX.send(player, PlaceholderRegistry.of("command", cmd + " ")); + break; + } + try{ + Message message = d.getMessages().get(Integer.parseInt(args[1])); + 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){ + DefaultErrors.sendInvalidNumber(player, args[1]); + }catch (IndexOutOfBoundsException ex) { + DefaultErrors.sendOutOfBounds(player, Integer.parseInt(args[1]), 0, d.getMessages().size()); + } + break; + + case ADDSOUND: + if (args.length < 3){ + Lang.TEXTLIST_SYNTAX.send(player, PlaceholderRegistry.of("command", "addSound ")); + break; + } + try{ + Message imsg = d.getMessages().get(Integer.parseInt(args[1])); + Lang.DIALOG_SOUND_ADDED.send(player, PlaceholderRegistry.of("sound", imsg.sound = args[2], "msg", args[1])); + }catch (IllegalArgumentException ex){ + DefaultErrors.sendInvalidNumber(player, args[1]); + }catch (IndexOutOfBoundsException ex) { + DefaultErrors.sendOutOfBounds(player, Integer.parseInt(args[1]), 0, d.getMessages().size()); + } + break; + + case SETTIME: + if (args.length < 3) { + Lang.TEXTLIST_SYNTAX.send(player, PlaceholderRegistry.of("command", "setTime