diff --git a/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java b/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java index 6827a778..7b2d8f17 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java +++ b/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java @@ -17,16 +17,33 @@ package net.momirealms.customfishing.api; +import net.momirealms.customfishing.api.mechanic.action.ActionManager; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.event.EventManager; +import net.momirealms.customfishing.api.mechanic.misc.placeholder.PlaceholderManager; +import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; import net.momirealms.customfishing.common.plugin.CustomFishingPlugin; +import net.momirealms.customfishing.common.sender.SenderFactory; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +import java.io.File; + +import static java.util.Objects.requireNonNull; public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin { private static BukkitCustomFishingPlugin instance; + private final Plugin boostrap = requireNonNull(Bukkit.getPluginManager().getPlugin("CustomFishing")); protected EventManager eventManager; protected ConfigManager configManager; + protected RequirementManager requirementManager; + protected ActionManager actionManager; + protected SenderFactory senderFactory; + protected PlaceholderManager placeholderManager; public BukkitCustomFishingPlugin() { instance = this; @@ -47,4 +64,28 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin { public ConfigManager getConfigManager() { return configManager; } + + public RequirementManager getRequirementManager() { + return requirementManager; + } + + public ActionManager getActionManager() { + return actionManager; + } + + public SenderFactory getSenderFactory() { + return senderFactory; + } + + public File getDataFolder() { + return boostrap.getDataFolder(); + } + + public PlaceholderManager getPlaceholderManager() { + return placeholderManager; + } + + public Plugin getBoostrap() { + return boostrap; + } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java deleted file mode 100644 index 922db18c..00000000 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.manager; - -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Map; - -public interface PlaceholderManager { - - /** - * Register a custom placeholder - * - * @param placeholder for instance {level} - * @param original for instance %player_level% - * @return success or not, it would fail if the placeholder has been registered - */ - boolean registerCustomPlaceholder(String placeholder, String original); - - /** - * Set placeholders in a text string for a player. - * - * @param player The player for whom the placeholders should be set. - * @param text The text string containing placeholders. - * @return The text string with placeholders replaced if PlaceholderAPI is available; otherwise, the original text. - */ - String setPlaceholders(Player player, String text); - - /** - * Set placeholders in a text string for an offline player. - * - * @param player The offline player for whom the placeholders should be set. - * @param text The text string containing placeholders. - * @return The text string with placeholders replaced if PlaceholderAPI is available; otherwise, the original text. - */ - String setPlaceholders(OfflinePlayer player, String text); - - /** - * Detect and extract placeholders from a text string. - * - * @param text The text string to search for placeholders. - * @return A list of detected placeholders in the text. - */ - List detectPlaceholders(String text); - - /** - * Get the value associated with a single placeholder. - * - * @param player The player for whom the placeholders are being resolved (nullable). - * @param placeholder The placeholder to look up. - * @param placeholders A map of placeholders to their corresponding values. - * @return The value associated with the placeholder, or the original placeholder if not found. - */ - String getSingleValue(@Nullable Player player, String placeholder, Map placeholders); - - /** - * Parse a text string by replacing placeholders with their corresponding values. - * - * @param player The offline player for whom the placeholders are being resolved (nullable). - * @param text The text string containing placeholders. - * @param placeholders A map of placeholders to their corresponding values. - * @return The text string with placeholders replaced by their values. - */ - String parse(@Nullable OfflinePlayer player, String text, Map placeholders); - - /** - * Parse a list of text strings by replacing placeholders with their corresponding values. - * - * @param player The player for whom the placeholders are being resolved (can be null for offline players). - * @param list The list of text strings containing placeholders. - * @param replacements A map of custom replacements for placeholders. - * @return The list of text strings with placeholders replaced by their values. - */ - List parse(@Nullable OfflinePlayer player, List list, Map replacements); - - /** - * Get an expression's value - * @param player player - * @param formula formula - * @param vars vars - * @return result - */ - double getExpressionValue(Player player, String formula, Map vars); - - /** - * Get an expression's value - * @param formula formula - * @return result - */ - double getExpressionValue(String formula); -} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionFactory.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionFactory.java index deb59304..a3d526e0 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionFactory.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionFactory.java @@ -30,5 +30,5 @@ public interface ActionFactory { * @param args the args containing the arguments needed to build the action * @return the constructed action */ - Action process(Object args); + Action process(Object args, double chance); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionManager.java index 7e516897..12e44807 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionManager.java @@ -22,106 +22,81 @@ import net.momirealms.customfishing.api.mechanic.context.Context; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; import java.util.List; +/** + * The ActionManager interface manages custom action types and provides methods for handling actions. + * + * @param the type of the context in which the actions are triggered. + */ public interface ActionManager { /** - * Registers an ActionFactory for a specific action type. - * This method allows you to associate an ActionFactory with a custom action type. + * Registers a custom action type with its corresponding factory. * - * @param type The custom action type to register. - * @param actionFactory The ActionFactory responsible for creating actions of the specified type. - * @return True if the registration was successful (the action type was not already registered), false otherwise. + * @param type The type identifier of the action. + * @param actionFactory The factory responsible for creating instances of the action. + * @return True if registration was successful, false if the type is already registered. */ boolean registerAction(String type, ActionFactory actionFactory); /** - * Unregisters an ActionFactory for a specific action type. - * This method allows you to remove the association between an action type and its ActionFactory. + * Unregisters a custom action type. * - * @param type The custom action type to unregister. - * @return True if the action type was successfully unregistered, false if it was not found. + * @param type The type identifier of the action to unregister. + * @return True if unregistration was successful, false if the type is not registered. */ boolean unregisterAction(String type); /** - * Retrieves an Action object based on the configuration provided in a ConfigurationSection. - * This method reads the type of action from the section, obtains the corresponding ActionFactory, - * and builds an Action object using the specified values and chance. - *

- * events: - * success: - * action_1: <- section - * ... + * Checks if an action type is registered. * - * @param section The ConfigurationSection containing the action configuration. - * @return An Action object created based on the configuration, or an EmptyAction instance if the action type is invalid. + * @param type The type identifier of the action. + * @return True if the action type is registered, otherwise false. */ - Action getAction(Section section); + boolean hasAction(@NotNull String type); /** - * Retrieves a mapping of ActionTriggers to arrays of Actions from a ConfigurationSection. - * This method iterates through the provided ConfigurationSection to extract action triggers - * and their associated arrays of Actions. - *

- * events: <- section - * success: - * action_1: - * ... + * Retrieves the action factory for the specified action type. * - * @param section The ConfigurationSection containing action mappings. - * @return A HashMap where keys are ActionTriggers and values are arrays of Action objects. - */ - HashMap[]> getActionMap(Section section); - - /** - * Retrieves an array of Action objects from a ConfigurationSection. - * This method iterates through the provided ConfigurationSection to extract Action configurations - * and build an array of Action objects. - *

- * events: - * success: <- section - * action_1: - * ... - * - * @param section The ConfigurationSection containing action configurations. - * @return An array of Action objects created based on the configurations in the section. - */ - @NotNull - Action[] getActions(@NotNull Section section); - - /** - * Retrieves an ActionFactory associated with a specific action type. - * - * @param type The action type for which to retrieve the ActionFactory. - * @return The ActionFactory associated with the specified action type, or null if not found. + * @param type The type identifier of the action. + * @return The action factory for the specified type, or null if no factory is found. */ @Nullable ActionFactory getActionFactory(@NotNull String type); /** - * Retrieves a mapping of success times to corresponding arrays of actions from a ConfigurationSection. - *

- * events: - * success-times: <- section - * 1: - * action_1: - * ... + * Parses an action from a configuration section. * - * @param section The ConfigurationSection containing success times actions. - * @return A HashMap where success times associated with actions. + * @param section The configuration section containing the action definition. + * @return The parsed action. */ - @NotNull - HashMap[]> getTimesActionMap(@NotNull Section section); + Action parseAction(Section section); /** - * Triggers a list of actions with the given condition. + * Parses an array of actions from a configuration section. + * + * @param section The configuration section containing the action definitions. + * @return An array of parsed actions. + */ + @NotNull + Action[] parseActions(@NotNull Section section); + + /** + * Parses an action from the given type and arguments. + * + * @param type The type identifier of the action. + * @param args The arguments for the action. + * @return The parsed action. + */ + Action parseAction(@NotNull String type, @NotNull Object args); + + /** + * Triggers a list of actions with the given context. * If the list of actions is not null, each action in the list is triggered. * - * @param actions The list of actions to trigger. * @param context The context associated with the actions. + * @param actions The list of actions to trigger. */ static void trigger(@NotNull Context context, @Nullable List> actions) { if (actions != null) @@ -129,6 +104,13 @@ public interface ActionManager { action.trigger(context); } + /** + * Triggers an array of actions with the given context. + * If the array of actions is not null, each action in the array is triggered. + * + * @param context The context associated with the actions. + * @param actions The array of actions to trigger. + */ static void trigger(@NotNull Context context, @Nullable Action[] actions) { if (actions != null) for (Action action : actions) diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/EmptyAction.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/EmptyAction.java new file mode 100644 index 00000000..401c6f5c --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/EmptyAction.java @@ -0,0 +1,17 @@ +package net.momirealms.customfishing.api.mechanic.action; + +import net.momirealms.customfishing.api.mechanic.context.Context; +import org.bukkit.entity.Player; + +/** + * An implementation of the Action interface that represents an empty action with no behavior. + * This class serves as a default action to prevent NPE. + */ +public class EmptyAction implements Action { + + public static final EmptyAction INSTANCE = new EmptyAction(); + + @Override + public void trigger(Context context) { + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfig.java index 077d7373..82e3b477 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfig.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfig.java @@ -1,197 +1,227 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package net.momirealms.customfishing.api.mechanic.competition; import net.momirealms.customfishing.api.mechanic.action.Action; -import net.momirealms.customfishing.api.mechanic.competition.info.ActionBarConfigImpl; -import net.momirealms.customfishing.api.mechanic.competition.info.BossBarConfigImpl; +import net.momirealms.customfishing.api.mechanic.competition.info.ActionBarConfig; +import net.momirealms.customfishing.api.mechanic.competition.info.BossBarConfig; import net.momirealms.customfishing.api.mechanic.requirement.Requirement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.bukkit.entity.Player; import java.util.HashMap; -public class CompetitionConfig { +/** + * Interface representing the configuration for a fishing competition. + */ +public interface CompetitionConfig { - private final String key; - private int duration; - private int minPlayers; - private BossBarConfigImpl bossBarConfigImpl; - private ActionBarConfigImpl actionBarConfigImpl; - private Action[] skipActions; - private Action[] startActions; - private Action[] endActions; - private Action[] joinActions; - private Requirement[] requirements; - private CompetitionGoal goal; - private HashMap rewards; + CompetitionGoal DEFAULT_GOAL = CompetitionGoal.CATCH_AMOUNT; + int DEFAULT_DURATION = 300; + int DEFAULT_MIN_PLAYERS = 0; + Requirement[] DEFAULT_REQUIREMENTS = null; + Action[] DEFAULT_SKIP_ACTIONS = null; + Action[] DEFAULT_START_ACTIONS = null; + Action[] DEFAULT_END_ACTIONS = null; + Action[] DEFAULT_JOIN_ACTIONS = null; + HashMap[]> DEFAULT_REWARDS = new HashMap<>(); - public CompetitionConfig(String key) { - this.key = key; - } + /** + * Gets the unique key for the competition. + * + * @return the key for the competition. + */ + String key(); - public String getKey() { - return key; - } + /** + * Gets the duration of the competition in seconds. + * + * @return the duration in seconds. + */ + int durationInSeconds(); - public int getDurationInSeconds() { - return duration; - } + /** + * Gets the minimum number of players required to start the competition. + * + * @return the minimum number of players. + */ + int minPlayersToStart(); - public int getMinPlayersToStart() { - return minPlayers; - } + /** + * Gets the actions to be performed when the competition starts. + * + * @return an array of start actions. + */ + Action[] startActions(); - @Nullable - public Action[] getStartActions() { - return startActions; - } + /** + * Gets the actions to be performed when the competition ends. + * + * @return an array of end actions. + */ + Action[] endActions(); - @Nullable - public Action[] getEndActions() { - return endActions; + /** + * Gets the actions to be performed when a player joins the competition. + * + * @return an array of join actions. + */ + Action[] joinActions(); + + /** + * Gets the actions to be performed when a player skips the competition. + * + * @return an array of skip actions. + */ + Action[] skipActions(); + + /** + * Gets the requirements that players must meet to join the competition. + * + * @return an array of join requirements. + */ + Requirement[] joinRequirements(); + + /** + * Gets the goal of the competition. + * + * @return the competition goal. + */ + CompetitionGoal goal(); + + /** + * Gets the rewards for the competition. + * + * @return a hashmap where the key is a string identifier and the value is an array of actions. + */ + HashMap[]> rewards(); + + /** + * Gets the configuration for the boss bar during the competition. + * + * @return the boss bar configuration. + */ + BossBarConfig bossBarConfig(); + + /** + * Gets the configuration for the action bar during the competition. + * + * @return the action bar configuration. + */ + ActionBarConfig actionBarConfig(); + + /** + * Creates a new builder for the competition configuration. + * + * @return a new builder instance. + */ + static Builder builder() { + return new CompetitionConfigImpl.BuilderImpl(); } /** - * Get the actions to perform if player joined the competition - * - * @return actions + * Builder interface for constructing a CompetitionConfig instance. */ - @Nullable - public Action[] getJoinActions() { - return joinActions; - } + interface Builder { - /** - * Get the actions to perform if the amount of players doesn't meet the requirement - * - * @return actions - */ - @Nullable - public Action[] getSkipActions() { - return skipActions; - } + /** + * Sets the unique key for the competition. + * + * @param key the key for the competition. + * @return the builder instance. + */ + Builder key(String key); - /** - * Get the requirements for participating the competition - * - * @return requirements - */ - @Nullable - public Requirement[] getRequirements() { - return requirements; - } + /** + * Sets the goal of the competition. + * + * @param goal the competition goal. + * @return the builder instance. + */ + Builder goal(CompetitionGoal goal); - @NotNull - public CompetitionGoal getGoal() { - return goal; - } + /** + * Sets the duration of the competition. + * + * @param duration the duration in seconds. + * @return the builder instance. + */ + Builder duration(int duration); - /** - * Get the reward map - * - * @return reward map - */ - public HashMap getRewards() { - return rewards; - } + /** + * Sets the minimum number of players required to start the competition. + * + * @param minPlayers the minimum number of players. + * @return the builder instance. + */ + Builder minPlayers(int minPlayers); - @Nullable - public BossBarConfigImpl getBossBarConfig() { - return bossBarConfigImpl; - } + /** + * Sets the requirements that players must meet to join the competition. + * + * @param joinRequirements an array of join requirements. + * @return the builder instance. + */ + Builder joinRequirements(Requirement[] joinRequirements); - @Nullable - public ActionBarConfigImpl getActionBarConfig() { - return actionBarConfigImpl; - } + /** + * Sets the actions to be performed when a player skips the competition. + * + * @param skipActions an array of skip actions. + * @return the builder instance. + */ + Builder skipActions(Action[] skipActions); - public static Builder builder(String key) { - return new Builder(key); - } + /** + * Sets the actions to be performed when the competition starts. + * + * @param startActions an array of start actions. + * @return the builder instance. + */ + Builder startActions(Action[] startActions); - public static class Builder { + /** + * Sets the actions to be performed when the competition ends. + * + * @param endActions an array of end actions. + * @return the builder instance. + */ + Builder endActions(Action[] endActions); - private final CompetitionConfig config; + /** + * Sets the actions to be performed when a player joins the competition. + * + * @param joinActions an array of join actions. + * @return the builder instance. + */ + Builder joinActions(Action[] joinActions); - public Builder(String key) { - this.config = new CompetitionConfig(key); - } + /** + * Sets the rewards for the competition. + * + * @param rewards a hashmap where the key is a string identifier and the value is an array of actions. + * @return the builder instance. + */ + Builder rewards(HashMap[]> rewards); - public Builder duration(int duration) { - config.duration = duration; - return this; - } + /** + * Sets the configuration for the boss bar during the competition. + * + * @param bossBarConfig the boss bar configuration. + * @return the builder instance. + */ + Builder bossBarConfig(BossBarConfig bossBarConfig); - public Builder minPlayers(int min) { - config.minPlayers = min; - return this; - } + /** + * Sets the configuration for the action bar during the competition. + * + * @param actionBarConfig the action bar configuration. + * @return the builder instance. + */ + Builder actionBarConfig(ActionBarConfig actionBarConfig); - public Builder startActions(Action[] startActions) { - config.startActions = startActions; - return this; - } - - public Builder endActions(Action[] endActions) { - config.endActions = endActions; - return this; - } - - public Builder skipActions(Action[] skipActions) { - config.skipActions = skipActions; - return this; - } - - public Builder joinActions(Action[] joinActions) { - config.joinActions = joinActions; - return this; - } - - @SuppressWarnings("UnusedReturnValue") - public Builder actionbar(ActionBarConfigImpl actionBarConfigImpl) { - config.actionBarConfigImpl = actionBarConfigImpl; - return this; - } - - @SuppressWarnings("UnusedReturnValue") - public Builder bossbar(BossBarConfigImpl bossBarConfigImpl) { - config.bossBarConfigImpl = bossBarConfigImpl; - return this; - } - - public Builder requirements(Requirement[] requirements) { - config.requirements = requirements; - return this; - } - - public Builder goal(CompetitionGoal goal) { - config.goal = goal; - return this; - } - - public Builder rewards(HashMap rewards) { - config.rewards = rewards; - return this; - } - - public CompetitionConfig build() { - return config; - } + /** + * Builds and returns the CompetitionConfig instance. + * + * @return the constructed CompetitionConfig instance. + */ + CompetitionConfig build(); } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfigImpl.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfigImpl.java new file mode 100644 index 00000000..14bad1e3 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfigImpl.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customfishing.api.mechanic.competition; + +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.competition.info.ActionBarConfig; +import net.momirealms.customfishing.api.mechanic.competition.info.BossBarConfig; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import org.bukkit.entity.Player; + +import java.util.HashMap; + +public class CompetitionConfigImpl implements CompetitionConfig { + + private final String key; + private final CompetitionGoal goal; + private final int duration; + private final int minPlayers; + private final Requirement[] joinRequirements; + private final Action[] skipActions; + private final Action[] startActions; + private final Action[] endActions; + private final Action[] joinActions; + private final HashMap[]> rewards; + private final BossBarConfig bossBarConfig; + private final ActionBarConfig actionBarConfig; + + public CompetitionConfigImpl(String key, CompetitionGoal goal, int duration, int minPlayers, Requirement[] joinRequirements, Action[] skipActions, Action[] startActions, Action[] endActions, Action[] joinActions, HashMap[]> rewards, BossBarConfig bossBarConfig, ActionBarConfig actionBarConfig) { + this.key = key; + this.goal = goal; + this.duration = duration; + this.minPlayers = minPlayers; + this.joinRequirements = joinRequirements; + this.skipActions = skipActions; + this.startActions = startActions; + this.endActions = endActions; + this.joinActions = joinActions; + this.rewards = rewards; + this.bossBarConfig = bossBarConfig; + this.actionBarConfig = actionBarConfig; + } + + @Override + public String key() { + return key; + } + + @Override + public int durationInSeconds() { + return duration; + } + + @Override + public int minPlayersToStart() { + return minPlayers; + } + + @Override + public Action[] startActions() { + return startActions; + } + + @Override + public Action[] endActions() { + return endActions; + } + + @Override + public Action[] joinActions() { + return joinActions; + } + + @Override + public Action[] skipActions() { + return skipActions; + } + + @Override + public Requirement[] joinRequirements() { + return joinRequirements; + } + + @Override + public CompetitionGoal goal() { + return goal; + } + + @Override + public HashMap[]> rewards() { + return rewards; + } + + @Override + public BossBarConfig bossBarConfig() { + return bossBarConfig; + } + + @Override + public ActionBarConfig actionBarConfig() { + return actionBarConfig; + } + + public static class BuilderImpl implements Builder { + private String key; + private CompetitionGoal goal = DEFAULT_GOAL; + private int duration = DEFAULT_DURATION; + private int minPlayers = DEFAULT_MIN_PLAYERS; + private Requirement[] joinRequirements = DEFAULT_REQUIREMENTS; + private Action[] skipActions = DEFAULT_SKIP_ACTIONS; + private Action[] startActions = DEFAULT_START_ACTIONS; + private Action[] endActions = DEFAULT_END_ACTIONS; + private Action[] joinActions = DEFAULT_JOIN_ACTIONS; + private HashMap[]> rewards = DEFAULT_REWARDS; + private BossBarConfig bossBarConfig; + private ActionBarConfig actionBarConfig; + @Override + public Builder key(String key) { + this.key = key; + return this; + } + @Override + public Builder goal(CompetitionGoal goal) { + this.goal = goal; + return this; + } + @Override + public Builder duration(int duration) { + this.duration = duration; + return this; + } + @Override + public Builder minPlayers(int minPlayers) { + this.minPlayers = minPlayers; + return this; + } + @Override + public Builder joinRequirements(Requirement[] joinRequirements) { + this.joinRequirements = joinRequirements; + return this; + } + @Override + public Builder skipActions(Action[] skipActions) { + this.skipActions = skipActions; + return this; + } + @Override + public Builder startActions(Action[] startActions) { + this.startActions = startActions; + return this; + } + @Override + public Builder endActions(Action[] endActions) { + this.endActions = endActions; + return this; + } + @Override + public Builder joinActions(Action[] joinActions) { + this.joinActions = joinActions; + return this; + } + @Override + public Builder rewards(HashMap[]> rewards) { + this.rewards = rewards; + return this; + } + @Override + public Builder bossBarConfig(BossBarConfig bossBarConfig) { + this.bossBarConfig = bossBarConfig; + return this; + } + @Override + public Builder actionBarConfig(ActionBarConfig actionBarConfig) { + this.actionBarConfig = actionBarConfig; + return this; + } + @Override + public CompetitionConfig build() { + return new CompetitionConfigImpl(key, goal, duration, minPlayers, joinRequirements, skipActions, startActions, endActions, joinActions, rewards, bossBarConfig, actionBarConfig); + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java index bbb169b6..04d07f51 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java @@ -19,6 +19,7 @@ package net.momirealms.customfishing.api.mechanic.competition; import net.kyori.adventure.key.Key; import net.kyori.adventure.util.Index; +import net.momirealms.customfishing.common.util.RandomUtils; import java.util.concurrent.ThreadLocalRandom; @@ -60,7 +61,7 @@ public final class CompetitionGoal { * @return A randomly selected competition goal. */ public static CompetitionGoal getRandom() { - return CompetitionGoal.values()[ThreadLocalRandom.current().nextInt(CompetitionGoal.values().length - 1)]; + return CompetitionGoal.values()[RandomUtils.generateRandomInt(0, values.length - 1)]; } private final Key key; diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java index 4795d037..759a5a7e 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java @@ -64,7 +64,7 @@ public interface CompetitionManager { * @param serverGroup Whether the competition should start across all servers that connected to Redis * @return True if the competition was started successfully, false otherwise. */ - boolean startCompetition(CompetitionConfig config, boolean force, @Nullable String serverGroup); + boolean startCompetition(CompetitionConfigImpl config, boolean force, @Nullable String serverGroup); /** * Gets the number of seconds until the next competition. @@ -77,7 +77,8 @@ public interface CompetitionManager { * Retrieves the configuration for a competition based on its key. * * @param key The key of the competition configuration to retrieve. - * @return The {@link CompetitionConfig} for the specified key, or {@code null} if no configuration exists with that key. + * @return The {@link CompetitionConfigImpl} for the specified key, or {@code null} if no configuration exists with that key. */ - @Nullable CompetitionConfig getConfig(String key); + @Nullable + CompetitionConfigImpl getConfig(String key); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionPlayer.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionPlayer.java index 4463987c..eb673a42 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionPlayer.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionPlayer.java @@ -19,53 +19,98 @@ package net.momirealms.customfishing.api.mechanic.competition; import org.jetbrains.annotations.NotNull; -public class CompetitionPlayer implements Comparable{ +/** + * Represents a player participating in a fishing competition. + */ +public class CompetitionPlayer implements Comparable { - private static CompetitionPlayer empty = new CompetitionPlayer("", 0); - private long time; private final String player; + private long time; private double score; + /** + * Constructs a new CompetitionPlayer with the specified player name and initial score. + * + * @param player the name of the player. + * @param score the initial score of the player. + */ public CompetitionPlayer(String player, double score) { this.player = player; this.score = score; this.time = System.currentTimeMillis(); } + /** + * Adds the specified score to the player's current score. + * If the added score is positive, updates the player's time to the current time. + * + * @param score the score to add. + */ public void addScore(double score) { this.score += score; if (score <= 0) return; this.time = System.currentTimeMillis(); } + /** + * Sets the player's score to the specified value and updates the player's time to the current time. + * + * @param score the new score for the player. + */ public void setScore(double score) { this.score = score; this.time = System.currentTimeMillis(); } + /** + * Gets the time when the player's score was last updated. + * + * @return the last update time in milliseconds. + */ public long getTime() { return time; } + /** + * Gets the player's current score. + * + * @return the current score. + */ public double getScore() { return this.score; } - public String getPlayer(){ + /** + * Gets the name of the player. + * + * @return the player's name. + */ + public String getPlayer() { return this.player; } + /** + * Compares this player to another CompetitionPlayer for ordering. + * Players are compared first by score, then by time if scores are equal. + * + * @param another the other player to compare to. + */ @Override - public int compareTo(@NotNull CompetitionPlayer competitionPlayer) { - if (competitionPlayer.getScore() != this.score) { - return (competitionPlayer.getScore() > this.score) ? 1 : -1; - } else if (competitionPlayer.getTime() != this.time) { - return (competitionPlayer.getTime() > this.time) ? 1 : -1; + public int compareTo(@NotNull CompetitionPlayer another) { + if (another.getScore() != this.score) { + return (another.getScore() > this.score) ? 1 : -1; + } else if (another.getTime() != this.time) { + return (another.getTime() > this.time) ? 1 : -1; } else { return 0; } } + /** + * Returns a string representation of the CompetitionPlayer. + * + * @return a string containing the player's name, score, and last update time. + */ @Override public String toString() { return "CompetitionPlayer[" + diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/FishingCompetition.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/FishingCompetition.java index b2c9a62e..8e984f1e 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/FishingCompetition.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/FishingCompetition.java @@ -91,7 +91,8 @@ public interface FishingCompetition { * * @return The configuration of the fishing competition. */ - @NotNull CompetitionConfig getConfig(); + @NotNull + CompetitionConfigImpl getConfig(); /** * Gets the goal of the fishing competition. @@ -105,7 +106,8 @@ public interface FishingCompetition { * * @return The ranking data for the fishing competition. */ - @NotNull Ranking getRanking(); + @NotNull + RankingProvider getRanking(); /** * Gets the cached placeholders for the fishing competition. diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/Ranking.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/RankingProvider.java similarity index 99% rename from api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/Ranking.java rename to api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/RankingProvider.java index 7adc09a9..e235b0b5 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/Ranking.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/RankingProvider.java @@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Iterator; -public interface Ranking { +public interface RankingProvider { /** * Clears the list of competition players. diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/AbstractCompetitionInfo.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/AbstractCompetitionInfo.java index ecf84ed1..d241e1ac 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/AbstractCompetitionInfo.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/AbstractCompetitionInfo.java @@ -27,12 +27,14 @@ public abstract class AbstractCompetitionInfo { protected int switchInterval; protected boolean showToAll; protected String[] texts; + protected boolean enabled; - protected AbstractCompetitionInfo(int refreshRate, int switchInterval, boolean showToAll, String[] texts) { + protected AbstractCompetitionInfo(boolean enabled, int refreshRate, int switchInterval, boolean showToAll, String[] texts) { this.refreshRate = refreshRate; this.switchInterval = switchInterval; this.showToAll = showToAll; this.texts = texts; + this.enabled = enabled; } /** @@ -70,4 +72,13 @@ public abstract class AbstractCompetitionInfo { public String[] texts() { return texts; } + + /** + * If the feature is enabled. + * + * @return enabled or not. + */ + public boolean enabled() { + return enabled; + } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfig.java index b8122d10..10eb0a4b 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfig.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfig.java @@ -35,6 +35,13 @@ public interface ActionBarConfig { */ String[] texts(); + /** + * Is action bar enabled + * + * @return enabled or not + */ + boolean enabled(); + /** * Creates a new builder instance for constructing {@code ActionBarConfig} objects. * @@ -81,6 +88,8 @@ public interface ActionBarConfig { */ Builder text(String[] texts); + Builder enable(boolean enable); + /** * Builds the {@code ActionBarConfig} object with the configured settings. * diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfigImpl.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfigImpl.java index f7510460..b0a359b4 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfigImpl.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/ActionBarConfigImpl.java @@ -19,8 +19,8 @@ package net.momirealms.customfishing.api.mechanic.competition.info; public class ActionBarConfigImpl extends AbstractCompetitionInfo implements ActionBarConfig { - public ActionBarConfigImpl(int refreshRate, int switchInterval, boolean showToAll, String[] texts) { - super(refreshRate, switchInterval, showToAll, texts); + public ActionBarConfigImpl(boolean enable, int refreshRate, int switchInterval, boolean showToAll, String[] texts) { + super(enable, refreshRate, switchInterval, showToAll, texts); } public static class BuilderImpl implements Builder { @@ -28,29 +28,35 @@ public class ActionBarConfigImpl extends AbstractCompetitionInfo implements Acti private int switchInterval = DEFAULT_SWITCH_INTERVAL; private boolean showToAll = DEFAULT_VISIBILITY; private String[] texts = DEFAULT_TEXTS; + private boolean enable = true; @Override - public BuilderImpl showToAll(boolean showToAll) { + public Builder showToAll(boolean showToAll) { this.showToAll = showToAll; return this; } @Override - public BuilderImpl refreshRate(int rate) { + public Builder refreshRate(int rate) { this.refreshRate = rate; return this; } @Override - public BuilderImpl switchInterval(int interval) { + public Builder switchInterval(int interval) { this.switchInterval = interval; return this; } @Override - public BuilderImpl text(String[] texts) { + public Builder text(String[] texts) { this.texts = texts; return this; } @Override - public ActionBarConfigImpl build() { - return new ActionBarConfigImpl(refreshRate, switchInterval, showToAll, texts); + public Builder enable(boolean enable) { + this.enable = enable; + return this; + } + @Override + public ActionBarConfig build() { + return new ActionBarConfigImpl(enable, refreshRate, switchInterval, showToAll, texts); } } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfig.java index 08c55a0e..5db5a10f 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfig.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfig.java @@ -53,6 +53,13 @@ public interface BossBarConfig { */ BossBar.Overlay overlay(); + /** + * Is boss bar enabled + * + * @return enabled or not + */ + boolean enabled(); + /** * Creates a new builder instance for constructing {@code BossBarConfig} objects. * @@ -115,6 +122,8 @@ public interface BossBarConfig { */ Builder overlay(BossBar.Overlay overlay); + Builder enable(boolean enable); + /** * Builds the {@code BossBarConfig} object with the configured settings. * diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfigImpl.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfigImpl.java index a00ed7d6..f2a50971 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfigImpl.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/info/BossBarConfigImpl.java @@ -24,8 +24,8 @@ public class BossBarConfigImpl extends AbstractCompetitionInfo implements BossBa private final BossBar.Color color; private final BossBar.Overlay overlay; - public BossBarConfigImpl(int refreshRate, int switchInterval, boolean showToAll, String[] texts, BossBar.Color color, BossBar.Overlay overlay) { - super(refreshRate, switchInterval, showToAll, texts); + public BossBarConfigImpl(boolean enable, int refreshRate, int switchInterval, boolean showToAll, String[] texts, BossBar.Color color, BossBar.Overlay overlay) { + super(enable, refreshRate, switchInterval, showToAll, texts); this.color = color; this.overlay = overlay; } @@ -46,40 +46,46 @@ public class BossBarConfigImpl extends AbstractCompetitionInfo implements BossBa private boolean showToAll = DEFAULT_VISIBILITY; private String[] texts = DEFAULT_TEXTS; private BossBar.Overlay overlay = DEFAULT_OVERLAY; - public BossBar.Color color = DEFAULT_COLOR; + private BossBar.Color color = DEFAULT_COLOR; + private boolean enable = true; @Override - public BuilderImpl showToAll(boolean showToAll) { + public Builder showToAll(boolean showToAll) { this.showToAll = showToAll; return this; } @Override - public BuilderImpl refreshRate(int rate) { + public Builder refreshRate(int rate) { this.refreshRate = rate; return this; } @Override - public BuilderImpl switchInterval(int interval) { + public Builder switchInterval(int interval) { this.switchInterval = interval; return this; } @Override - public BuilderImpl text(String[] texts) { + public Builder text(String[] texts) { this.texts = texts; return this; } @Override - public BuilderImpl color(BossBar.Color color) { + public Builder color(BossBar.Color color) { this.color = color; return this; } @Override - public BuilderImpl overlay(BossBar.Overlay overlay) { + public Builder overlay(BossBar.Overlay overlay) { this.overlay = overlay; return this; } @Override - public BossBarConfigImpl build() { - return new BossBarConfigImpl(refreshRate, switchInterval, showToAll, texts, color, overlay); + public Builder enable(boolean enable) { + this.enable = enable; + return this; + } + @Override + public BossBarConfig build() { + return new BossBarConfigImpl(enable, refreshRate, switchInterval, showToAll, texts, color, overlay); } } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/Context.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/Context.java index 3e5994a4..46d81e71 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/Context.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/Context.java @@ -18,7 +18,6 @@ package net.momirealms.customfishing.api.mechanic.context; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; @@ -40,6 +39,13 @@ public interface Context { */ Map, Object> args(); + /** + * Converts the context to a map of placeholders + * + * @return a map of placeholders + */ + Map toPlaceholderMap(); + /** * Adds or updates an argument in the context. * This method allows adding a new argument or updating the value of an existing argument. @@ -75,7 +81,7 @@ public interface Context { * @param player the player to be used as the holder of the context. * @return a new Context instance with the specified player as the holder. */ - static Context player(@NotNull Player player) { + static Context player(@Nullable Player player) { return new PlayerContextImpl(player); } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java index a588eafd..a01cce4b 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java @@ -32,6 +32,7 @@ public class ContextKeys { public static final ContextKeys TYPE = of("type", String.class); public static final ContextKeys SIZE = of("size", Float.class); public static final ContextKeys PRICE = of("price", Double.class); + public static final ContextKeys SURROUNDING = of("surrounding", String.class); private final String key; private final Class type; diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/PlayerContextImpl.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/PlayerContextImpl.java index dc1dc1df..6854d8ae 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/PlayerContextImpl.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/PlayerContextImpl.java @@ -19,7 +19,7 @@ package net.momirealms.customfishing.api.mechanic.context; import org.bukkit.Location; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; @@ -39,8 +39,9 @@ public final class PlayerContextImpl implements Context { * * @param player the player to be associated with this context. */ - public PlayerContextImpl(@NotNull Player player) { + public PlayerContextImpl(@Nullable Player player) { this.player = player; + if (player == null) return; final Location location = player.getLocation(); arg(ContextKeys.LOCATION, location) .arg(ContextKeys.X, location.getBlockX()) @@ -49,47 +50,32 @@ public final class PlayerContextImpl implements Context { .arg(ContextKeys.WORLD, location.getWorld().getName()); } - /** - * Retrieves the map of arguments associated with this context. - * - * @return a map where the keys are argument names and the values are argument values. - */ @Override public Map, Object> args() { return args; } - /** - * Adds an argument to the context and returns the context itself - * to allow for method chaining. - * - * @param key the name of the argument to add. - * @param value the value of the argument to add. - * @return the PlayerContextImpl instance to allow for method chaining. - */ + @Override + public Map toPlaceholderMap() { + HashMap placeholders = new HashMap<>(); + for (Map.Entry, Object> entry : args.entrySet()) { + placeholders.put(entry.getKey().toString(), entry.getValue().toString()); + } + return placeholders; + } + @Override public PlayerContextImpl arg(ContextKeys key, C value) { args.put(key, value); return this; } - /** - * Retrieves the value of a specific argument from the context. - * - * @param key the name of the argument to retrieve. - * @return the value of the argument, or null if no argument with the given key exists. - */ @Override @SuppressWarnings("unchecked") public C arg(ContextKeys key) { return (C) args.get(key); } - /** - * Gets the player associated with this context. - * - * @return the player object associated with this context. - */ @Override public Player getHolder() { return player; diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectProperties.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectProperties.java index b901b245..2e8d542d 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectProperties.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectProperties.java @@ -23,6 +23,8 @@ public class EffectProperties { public static final EffectProperties LAVA_FISHING = of("lava", Boolean.class); public static final EffectProperties VOID_FISHING = of("void", Boolean.class); + // It's not actually used because it's a vanilla mechanic + public static final EffectProperties WATER_FISHING = of("water", Boolean.class); private final String key; private final Class type; diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingManager.java index 65580cbb..aef686c6 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingManager.java @@ -17,95 +17,7 @@ package net.momirealms.customfishing.api.mechanic.fishing; -import net.momirealms.customfishing.api.mechanic.effect.Effect; -import net.momirealms.customfishing.api.mechanic.game.GameInstance; -import net.momirealms.customfishing.api.mechanic.game.GameSettings; -import net.momirealms.customfishing.api.mechanic.game.GamingPlayer; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.UUID; - public interface FishingManager { - /** - * Removes a fishing hook entity associated with a given player's UUID. - * - * @param uuid The UUID of the player - * @return {@code true} if the fishing hook was successfully removed, {@code false} otherwise. - */ - boolean removeHook(UUID uuid); - /** - * Retrieves a FishHook object associated with the provided player's UUID - * - * @param uuid The UUID of the player - * @return fishhook entity, null if not exists - */ - @Nullable FishHook getHook(UUID uuid); - - /** - * Sets the temporary fishing state for a player. - * - * @param player The player for whom to set the temporary fishing state. - * @param tempFishingState The temporary fishing state to set for the player. - */ - void setTempFishingState(Player player, TempFishingState tempFishingState); - - /** - * Gets the {@link TempFishingState} object associated with the given UUID. - * - * @param uuid The UUID of the player. - * @return The {@link TempFishingState} object if found, or {@code null} if not found. - */ - @Nullable TempFishingState getTempFishingState(UUID uuid); - - /** - * Removes the temporary fishing state associated with a player. - * - * @param player The player whose temporary fishing state should be removed. - */ - @Nullable TempFishingState removeTempFishingState(Player player); - - /** - * Processes the game result for a gaming player - * - * @param gamingPlayer The gaming player whose game result should be processed. - */ - void processGameResult(GamingPlayer gamingPlayer); - - /** - * Starts a fishing game for the specified player with the given condition and effect. - * - * @param player The player starting the fishing game. - * @param playerContext The condition used to determine the game. - * @param effect The effect applied to the game. - */ - boolean startFishingGame(Player player, PlayerContext playerContext, Effect effect); - - /** - * Starts a fishing game for the specified player with the given settings and game instance. - * - * @param player The player starting the fishing game. - * @param settings The game settings for the fishing game. - * @param gameInstance The instance of the fishing game to start. - */ - boolean startFishingGame(Player player, GameSettings settings, GameInstance gameInstance); - - /** - * Checks if a player with the given UUID has cast their fishing hook. - * - * @param uuid The UUID of the player to check. - * @return {@code true} if the player has cast their fishing hook, {@code false} otherwise. - */ - boolean hasPlayerCastHook(UUID uuid); - - /** - * Gets the {@link GamingPlayer} object associated with the given UUID. - * - * @param uuid The UUID of the player. - * @return The {@link GamingPlayer} object if found, or {@code null} if not found. - */ - @Nullable GamingPlayer getGamingPlayer(UUID uuid); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/placeholder/PlaceholderManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/placeholder/PlaceholderManager.java new file mode 100644 index 00000000..cb834a50 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/placeholder/PlaceholderManager.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customfishing.api.mechanic.misc.placeholder; + +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +public interface PlaceholderManager { + + Pattern PATTERN = Pattern.compile("\\{[^{}]+}"); + + /** + * Registers a custom placeholder with its corresponding original string. + * + * @param placeholder the placeholder to register. + * @param original the original string corresponding to the placeholder. + * @return true if the placeholder was successfully registered, false if it already exists. + */ + boolean registerCustomPlaceholder(String placeholder, String original); + + /** + * Resolves all placeholders within a given text. + * + * @param text the text to resolve placeholders in. + * @return a list of found placeholders. + */ + List resolvePlaceholders(String text); + + /** + * Parses a single placeholder for a specified player, optionally using a map of replacements. + * + * @param player the player for whom the placeholder should be parsed. + * @param placeholder the placeholder to parse. + * @param replacements a map of replacement strings for placeholders. + * @return the parsed placeholder string. + */ + String parseSingle(@Nullable OfflinePlayer player, String placeholder, Map replacements); + + /** + * Parses all placeholders in the given text for a specified player, optionally using a map of replacements. + * + * @param player the player for whom the placeholders should be parsed. + * @param text the text containing placeholders. + * @param replacements a map of replacement strings for placeholders. + * @return the text with parsed placeholders. + */ + String parse(@Nullable OfflinePlayer player, String text, Map replacements); + + /** + * Parses all placeholders in a list of strings for a specified player, optionally using a map of replacements. + * + * @param player the player for whom the placeholders should be parsed. + * @param list the list of strings containing placeholders. + * @param replacements a map of replacement strings for placeholders. + * @return the list of strings with parsed placeholders. + */ + List parse(@Nullable OfflinePlayer player, List list, Map replacements); +} diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/requirement/EmptyRequirement.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/EmptyRequirement.java similarity index 69% rename from core/src/main/java/net/momirealms/customfishing/mechanic/requirement/EmptyRequirement.java rename to api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/EmptyRequirement.java index 1c2d5251..e82217fc 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/requirement/EmptyRequirement.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/EmptyRequirement.java @@ -15,19 +15,20 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.requirement; +package net.momirealms.customfishing.api.mechanic.requirement; -import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import net.momirealms.customfishing.api.mechanic.context.Context; +import org.bukkit.entity.Player; /** * Represents an empty requirement that always returns true when checking conditions. */ -public class EmptyRequirement implements Requirement { +public class EmptyRequirement implements Requirement { - public static EmptyRequirement instance = new EmptyRequirement(); + public static final EmptyRequirement INSTANCE = new EmptyRequirement(); @Override - public boolean isConditionMet(PlayerContext playerContext) { + public boolean isSatisfied(Context context) { return true; } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/RequirementManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/RequirementManager.java index d9b3cf19..fbfcf2d7 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/RequirementManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/RequirementManager.java @@ -22,6 +22,13 @@ import net.momirealms.customfishing.api.mechanic.context.Context; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + +/** + * The RequirementManager interface manages custom requirement types and provides methods for handling requirements. + * + * @param the type of the context in which the requirements are evaluated. + */ public interface RequirementManager { /** @@ -42,52 +49,13 @@ public interface RequirementManager { boolean unregisterRequirement(@NotNull String type); /** - * Retrieves an array of requirements based on a configuration section. + * Checks if a requirement type is registered. * - * @param section The configuration section containing requirement definitions. - * @param runActions A flag indicating whether to use advanced requirements. - * @return An array of Requirement objects based on the configuration section - */ - @Nullable - Requirement[] getRequirements(@NotNull Section section, boolean runActions); - - /** - * If a requirement type exists - * - * @param type type - * @return exists or not + * @param type The type identifier of the requirement. + * @return True if the requirement type is registered, otherwise false. */ boolean hasRequirement(@NotNull String type); - /** - * Retrieves a Requirement object based on a configuration section and advanced flag. - *

- * requirement_1: <- section - * type: xxx - * value: xxx - * - * @param section The configuration section containing requirement definitions. - * @param runActions A flag indicating whether to use advanced requirements. - * @return A Requirement object based on the configuration section, or an EmptyRequirement if the section is null or invalid. - */ - @NotNull - Requirement getRequirement(@NotNull Section section, boolean runActions); - - /** - * Gets a requirement based on the provided type and value. - * If a valid RequirementFactory is found for the type, it is used to create the requirement. - * If no factory is found, a warning is logged, and an empty requirement instance is returned. - *

- * world: <- type - * - world <- value - * - * @param type The type representing the requirement type. - * @param value The value associated with the requirement. - * @return A Requirement instance based on the type and value, or an EmptyRequirement if the type is invalid. - */ - @NotNull - Requirement getRequirement(@NotNull String type, @NotNull Object value); - /** * Retrieves a RequirementFactory based on the specified requirement type. * @@ -97,6 +65,44 @@ public interface RequirementManager { @Nullable RequirementFactory getRequirementFactory(@NotNull String type); + /** + * Retrieves an array of requirements based on a configuration section. + * + * @param section The configuration section containing requirement definitions. + * @param runActions A flag indicating whether to use advanced requirements. + * @return An array of Requirement objects based on the configuration section. + */ + @NotNull + Requirement[] parseRequirements(@NotNull Section section, boolean runActions); + + /** + * Retrieves a Requirement object based on a configuration section and advanced flag. + * + * @param section The configuration section containing requirement definitions. + * @param runActions A flag indicating whether to use advanced requirements. + * @return A Requirement object based on the configuration section, or an EmptyRequirement if the section is null or invalid. + */ + @NotNull + Requirement parseRequirement(@NotNull Section section, boolean runActions); + + /** + * Gets a requirement based on the provided type and value. + * If a valid RequirementFactory is found for the type, it is used to create the requirement. + * + * @param type The type representing the requirement type. + * @param value The value associated with the requirement. + * @return A Requirement instance based on the type and value, or an EmptyRequirement if the type is invalid. + */ + @NotNull + Requirement parseRequirement(@NotNull String type, @NotNull Object value); + + /** + * Checks if all requirements in the provided array are satisfied within the given context. + * + * @param context The context in which the requirements are evaluated. + * @param requirements An array of requirements to check. + * @return True if all requirements are satisfied, otherwise false. + */ static boolean isSatisfied(Context context, @Nullable Requirement[] requirements) { if (requirements == null) return true; for (Requirement requirement : requirements) { @@ -106,4 +112,14 @@ public interface RequirementManager { } return true; } + + static boolean isSatisfied(Context context, @Nullable List> requirements) { + if (requirements == null) return true; + for (Requirement requirement : requirements) { + if (!requirement.isSatisfied(context)) { + return false; + } + } + return true; + } } diff --git a/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCommandFeature.java b/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCommandFeature.java index a0ea4ada..c8d7d40c 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCommandFeature.java +++ b/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCommandFeature.java @@ -9,11 +9,11 @@ import org.incendo.cloud.context.CommandContext; public abstract class AbstractCommandFeature implements CommandFeature { - protected final CustomFishingCommandManager customFishingCommandManager; + protected final CustomFishingCommandManager commandManager; protected CommandConfig commandConfig; - public AbstractCommandFeature(CustomFishingCommandManager customFishingCommandManager) { - this.customFishingCommandManager = customFishingCommandManager; + public AbstractCommandFeature(CustomFishingCommandManager commandManager) { + this.commandManager = commandManager; } protected abstract SenderFactory getSenderFactory(); @@ -44,17 +44,17 @@ public abstract class AbstractCommandFeature implements CommandFeature { if (context.flags().hasFlag("silent")) { return; } - customFishingCommandManager.handleCommandFeedback((C) context.sender(), key, args); + commandManager.handleCommandFeedback((C) context.sender(), key, args); } @Override public void handleFeedback(C sender, TranslatableComponent.Builder key, Component... args) { - customFishingCommandManager.handleCommandFeedback(sender, key, args); + commandManager.handleCommandFeedback(sender, key, args); } @Override public CustomFishingCommandManager getCustomFishingCommandManager() { - return customFishingCommandManager; + return commandManager; } @Override diff --git a/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCustomFishingCommandManager.java b/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCommandManager.java similarity index 97% rename from common/src/main/java/net/momirealms/customfishing/common/command/AbstractCustomFishingCommandManager.java rename to common/src/main/java/net/momirealms/customfishing/common/command/AbstractCommandManager.java index 0e1541ad..79c070f5 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCustomFishingCommandManager.java +++ b/common/src/main/java/net/momirealms/customfishing/common/command/AbstractCommandManager.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -public abstract class AbstractCustomFishingCommandManager implements CustomFishingCommandManager { +public abstract class AbstractCommandManager implements CustomFishingCommandManager { protected final HashSet> registeredRootCommandComponents = new HashSet<>(); protected final HashSet> registeredFeatures = new HashSet<>(); @@ -38,7 +38,7 @@ public abstract class AbstractCustomFishingCommandManager implements CustomFi private TriConsumer feedbackConsumer; - public AbstractCustomFishingCommandManager(CustomFishingPlugin plugin, CommandManager commandManager) { + public AbstractCommandManager(CustomFishingPlugin plugin, CommandManager commandManager) { this.commandManager = commandManager; this.plugin = plugin; this.inject(); diff --git a/compatibility/build.gradle.kts b/compatibility/build.gradle.kts index bfb8bac9..fe2209ed 100644 --- a/compatibility/build.gradle.kts +++ b/compatibility/build.gradle.kts @@ -1,6 +1,19 @@ dependencies { compileOnly(project(":common")) compileOnly(project(":api")) + // papi + compileOnly("me.clip:placeholderapi:2.11.5") + // server + compileOnly("dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT") + + // local jars + compileOnly(files("libs/AdvancedEnchantments-api.jar")) + compileOnly(files("libs/BattlePass-4.0.6-api.jar")) + compileOnly(files("libs/RealisticSeasons-api.jar")) + compileOnly(files("libs/mcMMO-api.jar")) + compileOnly(files("libs/ClueScrolls-4.8.7-api.jar")) + compileOnly(files("libs/notquests-5.17.1.jar")) + compileOnly(files("libs/zaphkiel-2.0.24.jar")) } java { diff --git a/core/libs/AdvancedEnchantments-api.jar b/compatibility/libs/AdvancedEnchantments-api.jar similarity index 100% rename from core/libs/AdvancedEnchantments-api.jar rename to compatibility/libs/AdvancedEnchantments-api.jar diff --git a/core/libs/BattlePass-4.0.6-api.jar b/compatibility/libs/BattlePass-4.0.6-api.jar similarity index 100% rename from core/libs/BattlePass-4.0.6-api.jar rename to compatibility/libs/BattlePass-4.0.6-api.jar diff --git a/core/libs/ClueScrolls-4.8.7-api.jar b/compatibility/libs/ClueScrolls-4.8.7-api.jar similarity index 100% rename from core/libs/ClueScrolls-4.8.7-api.jar rename to compatibility/libs/ClueScrolls-4.8.7-api.jar diff --git a/core/libs/RealisticSeasons-api.jar b/compatibility/libs/RealisticSeasons-api.jar similarity index 100% rename from core/libs/RealisticSeasons-api.jar rename to compatibility/libs/RealisticSeasons-api.jar diff --git a/core/libs/mcMMO-api.jar b/compatibility/libs/mcMMO-api.jar similarity index 100% rename from core/libs/mcMMO-api.jar rename to compatibility/libs/mcMMO-api.jar diff --git a/core/libs/notquests-5.17.1.jar b/compatibility/libs/notquests-5.17.1.jar similarity index 100% rename from core/libs/notquests-5.17.1.jar rename to compatibility/libs/notquests-5.17.1.jar diff --git a/core/libs/zaphkiel-2.0.24.jar b/compatibility/libs/zaphkiel-2.0.24.jar similarity index 100% rename from core/libs/zaphkiel-2.0.24.jar rename to compatibility/libs/zaphkiel-2.0.24.jar diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/ParseUtils.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/PlaceholderAPIUtils.java similarity index 79% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/ParseUtils.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/PlaceholderAPIUtils.java index b71dc732..fd15330e 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/ParseUtils.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/PlaceholderAPIUtils.java @@ -15,19 +15,19 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.papi; +package net.momirealms.customfishing.bukkit.compatibility; import me.clip.placeholderapi.PlaceholderAPI; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -public class ParseUtils { +public class PlaceholderAPIUtils { - public static String setPlaceholders(Player player, String text) { + public static String parse(Player player, String text) { return PlaceholderAPI.setPlaceholders(player, text); } - public static String setPlaceholders(OfflinePlayer player, String text) { + public static String parse(OfflinePlayer player, String text) { return PlaceholderAPI.setPlaceholders(player, text); } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/VaultHook.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/VaultHook.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/VaultHook.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/VaultHook.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/ItemsAdderBlockImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/ItemsAdderBlockImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/ItemsAdderBlockImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/ItemsAdderBlockImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/VanillaBlockImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/VanillaBlockImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/VanillaBlockImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/VanillaBlockImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/AdvancedEnchantmentsImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/AdvancedEnchantmentsImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/AdvancedEnchantmentsImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/AdvancedEnchantmentsImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/VanillaEnchantmentsImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/VanillaEnchantmentsImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/VanillaEnchantmentsImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/VanillaEnchantmentsImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/ItemsAdderEntityImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/ItemsAdderEntityImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/ItemsAdderEntityImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/ItemsAdderEntityImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/MythicEntityImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/MythicEntityImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/MythicEntityImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/MythicEntityImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/VanillaEntityImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/VanillaEntityImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/VanillaEntityImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/VanillaEntityImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/CustomFishingItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/CustomFishingItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/CustomFishingItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/CustomFishingItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ItemsAdderItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ItemsAdderItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ItemsAdderItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ItemsAdderItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MMOItemsItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MMOItemsItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MMOItemsItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MMOItemsItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/McMMOTreasureImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/McMMOTreasureImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/McMMOTreasureImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/McMMOTreasureImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MythicMobsItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MythicMobsItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MythicMobsItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MythicMobsItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/NeigeItemsItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/NeigeItemsItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/NeigeItemsItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/NeigeItemsItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/OraxenItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/OraxenItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/OraxenItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/OraxenItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/VanillaItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/VanillaItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/VanillaItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/VanillaItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ZaphkielItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ZaphkielItemImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ZaphkielItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ZaphkielItemImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AuraSkillsImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AuraSkillsImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AuraSkillsImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AuraSkillsImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AureliumSkillsImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AureliumSkillsImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AureliumSkillsImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AureliumSkillsImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoJobsImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoJobsImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoJobsImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoJobsImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoSkillsImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoSkillsImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoSkillsImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoSkillsImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/JobsRebornImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/JobsRebornImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/JobsRebornImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/JobsRebornImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/MMOCoreImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/MMOCoreImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/MMOCoreImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/MMOCoreImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/McMMOImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/McMMOImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/McMMOImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/McMMOImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CompetitionPapi.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CompetitionPapi.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CompetitionPapi.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CompetitionPapi.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CFPapi.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CustomFishingPapi.java similarity index 97% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CFPapi.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CustomFishingPapi.java index 39e54f63..43a8d541 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CFPapi.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CustomFishingPapi.java @@ -25,11 +25,11 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class CFPapi extends PlaceholderExpansion { +public class CustomFishingPapi extends PlaceholderExpansion { private final BukkitCustomFishingPlugin plugin; - public CFPapi(BukkitCustomFishingPlugin plugin) { + public CustomFishingPapi(BukkitCustomFishingPlugin plugin) { this.plugin = plugin; } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/StatisticsPapi.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/StatisticsPapi.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/StatisticsPapi.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/StatisticsPapi.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BattlePassHook.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BattlePassHook.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BattlePassHook.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BattlePassHook.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BetonQuestHook.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BetonQuestHook.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BetonQuestHook.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BetonQuestHook.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/ClueScrollsHook.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/ClueScrollsHook.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/ClueScrollsHook.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/ClueScrollsHook.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/NotQuestHook.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/NotQuestHook.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/NotQuestHook.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/NotQuestHook.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/CustomCropsSeasonImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/CustomCropsSeasonImpl.java similarity index 100% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/CustomCropsSeasonImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/CustomCropsSeasonImpl.java diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsImpl.java similarity index 81% rename from core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsImpl.java index 620e9795..af2ea8fd 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsImpl.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsImpl.java @@ -28,12 +28,12 @@ public class RealisticSeasonsImpl implements SeasonProvider { @Override public String getSeason(World world) { return switch (SeasonsAPI.getInstance().getSeason(world)) { - case WINTER -> "winter"; - case SPRING -> "spring"; - case SUMMER -> "summer"; - case FALL -> "autumn"; - case DISABLED -> "disabled"; - case RESTORE -> "restore"; + case Season.WINTER -> "winter"; + case Season.SPRING -> "spring"; + case Season.SUMMER -> "summer"; + case Season.FALL -> "autumn"; + case Season.DISABLED -> "disabled"; + case Season.RESTORE -> "restore"; }; } } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 23e78aa8..a85b70e2 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { implementation(project(":common")) implementation(project(":api")) + implementation(project(":compatibility")) // adventure implementation("net.kyori:adventure-api:4.17.0") implementation("net.kyori:adventure-text-minimessage:4.17.0") @@ -25,8 +26,7 @@ dependencies { compileOnly("dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT") // bStats compileOnly("org.bstats:bstats-bukkit:3.0.2") - // papi - compileOnly("me.clip:placeholderapi:2.11.5") + // config compileOnly("dev.dejvokep:boosted-yaml:1.3.4") // Gson @@ -37,14 +37,10 @@ dependencies { compileOnly("org.mongodb:mongodb-driver-sync:5.0.1") compileOnly("com.zaxxer:HikariCP:5.0.1") compileOnly("redis.clients:jedis:5.1.2") - // local jars - compileOnly(files("libs/AdvancedEnchantments-api.jar")) - compileOnly(files("libs/BattlePass-4.0.6-api.jar")) - compileOnly(files("libs/RealisticSeasons-api.jar")) - compileOnly(files("libs/mcMMO-api.jar")) - compileOnly(files("libs/ClueScrolls-4.8.7-api.jar")) - compileOnly(files("libs/notquests-5.17.1.jar")) - compileOnly(files("libs/zaphkiel-2.0.24.jar")) + + compileOnly("org.incendo:cloud-core:${rootProject.properties["cloud_core_version"]}") + compileOnly("org.incendo:cloud-minecraft-extras:${rootProject.properties["cloud_minecraft_extras_version"]}") + compileOnly("org.incendo:cloud-paper:${rootProject.properties["cloud_paper_version"]}") } tasks { diff --git a/core/src/main/java/net/momirealms/customfishing/BukkitCustomFishingPluginImpl.java b/core/src/main/java/net/momirealms/customfishing/BukkitCustomFishingPluginImpl.java index c65b3658..2f5c3b5e 100644 --- a/core/src/main/java/net/momirealms/customfishing/BukkitCustomFishingPluginImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/BukkitCustomFishingPluginImpl.java @@ -20,11 +20,11 @@ package net.momirealms.customfishing; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.event.CustomFishingReloadEvent; import net.momirealms.customfishing.bukkit.compatibility.IntegrationManagerImpl; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import net.momirealms.customfishing.mechanic.action.ActionManagerImpl; import net.momirealms.customfishing.mechanic.bag.BagManagerImpl; import net.momirealms.customfishing.mechanic.block.BlockManagerImpl; -import net.momirealms.customfishing.mechanic.competition.CompetitionManagerImpl; +import net.momirealms.customfishing.bukkit.competition.CompetitionManagerImpl; import net.momirealms.customfishing.mechanic.effect.EffectManagerImpl; import net.momirealms.customfishing.mechanic.entity.EntityManagerImpl; import net.momirealms.customfishing.mechanic.fishing.FishingManagerImpl; @@ -111,7 +111,7 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { this.lootManager = new LootManagerImpl(this); this.marketManager = new MarketManagerImpl(this); this.entityManager = new EntityManagerImpl(this); - this.placeholderManager = new PlaceholderManagerImpl(this); + this.placeholderManager = new BukkitPlaceholderManager(this); this.requirementManager = new RequirementManagerImpl(this); this.scheduler = new SchedulerImpl(this); this.storageManager = new StorageManagerImpl(this); @@ -150,7 +150,7 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { if (this.integrationManager != null) ((IntegrationManagerImpl) this.integrationManager).disable(); if (this.competitionManager != null) ((CompetitionManagerImpl) this.competitionManager).disable(); if (this.storageManager != null) ((StorageManagerImpl) this.storageManager).disable(); - if (this.placeholderManager != null) ((PlaceholderManagerImpl) this.placeholderManager).disable(); + if (this.placeholderManager != null) ((BukkitPlaceholderManager) this.placeholderManager).disable(); if (this.statisticsManager != null) ((StatisticsManagerImpl) this.statisticsManager).disable(); if (this.actionManager != null) ((ActionManagerImpl) this.actionManager).disable(); if (this.totemManager != null) ((TotemManagerImpl) this.totemManager).disable(); @@ -198,8 +198,8 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { ((StorageManagerImpl) this.storageManager).reload(); ((StatisticsManagerImpl) this.statisticsManager).unload(); ((StatisticsManagerImpl) this.statisticsManager).load(); - ((PlaceholderManagerImpl) this.placeholderManager).unload(); - ((PlaceholderManagerImpl) this.placeholderManager).load(); + ((BukkitPlaceholderManager) this.placeholderManager).unload(); + ((BukkitPlaceholderManager) this.placeholderManager).load(); ((HookManagerImpl) this.hookManager).unload(); ((HookManagerImpl) this.hookManager).load(); this.commandManager.unload(); diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/action/BukkitActionManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/action/BukkitActionManager.java new file mode 100644 index 00000000..d4f325d4 --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/action/BukkitActionManager.java @@ -0,0 +1,144 @@ +package net.momirealms.customfishing.bukkit.action; + +import dev.dejvokep.boostedyaml.block.implementation.Section; +import net.kyori.adventure.audience.Audience; +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.*; +import net.momirealms.customfishing.common.helper.AdventureHelper; +import net.momirealms.customfishing.common.util.ClassUtils; +import net.momirealms.customfishing.common.util.ListUtils; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BukkitActionManager implements ActionManager { + + private final BukkitCustomFishingPlugin plugin; + private final HashMap> actionFactoryMap = new HashMap<>(); + private static final String EXPANSION_FOLDER = "expansions/action"; + + public BukkitActionManager(BukkitCustomFishingPlugin plugin) { + this.plugin = plugin; + this.registerBuiltInActions(); + } + + @Override + public boolean registerAction(String type, ActionFactory actionFactory) { + if (this.actionFactoryMap.containsKey(type)) return false; + this.actionFactoryMap.put(type, actionFactory); + return true; + } + + @Override + public boolean unregisterAction(String type) { + return this.actionFactoryMap.remove(type) != null; + } + + @Nullable + @Override + public ActionFactory getActionFactory(@NotNull String type) { + return actionFactoryMap.get(type); + } + + @Override + public boolean hasAction(@NotNull String type) { + return actionFactoryMap.containsKey(type); + } + + @Override + public Action parseAction(Section section) { + ActionFactory factory = getActionFactory(section.getString("type")); + if (factory == null) { + plugin.getPluginLogger().warn("Action type: " + section.getString("type") + " doesn't exist."); + return EmptyAction.INSTANCE; + } + return factory.process(section.get("value"), section.getDouble("chance", 1d)); + } + + @NotNull + @Override + @SuppressWarnings("unchecked") + public Action[] parseActions(@NotNull Section section) { + ArrayList> actionList = new ArrayList<>(); + for (Map.Entry entry : section.getStringRouteMappedValues(false).entrySet()) { + if (entry.getValue() instanceof Section innerSection) { + Action action = parseAction(innerSection); + if (action != null) + actionList.add(action); + } + } + return actionList.toArray(new Action[0]); + } + + @Override + public Action parseAction(@NotNull String type, @NotNull Object args) { + ActionFactory factory = getActionFactory(type); + if (factory == null) { + plugin.getPluginLogger().warn("Action type: " + type + " doesn't exist."); + return EmptyAction.INSTANCE; + } + return factory.process(args, 1); + } + + private void registerBuiltInActions() { + this.registerMessageAction(); + } + + private void registerMessageAction() { + registerAction("message", (args, chance) -> { + List messages = ListUtils.toList(args); + return context -> { + if (Math.random() > chance) return; + List replaced = plugin.getPlaceholderManager().parse(context.getHolder(), messages, context.toPlaceholderMap()); + Audience audience = plugin.getSenderFactory().getAudience(context.getHolder()); + for (String text : replaced) { + audience.sendMessage(AdventureHelper.getMiniMessage().deserialize(text)); + } + }; + }); + } + + /** + * Loads custom ActionExpansions from JAR files located in the expansion directory. + * This method scans the expansion folder for JAR files, loads classes that extend ActionExpansion, + * and registers them with the appropriate action type and ActionFactory. + */ + @SuppressWarnings({"ResultOfMethodCallIgnored", "unchecked"}) + private void loadExpansions() { + File expansionFolder = new File(plugin.getDataFolder(), EXPANSION_FOLDER); + if (!expansionFolder.exists()) + expansionFolder.mkdirs(); + + List>> classes = new ArrayList<>(); + File[] expansionJars = expansionFolder.listFiles(); + if (expansionJars == null) return; + for (File expansionJar : expansionJars) { + if (expansionJar.getName().endsWith(".jar")) { + try { + Class> expansionClass = (Class>) ClassUtils.findClass(expansionJar, ActionExpansion.class); + classes.add(expansionClass); + } catch (IOException | ClassNotFoundException e) { + plugin.getPluginLogger().warn("Failed to load expansion: " + expansionJar.getName(), e); + } + } + } + try { + for (Class> expansionClass : classes) { + ActionExpansion expansion = expansionClass.getDeclaredConstructor().newInstance(); + unregisterAction(expansion.getActionType()); + registerAction(expansion.getActionType(), expansion.getActionFactory()); + plugin.getPluginLogger().info("Loaded action expansion: " + expansion.getActionType() + "[" + expansion.getVersion() + "]" + " by " + expansion.getAuthor() ); + } + } catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) { + plugin.getPluginLogger().warn("Error occurred when creating expansion instance.", e); + } + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/command/BukkitCommandFeature.java b/core/src/main/java/net/momirealms/customfishing/bukkit/command/BukkitCommandFeature.java new file mode 100644 index 00000000..59fb5148 --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/command/BukkitCommandFeature.java @@ -0,0 +1,44 @@ +package net.momirealms.customfishing.bukkit.command; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TranslatableComponent; +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.common.command.AbstractCommandFeature; +import net.momirealms.customfishing.common.command.CustomFishingCommandManager; +import net.momirealms.customfishing.common.sender.SenderFactory; +import net.momirealms.customfishing.common.util.Pair; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; +import org.incendo.cloud.bukkit.data.Selector; + +import java.util.Collection; + +public abstract class BukkitCommandFeature extends AbstractCommandFeature { + + public BukkitCommandFeature(CustomFishingCommandManager commandManager) { + super(commandManager); + } + + @Override + @SuppressWarnings("unchecked") + protected SenderFactory getSenderFactory() { + return (SenderFactory) BukkitCustomFishingPlugin.getInstance().getSenderFactory(); + } + + public Pair resolveSelector(Selector selector, TranslatableComponent.Builder single, TranslatableComponent.Builder multiple) { + Collection entities = selector.values(); + if (entities.size() == 1) { + return Pair.of(single, Component.text(entities.iterator().next().getName())); + } else { + return Pair.of(multiple, Component.text(entities.size())); + } + } + + public Pair resolveSelector(Collection selector, TranslatableComponent.Builder single, TranslatableComponent.Builder multiple) { + if (selector.size() == 1) { + return Pair.of(single, Component.text(selector.iterator().next().getName())); + } else { + return Pair.of(multiple, Component.text(selector.size())); + } + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/command/BukkitCommandManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/command/BukkitCommandManager.java new file mode 100644 index 00000000..a3c53825 --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/command/BukkitCommandManager.java @@ -0,0 +1,41 @@ +package net.momirealms.customfishing.bukkit.command; + +import net.kyori.adventure.util.Index; +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.bukkit.command.feature.ReloadCommand; +import net.momirealms.customfishing.common.command.AbstractCommandManager; +import net.momirealms.customfishing.common.command.CommandFeature; +import net.momirealms.customfishing.common.sender.Sender; +import org.bukkit.command.CommandSender; +import org.incendo.cloud.SenderMapper; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.paper.PaperCommandManager; + +import java.util.List; + +public class BukkitCommandManager extends AbstractCommandManager { + + private final List> FEATURES = List.of( + new ReloadCommand(this) + ); + + private final Index> INDEX = Index.create(CommandFeature::getFeatureID, FEATURES); + + public BukkitCommandManager(BukkitCustomFishingPlugin plugin) { + super(plugin, new PaperCommandManager<>( + plugin.getBoostrap(), + ExecutionCoordinator.simpleCoordinator(), + SenderMapper.identity() + )); + } + + @Override + protected Sender wrapSender(CommandSender sender) { + return ((BukkitCustomFishingPlugin) plugin).getSenderFactory().wrap(sender); + } + + @Override + public Index> getFeatures() { + return INDEX; + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/command/feature/ReloadCommand.java b/core/src/main/java/net/momirealms/customfishing/bukkit/command/feature/ReloadCommand.java new file mode 100644 index 00000000..a1ae97ad --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/command/feature/ReloadCommand.java @@ -0,0 +1,24 @@ +package net.momirealms.customfishing.bukkit.command.feature; + +import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature; +import net.momirealms.customfishing.common.command.CustomFishingCommandManager; +import org.bukkit.command.CommandSender; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; + +public class ReloadCommand extends BukkitCommandFeature { + + public ReloadCommand(CustomFishingCommandManager commandManager) { + super(commandManager); + } + + @Override + public Command.Builder assembleCommand(CommandManager manager, Command.Builder builder) { + return null; + } + + @Override + public String getFeatureID() { + return "reload"; + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/PlaceholderManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/PlaceholderManagerImpl.java deleted file mode 100644 index eb4553e6..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/PlaceholderManagerImpl.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.bukkit.compatibility.papi; - -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.manager.PlaceholderManager; -import net.momirealms.customfishing.util.ConfigUtils; -import net.objecthunter.exp4j.ExpressionBuilder; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -public class PlaceholderManagerImpl implements PlaceholderManager { - - private static PlaceholderManagerImpl instance; - private final BukkitCustomFishingPlugin plugin; - private final boolean hasPapi; - private final Pattern pattern; - private final HashMap customPlaceholderMap; - private CompetitionPapi competitionPapi; - private StatisticsPapi statisticsPapi; - private CFPapi cfPapi; - - public PlaceholderManagerImpl(BukkitCustomFishingPlugin plugin) { - instance = this; - this.plugin = plugin; - this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); - this.pattern = Pattern.compile("\\{[^{}]+}"); - this.customPlaceholderMap = new HashMap<>(); - if (this.hasPapi) { - competitionPapi = new CompetitionPapi(plugin); - statisticsPapi = new StatisticsPapi(plugin); - cfPapi = new CFPapi(plugin); - } - } - - public void load() { - if (competitionPapi != null) competitionPapi.load(); - if (statisticsPapi != null) statisticsPapi.load(); - if (cfPapi != null) cfPapi.load(); - loadCustomPlaceholders(); - } - - public void unload() { - if (competitionPapi != null) competitionPapi.unload(); - if (statisticsPapi != null) statisticsPapi.unload(); - if (cfPapi != null) cfPapi.unload(); - } - - public void disable() { - this.customPlaceholderMap.clear(); - } - - public void loadCustomPlaceholders() { - YamlConfiguration config = plugin.getConfig("config.yml"); - ConfigurationSection section = config.getConfigurationSection("other-settings.placeholder-register"); - if (section != null) { - for (Map.Entry entry : section.getValues(false).entrySet()) { - registerCustomPlaceholder(entry.getKey(), (String) entry.getValue()); - } - } - } - - @Override - public boolean registerCustomPlaceholder(String placeholder, String original) { - if (this.customPlaceholderMap.containsKey(placeholder)) { - return false; - } - this.customPlaceholderMap.put(placeholder, original); - return true; - } - - /** - * Set placeholders in a text string for a player. - * - * @param player The player for whom the placeholders should be set. - * @param text The text string containing placeholders. - * @return The text string with placeholders replaced if PlaceholderAPI is available; otherwise, the original text. - */ - @Override - public String setPlaceholders(Player player, String text) { - return hasPapi ? ParseUtils.setPlaceholders(player, text) : text; - } - - /** - * Set placeholders in a text string for an offline player. - * - * @param player The offline player for whom the placeholders should be set. - * @param text The text string containing placeholders. - * @return The text string with placeholders replaced if PlaceholderAPI is available; otherwise, the original text. - */ - @Override - public String setPlaceholders(OfflinePlayer player, String text) { - return hasPapi ? ParseUtils.setPlaceholders(player, text) : text; - } - - /** - * Detect and extract placeholders from a text string. - * - * @param text The text string to search for placeholders. - * @return A list of detected placeholders in the text. - */ - @Override - public List detectPlaceholders(String text) { - List placeholders = new ArrayList<>(); - Matcher matcher = pattern.matcher(text); - while (matcher.find()) placeholders.add(matcher.group()); - return placeholders; - } - - /** - * Get the value associated with a single placeholder. - * - * @param player The player for whom the placeholders are being resolved (nullable). - * @param placeholder The placeholder to look up. - * @param placeholders A map of placeholders to their corresponding values. - * @return The value associated with the placeholder, or the original placeholder if not found. - */ - @Override - public String getSingleValue(@Nullable Player player, String placeholder, Map placeholders) { - String result = null; - if (placeholders != null) - result = placeholders.get(placeholder); - if (result != null) - return result; - String custom = customPlaceholderMap.get(placeholder); - if (custom == null) - return placeholder; - return setPlaceholders(player, custom); - } - - /** - * Parse a text string by replacing placeholders with their corresponding values. - * - * @param player The offline player for whom the placeholders are being resolved (nullable). - * @param text The text string containing placeholders. - * @param placeholders A map of placeholders to their corresponding values. - * @return The text string with placeholders replaced by their values. - */ - @Override - public String parse(@Nullable OfflinePlayer player, String text, Map placeholders) { - var list = detectPlaceholders(text); - for (String papi : list) { - String replacer = null; - if (placeholders != null) { - replacer = placeholders.get(papi); - } - if (replacer == null) { - String custom = customPlaceholderMap.get(papi); - if (custom != null) { - replacer = setPlaceholders(player, parse(player, custom, placeholders)); - } - } - if (replacer != null) { - text = text.replace(papi, replacer); - } - } - return text; - } - - /** - * Parse a list of text strings by replacing placeholders with their corresponding values. - * - * @param player The player for whom the placeholders are being resolved (can be null for offline players). - * @param list The list of text strings containing placeholders. - * @param replacements A map of custom replacements for placeholders. - * @return The list of text strings with placeholders replaced by their values. - */ - @Override - public List parse(@Nullable OfflinePlayer player, List list, Map replacements) { - return list.stream() - .map(s -> parse(player, s, replacements)) - .collect(Collectors.toList()); - } - - - public static PlaceholderManagerImpl getInstance() { - return instance; - } - - public boolean hasPapi() { - return hasPapi; - } - - @Override - public double getExpressionValue(Player player, String formula, Map vars) { - return ConfigUtils.getExpressionValue(player, formula, vars); - } - - @Override - public double getExpressionValue(String formula) { - return new ExpressionBuilder(formula).build().evaluate(); - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/Competition.java similarity index 88% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/Competition.java index c4d03ec2..eaa4a43c 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/Competition.java @@ -15,21 +15,21 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition; +package net.momirealms.customfishing.bukkit.competition; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.common.Pair; import net.momirealms.customfishing.api.event.CompetitionEvent; import net.momirealms.customfishing.api.mechanic.action.Action; -import net.momirealms.customfishing.api.mechanic.competition.CompetitionConfig; +import net.momirealms.customfishing.api.mechanic.competition.CompetitionConfigImpl; import net.momirealms.customfishing.api.mechanic.competition.CompetitionGoal; import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; -import net.momirealms.customfishing.api.mechanic.competition.Ranking; +import net.momirealms.customfishing.api.mechanic.competition.RankingProvider; import net.momirealms.customfishing.api.scheduler.CancellableTask; -import net.momirealms.customfishing.mechanic.competition.actionbar.ActionBarManager; -import net.momirealms.customfishing.mechanic.competition.bossbar.BossBarManager; -import net.momirealms.customfishing.mechanic.competition.ranking.LocalRankingImpl; -import net.momirealms.customfishing.mechanic.competition.ranking.RedisRankingImpl; +import net.momirealms.customfishing.bukkit.competition.bossbar.BossBarManager; +import net.momirealms.customfishing.bukkit.competition.ranking.LocalRankingProvider; +import net.momirealms.customfishing.bukkit.competition.actionbar.ActionBarManager; +import net.momirealms.customfishing.bukkit.competition.ranking.RedisRankingProvider; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -45,22 +45,22 @@ import java.util.concurrent.TimeUnit; public class Competition implements FishingCompetition { - private final CompetitionConfig config; + private final CompetitionConfigImpl config; private CancellableTask competitionTimerTask; private final CompetitionGoal goal; private final ConcurrentHashMap publicPlaceholders; - private final Ranking ranking; + private final RankingProvider rankingProvider; private float progress; private long remainingTime; private long startTime; private BossBarManager bossBarManager; private ActionBarManager actionBarManager; - public Competition(CompetitionConfig config) { + public Competition(CompetitionConfigImpl config) { this.config = config; this.goal = config.getGoal() == CompetitionGoal.RANDOM ? CompetitionGoal.getRandom() : config.getGoal(); - if (CFConfig.redisRanking) this.ranking = new RedisRankingImpl(); - else this.ranking = new LocalRankingImpl(); + if (CFConfig.redisRanking) this.rankingProvider = new RedisRankingProvider(); + else this.rankingProvider = new LocalRankingProvider(); this.publicPlaceholders = new ConcurrentHashMap<>(); this.publicPlaceholders.put("{goal}", BukkitCustomFishingPlugin.get().getCompetitionManager().getCompetitionGoalLocale(goal)); } @@ -87,7 +87,7 @@ public class Competition implements FishingCompetition { this.actionBarManager.load(); } - Action[] actions = config.getStartActions(); + Action[] actions = config.startActions(); if (actions != null) { PlayerContext playerContext = new PlayerContext(null, null, this.publicPlaceholders); for (Action action : actions) { @@ -95,7 +95,7 @@ public class Competition implements FishingCompetition { } } - this.ranking.clear(); + this.rankingProvider.clear(); this.updatePublicPlaceholders(); CompetitionEvent competitionStartEvent = new CompetitionEvent(CompetitionEvent.State.START, this); @@ -126,9 +126,9 @@ public class Competition implements FishingCompetition { private void updatePublicPlaceholders() { for (int i = 1; i < CFConfig.placeholderLimit + 1; i++) { int finalI = i; - Optional.ofNullable(ranking.getPlayerAt(i)).ifPresentOrElse(player -> { + Optional.ofNullable(rankingProvider.getPlayerAt(i)).ifPresentOrElse(player -> { publicPlaceholders.put("{" + finalI + "_player}", player); - publicPlaceholders.put("{" + finalI + "_score}", String.format("%.2f", ranking.getScoreAt(finalI))); + publicPlaceholders.put("{" + finalI + "_score}", String.format("%.2f", rankingProvider.getScoreAt(finalI))); }, () -> { publicPlaceholders.put("{" + finalI + "_player}", CFLocale.MSG_No_Player); publicPlaceholders.put("{" + finalI + "_score}", CFLocale.MSG_No_Score); @@ -150,7 +150,7 @@ public class Competition implements FishingCompetition { if (!competitionTimerTask.isCancelled()) this.competitionTimerTask.cancel(); if (this.bossBarManager != null) this.bossBarManager.unload(); if (this.actionBarManager != null) this.actionBarManager.unload(); - this.ranking.clear(); + this.rankingProvider.clear(); this.remainingTime = 0; if (triggerEvent) { @@ -176,8 +176,8 @@ public class Competition implements FishingCompetition { // give prizes HashMap rewardsMap = config.getRewards(); - if (ranking.getSize() != 0 && rewardsMap != null) { - Iterator> iterator = ranking.getIterator(); + if (rankingProvider.getSize() != 0 && rewardsMap != null) { + Iterator> iterator = rankingProvider.getIterator(); int i = 1; while (iterator.hasNext()) { Pair competitionPlayer = iterator.next(); @@ -218,7 +218,7 @@ public class Competition implements FishingCompetition { } // 1 seconds delay for other servers to read the redis data - BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncLater(this.ranking::clear, 1, TimeUnit.SECONDS); + BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncLater(this.rankingProvider::clear, 1, TimeUnit.SECONDS); } /** @@ -270,11 +270,11 @@ public class Competition implements FishingCompetition { // refresh data switch (this.goal) { - case CATCH_AMOUNT -> ranking.refreshData(player.getName(), 1); - case TOTAL_SIZE, TOTAL_SCORE -> ranking.refreshData(player.getName(), score); + case CATCH_AMOUNT -> rankingProvider.refreshData(player.getName(), 1); + case TOTAL_SIZE, TOTAL_SCORE -> rankingProvider.refreshData(player.getName(), score); case MAX_SIZE -> { - if (score > ranking.getPlayerScore(player.getName())) { - ranking.setData(player.getName(), score); + if (score > rankingProvider.getPlayerScore(player.getName())) { + rankingProvider.setData(player.getName(), score); } } } @@ -288,7 +288,7 @@ public class Competition implements FishingCompetition { */ @Override public boolean hasPlayerJoined(OfflinePlayer player) { - return ranking.getPlayerRank(player.getName()) != -1; + return rankingProvider.getPlayerRank(player.getName()) != -1; } /** @@ -328,7 +328,7 @@ public class Competition implements FishingCompetition { */ @NotNull @Override - public CompetitionConfig getConfig() { + public CompetitionConfigImpl getConfig() { return config; } @@ -350,8 +350,8 @@ public class Competition implements FishingCompetition { */ @NotNull @Override - public Ranking getRanking() { - return ranking; + public RankingProvider getRanking() { + return rankingProvider; } /** diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/CompetitionManagerImpl.java similarity index 93% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionManagerImpl.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/CompetitionManagerImpl.java index 52df26a7..0774a3c8 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/CompetitionManagerImpl.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition; +package net.momirealms.customfishing.bukkit.competition; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.common.Pair; @@ -42,8 +42,8 @@ import java.util.concurrent.TimeUnit; public class CompetitionManagerImpl implements CompetitionManager { private final BukkitCustomFishingPlugin plugin; - private final HashMap timeConfigMap; - private final HashMap commandConfigMap; + private final HashMap timeConfigMap; + private final HashMap commandConfigMap; private Competition currentCompetition; private CancellableTask timerCheckTask; private int nextCompetitionSeconds; @@ -124,12 +124,12 @@ public class CompetitionManagerImpl implements CompetitionManager { for (Map.Entry entry : config.getValues(false).entrySet()) { if (entry.getValue() instanceof ConfigurationSection section) { - CompetitionConfig.Builder builder = new CompetitionConfig.Builder(entry.getKey()) + CompetitionConfigImpl.Builder builder = new CompetitionConfigImpl.Builder(entry.getKey()) .goal(CompetitionGoal.valueOf(section.getString("goal", "TOTAL_SCORE").toUpperCase(Locale.ENGLISH))) .minPlayers(section.getInt("min-players", 0)) .duration(section.getInt("duration", 300)) .rewards(getPrizeActions(section.getConfigurationSection("rewards"))) - .requirements(plugin.getRequirementManager().getRequirements(section.getConfigurationSection("participate-requirements"), false)) + .requirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("participate-requirements"), false)) .joinActions(plugin.getActionManager().getActions(section.getConfigurationSection("participate-actions"))) .startActions(plugin.getActionManager().getActions(section.getConfigurationSection("start-actions"))) .endActions(plugin.getActionManager().getActions(section.getConfigurationSection("end-actions"))) @@ -155,7 +155,7 @@ public class CompetitionManagerImpl implements CompetitionManager { .build()); } - CompetitionConfig competitionConfig = builder.build(); + CompetitionConfigImpl competitionConfigImpl = builder.build(); List> timePairs = section.getStringList("start-time") .stream().map(it -> ConfigUtils.splitStringIntegerArgs(it, ":")).toList(); List weekdays = section.getIntegerList("start-weekday"); @@ -165,10 +165,10 @@ public class CompetitionManagerImpl implements CompetitionManager { for (Integer weekday : weekdays) { for (Pair timePair : timePairs) { CompetitionSchedule schedule = new CompetitionSchedule(weekday, timePair.left(), timePair.right(), 0); - timeConfigMap.put(schedule, competitionConfig); + timeConfigMap.put(schedule, competitionConfigImpl); } } - commandConfigMap.put(entry.getKey(), competitionConfig); + commandConfigMap.put(entry.getKey(), competitionConfigImpl); } } } @@ -207,7 +207,7 @@ public class CompetitionManagerImpl implements CompetitionManager { nextCompetitionTime = Math.min(nextCompetitionTime, schedule.getTimeDelta(seconds)); } this.nextCompetitionSeconds = nextCompetitionTime; - CompetitionConfig config = timeConfigMap.get(competitionSchedule); + CompetitionConfigImpl config = timeConfigMap.get(competitionSchedule); if (config != null) { startCompetition(config, false, null); } @@ -241,7 +241,7 @@ public class CompetitionManagerImpl implements CompetitionManager { @Override public boolean startCompetition(String competition, boolean force, String serverGroup) { - CompetitionConfig config = commandConfigMap.get(competition); + CompetitionConfigImpl config = commandConfigMap.get(competition); if (config == null) { LogUtils.warn("Competition " + competition + " doesn't exist."); return false; @@ -262,7 +262,7 @@ public class CompetitionManagerImpl implements CompetitionManager { } @Override - public boolean startCompetition(CompetitionConfig config, boolean force, @Nullable String serverGroup) { + public boolean startCompetition(CompetitionConfigImpl config, boolean force, @Nullable String serverGroup) { if (!force) { int players = Bukkit.getOnlinePlayers().size(); if (players < config.getMinPlayersToStart()) { @@ -286,7 +286,7 @@ public class CompetitionManagerImpl implements CompetitionManager { } } - private void start(CompetitionConfig config) { + private void start(CompetitionConfigImpl config) { if (getOnGoingCompetition() != null) { // END currentCompetition.end(true); @@ -318,11 +318,11 @@ public class CompetitionManagerImpl implements CompetitionManager { * Retrieves the configuration for a competition based on its key. * * @param key The key of the competition configuration to retrieve. - * @return The {@link CompetitionConfig} for the specified key, or {@code null} if no configuration exists with that key. + * @return The {@link CompetitionConfigImpl} for the specified key, or {@code null} if no configuration exists with that key. */ @Nullable @Override - public CompetitionConfig getConfig(String key) { + public CompetitionConfigImpl getConfig(String key) { return commandConfigMap.get(key); } } diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionSchedule.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/CompetitionSchedule.java similarity index 98% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionSchedule.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/CompetitionSchedule.java index 03564cf3..63eb82b9 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionSchedule.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/CompetitionSchedule.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition; +package net.momirealms.customfishing.bukkit.competition; public class CompetitionSchedule { diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarManager.java similarity index 97% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarManager.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarManager.java index 8d88372d..378fe1d2 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarManager.java @@ -15,11 +15,11 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition.actionbar; +package net.momirealms.customfishing.bukkit.competition.actionbar; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.competition.info.ActionBarConfigImpl; -import net.momirealms.customfishing.mechanic.competition.Competition; +import net.momirealms.customfishing.bukkit.competition.Competition; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarSender.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarSender.java similarity index 97% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarSender.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarSender.java index 57878a56..c7568af8 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarSender.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarSender.java @@ -15,12 +15,12 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition.actionbar; +package net.momirealms.customfishing.bukkit.competition.actionbar; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.competition.info.ActionBarConfigImpl; import net.momirealms.customfishing.api.scheduler.CancellableTask; -import net.momirealms.customfishing.mechanic.competition.Competition; +import net.momirealms.customfishing.bukkit.competition.Competition; import net.momirealms.customfishing.mechanic.misc.DynamicText; import org.bukkit.entity.Player; diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarManager.java similarity index 97% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarManager.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarManager.java index 6eea2af5..e88c9156 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarManager.java @@ -15,11 +15,11 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition.bossbar; +package net.momirealms.customfishing.bukkit.competition.bossbar; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.competition.info.BossBarConfigImpl; -import net.momirealms.customfishing.mechanic.competition.Competition; +import net.momirealms.customfishing.bukkit.competition.Competition; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarSender.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarSender.java similarity index 98% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarSender.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarSender.java index 34b6ecc0..957be254 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarSender.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarSender.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition.bossbar; +package net.momirealms.customfishing.bukkit.competition.bossbar; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.InternalStructure; @@ -28,7 +28,7 @@ import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.competition.info.BossBarConfigImpl; import net.momirealms.customfishing.api.scheduler.CancellableTask; import net.momirealms.customfishing.api.util.ReflectionUtils; -import net.momirealms.customfishing.mechanic.competition.Competition; +import net.momirealms.customfishing.bukkit.competition.Competition; import net.momirealms.customfishing.mechanic.misc.DynamicText; import org.bukkit.boss.BarColor; import org.bukkit.entity.Player; diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/LocalRankingImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/ranking/LocalRankingProvider.java similarity index 97% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/LocalRankingImpl.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/ranking/LocalRankingProvider.java index 8b00564d..8c60698e 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/LocalRankingImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/ranking/LocalRankingProvider.java @@ -15,22 +15,21 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition.ranking; +package net.momirealms.customfishing.bukkit.competition.ranking; -import net.momirealms.customfishing.api.common.Pair; import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer; -import net.momirealms.customfishing.api.mechanic.competition.Ranking; +import net.momirealms.customfishing.api.mechanic.competition.RankingProvider; import java.util.*; /** * Implementation of the Ranking interface that manages the ranking of competition players locally. */ -public class LocalRankingImpl implements Ranking { +public class LocalRankingProvider implements RankingProvider { private final Set competitionPlayers; - public LocalRankingImpl() { + public LocalRankingProvider() { competitionPlayers = Collections.synchronizedSet(new TreeSet<>()); } diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/RedisRankingImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/ranking/RedisRankingProvider.java similarity index 98% rename from core/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/RedisRankingImpl.java rename to core/src/main/java/net/momirealms/customfishing/bukkit/competition/ranking/RedisRankingProvider.java index 4b9230bf..1625b00c 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/RedisRankingImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/ranking/RedisRankingProvider.java @@ -15,11 +15,11 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.competition.ranking; +package net.momirealms.customfishing.bukkit.competition.ranking; import net.momirealms.customfishing.api.common.Pair; import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer; -import net.momirealms.customfishing.api.mechanic.competition.Ranking; +import net.momirealms.customfishing.api.mechanic.competition.RankingProvider; import net.momirealms.customfishing.storage.method.database.nosql.RedisManager; import redis.clients.jedis.Jedis; import redis.clients.jedis.resps.Tuple; @@ -27,7 +27,7 @@ import redis.clients.jedis.resps.Tuple; import java.util.Iterator; import java.util.List; -public class RedisRankingImpl implements Ranking { +public class RedisRankingProvider implements RankingProvider { /** * Clears the ranking data by removing all players and scores. diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/misc/placeholder/BukkitPlaceholderManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/misc/placeholder/BukkitPlaceholderManager.java new file mode 100644 index 00000000..d5739bc7 --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/misc/placeholder/BukkitPlaceholderManager.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customfishing.bukkit.misc.placeholder; + +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.misc.placeholder.PlaceholderManager; +import net.momirealms.customfishing.bukkit.compatibility.PlaceholderAPIUtils; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.stream.Collectors; + +public class BukkitPlaceholderManager implements PlaceholderManager { + + private final BukkitCustomFishingPlugin plugin; + private final boolean hasPapi; + private final HashMap customPlaceholderMap; + + public BukkitPlaceholderManager(BukkitCustomFishingPlugin plugin) { + this.plugin = plugin; + this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); + this.customPlaceholderMap = new HashMap<>(); + } + + @Override + public boolean registerCustomPlaceholder(String placeholder, String original) { + if (this.customPlaceholderMap.containsKey(placeholder)) return false; + this.customPlaceholderMap.put(placeholder, original); + return true; + } + + @Override + public List resolvePlaceholders(String text) { + List placeholders = new ArrayList<>(); + Matcher matcher = PATTERN.matcher(text); + while (matcher.find()) placeholders.add(matcher.group()); + return placeholders; + } + + private String setPlaceholders(OfflinePlayer player, String text) { + return hasPapi ? PlaceholderAPIUtils.parse(player, text) : text; + } + + @Override + public String parseSingle(@Nullable OfflinePlayer player, String placeholder, Map replacements) { + String result = null; + if (replacements != null) + result = replacements.get(placeholder); + if (result != null) + return result; + String custom = customPlaceholderMap.get(placeholder); + if (custom == null) + return placeholder; + return hasPapi ? PlaceholderAPIUtils.parse(player, custom) : custom; + } + + @Override + public String parse(@Nullable OfflinePlayer player, String text, Map replacements) { + var list = resolvePlaceholders(text); + for (String papi : list) { + String replacer = null; + if (replacements != null) { + replacer = replacements.get(papi); + } + if (replacer == null) { + String custom = customPlaceholderMap.get(papi); + if (custom != null) { + replacer = setPlaceholders(player, parse(player, custom, replacements)); + } + } + if (replacer != null) { + text = text.replace(papi, replacer); + } + } + return text; + } + + @Override + public List parse(@Nullable OfflinePlayer player, List list, Map replacements) { + return list.stream() + .map(s -> parse(player, s, replacements)) + .collect(Collectors.toList()); + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/requirement/BukkitRequirementManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/requirement/BukkitRequirementManager.java new file mode 100644 index 00000000..afd9800f --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/requirement/BukkitRequirementManager.java @@ -0,0 +1,280 @@ +package net.momirealms.customfishing.bukkit.requirement; + +import dev.dejvokep.boostedyaml.block.implementation.Section; +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionManager; +import net.momirealms.customfishing.api.mechanic.context.ContextKeys; +import net.momirealms.customfishing.api.mechanic.effect.EffectProperties; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import net.momirealms.customfishing.api.mechanic.requirement.RequirementExpansion; +import net.momirealms.customfishing.api.mechanic.requirement.RequirementFactory; +import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; +import net.momirealms.customfishing.common.util.ClassUtils; +import net.momirealms.customfishing.common.util.ListUtils; +import net.momirealms.customfishing.common.util.Pair; +import net.momirealms.customfishing.api.mechanic.requirement.EmptyRequirement; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.*; + +import static java.util.Objects.requireNonNull; + +public class BukkitRequirementManager implements RequirementManager { + + private final BukkitCustomFishingPlugin plugin; + private final HashMap> requirementFactoryMap = new HashMap<>(); + private static final String EXPANSION_FOLDER = "expansions/requirement"; + + public BukkitRequirementManager(BukkitCustomFishingPlugin plugin) { + this.plugin = plugin; + this.registerBuiltInRequirements(); + this.loadExpansions(); + } + + @Override + public boolean registerRequirement(@NotNull String type, @NotNull RequirementFactory requirementFactory) { + if (this.requirementFactoryMap.containsKey(type)) return false; + this.requirementFactoryMap.put(type, requirementFactory); + return true; + } + + @Override + public boolean unregisterRequirement(@NotNull String type) { + return this.requirementFactoryMap.remove(type) != null; + } + + @Nullable + @Override + public RequirementFactory getRequirementFactory(@NotNull String type) { + return requirementFactoryMap.get(type); + } + + @Override + public boolean hasRequirement(@NotNull String type) { + return requirementFactoryMap.containsKey(type); + } + + @NotNull + @Override + @SuppressWarnings("unchecked") + public Requirement[] parseRequirements(@NotNull Section section, boolean runActions) { + List> requirements = new ArrayList<>(); + for (Map.Entry entry : section.getStringRouteMappedValues(false).entrySet()) { + String typeOrName = entry.getKey(); + if (hasRequirement(typeOrName)) { + requirements.add(parseRequirement(typeOrName, entry.getValue())); + } else { + requirements.add(parseRequirement(section.getSection(typeOrName), runActions)); + } + } + return requirements.toArray(new Requirement[0]); + } + + @NotNull + @Override + public Requirement parseRequirement(@NotNull Section section, boolean runActions) { + List> actionList = new ArrayList<>(); + if (runActions && section.contains("not-met-actions")) { + actionList.addAll(List.of(plugin.getActionManager().parseActions(requireNonNull(section.getSection("not-met-actions"))))); + } + String type = section.getString("type"); + if (type == null) { + plugin.getPluginLogger().warn("No requirement type found at " + section.getRouteAsString()); + return EmptyRequirement.INSTANCE; + } + var factory = getRequirementFactory(type); + if (factory == null) { + plugin.getPluginLogger().warn("No requirement type found at " + section.getRouteAsString()); + return EmptyRequirement.INSTANCE; + } + return factory.process(section.get("value"), actionList, runActions); + } + + @NotNull + @Override + public Requirement parseRequirement(@NotNull String type, @NotNull Object value) { + RequirementFactory factory = getRequirementFactory(type); + if (factory == null) { + plugin.getPluginLogger().warn("Requirement type: " + type + " doesn't exist."); + return EmptyRequirement.INSTANCE; + } + return factory.process(value); + } + + private void registerBuiltInRequirements() { + this.registerTimeRequirement(); + this.registerYRequirement(); + this.registerInWaterRequirement(); + this.registerInVoidRequirement(); + this.registerInLavaRequirement(); + this.registerAndRequirement(); + this.registerOrRequirement(); + } + + private void registerTimeRequirement() { + registerRequirement("time", (args, actions, advanced) -> { + List list = ListUtils.toList(args); + List> timePairs = list.stream().map(line -> { + String[] split = line.split("~"); + return new Pair<>(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + }).toList(); + return context -> { + Location location = requireNonNull(context.arg(ContextKeys.LOCATION)); + long time = location.getWorld().getTime(); + for (Pair pair : timePairs) + if (time >= pair.left() && time <= pair.right()) + return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + }); + } + + private void registerYRequirement() { + registerRequirement("ypos", (args, actions, advanced) -> { + List list = ListUtils.toList(args); + List> posPairs = list.stream().map(line -> { + String[] split = line.split("~"); + return new Pair<>(Double.parseDouble(split[0]), Double.parseDouble(split[1])); + }).toList(); + return context -> { + Location location = requireNonNull(context.arg(ContextKeys.LOCATION)); + double y = location.getY(); + for (Pair pair : posPairs) + if (y >= pair.left() && y <= pair.right()) + return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + }); + } + + private void registerOrRequirement() { + registerRequirement("||", (args, actions, advanced) -> { + if (args instanceof Section section) { + Requirement[] requirements = parseRequirements(section, advanced); + return context -> { + for (Requirement requirement : requirements) + if (requirement.isSatisfied(context)) + return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + } else { + plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at || requirement which should be Section"); + return EmptyRequirement.INSTANCE; + } + }); + } + + private void registerAndRequirement() { + registerRequirement("&&", (args, actions, advanced) -> { + if (args instanceof Section section) { + Requirement[] requirements = parseRequirements(section, advanced); + return context -> { + outer: { + for (Requirement requirement : requirements) + if (!requirement.isSatisfied(context)) + break outer; + return true; + } + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + } else { + plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at && requirement which should be Section"); + return EmptyRequirement.INSTANCE; + } + }); + } + + private void registerInWaterRequirement() { + registerRequirement("in-water", (args, actions, advanced) -> { + boolean inWater = (boolean) args; + return context -> { + boolean in_water = Optional.ofNullable(context.arg(ContextKeys.SURROUNDING)).orElse("").equals(EffectProperties.WATER_FISHING.key()); + if (in_water == inWater) return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + }); + } + + private void registerInVoidRequirement() { + registerRequirement("in-void", (args, actions, advanced) -> { + boolean inWater = (boolean) args; + return context -> { + boolean in_water = Optional.ofNullable(context.arg(ContextKeys.SURROUNDING)).orElse("").equals(EffectProperties.VOID_FISHING.key()); + if (in_water == inWater) return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + }); + } + + private void registerInLavaRequirement() { + registerRequirement("lava-fishing", (args, actions, advanced) -> { + boolean inLava = (boolean) args; + if (!inLava) { + throw new IllegalArgumentException(""); + } + return context -> { + boolean in_lava = Optional.ofNullable(context.arg(ContextKeys.SURROUNDING)).orElse("").equals(EffectProperties.LAVA_FISHING.key()); + if (in_lava) return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + }); + registerRequirement("in-lava", (args, actions, advanced) -> { + boolean inLava = (boolean) args; + return context -> { + boolean in_lava = Optional.ofNullable(context.arg(ContextKeys.SURROUNDING)).orElse("").equals(EffectProperties.LAVA_FISHING.key()); + if (in_lava == inLava) return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + }); + } + + /** + * Loads requirement expansions from external JAR files located in the expansion folder. + * Each expansion JAR should contain classes that extends the RequirementExpansion class. + * Expansions are registered and used to create custom requirements. + */ + @SuppressWarnings({"ResultOfMethodCallIgnored", "unchecked"}) + private void loadExpansions() { + File expansionFolder = new File(plugin.getDataFolder(), EXPANSION_FOLDER); + if (!expansionFolder.exists()) + expansionFolder.mkdirs(); + List>> classes = new ArrayList<>(); + File[] expansionJars = expansionFolder.listFiles(); + if (expansionJars == null) return; + for (File expansionJar : expansionJars) { + if (expansionJar.getName().endsWith(".jar")) { + try { + Class> expansionClass = (Class>) ClassUtils.findClass(expansionJar, RequirementExpansion.class); + classes.add(expansionClass); + } catch (IOException | ClassNotFoundException e) { + plugin.getPluginLogger().warn("Failed to load expansion: " + expansionJar.getName(), e); + } + } + } + try { + for (Class> expansionClass : classes) { + RequirementExpansion expansion = expansionClass.getDeclaredConstructor().newInstance(); + unregisterRequirement(expansion.getRequirementType()); + registerRequirement(expansion.getRequirementType(), expansion.getRequirementFactory()); + plugin.getPluginLogger().info("Loaded requirement expansion: " + expansion.getRequirementType() + "[" + expansion.getVersion() + "]" + " by " + expansion.getAuthor()); + } + } catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) { + plugin.getPluginLogger().warn("Error occurred when creating expansion instance.", e); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/sender/BukkitSenderFactory.java b/core/src/main/java/net/momirealms/customfishing/bukkit/sender/BukkitSenderFactory.java new file mode 100644 index 00000000..bb71b1f2 --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/sender/BukkitSenderFactory.java @@ -0,0 +1,112 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * 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 net.momirealms.customfishing.bukkit.sender; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.Component; +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.common.sender.Sender; +import net.momirealms.customfishing.common.sender.SenderFactory; +import net.momirealms.customfishing.common.util.Tristate; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.command.RemoteConsoleCommandSender; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class BukkitSenderFactory extends SenderFactory { + private final BukkitAudiences audiences; + + public BukkitSenderFactory(BukkitCustomFishingPlugin plugin) { + super(plugin); + this.audiences = BukkitAudiences.create(plugin.getBoostrap()); + } + + @Override + protected String getName(CommandSender sender) { + if (sender instanceof Player) { + return sender.getName(); + } + return Sender.CONSOLE_NAME; + } + + @Override + protected UUID getUniqueId(CommandSender sender) { + if (sender instanceof Player) { + return ((Player) sender).getUniqueId(); + } + return Sender.CONSOLE_UUID; + } + + @Override + public Audience getAudience(CommandSender sender) { + return this.audiences.sender(sender); + } + + @Override + protected void sendMessage(CommandSender sender, Component message) { + // we can safely send async for players and the console - otherwise, send it sync + if (sender instanceof Player || sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) { + getAudience(sender).sendMessage(message); + } else { + getPlugin().getScheduler().executeSync(() -> getAudience(sender).sendMessage(message)); + } + } + + @Override + protected Tristate getPermissionValue(CommandSender sender, String node) { + if (sender.hasPermission(node)) { + return Tristate.TRUE; + } else if (sender.isPermissionSet(node)) { + return Tristate.FALSE; + } else { + return Tristate.UNDEFINED; + } + } + + @Override + protected boolean hasPermission(CommandSender sender, String node) { + return sender.hasPermission(node); + } + + @Override + protected void performCommand(CommandSender sender, String command) { + getPlugin().getBoostrap().getServer().dispatchCommand(sender, command); + } + + @Override + protected boolean isConsole(CommandSender sender) { + return sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender; + } + + @Override + public void close() { + super.close(); + this.audiences.close(); + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java index ec12db69..2435cd60 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java @@ -30,8 +30,9 @@ import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.mechanic.requirement.Requirement; import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.api.mechanic.action.EmptyAction; import net.momirealms.customfishing.bukkit.compatibility.VaultHook; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import net.momirealms.customfishing.common.util.ClassUtils; import net.momirealms.customfishing.util.*; import org.bukkit.Bukkit; @@ -157,9 +158,9 @@ public class ActionManagerImpl implements ActionManager { if (factory == null) { LogUtils.warn("Action type: " + section.getString("type") + " doesn't exist."); // to prevent NPE - return EmptyAction.instance; + return EmptyAction.INSTANCE; } - return factory.build( + return factory.process( section.get("value"), section.getDouble("chance", 1d) ); @@ -297,7 +298,7 @@ public class ActionManagerImpl implements ActionManager { ArrayList msg = ConfigUtils.stringListArgs(args); return condition -> { if (Math.random() > chance) return; - List replaced = PlaceholderManagerImpl.getInstance().parse( + List replaced = BukkitPlaceholderManager.getInstance().parse( condition.getPlayer(), msg, condition.getArgs() @@ -311,7 +312,7 @@ public class ActionManagerImpl implements ActionManager { ArrayList msg = ConfigUtils.stringListArgs(args); return condition -> { if (Math.random() > chance) return; - List replaced = PlaceholderManagerImpl.getInstance().parse( + List replaced = BukkitPlaceholderManager.getInstance().parse( condition.getPlayer(), msg, condition.getArgs() @@ -335,7 +336,7 @@ public class ActionManagerImpl implements ActionManager { double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); if (distance <= range) { condition.insertArg("{near}", player.getName()); - List replaced = PlaceholderManagerImpl.getInstance().parse( + List replaced = BukkitPlaceholderManager.getInstance().parse( owner, msg, condition.getArgs() @@ -350,7 +351,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: message-nearby"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); registerAction("random-message", (args, chance) -> { @@ -358,7 +359,7 @@ public class ActionManagerImpl implements ActionManager { return condition -> { if (Math.random() > chance) return; String random = msg.get(ThreadLocalRandom.current().nextInt(msg.size())); - random = PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); + random = BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); AdventureHelper.getInstance().sendPlayerMessage(condition.getPlayer(), random); }; }); @@ -369,7 +370,7 @@ public class ActionManagerImpl implements ActionManager { ArrayList cmd = ConfigUtils.stringListArgs(args); return condition -> { if (Math.random() > chance) return; - List replaced = PlaceholderManagerImpl.getInstance().parse( + List replaced = BukkitPlaceholderManager.getInstance().parse( condition.getPlayer(), cmd, condition.getArgs() @@ -386,7 +387,7 @@ public class ActionManagerImpl implements ActionManager { return condition -> { if (Math.random() > chance) return; String random = cmd.get(ThreadLocalRandom.current().nextInt(cmd.size())); - random = PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); + random = BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); String finalRandom = random; plugin.getScheduler().runTaskSync(() -> { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), finalRandom); @@ -405,7 +406,7 @@ public class ActionManagerImpl implements ActionManager { double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); if (distance <= range) { condition.insertArg("{near}", player.getName()); - List replaced = PlaceholderManagerImpl.getInstance().parse( + List replaced = BukkitPlaceholderManager.getInstance().parse( owner, cmd, condition.getArgs() @@ -420,7 +421,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: command-nearby"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -442,7 +443,7 @@ public class ActionManagerImpl implements ActionManager { return condition -> { if (Math.random() > chance) return; String random = texts.get(ThreadLocalRandom.current().nextInt(texts.size())); - random = PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); + random = BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); AdventureHelper.getInstance().sendActionbar(condition.getPlayer(), random); }; }); @@ -458,7 +459,7 @@ public class ActionManagerImpl implements ActionManager { double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); if (distance <= range) { condition.insertArg("{near}", player.getName()); - String replaced = PlaceholderManagerImpl.getInstance().parse( + String replaced = BukkitPlaceholderManager.getInstance().parse( owner, actionbar, condition.getArgs() @@ -472,7 +473,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: command-nearby"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -545,7 +546,7 @@ public class ActionManagerImpl implements ActionManager { (Player) player, location.clone().add(x, y, z), AdventureHelper.getInstance().getComponentFromMiniMessage( - PlaceholderManagerImpl.getInstance().parse(owner, text, condition.getArgs()) + BukkitPlaceholderManager.getInstance().parse(owner, text, condition.getArgs()) ), duration ); @@ -558,7 +559,7 @@ public class ActionManagerImpl implements ActionManager { owner, location.clone().add(x, y, z), AdventureHelper.getInstance().getComponentFromMiniMessage( - PlaceholderManagerImpl.getInstance().parse(owner, text, condition.getArgs()) + BukkitPlaceholderManager.getInstance().parse(owner, text, condition.getArgs()) ), duration ); @@ -566,7 +567,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: hologram"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -584,7 +585,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: item-amount"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -606,7 +607,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: durability"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -623,7 +624,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: give-item"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -686,7 +687,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: fake-item"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -825,8 +826,8 @@ public class ActionManagerImpl implements ActionManager { if (Math.random() > chance) return; AdventureHelper.getInstance().sendTitle( condition.getPlayer(), - PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), title, condition.getArgs()), - PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), subtitle, condition.getArgs()), + BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), title, condition.getArgs()), + BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), subtitle, condition.getArgs()), fadeIn, stay, fadeOut @@ -834,7 +835,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: title"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); registerAction("title-nearby", (args, chance) -> { @@ -854,8 +855,8 @@ public class ActionManagerImpl implements ActionManager { condition.insertArg("{near}", player.getName()); AdventureHelper.getInstance().sendTitle( condition.getPlayer(), - PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), title, condition.getArgs()), - PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), subtitle, condition.getArgs()), + BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), title, condition.getArgs()), + BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), subtitle, condition.getArgs()), fadeIn, stay, fadeOut @@ -868,7 +869,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: title-nearby"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); registerAction("random-title", (args, chance) -> { @@ -884,8 +885,8 @@ public class ActionManagerImpl implements ActionManager { if (Math.random() > chance) return; AdventureHelper.getInstance().sendTitle( condition.getPlayer(), - PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), titles.get(ThreadLocalRandom.current().nextInt(titles.size())), condition.getArgs()), - PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), subtitles.get(ThreadLocalRandom.current().nextInt(subtitles.size())), condition.getArgs()), + BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), titles.get(ThreadLocalRandom.current().nextInt(titles.size())), condition.getArgs()), + BukkitPlaceholderManager.getInstance().parse(condition.getPlayer(), subtitles.get(ThreadLocalRandom.current().nextInt(subtitles.size())), condition.getArgs()), fadeIn, stay, fadeOut @@ -893,7 +894,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: random-title"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -912,7 +913,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: potion-effect"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -944,7 +945,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: sound"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -953,7 +954,7 @@ public class ActionManagerImpl implements ActionManager { registerAction("conditional", (args, chance) -> { if (args instanceof ConfigurationSection section) { Action[] actions = getActions(section.getConfigurationSection("actions")); - Requirement[] requirements = plugin.getRequirementManager().getRequirements(section.getConfigurationSection("conditions"), true); + Requirement[] requirements = plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("conditions"), true); return condition -> { if (Math.random() > chance) return; if (requirements != null) @@ -968,7 +969,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: conditional"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -980,7 +981,7 @@ public class ActionManagerImpl implements ActionManager { for (Map.Entry entry : section.getValues(false).entrySet()) { if (entry.getValue() instanceof ConfigurationSection inner) { Action[] actions = getActions(inner.getConfigurationSection("actions")); - Requirement[] requirements = plugin.getRequirementManager().getRequirements(inner.getConfigurationSection("conditions"), false); + Requirement[] requirements = plugin.getRequirementManager().parseRequirements(inner.getConfigurationSection("conditions"), false); conditionActionPairList.add(Pair.of(requirements, actions)); } } @@ -1003,7 +1004,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: priority"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } @@ -1022,7 +1023,7 @@ public class ActionManagerImpl implements ActionManager { }; } else { LogUtils.warn("Illegal value format found at action: plugin-exp"); - return EmptyAction.instance; + return EmptyAction.INSTANCE; } }); } diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/action/EmptyAction.java b/core/src/main/java/net/momirealms/customfishing/mechanic/action/EmptyAction.java deleted file mode 100644 index e2cb14d9..00000000 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/action/EmptyAction.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.momirealms.customfishing.mechanic.action; - -import net.momirealms.customfishing.api.mechanic.action.Action; - -/** - * An implementation of the Action interface that represents an empty action with no behavior. - * This class serves as a default action to prevent NPE. - */ -public class EmptyAction implements Action { - - public static EmptyAction instance = new EmptyAction(); - - @Override - public void trigger(PlayerContext playerContext) { - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/bag/BagManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/bag/BagManagerImpl.java index 727d298a..d71f2750 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/bag/BagManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/bag/BagManagerImpl.java @@ -23,7 +23,7 @@ import net.momirealms.customfishing.api.storage.user.UserData; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.requirement.Requirement; import net.momirealms.customfishing.api.util.InventoryUtils; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -73,7 +73,7 @@ public class BagManagerImpl implements BagManager, Listener { if (bagStoreLoots) { collectLootActions = plugin.getActionManager().getActions(bagSection.getConfigurationSection("collect-actions")); bagFullActions = plugin.getActionManager().getActions(bagSection.getConfigurationSection("full-actions")); - collectRequirements = plugin.getRequirementManager().getRequirements(bagSection.getConfigurationSection("collect-requirements"), false); + collectRequirements = plugin.getRequirementManager().parseRequirements(bagSection.getConfigurationSection("collect-requirements"), false); } } } @@ -106,7 +106,7 @@ public class BagManagerImpl implements BagManager, Listener { if (bag.getSize() != rows * 9) { Inventory newBag = InventoryUtils.createInventory(onlinePlayer.getHolder(), rows * 9, AdventureHelper.getInstance().getComponentFromMiniMessage( - PlaceholderManagerImpl.getInstance().parse( + BukkitPlaceholderManager.getInstance().parse( player, bagTitle, Map.of("{player}", player.getName()) ) )); diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java index d5c35ce2..cc6bfd63 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java @@ -165,7 +165,7 @@ public class EffectManagerImpl implements EffectManager { if (section == null) return null; return new EffectCarrier.Builder() .key(key) - .requirements(plugin.getRequirementManager().getRequirements(section.getConfigurationSection("requirements"), true)) + .requirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), true)) .effect(getEffectModifiers(section.getConfigurationSection("effects"))) .actionMap(plugin.getActionManager().getActionMap(section.getConfigurationSection("events"))) .build(); @@ -368,7 +368,7 @@ public class EffectManagerImpl implements EffectManager { return ((effect, condition) -> effect.setLavaFishing(true)); } case "conditional" -> { - Requirement[] requirements = plugin.getRequirementManager().getRequirements(section.getConfigurationSection("conditions"), true); + Requirement[] requirements = plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("conditions"), true); EffectModifier[] modifiers = getEffectModifiers(section.getConfigurationSection("effects")); return ((effect, condition) -> { for (Requirement requirement : requirements) diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java index 99a36643..97fdc203 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java @@ -708,7 +708,7 @@ public class FishingManagerImpl implements Listener, FishingManager { */ private void doSuccessActions(Loot loot, Effect effect, FishingPreparation fishingPreparation, Player player) { FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition(); - if (competition != null && RequirementManager.isRequirementMet(fishingPreparation, competition.getConfig().getRequirements())) { + if (competition != null && RequirementManager.isRequirementMet(fishingPreparation, competition.getConfig().getJoinRequirements())) { String scoreStr = fishingPreparation.getArg("{CUSTOM_SCORE}"); if (scoreStr != null) { competition.refreshData(player, Double.parseDouble(scoreStr)); diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java index 40f2c59d..ac24a68f 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java @@ -38,7 +38,7 @@ import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.mechanic.misc.value.MathValue; import net.momirealms.customfishing.bukkit.compatibility.item.CustomFishingItemImpl; import net.momirealms.customfishing.bukkit.compatibility.item.VanillaItemImpl; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import net.momirealms.customfishing.util.ConfigUtils; import net.momirealms.customfishing.util.ItemUtils; import net.momirealms.customfishing.util.LocationUtils; @@ -580,7 +580,7 @@ public class ItemManagerImpl implements ItemManager, Listener { editors.put("name", (player, nbtItem, placeholders) -> { nbtItem.set(AdventureHelper.getInstance().componentToJson( AdventureHelper.getInstance().getComponentFromMiniMessage( - "" + PlaceholderManagerImpl.getInstance().parse(player, name, placeholders) + "" + BukkitPlaceholderManager.getInstance().parse(player, name, placeholders) ) ), "display", "Name"); }); @@ -635,7 +635,7 @@ public class ItemManagerImpl implements ItemManager, Listener { editors.put("lore", (player, nbtItem, placeholders) -> { List list = new ArrayList<>(lore.stream().map(s -> AdventureHelper.getInstance().componentToJson( AdventureHelper.getInstance().getComponentFromMiniMessage( - "" + PlaceholderManagerImpl.getInstance().parse(player, s, placeholders) + "" + BukkitPlaceholderManager.getInstance().parse(player, s, placeholders) ) )).toList()); nbtItem.set(list, "display", "Lore"); diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java index 29f03085..4e24fcd0 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java @@ -240,7 +240,7 @@ public class LootManagerImpl implements LootManager { if (section.contains("requirements") && section.contains("weight")) { plugin.getRequirementManager().putLegacyLootToMap( loot.getID(), - plugin.getRequirementManager().getRequirements(section.getConfigurationSection("requirements"), false), + plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), false), section.getDouble("weight", 0) ); } diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java index 3456452a..7c6eb1ea 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java @@ -24,7 +24,7 @@ import net.momirealms.customfishing.api.mechanic.market.MarketManager; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.market.MarketGUIHolder; import net.momirealms.customfishing.api.scheduler.CancellableTask; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import net.momirealms.customfishing.util.ConfigUtils; import net.momirealms.customfishing.util.NumberUtils; import net.objecthunter.exp4j.ExpressionBuilder; @@ -497,8 +497,8 @@ public class MarketManagerImpl implements MarketManager, Listener { @Override public double getFishPrice(Player player, Map vars) { - String temp = PlaceholderManagerImpl.getInstance().parse(player, formula, vars); - var placeholders = PlaceholderManagerImpl.getInstance().detectPlaceholders(temp); + String temp = BukkitPlaceholderManager.getInstance().parse(player, formula, vars); + var placeholders = BukkitPlaceholderManager.getInstance().resolvePlaceholders(temp); for (String placeholder : placeholders) { temp = temp.replace(placeholder, "0"); } @@ -533,7 +533,7 @@ public class MarketManagerImpl implements MarketManager, Listener { @Override public double getEarningLimit(Player player) { return new ExpressionBuilder( - PlaceholderManagerImpl.getInstance().parse( + BukkitPlaceholderManager.getInstance().parse( player, earningLimitExpression, new HashMap<>() diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/misc/DynamicText.java b/core/src/main/java/net/momirealms/customfishing/mechanic/misc/DynamicText.java index 8f76869f..095f0e76 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/misc/DynamicText.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/misc/DynamicText.java @@ -17,7 +17,7 @@ package net.momirealms.customfishing.mechanic.misc; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import org.bukkit.entity.Player; import java.util.ArrayList; @@ -39,7 +39,7 @@ public class DynamicText { private void analyze(String value) { // Analyze the provided text to find and replace placeholders with '%s'. // Store the original value, placeholders, and the initial latest value. - List placeholdersOwner = new ArrayList<>(PlaceholderManagerImpl.getInstance().detectPlaceholders(value)); + List placeholdersOwner = new ArrayList<>(BukkitPlaceholderManager.getInstance().resolvePlaceholders(value)); String origin = value; for (String placeholder : placeholdersOwner) { origin = origin.replace(placeholder, "%s"); @@ -57,13 +57,13 @@ public class DynamicText { // Update the dynamic text by replacing placeholders with actual values. String string = originalValue; if (this.placeholders.length != 0) { - PlaceholderManagerImpl placeholderManagerImpl = PlaceholderManagerImpl.getInstance(); + BukkitPlaceholderManager bukkitPlaceholderManager = BukkitPlaceholderManager.getInstance(); if ("%s".equals(originalValue)) { - string = placeholderManagerImpl.getSingleValue(owner, this.placeholders[0], placeholders); + string = bukkitPlaceholderManager.getSingleValue(owner, this.placeholders[0], placeholders); } else { Object[] values = new String[this.placeholders.length]; for (int i = 0; i < this.placeholders.length; i++) { - values[i] = placeholderManagerImpl.getSingleValue(owner, this.placeholders[i], placeholders); + values[i] = bukkitPlaceholderManager.getSingleValue(owner, this.placeholders[i], placeholders); } string = String.format(originalValue, values); } diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java index b62ede36..bbf9c2d5 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java @@ -21,15 +21,12 @@ import net.momirealms.customfishing.BukkitCustomFishingPluginImpl; import net.momirealms.customfishing.api.common.Pair; import net.momirealms.customfishing.api.integration.LevelerProvider; import net.momirealms.customfishing.api.integration.SeasonProvider; -import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; +import net.momirealms.customfishing.api.mechanic.requirement.*; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; import net.momirealms.customfishing.api.mechanic.loot.Loot; -import net.momirealms.customfishing.api.mechanic.requirement.Requirement; -import net.momirealms.customfishing.api.mechanic.requirement.RequirementExpansion; -import net.momirealms.customfishing.api.mechanic.requirement.RequirementFactory; import net.momirealms.customfishing.bukkit.compatibility.VaultHook; -import net.momirealms.customfishing.bukkit.compatibility.papi.ParseUtils; +import net.momirealms.customfishing.bukkit.misc.placeholder.papi.ParseUtils; import net.momirealms.customfishing.common.util.ClassUtils; import net.momirealms.customfishing.util.ClassUtils; import net.momirealms.customfishing.util.ConfigUtils; @@ -271,7 +268,7 @@ public class RequirementManagerImpl implements RequirementManager { for (Map.Entry entry : section.getValues(false).entrySet()) { String typeOrName = entry.getKey(); if (hasRequirement(typeOrName)) { - requirements.add(getRequirement(typeOrName, entry.getValue())); + requirements.add(parseRequirement(typeOrName, entry.getValue())); } else { requirements.add(getRequirement(section.getConfigurationSection(typeOrName), advanced)); } @@ -294,7 +291,7 @@ public class RequirementManagerImpl implements RequirementManager { @NotNull @Override public Requirement getRequirement(ConfigurationSection section, boolean advanced) { - if (section == null) return EmptyRequirement.instance; + if (section == null) return EmptyRequirement.INSTANCE; List actionList = null; if (advanced) { actionList = new ArrayList<>(); @@ -311,11 +308,11 @@ public class RequirementManagerImpl implements RequirementManager { String type = section.getString("type"); if (type == null) { LogUtils.warn("No requirement type found at " + section.getCurrentPath()); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } var builder = getRequirementFactory(type); if (builder == null) { - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } return builder.build(section.get("value"), actionList, advanced); } @@ -331,11 +328,11 @@ public class RequirementManagerImpl implements RequirementManager { */ @Override @NotNull - public Requirement getRequirement(@NotNull String type, @NotNull Object value) { + public Requirement parseRequirement(@NotNull String type, @NotNull Object value) { RequirementFactory factory = getRequirementFactory(type); if (factory == null) { LogUtils.warn("Requirement type: " + type + " doesn't exist."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } return factory.build(value); } @@ -457,7 +454,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at || requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -480,7 +477,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at && requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -675,7 +672,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at cooldown requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -747,7 +744,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at >= requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement(">", (args, actions, advanced) -> { @@ -763,7 +760,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at > requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -780,7 +777,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at regex requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -799,7 +796,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at !startsWith requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement("!=", (args, actions, advanced) -> { @@ -815,7 +812,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at !startsWith requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -835,7 +832,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at < requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement("<=", (args, actions, advanced) -> { @@ -851,7 +848,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at <= requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -870,7 +867,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at startsWith requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement("!startsWith", (args, actions, advanced) -> { @@ -886,7 +883,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at !startsWith requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -905,7 +902,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at endsWith requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement("!endsWith", (args, actions, advanced) -> { @@ -921,7 +918,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at !endsWith requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -940,7 +937,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at contains requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement("!contains", (args, actions, advanced) -> { @@ -956,7 +953,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at !contains requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -974,7 +971,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at in-list requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement("!in-list", (args, actions, advanced) -> { @@ -989,7 +986,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at in-list requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -1008,7 +1005,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at equals requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); registerRequirement("!equals", (args, actions, advanced) -> { @@ -1024,7 +1021,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at !equals requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -1067,7 +1064,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at item-in-hand requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -1232,7 +1229,7 @@ public class RequirementManagerImpl implements RequirementManager { for (String e : list) { LogUtils.warn(" - " + e); } - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; }); } @@ -1265,7 +1262,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at competition requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -1289,7 +1286,7 @@ public class RequirementManagerImpl implements RequirementManager { }; } else { LogUtils.warn("Wrong value format found at plugin-level requirement."); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } }); } @@ -1302,7 +1299,7 @@ public class RequirementManagerImpl implements RequirementManager { PotionEffectType type = PotionEffectType.getByName(split[0]); if (type == null) { LogUtils.warn("Potion effect doesn't exist: " + split[0]); - return EmptyRequirement.instance; + return EmptyRequirement.INSTANCE; } int required = Integer.parseInt(split[1]); String operator = potions.substring(split[0].length(), potions.length() - split[1].length()); diff --git a/core/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java index 0c2e2b65..0b3e21cc 100644 --- a/core/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java @@ -220,7 +220,7 @@ public class TotemManagerImpl implements TotemManager, Listener { TotemConfig totemConfig = new TotemConfig.Builder(entry.getKey()) .setTotemModels(getTotemModels(section.getConfigurationSection("pattern"))) .setParticleSettings(getParticleSettings(section.getConfigurationSection("particles"))) - .setRequirements(plugin.getRequirementManager().getRequirements(section.getConfigurationSection("requirements"), true)) + .setRequirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), true)) .setRadius(section.getDouble("radius", 8)) .setDuration(section.getInt("duration", 300)) .build(); diff --git a/core/src/main/java/net/momirealms/customfishing/storage/user/OfflineUser.java b/core/src/main/java/net/momirealms/customfishing/storage/user/OfflineUser.java index 845b95f4..745eb415 100644 --- a/core/src/main/java/net/momirealms/customfishing/storage/user/OfflineUser.java +++ b/core/src/main/java/net/momirealms/customfishing/storage/user/OfflineUser.java @@ -23,7 +23,7 @@ import net.momirealms.customfishing.api.storage.data.InventoryData; import net.momirealms.customfishing.api.storage.data.PlayerData; import net.momirealms.customfishing.api.storage.data.StatisticData; import net.momirealms.customfishing.api.storage.user.UserData; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -59,7 +59,7 @@ public class OfflineUser implements UserData { // Set up the inventory for the FishingBagHolder this.holder.setInventory(InventoryUtils.createInventory(this.holder, playerData.getBagData().size, AdventureHelper.getInstance().getComponentFromMiniMessage( - PlaceholderManagerImpl.getInstance().parse( + BukkitPlaceholderManager.getInstance().parse( offlinePlayer, BukkitCustomFishingPlugin.get().getBagManager().getBagTitle(), Map.of("{player}", Optional.ofNullable(offlinePlayer.getName()).orElse(String.valueOf(uuid))) diff --git a/core/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java b/core/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java index 35e09607..7127aea1 100644 --- a/core/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java +++ b/core/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java @@ -20,7 +20,7 @@ package net.momirealms.customfishing.util; import net.momirealms.customfishing.api.common.Pair; import net.momirealms.customfishing.api.common.Tuple; import net.momirealms.customfishing.api.mechanic.misc.value.MathValue; -import net.momirealms.customfishing.bukkit.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.bukkit.misc.placeholder.BukkitPlaceholderManager; import net.momirealms.customfishing.mechanic.misc.value.ExpressionMathValue; import net.momirealms.customfishing.mechanic.misc.value.PlainMathValue; import net.objecthunter.exp4j.ExpressionBuilder; @@ -328,7 +328,7 @@ public class ConfigUtils { } public static double getExpressionValue(Player player, String formula, Map vars) { - formula = PlaceholderManagerImpl.getInstance().parse(player, formula, vars); + formula = BukkitPlaceholderManager.getInstance().parse(player, formula, vars); return new ExpressionBuilder(formula).build().evaluate(); } diff --git a/core/src/main/resources/commands.yml b/core/src/main/resources/commands.yml new file mode 100644 index 00000000..54bdb897 --- /dev/null +++ b/core/src/main/resources/commands.yml @@ -0,0 +1,20 @@ +# +# Don't change this +# +config-version: "${config_version}" + +# +# For safety reasons, editing this file requires a restart to apply +# +reload: + enable: true + permission: customfishing.reload + usage: + - /customfishing reload + - /cfishing reload + +sellfish: + enable: true + permission: customfishing.sellfish + usage: + - /sellfish \ No newline at end of file