diff --git a/api-bukkit/pom.xml b/api-bukkit/pom.xml new file mode 100644 index 00000000..1837665f --- /dev/null +++ b/api-bukkit/pom.xml @@ -0,0 +1,38 @@ + + + + treasury-parent + me.lokka30 + 1.0.0-SNAPSHOT + + 4.0.0 + + treasury-api-bukkit + + Treasury-API-Bukkit + Additions to Treasury's API for Bukkit + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + + org.spigotmc + spigot-api + ${spigot.version} + provided + + + me.lokka30 + treasury-api + ${project.version} + + + + \ No newline at end of file diff --git a/src/main/java/me/lokka30/treasury/api/economy/event/AccountEvent.java b/api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/AccountEvent.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/event/AccountEvent.java rename to api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/AccountEvent.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/event/AccountTransactionEvent.java b/api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/AccountTransactionEvent.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/event/AccountTransactionEvent.java rename to api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/AccountTransactionEvent.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/event/BankAccountTransactionEvent.java b/api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/BankAccountTransactionEvent.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/event/BankAccountTransactionEvent.java rename to api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/BankAccountTransactionEvent.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/event/PlayerAccountTransactionEvent.java b/api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/PlayerAccountTransactionEvent.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/event/PlayerAccountTransactionEvent.java rename to api-bukkit/src/main/java/me/lokka30/treasury/api/economy/event/PlayerAccountTransactionEvent.java diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 00000000..5614ee0d --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,25 @@ + + + + treasury-parent + me.lokka30 + 1.0.0-SNAPSHOT + + 4.0.0 + + treasury-api + + Treasury-API + Base API for Treasury. + + + + org.jetbrains + annotations + ${jetbrains.annotations.version} + + + + \ No newline at end of file diff --git a/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java b/api/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java similarity index 93% rename from src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java rename to api/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java index 25560043..6b51bf42 100644 --- a/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java +++ b/api/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java @@ -17,17 +17,15 @@ import me.lokka30.treasury.api.economy.currency.Currency; import me.lokka30.treasury.api.economy.misc.EconomyAPIVersion; import me.lokka30.treasury.api.economy.response.EconomySubscriber; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.UUID; /** - * {@link Plugin Plugins} providing and managing economy data create a class - * which implements this interface to be registered via the - * {@link org.bukkit.plugin.ServicesManager ServicesManager} as a - * {@link org.bukkit.plugin.RegisteredServiceProvider RegisteredServiceProvider<EconomyProvider>}. + * Implementors providing and managing economy data create a class + * which implements this interface to be registered in + * the specific platform they're implementing it for. * * @author lokka30 * @since v1.0.0 @@ -35,16 +33,6 @@ @SuppressWarnings({"unused", "UnusedReturnValue"}) public interface EconomyProvider { - /** - * Get the "Economy Provider" - the {@link Plugin} facilitating the economy. - * - * @author lokka30 - * @return the {@code Plugin} facilitating the economy - * @since v1.0.0 - */ - @NotNull - Plugin getProvider(); - /** * Get the version of the Treasury API the {@code EconomyProvider} is based on. * diff --git a/src/main/java/me/lokka30/treasury/api/economy/account/Account.java b/api/src/main/java/me/lokka30/treasury/api/economy/account/Account.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/account/Account.java rename to api/src/main/java/me/lokka30/treasury/api/economy/account/Account.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/account/BankAccount.java b/api/src/main/java/me/lokka30/treasury/api/economy/account/BankAccount.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/account/BankAccount.java rename to api/src/main/java/me/lokka30/treasury/api/economy/account/BankAccount.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/account/PlayerAccount.java b/api/src/main/java/me/lokka30/treasury/api/economy/account/PlayerAccount.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/account/PlayerAccount.java rename to api/src/main/java/me/lokka30/treasury/api/economy/account/PlayerAccount.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java b/api/src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java rename to api/src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/ConversionPriority.java b/api/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/ConversionPriority.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/currency/conversion/ConversionPriority.java rename to api/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/ConversionPriority.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConversion.java b/api/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConversion.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConversion.java rename to api/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConversion.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConverter.java b/api/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConverter.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConverter.java rename to api/src/main/java/me/lokka30/treasury/api/economy/currency/conversion/CurrencyConverter.java diff --git a/api/src/main/java/me/lokka30/treasury/api/economy/misc/AmountUtils.java b/api/src/main/java/me/lokka30/treasury/api/economy/misc/AmountUtils.java new file mode 100644 index 00000000..a5071c1b --- /dev/null +++ b/api/src/main/java/me/lokka30/treasury/api/economy/misc/AmountUtils.java @@ -0,0 +1,28 @@ +package me.lokka30.treasury.api.economy.misc; + +/** + * Represents a utility class for handling double values, or economy amounts. + * + * @since v1.0.0 + */ +public final class AmountUtils { + + /** + * If the specified amount is less than zero + * then zero is returned. Otherwise, the amount + * is returned. This ensures an amount is at least zero + * since negative values are not allowed in the API. + * + * @param amount to check for. + * @return the unmodified or modified amount. + * @author lokka30 + * @since v1.0.0 + */ + public static double ensureAtLeastZero(final double amount) { + return Math.max(amount, 0.0d); + } + + private AmountUtils() { + throw new IllegalArgumentException("Initialization of utility-type class"); + } +} diff --git a/src/main/java/me/lokka30/treasury/api/economy/misc/EconomyAPIVersion.java b/api/src/main/java/me/lokka30/treasury/api/economy/misc/EconomyAPIVersion.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/misc/EconomyAPIVersion.java rename to api/src/main/java/me/lokka30/treasury/api/economy/misc/EconomyAPIVersion.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/response/EconomyException.java b/api/src/main/java/me/lokka30/treasury/api/economy/response/EconomyException.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/response/EconomyException.java rename to api/src/main/java/me/lokka30/treasury/api/economy/response/EconomyException.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/response/EconomySubscriber.java b/api/src/main/java/me/lokka30/treasury/api/economy/response/EconomySubscriber.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/response/EconomySubscriber.java rename to api/src/main/java/me/lokka30/treasury/api/economy/response/EconomySubscriber.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/response/FailureReason.java b/api/src/main/java/me/lokka30/treasury/api/economy/response/FailureReason.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/response/FailureReason.java rename to api/src/main/java/me/lokka30/treasury/api/economy/response/FailureReason.java diff --git a/src/main/java/me/lokka30/treasury/api/economy/transaction/Transaction.java b/api/src/main/java/me/lokka30/treasury/api/economy/transaction/Transaction.java similarity index 92% rename from src/main/java/me/lokka30/treasury/api/economy/transaction/Transaction.java rename to api/src/main/java/me/lokka30/treasury/api/economy/transaction/Transaction.java index a0ff11f9..26c3d59d 100644 --- a/src/main/java/me/lokka30/treasury/api/economy/transaction/Transaction.java +++ b/api/src/main/java/me/lokka30/treasury/api/economy/transaction/Transaction.java @@ -12,7 +12,7 @@ package me.lokka30.treasury.api.economy.transaction; -import me.lokka30.treasury.plugin.misc.Utils; +import me.lokka30.treasury.api.economy.misc.AmountUtils; import org.jetbrains.annotations.NotNull; @SuppressWarnings("unused") @@ -23,8 +23,8 @@ public class Transaction { @NotNull private final TransactionType transactionType; public Transaction(final double newBalance, final double transactionAmount, @NotNull final TransactionType transactionType) { - this.newBalance = Utils.ensureAtLeastZero(newBalance); - this.transactionAmount = Utils.ensureAtLeastZero(newBalance); + this.newBalance = AmountUtils.ensureAtLeastZero(newBalance); + this.transactionAmount = AmountUtils.ensureAtLeastZero(newBalance); this.transactionType = transactionType; } diff --git a/src/main/java/me/lokka30/treasury/api/economy/transaction/TransactionType.java b/api/src/main/java/me/lokka30/treasury/api/economy/transaction/TransactionType.java similarity index 100% rename from src/main/java/me/lokka30/treasury/api/economy/transaction/TransactionType.java rename to api/src/main/java/me/lokka30/treasury/api/economy/transaction/TransactionType.java diff --git a/bukkit/pom.xml b/bukkit/pom.xml new file mode 100644 index 00000000..34cba66b --- /dev/null +++ b/bukkit/pom.xml @@ -0,0 +1,130 @@ + + + + treasury-parent + me.lokka30 + 1.0.0-SNAPSHOT + + 4.0.0 + + treasury-bukkit + + Treasury-Bukkit + A modern code library for plugins. + + + true + true + + + + clean package + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + false + + + org.bstats + me.lokka30.treasury.plugin.bukkit.shade.bstats + + + com.mrivanplays.annotationconfig + me.lokka30.treasury.plugin.shade.annotationconfig + + + + + + package + + shade + + + + + + + + src/main/resources + true + + + + + + + papermc + https://papermc.io/repo/repository/maven-public/ + + + jitpack.io + https://jitpack.io + + + CodeMC + https://repo.codemc.org/repository/maven-public + + + + + + me.lokka30 + treasury-api-bukkit + ${project.version} + compile + + + org.jetbrains + annotations + + + + + me.lokka30 + treasury-core + ${project.version} + compile + + + org.yaml + snakeyaml + + + + + + io.papermc.paper + paper-api + ${spigot.version} + provided + + + io.papermc.paper + paper-mojangapi + ${spigot.version} + provided + + + org.jetbrains + annotations + ${jetbrains.annotations.version} + provided + + + org.bstats + bstats-bukkit + ${bstats.version} + compile + + + + \ No newline at end of file diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/BukkitTreasuryPlugin.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/BukkitTreasuryPlugin.java new file mode 100644 index 00000000..dfb1928c --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/BukkitTreasuryPlugin.java @@ -0,0 +1,213 @@ +package me.lokka30.treasury.plugin.bukkit; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.logging.Level; +import java.util.stream.Collectors; +import me.lokka30.treasury.api.economy.EconomyProvider; +import me.lokka30.treasury.api.economy.misc.EconomyAPIVersion; +import me.lokka30.treasury.plugin.bukkit.vendor.BukkitVendor; +import me.lokka30.treasury.plugin.core.ProviderEconomy; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.config.ConfigAdapter; +import me.lokka30.treasury.plugin.core.config.messaging.Messages; +import me.lokka30.treasury.plugin.core.config.settings.Settings; +import me.lokka30.treasury.plugin.core.logging.Logger; +import me.lokka30.treasury.plugin.core.schedule.Scheduler; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.plugin.ServicePriority; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +// yeye I know single responsibility principle +// stop spanking me for doing this, but the heavy stuff have been abstracted away so there's literally no logic +// for the platform implementation to be split in different classes. SO STFU +public class BukkitTreasuryPlugin extends TreasuryPlugin + implements Logger, Scheduler, ConfigAdapter { + + private final TreasuryBukkit plugin; + private Messages messages; + private Settings settings; + + private final File messagesFile; + private final File settingsFile; + + private List cachedPluginList = null; + + public BukkitTreasuryPlugin(@NotNull TreasuryBukkit plugin) { + this.plugin = Objects.requireNonNull(plugin, "plugin"); + messagesFile = new File(plugin.getDataFolder(), "messages.yml"); + settingsFile = new File(plugin.getDataFolder(), "settings.yml"); + } + + @Override + public @NotNull String getVersion() { + return plugin.getDescription().getVersion(); + } + + @Override + public @Nullable String getDescription() { + return plugin.getDescription().getDescription(); + } + + @Override + public @NotNull List allProviders() { + Collection> providers = + Bukkit.getServicesManager().getRegistrations(EconomyProvider.class); + List ret = new ArrayList<>(); + for (RegisteredServiceProvider rsp : providers) { + ret.add(new ProviderEconomyImpl(rsp.getPriority(), new RegistrarInfoImpl(rsp.getPlugin()), rsp.getProvider())); + } + if (!ret.isEmpty()) { + ret.sort(((Comparator) (o1, o2) -> { + ServicePriority priority1 = ServicePriority.valueOf(capitalizeFirstLetter(o1.getPriority())); + ServicePriority priority2 = ServicePriority.valueOf(capitalizeFirstLetter(o2.getPriority())); + return priority1.compareTo(priority2); + }).reversed()); + } + return ret; + } + + private String capitalizeFirstLetter(String val) { + char[] c = val.toCharArray(); + c[0] = Character.toUpperCase(c[0]); + return new String(c); + } + + @Override + public void registerProvider(@NotNull EconomyProvider newProvider) { + Bukkit.getServicesManager().register(EconomyProvider.class, newProvider, plugin, ServicePriority.Highest); + } + + @Override + public void reregisterProvider(@NotNull ProviderEconomy provider, boolean lowPriority) { + ServicePriority priority = lowPriority ? ServicePriority.Low : ServicePriority.High; + if (provider.getPriority().equalsIgnoreCase(priority.name().toLowerCase(Locale.ROOT))) { + return; + } + Plugin plugin = Bukkit.getPluginManager().getPlugin(provider.registrar().getName()); + EconomyProvider eco = provider.provide(); + Bukkit.getServicesManager().unregister(eco); + Bukkit.getServicesManager().register(EconomyProvider.class, eco, plugin, priority); + } + + @Override + public void unregisterProvider(@NotNull EconomyProvider provider) { + runSync(() -> Bukkit.getServicesManager().unregister(provider)); + } + + @Override + public @NotNull Logger logger() { + return this; + } + + @Override + public @NotNull Scheduler scheduler() { + return this; + } + + @Override + public @NotNull ConfigAdapter configAdapter() { + return this; + } + + @Override + public void reload() { + loadMessages(); + loadSettings(); + } + + public void loadMessages() { + messages = Messages.load(messagesFile); + } + + public void loadSettings() { + settings = Settings.load(settingsFile); + } + + @Override + public @NotNull EconomyAPIVersion getEconomyAPIVersion() { + return TreasuryBukkit.ECONOMY_API_VERSION; + } + + @Override + public @NotNull List pluginsListRegisteringProvider() { + if (cachedPluginList != null) { + return cachedPluginList; + } + cachedPluginList = Arrays.stream( + Bukkit.getPluginManager().getPlugins() + ).filter(pl -> { + List> registrations = Bukkit.getServicesManager().getRegistrations(pl); + if (registrations.isEmpty()) { + return false; + } + if (registrations.size() == 1) { + return registrations.get(0).getProvider().getClass().isAssignableFrom(EconomyProvider.class); + } + boolean hasRegistration = false; + for (RegisteredServiceProvider provider : registrations) { + if (provider.getProvider().getClass().isAssignableFrom(EconomyProvider.class)) { + hasRegistration = true; + break; + } + } + return hasRegistration; + }).map(Plugin::getName).collect(Collectors.toList()); + return cachedPluginList; + } + + @Override + public @NotNull Messages getMessages() { + return messages; + } + + @Override + public @NotNull Settings getSettings() { + return settings; + } + + public String colorize(@NotNull String message) { + return BukkitVendor.isSpigot() + ? net.md_5.bungee.api.ChatColor.translateAlternateColorCodes('&', message) + : org.bukkit.ChatColor.translateAlternateColorCodes('&', message); + } + + @Override + public void info(String message) { + plugin.getLogger().info(colorize(message)); + } + + @Override + public void warn(String message) { + plugin.getLogger().warning(colorize(message)); + } + + @Override + public void error(String message) { + plugin.getLogger().severe(colorize(message)); + } + + @Override + public void error(String message, Throwable t) { + plugin.getLogger().log(Level.SEVERE, colorize(message), t); + } + + @Override + public void runSync(Runnable task) { + Bukkit.getScheduler().runTask(plugin, task); + } + + @Override + public void runAsync(Runnable task) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, task); + } +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/ProviderEconomyImpl.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/ProviderEconomyImpl.java new file mode 100644 index 00000000..33579b6c --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/ProviderEconomyImpl.java @@ -0,0 +1,41 @@ +package me.lokka30.treasury.plugin.bukkit; + +import java.util.Locale; +import java.util.Objects; +import me.lokka30.treasury.api.economy.EconomyProvider; +import me.lokka30.treasury.plugin.core.ProviderEconomy; +import me.lokka30.treasury.plugin.core.RegistrarInfo; +import org.bukkit.plugin.ServicePriority; +import org.jetbrains.annotations.NotNull; + +public class ProviderEconomyImpl implements ProviderEconomy { + + private final ServicePriority priority; + private final RegistrarInfo registrar; + private final EconomyProvider economyProvider; + + public ProviderEconomyImpl( + @NotNull ServicePriority priority, + @NotNull RegistrarInfo registrar, + @NotNull EconomyProvider economyProvider + ) { + this.priority = Objects.requireNonNull(priority, "priority"); + this.registrar = Objects.requireNonNull(registrar, "registrar"); + this.economyProvider = Objects.requireNonNull(economyProvider, "economyProvider"); + } + + @Override + public @NotNull EconomyProvider provide() { + return economyProvider; + } + + @Override + public @NotNull RegistrarInfo registrar() { + return registrar; + } + + @Override + public @NotNull String getPriority() { + return priority.name().toLowerCase(Locale.ROOT); + } +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/RegistrarInfoImpl.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/RegistrarInfoImpl.java new file mode 100644 index 00000000..c9a0d5b2 --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/RegistrarInfoImpl.java @@ -0,0 +1,19 @@ +package me.lokka30.treasury.plugin.bukkit; + +import me.lokka30.treasury.plugin.core.RegistrarInfo; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +public class RegistrarInfoImpl implements RegistrarInfo { + + private final Plugin plugin; + + public RegistrarInfoImpl(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public @NotNull String getName() { + return plugin.getName(); + } +} diff --git a/src/main/java/me/lokka30/treasury/plugin/Treasury.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/TreasuryBukkit.java similarity index 67% rename from src/main/java/me/lokka30/treasury/plugin/Treasury.java rename to bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/TreasuryBukkit.java index 2b855cc4..1d565e60 100644 --- a/src/main/java/me/lokka30/treasury/plugin/Treasury.java +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/TreasuryBukkit.java @@ -10,23 +10,20 @@ * 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 me.lokka30.treasury.plugin; +package me.lokka30.treasury.plugin.bukkit; -import me.lokka30.microlib.files.YamlConfigFile; -import me.lokka30.microlib.maths.QuickTimer; import me.lokka30.treasury.api.economy.currency.conversion.CurrencyConverter; import me.lokka30.treasury.api.economy.misc.EconomyAPIVersion; -import me.lokka30.treasury.plugin.command.CommandHandler; -import me.lokka30.treasury.plugin.debug.DebugHandler; -import me.lokka30.treasury.plugin.file.FileHandler; -import me.lokka30.treasury.plugin.misc.UpdateCheckerHandler; -import me.lokka30.treasury.plugin.misc.Utils; +import me.lokka30.treasury.plugin.bukkit.command.TreasuryCommand; +import me.lokka30.treasury.plugin.bukkit.vendor.BukkitVendor; +import me.lokka30.treasury.plugin.bukkit.vendor.paper.PaperEnhancements; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.utils.QuickTimer; +import me.lokka30.treasury.plugin.core.utils.UpdateChecker; import org.bstats.bukkit.Metrics; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; -import java.io.File; - /** * @author lokka30 * @since v1.0.0 @@ -35,7 +32,7 @@ * the plugin. */ @SuppressWarnings("unused") -public class Treasury extends JavaPlugin { +public class TreasuryBukkit extends JavaPlugin { /** * This is Treasury's API version. (Not the same as api-version from plugin.yml!) @@ -48,13 +45,7 @@ public class Treasury extends JavaPlugin { @NotNull private final CurrencyConverter currencyConverter = new CurrencyConverter(); @NotNull public CurrencyConverter getCurrencyConverter() { return currencyConverter; } - @NotNull public final FileHandler fileHandler = new FileHandler(this); - @NotNull public final DebugHandler debugHandler = new DebugHandler(this); - @NotNull public final CommandHandler commandHandler = new CommandHandler(this); - @NotNull public final UpdateCheckerHandler updateCheckerHandler = new UpdateCheckerHandler(this); - - @NotNull public final YamlConfigFile settingsCfg = new YamlConfigFile(this, new File(getDataFolder(), "settings.yml")); - @NotNull public final YamlConfigFile messagesCfg = new YamlConfigFile(this, new File(getDataFolder(), "messages.yml")); + private BukkitTreasuryPlugin treasuryPlugin; /** * @author lokka30 @@ -66,14 +57,23 @@ public class Treasury extends JavaPlugin { public void onEnable() { final QuickTimer startupTimer = new QuickTimer(); - fileHandler.loadFiles(); - debugHandler.loadEnabledCategories(); - commandHandler.registerCommands(); + if (!getDataFolder().exists()) { + getDataFolder().mkdirs(); + } + treasuryPlugin = new BukkitTreasuryPlugin(this); + TreasuryPlugin.setInstance(treasuryPlugin); + treasuryPlugin.loadMessages(); + treasuryPlugin.loadSettings(); + TreasuryCommand.register(this); + + if (BukkitVendor.isPaper()) { + PaperEnhancements.enhance(this); + } - updateCheckerHandler.checkForUpdates(); + UpdateChecker.checkForUpdates(); new Metrics(this, 12927); - Utils.logger.info("&fStart-up complete (took &b" + startupTimer.getTimer() + "ms&f)."); + treasuryPlugin.info("&fStart-up complete (took &b" + startupTimer.getTimer() + "ms&f)."); } /** @@ -88,6 +88,6 @@ public void onDisable() { // Add onDisable code here if required. - Utils.logger.info("&fShut-down complete (took &b" + shutdownTimer.getTimer() + "ms&f)."); + treasuryPlugin.info("&fShut-down complete (took &b" + shutdownTimer.getTimer() + "ms&f)."); } } diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/BukkitCommandSource.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/BukkitCommandSource.java new file mode 100644 index 00000000..5843b752 --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/BukkitCommandSource.java @@ -0,0 +1,26 @@ +package me.lokka30.treasury.plugin.bukkit.command; + +import me.lokka30.treasury.plugin.bukkit.BukkitTreasuryPlugin; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.command.CommandSource; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class BukkitCommandSource implements CommandSource { + + private final CommandSender sender; + + public BukkitCommandSource(CommandSender sender) { + this.sender = sender; + } + + @Override + public void sendMessage(@NotNull String message) { + sender.sendMessage(((BukkitTreasuryPlugin) TreasuryPlugin.getInstance()).colorize(message)); + } + + @Override + public boolean hasPermission(@NotNull String node) { + return sender.hasPermission(node); + } +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/CommandSources.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/CommandSources.java new file mode 100644 index 00000000..28f41382 --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/CommandSources.java @@ -0,0 +1,39 @@ +package me.lokka30.treasury.plugin.bukkit.command; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import me.lokka30.treasury.plugin.core.command.CommandSource; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; + +public class CommandSources implements Listener { + + public static final CommandSource CONSOLE = new BukkitCommandSource( + Bukkit.getConsoleSender() + ); + + private Map byUUID = new HashMap<>(); + + public CommandSource obtainSource(CommandSender sender) { + if (sender instanceof ConsoleCommandSender) { + return CONSOLE; + } + Player player = (Player) sender; + if (!byUUID.containsKey(player.getUniqueId())) { + byUUID.put(player.getUniqueId(), new BukkitCommandSource(player)); + } + return byUUID.get(player.getUniqueId()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + byUUID.remove(event.getPlayer().getUniqueId()); + } + +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/TreasuryCommand.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/TreasuryCommand.java new file mode 100644 index 00000000..247758ff --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/command/TreasuryCommand.java @@ -0,0 +1,60 @@ +package me.lokka30.treasury.plugin.bukkit.command; + +import java.util.List; +import me.lokka30.treasury.plugin.bukkit.TreasuryBukkit; +import me.lokka30.treasury.plugin.core.command.TreasuryBaseCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.TabExecutor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class TreasuryCommand implements TabExecutor { + + public static void register(TreasuryBukkit plugin) { + PluginCommand cmd = plugin.getCommand("treasury"); + CommandSources sources = new CommandSources(); + plugin.getServer().getPluginManager().registerEvents(sources, plugin); + TreasuryCommand executor = new TreasuryCommand(sources); + cmd.setExecutor(executor); + cmd.setTabCompleter(executor); + } + + private final TreasuryBaseCommand base; + private final CommandSources sources; + + private TreasuryCommand(CommandSources sources) { + base = new TreasuryBaseCommand(); + this.sources = sources; + } + + @Override + public boolean onCommand( + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String[] args + ) { + base.execute( + sources.obtainSource(sender), + label, + args + ); + return true; + } + + @Override + public @Nullable List onTabComplete( + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String[] args + ) { + return base.complete( + sources.obtainSource(sender), + label, + args + ); + } +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/BukkitVendor.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/BukkitVendor.java new file mode 100644 index 00000000..346d0da5 --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/BukkitVendor.java @@ -0,0 +1,57 @@ +package me.lokka30.treasury.plugin.bukkit.vendor; + +/** + * Represents a handler for determining on what server vendor we're running. This is in order + * to optimise some stuff which can be optimised. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public final class BukkitVendor { + + private static boolean paper = false; + private static boolean ranPaperCheck = false; + private static boolean spigot = false; + private static boolean ranSpigotCheck = false; + + /** + * Returns whether we're running spigot. + * + * @return spigot? + */ + public static boolean isSpigot() { + if (!ranSpigotCheck) { + try { + Class.forName("net.md_5.bungee.api.chat.ChatColor"); + spigot = true; + } catch (ClassNotFoundException e) { + spigot = false; + } + ranSpigotCheck = true; + } + return spigot; + } + + /** + * Returns whether we're running paper. + * + * @return paper? + */ + public static boolean isPaper() { + if (!ranPaperCheck) { + try { + Class.forName("com.destroystokyo.paper.PaperConfig"); + paper = true; + } catch (ClassNotFoundException e) { + paper = false; + } + ranPaperCheck = true; + } + return paper; + } + + private BukkitVendor() { + throw new IllegalArgumentException("Initialization of utility-type class"); + } + +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperAsyncTabEnhancement.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperAsyncTabEnhancement.java new file mode 100644 index 00000000..b8c4cc19 --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperAsyncTabEnhancement.java @@ -0,0 +1,55 @@ +package me.lokka30.treasury.plugin.bukkit.vendor.paper; + +import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.command.TreasuryBaseCommand; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class PaperAsyncTabEnhancement implements Listener { + + @EventHandler + public void onAsyncTab(AsyncTabCompleteEvent event) { + String buffer = event.getBuffer(); + if ((!event.isCommand() && !buffer.startsWith("/")) || buffer.indexOf(' ') == -1) { + return; + } + + String[] parts = buffer.split(" "); + if (!parts[0].equalsIgnoreCase("/treasury") && !parts[0].equalsIgnoreCase("/treasury:treasury")) { + return; + } + if (parts[1] != null) { + String subcommand = parts[1]; + if (subcommand.equalsIgnoreCase("migrate")) { + if (parts.length > 4) { + return; + } + event.setCompletions(getCompletions(parts[parts.length - 1].toLowerCase(Locale.ROOT))); + event.setHandled(true); + return; + } + if (parts.length > 2) { + event.setCompletions(Collections.emptyList()); + } else { + event.setCompletions( + TreasuryBaseCommand.SUBCOMMAND_COMPLETIONS.stream() + .filter(s -> s.startsWith(subcommand.toLowerCase(Locale.ROOT))) + .collect(Collectors.toList()) + ); + } + event.setHandled(true); + } + } + + private List getCompletions(String lastArg) { + return TreasuryPlugin.getInstance().pluginsListRegisteringProvider() + .stream() + .filter(name -> name.toLowerCase(Locale.ROOT).startsWith(lastArg)) + .collect(Collectors.toList()); + } +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperBrigadierEnhancement.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperBrigadierEnhancement.java new file mode 100644 index 00000000..68938d3d --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperBrigadierEnhancement.java @@ -0,0 +1,85 @@ +package me.lokka30.treasury.plugin.bukkit.vendor.paper; + +import com.destroystokyo.paper.brigadier.BukkitBrigadierCommand; +import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; +import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.suggestion.SuggestionProvider; +import com.mojang.brigadier.tree.LiteralCommandNode; +import java.util.Locale; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class PaperBrigadierEnhancement implements Listener { + + @EventHandler + public void onCommandRegister(CommandRegisteredEvent event) { + String label = event.getCommandLabel(); + if (label.equalsIgnoreCase("treasury") || label.equalsIgnoreCase("treasury:treasury")) { + event.setLiteral(buildLiteral(label, event.getBrigadierCommand())); + } + } + + private LiteralCommandNode buildLiteral( + String label, + BukkitBrigadierCommand command + ) { + return LiteralArgumentBuilder.literal(label) + .executes(command) + .then( + LiteralArgumentBuilder.literal("help") + .requires(source -> source.getBukkitSender() + .hasPermission("treasury.command.treasury.help")) + .executes(command) + ) + .then( + LiteralArgumentBuilder.literal("info") + .requires(source -> source.getBukkitSender() + .hasPermission("treasury.command.treasury.info")) + .executes(command) + ) + .then( + LiteralArgumentBuilder.literal("reload") + .requires(source -> source.getBukkitSender() + .hasPermission("treasury.command.treasury.reload")) + .executes(command) + ) + .then( + LiteralArgumentBuilder.literal("migrate") + .requires(source -> source.getBukkitSender() + .hasPermission("treasury.command.treasury.migrate")) + .executes(command) + .then( + RequiredArgumentBuilder.argument("plugin1", StringArgumentType.word()) + .requires(source -> source.getBukkitSender() + .hasPermission("treasury.command.treasury.migrate")) + .suggests(plugins()) + .executes(command) + .then( + RequiredArgumentBuilder.argument("plugin2", StringArgumentType.word()) + .requires(source -> source.getBukkitSender() + .hasPermission("treasury.command.treasury.migrate")) + .suggests(plugins()) + .executes(command) + ) + ) + ).build(); + } + + private SuggestionProvider plugins() { + return (context, builder) -> { + String lastArg = builder.getRemainingLowerCase(); + + for (String pluginRegistering : TreasuryPlugin.getInstance().pluginsListRegisteringProvider()) { + if (pluginRegistering.toLowerCase(Locale.ROOT).startsWith(lastArg)) { + builder.suggest(pluginRegistering); + } + } + + return builder.buildFuture(); + }; + } +} diff --git a/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperEnhancements.java b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperEnhancements.java new file mode 100644 index 00000000..09e7eb2e --- /dev/null +++ b/bukkit/src/main/java/me/lokka30/treasury/plugin/bukkit/vendor/paper/PaperEnhancements.java @@ -0,0 +1,29 @@ +package me.lokka30.treasury.plugin.bukkit.vendor.paper; + +import java.util.Arrays; +import me.lokka30.treasury.plugin.bukkit.TreasuryBukkit; + +public class PaperEnhancements { + + public static void enhance(TreasuryBukkit plugin) { + String pckg = plugin.getServer().getClass().getPackage().getName(); + int[] version = Arrays.stream( + pckg.substring(pckg.lastIndexOf('.') + 1) + .replace("v", "") + .replace("_", ".") + .replace("R", "") + .split("\\.") + ).mapToInt(Integer::parseInt).toArray(); + + if (version[1] >= 15) { + // brigadier enhancement + plugin.getServer().getPluginManager().registerEvents(new PaperBrigadierEnhancement(), plugin); + } else { + // 1.12, 1.13 and 1.14 + if (version[1] >= 12) { + // async completions + plugin.getServer().getPluginManager().registerEvents(new PaperAsyncTabEnhancement(), plugin); + } + } + } +} diff --git a/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml similarity index 96% rename from src/main/resources/plugin.yml rename to bukkit/src/main/resources/plugin.yml index 594b8f53..8d5b6cb1 100644 --- a/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -22,7 +22,7 @@ depend: [] softdepend: [] # General info for the plugin loader -main: 'me.lokka30.treasury.plugin.Treasury' +main: 'me.lokka30.treasury.plugin.bukkit.Treasury' api-version: '1.13' # This is Spigot's API version, NOT Treasury's API version. load: 'STARTUP' loadbefore: [] diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 00000000..4db6e974 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,55 @@ + + + + treasury-parent + me.lokka30 + 1.0.0-SNAPSHOT + + 4.0.0 + + treasury-core + + Treasury-Core + Abstracted implementation of the Treasury Plugin. + + + true + true + + + + + + ivan + https://repo.mrivanplays.com/repository/ivan/ + + + + + + me.lokka30 + treasury-api + ${project.version} + + + com.google.guava + guava + ${guava.version} + provided + + + com.google.code.gson + gson + ${gson.version} + provided + + + com.mrivanplays + annotationconfg-yaml + ${annotationconfig.version} + + + + \ No newline at end of file diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/ProviderEconomy.java b/core/src/main/java/me/lokka30/treasury/plugin/core/ProviderEconomy.java new file mode 100644 index 00000000..2c269551 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/ProviderEconomy.java @@ -0,0 +1,39 @@ +package me.lokka30.treasury.plugin.core; + +import me.lokka30.treasury.api.economy.EconomyProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A class, implemented by Treasury's plugin implementations on different platforms, + * providing an {@link EconomyProvider} and a {@link RegistrarInfo} + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public interface ProviderEconomy { + + /** + * Returns an economy provider + * + * @return provider + */ + @NotNull + EconomyProvider provide(); + + /** + * Returns a registrar info + * + * @return registrar info + */ + @NotNull + RegistrarInfo registrar(); + + /** + * Returns the priority the provider has been registered on + * + * @return priority + */ + @NotNull + String getPriority(); +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/RegistrarInfo.java b/core/src/main/java/me/lokka30/treasury/plugin/core/RegistrarInfo.java new file mode 100644 index 00000000..31394263 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/RegistrarInfo.java @@ -0,0 +1,20 @@ +package me.lokka30.treasury.plugin.core; + +import org.jetbrains.annotations.NotNull; + +/** + * A class, giving information about whom registered an {@link me.lokka30.treasury.api.economy.EconomyProvider} + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public interface RegistrarInfo { + + /** + * Get the name of the registrar + * + * @return name + */ + @NotNull + String getName(); +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/TreasuryPlugin.java b/core/src/main/java/me/lokka30/treasury/plugin/core/TreasuryPlugin.java new file mode 100644 index 00000000..d81e6425 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/TreasuryPlugin.java @@ -0,0 +1,154 @@ +package me.lokka30.treasury.plugin.core; + +import java.util.List; +import java.util.Objects; +import me.lokka30.treasury.api.economy.EconomyProvider; +import me.lokka30.treasury.api.economy.misc.EconomyAPIVersion; +import me.lokka30.treasury.plugin.core.config.ConfigAdapter; +import me.lokka30.treasury.plugin.core.logging.Logger; +import me.lokka30.treasury.plugin.core.schedule.Scheduler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Treasury core implementations must implement this class and set its instance in order for the core + * to function properly. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public abstract class TreasuryPlugin { + + private static TreasuryPlugin instance; + + /** + * Returns the instance set for this class. + * + * @return instance + */ + public static TreasuryPlugin getInstance() { + return instance; + } + + /** + * Sets an instance for this treasury plugin. + * + * @param newInstance the instance set + * @throws IllegalArgumentException if instance is already set + */ + public static void setInstance(@NotNull TreasuryPlugin newInstance) { + Objects.requireNonNull(newInstance, "newInstance"); + if (instance != null) { + throw new IllegalArgumentException("Instance already set"); + } + instance = newInstance; + } + + /** + * Returns the version of the treasury plugin. + * + * @return version + */ + @NotNull + public abstract String getVersion(); + + /** + * Returns the description of the treasury plugin. + * + * @return description + */ + @Nullable + public abstract String getDescription(); + + /** + * Returns the first {@link ProviderEconomy} + * + * @return highest priority provider of economy provider + */ + @Nullable + public ProviderEconomy economyProviderProvider() { + List allProviders = allProviders(); + if (allProviders.isEmpty()) { + return null; + } + return allProviders.get(0); + } + + /** + * Should give all the economy providers registered, ordered by highest priority. + * + * @return ordered providers list + */ + @NotNull + public abstract List allProviders(); + + /** + * Should register the specified {@link EconomyProvider} at the highest priority. + * + * @param newProvider provider to register + */ + public abstract void registerProvider(@NotNull EconomyProvider newProvider); + + /** + * Should re register the specified {@link ProviderEconomy} at the priority defined by the {@code lowPriority} + * param. + * + * @param provider the provider to re register + * @param lowPriority should register on low priority + */ + public abstract void reregisterProvider(@NotNull ProviderEconomy provider, boolean lowPriority); + + /** + * Should unregister the specified {@link EconomyProvider} + * + * @param provider provider to unregister + */ + public abstract void unregisterProvider(@NotNull EconomyProvider provider); + + /** + * Returns the logger wrapper. + * + * @return logger + */ + @NotNull + public abstract Logger logger(); + + /** + * Returns the scheduler wrapper. + * + * @return scheduler + */ + @NotNull + public abstract Scheduler scheduler(); + + /** + * Returns the config adapter. + * + * @return config adapter + */ + @NotNull + public abstract ConfigAdapter configAdapter(); + + /** + * Should reload the plugin + */ + public abstract void reload(); + + /** + * Returns the treasury api version + * + * @return treasury api version + */ + @NotNull + public abstract EconomyAPIVersion getEconomyAPIVersion(); + + /** + * Returns the plugins' names, which are registering an economy provider, + * as a list with {@link String strings}, as this is being used in + * {@link me.lokka30.treasury.plugin.core.command.subcommand.migrate.MigrateSubcommand}. + * + * @return plugins' names + */ + @NotNull + public abstract List pluginsListRegisteringProvider(); +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/CommandSource.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/CommandSource.java new file mode 100644 index 00000000..85c7f9c4 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/CommandSource.java @@ -0,0 +1,61 @@ +package me.lokka30.treasury.plugin.core.command; + +import java.util.List; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.config.messaging.Message; +import org.jetbrains.annotations.NotNull; + +/** + * Represents an executor of a command + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public interface CommandSource { + + /** + * Sends the specified {@link Message} + * + *

Example usage: + *

+     * source.sendMessage(Message.of(MessageKey.MESSAGE_KEY, MessagePlaceholder.placeholder("%something%", foo)));
+     * 
+ * + * @param message the message to send + * @author MrIvanPlays + * @since v1.0.0 + */ + default void sendMessage(@NotNull Message message) { + List toSend = message.handlePlaceholders( + TreasuryPlugin.getInstance().configAdapter().getMessages().getMessage(message.getKey()) + ); + if (toSend.size() == 1) { + sendMessage(toSend.get(0)); + return; + } + for (String msg : toSend) { + sendMessage(msg); + } + } + + /** + * Sends the specified {@link String} {@code message} + * + *

CONTRIBUTOR WARNING: THIS SHOULD ONLY BE USED FOR DEBUGGING AND NOTHING ELSE. + * + * @param message message to send + * @author MrIvanPlays + * @since v1.0.0 + */ + void sendMessage(@NotNull String message); + + /** + * Checks if this source has the specified permission node. + * + * @param node the node you want to check + * @return true if has permission, false otherwise + * @author MrIvanPlays + * @since v1.0.0 + */ + boolean hasPermission(@NotNull String node); +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/Subcommand.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/Subcommand.java new file mode 100644 index 00000000..97f7c5fd --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/Subcommand.java @@ -0,0 +1,35 @@ +package me.lokka30.treasury.plugin.core.command; + +import java.util.Collections; +import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a treasury subcommand. + * + * @author lokka30, MrIvanPlays + * @since v1.0.0 + */ +public interface Subcommand { + + /** + * @param source who ran the command + * @param label subcommand label + * @param args subcommand arguments + * @since v1.0.0 + */ + void execute(@NotNull CommandSource source, @NotNull String label, @NotNull String[] args); + + /** + * @param source who asked for tab completion + * @param label subcommand label + * @param args subcommand args + * @return list of completions, can be null + * @since v1.0.0 + */ + @Nullable + default List complete(@NotNull CommandSource source, @NotNull String label, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/TreasuryBaseCommand.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/TreasuryBaseCommand.java new file mode 100644 index 00000000..e1223f46 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/TreasuryBaseCommand.java @@ -0,0 +1,112 @@ +package me.lokka30.treasury.plugin.core.command; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import me.lokka30.treasury.plugin.core.command.subcommand.HelpSubcommand; +import me.lokka30.treasury.plugin.core.command.subcommand.InfoSubcommand; +import me.lokka30.treasury.plugin.core.command.subcommand.ReloadSubcommand; +import me.lokka30.treasury.plugin.core.command.subcommand.migrate.MigrateSubcommand; +import me.lokka30.treasury.plugin.core.config.messaging.Message; +import me.lokka30.treasury.plugin.core.config.messaging.MessageKey; +import me.lokka30.treasury.plugin.core.config.messaging.MessagePlaceholder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A class, containing the logic of the treasury command. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public final class TreasuryBaseCommand { + + private Map subcommands; + + public TreasuryBaseCommand() { + this.subcommands = new HashMap<>(); + registerSubcommand("help", new HelpSubcommand()); + registerSubcommand("info", new InfoSubcommand()); + registerSubcommand("reload", new ReloadSubcommand()); + registerSubcommand("migrate", new MigrateSubcommand()); + } + + /** + * Registers a new subcommand to handle. + * + * @param name subcommand name + * @param subcommand subcommand + */ + private void registerSubcommand(@NotNull String name, @NotNull Subcommand subcommand) { + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(subcommand, "subcommand"); + if (subcommands.containsKey(name)) { + subcommands.replace(name, subcommand); + } else { + subcommands.put(name, subcommand); + } + } + + /** + * Executes the base /treasury command. + * + * @param sender who ran the command + * @param label command label + * @param args command args + */ + public void execute(@NotNull CommandSource sender, @NotNull String label, @NotNull String[] args) { + if (args.length == 0) { + sender.sendMessage( + Message.of(MessageKey.INVALID_USAGE_UNSPECIFIED, MessagePlaceholder.placeholder("label", label)) + ); + return; + } + Subcommand subcommand = subcommands.get(args[0]); + if (subcommand == null) { + sender.sendMessage(Message.of( + MessageKey.INVALID_USAGE_SPECIFIED, + MessagePlaceholder.placeholder("label", label), + MessagePlaceholder.placeholder("subcommand", args[0])) + ); + return; + } + subcommand.execute( + sender, + label, + args.length == 1 ? new String[0] : Arrays.copyOfRange(args, 1, args.length) + ); + } + + @NotNull + public static final List SUBCOMMAND_COMPLETIONS = Arrays.asList("help", "info", "migrate", "reload"); + + /** + * Runs completions for the base /treasury command. + * + * @param sender who asked for tab completions + * @param label command label + * @param args command arguments + * @return list with completions, can be null + */ + @Nullable + public List complete(@NotNull CommandSource sender, @NotNull String label, @NotNull String[] args) { + if (args.length == 0) { + return Collections.emptyList(); + } else if (args.length == 1) { + return SUBCOMMAND_COMPLETIONS.stream() + .filter(c -> c.startsWith(args[0].toLowerCase(Locale.ROOT))) + .collect(Collectors.toList()); + } else { + Subcommand subcommand = subcommands.get(args[0]); + if (subcommand == null) { + return Collections.emptyList(); + } + return subcommand.complete(sender, label, Arrays.copyOfRange(args, 1, args.length)); + } + } +} diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/HelpSubcommand.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/HelpSubcommand.java similarity index 53% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/HelpSubcommand.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/HelpSubcommand.java index d47146df..897dff2e 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/HelpSubcommand.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/HelpSubcommand.java @@ -10,18 +10,16 @@ * 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 me.lokka30.treasury.plugin.command.treasury.subcommand; - -import me.lokka30.microlib.messaging.MultiMessage; -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.command.Subcommand; -import me.lokka30.treasury.plugin.misc.Utils; -import org.bukkit.command.CommandSender; +package me.lokka30.treasury.plugin.core.command.subcommand; + +import me.lokka30.treasury.plugin.core.command.CommandSource; +import me.lokka30.treasury.plugin.core.command.Subcommand; +import me.lokka30.treasury.plugin.core.config.messaging.Message; +import me.lokka30.treasury.plugin.core.config.messaging.MessageKey; +import me.lokka30.treasury.plugin.core.config.messaging.MessagePlaceholder; +import me.lokka30.treasury.plugin.core.utils.Utils; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -import java.util.Collections; - public class HelpSubcommand implements Subcommand { /* @@ -31,23 +29,19 @@ public class HelpSubcommand implements Subcommand { len: 0 1 */ - @NotNull private final Treasury main; - public HelpSubcommand(@NotNull final Treasury main) { this.main = main; } - @Override - public void run(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { - if(!Utils.checkPermissionForCommand(main, sender, "treasury.command.treasury.help")) return; + public void execute(@NotNull CommandSource sender, @NotNull String label, @NotNull String[] args) { + if (!Utils.checkPermissionForCommand(sender, "treasury.command.treasury.help")) { + return; + } - if(args.length != 1) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.help.invalid-usage"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("label", label, false) - )); + if (args.length != 0) { + sender.sendMessage( + Message.of(MessageKey.HELP_INVALID_USAGE, MessagePlaceholder.placeholder("label", label)) + ); return; } - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.help.available-commands"), Collections.singletonList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true) - )); + sender.sendMessage(Message.of(MessageKey.HELP_AVAILABLE_COMMANDS)); } } diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/InfoSubcommand.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/InfoSubcommand.java new file mode 100644 index 00000000..91a018f8 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/InfoSubcommand.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021-2021 lokka30. + * + * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. + * + * 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 me.lokka30.treasury.plugin.core.command.subcommand; + +import me.lokka30.treasury.api.economy.EconomyProvider; +import me.lokka30.treasury.plugin.core.ProviderEconomy; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.command.CommandSource; +import me.lokka30.treasury.plugin.core.command.Subcommand; +import me.lokka30.treasury.plugin.core.config.messaging.Message; +import me.lokka30.treasury.plugin.core.config.messaging.MessageKey; +import me.lokka30.treasury.plugin.core.config.messaging.MessagePlaceholder; +import me.lokka30.treasury.plugin.core.utils.Utils; +import org.jetbrains.annotations.NotNull; + +import static me.lokka30.treasury.plugin.core.config.messaging.MessagePlaceholder.placeholder; + +public class InfoSubcommand implements Subcommand { + + /* + inf: Prints generic information about the plugin. + cmd: /treasury info + arg: | 0 + len: 0 1 + */ + + @Override + public void execute(@NotNull CommandSource sender, @NotNull String label, @NotNull String[] args) { + if (!Utils.checkPermissionForCommand(sender, "treasury.command.treasury.info")) { + return; + } + + if (args.length != 0) { + sender.sendMessage( + Message.of(MessageKey.INFO_INVALID_USAGE, MessagePlaceholder.placeholder("label", label)) + ); + return; + } + + TreasuryPlugin main = TreasuryPlugin.getInstance(); + + sender.sendMessage(Message.of( + MessageKey.INFO_TREASURY, + placeholder("version", main.getVersion()), + placeholder("description", main.getDescription()), + placeholder("credits", "https://github.com/lokka30/Treasury/wiki/Credits"), + placeholder("latest-api-version", main.getEconomyAPIVersion()), + placeholder("repository", "https://github.com/lokka30/Treasury/")) + ); + + ProviderEconomy providerProvider = main.economyProviderProvider(); + if (providerProvider == null) { + sender.sendMessage(Message.of(MessageKey.INFO_ECONOMY_PROVIDER_UNAVAILABLE)); + } else { + EconomyProvider provider = providerProvider.provide(); + sender.sendMessage(Message.of( + MessageKey.INFO_ECONOMY_PROVIDER_AVAILABLE, + placeholder("name", providerProvider.registrar().getName()), + placeholder("priority", providerProvider.getPriority()), + placeholder("api-version", provider.getSupportedAPIVersion()), + placeholder("supports-bank-accounts", Utils.getYesNoStateMessage(provider.hasBankAccountSupport())), + placeholder("supports-transaction-events", Utils.getYesNoStateMessage(provider.hasTransactionEventSupport())), + placeholder("primary-currency", provider.getPrimaryCurrency().getCurrencyName())) + ); + } + + sender.sendMessage(Message.of(MessageKey.INFO_MISC_INFO)); + } +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/ReloadSubcommand.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/ReloadSubcommand.java new file mode 100644 index 00000000..44dae92c --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/ReloadSubcommand.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-2021 lokka30. + * + * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. + * + * 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 me.lokka30.treasury.plugin.core.command.subcommand; + +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.command.CommandSource; +import me.lokka30.treasury.plugin.core.command.Subcommand; +import me.lokka30.treasury.plugin.core.config.messaging.Message; +import me.lokka30.treasury.plugin.core.config.messaging.MessageKey; +import me.lokka30.treasury.plugin.core.config.messaging.MessagePlaceholder; +import me.lokka30.treasury.plugin.core.utils.QuickTimer; +import me.lokka30.treasury.plugin.core.utils.Utils; +import org.jetbrains.annotations.NotNull; + +public class ReloadSubcommand implements Subcommand { + + /* + inf: View the plugin's available commands. + cmd: /treasury reload + arg: | 0 + len: 0 1 + */ + + @Override + public void execute(@NotNull CommandSource sender, @NotNull String label, @NotNull String[] args) { + if (!Utils.checkPermissionForCommand(sender, "treasury.command.treasury.reload")) { + return; + } + + if (args.length != 0) { + sender.sendMessage( + Message.of(MessageKey.RELOAD_INVALID_USAGE, MessagePlaceholder.placeholder("label", label)) + ); + return; + } + + sender.sendMessage(Message.of(MessageKey.RELOAD_START)); + + final QuickTimer timer = new QuickTimer(); + + TreasuryPlugin.getInstance().reload(); + + sender.sendMessage( + Message.of(MessageKey.RELOAD_COMPLETE, MessagePlaceholder.placeholder("time", timer.getTimer())) + ); + } +} diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/AccountMigrator.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/AccountMigrator.java similarity index 98% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/AccountMigrator.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/AccountMigrator.java index 44c8768d..ac6f2dc9 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/AccountMigrator.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/AccountMigrator.java @@ -1,4 +1,4 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; import me.lokka30.treasury.api.economy.EconomyProvider; import me.lokka30.treasury.api.economy.account.Account; diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/BankAccountMigrator.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/BankAccountMigrator.java similarity index 97% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/BankAccountMigrator.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/BankAccountMigrator.java index e1990cb4..c07e10d6 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/BankAccountMigrator.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/BankAccountMigrator.java @@ -1,4 +1,4 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; import me.lokka30.treasury.api.economy.EconomyProvider; import me.lokka30.treasury.api.economy.account.BankAccount; diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/FailureConsumer.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/FailureConsumer.java similarity index 90% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/FailureConsumer.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/FailureConsumer.java index 8a311bec..f4a00af2 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/FailureConsumer.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/FailureConsumer.java @@ -1,4 +1,4 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; import me.lokka30.treasury.api.economy.response.EconomyException; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrateSubcommand.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrateSubcommand.java similarity index 51% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrateSubcommand.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrateSubcommand.java index f6e95af9..5607f8fe 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrateSubcommand.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrateSubcommand.java @@ -10,35 +10,37 @@ * 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 me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; -import me.lokka30.microlib.messaging.MultiMessage; -import me.lokka30.treasury.api.economy.EconomyProvider; -import me.lokka30.treasury.api.economy.account.Account; -import me.lokka30.treasury.api.economy.currency.Currency; -import me.lokka30.treasury.api.economy.response.EconomyException; -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.command.Subcommand; -import me.lokka30.treasury.plugin.debug.DebugCategory; -import me.lokka30.treasury.plugin.misc.Utils; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.ServicePriority; -import org.bukkit.plugin.ServicesManager; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Phaser; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiConsumer; import java.util.stream.Collectors; +import me.lokka30.treasury.api.economy.EconomyProvider; +import me.lokka30.treasury.api.economy.account.Account; +import me.lokka30.treasury.api.economy.currency.Currency; +import me.lokka30.treasury.api.economy.response.EconomyException; +import me.lokka30.treasury.plugin.core.ProviderEconomy; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.command.CommandSource; +import me.lokka30.treasury.plugin.core.command.Subcommand; +import me.lokka30.treasury.plugin.core.config.messaging.Message; +import me.lokka30.treasury.plugin.core.config.messaging.MessageKey; +import me.lokka30.treasury.plugin.core.debug.DebugCategory; +import me.lokka30.treasury.plugin.core.debug.DebugHandler; +import me.lokka30.treasury.plugin.core.utils.Utils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static me.lokka30.treasury.plugin.core.config.messaging.MessagePlaceholder.placeholder; public class MigrateSubcommand implements Subcommand { @@ -49,96 +51,99 @@ public class MigrateSubcommand implements Subcommand { len: 0 1 2 3 */ - private final @NotNull Treasury main; - public MigrateSubcommand(@NotNull final Treasury main) { this.main = main; } - @Override - public void run(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { - final boolean debugEnabled = main.debugHandler.isCategoryEnabled(DebugCategory.MIGRATE_SUBCOMMAND); - - if(!Utils.checkPermissionForCommand(main, sender, "treasury.command.treasury.migrate")) return; - - if(args.length != 3) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.migrate.invalid-usage"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("label", label, false) - )); + public void execute(@NotNull CommandSource sender, @NotNull String label, @NotNull String[] args) { + final boolean debugEnabled = DebugHandler.isCategoryEnabled(DebugCategory.MIGRATE_SUBCOMMAND); + + if (!Utils.checkPermissionForCommand(sender, "treasury.command.treasury.migrate")) return; + + List serviceProviders = TreasuryPlugin.getInstance().allProviders(); + + if (args.length != 2) { + sender.sendMessage(Message.of( + MessageKey.MIGRATE_INVALID_USAGE, + placeholder("label", label), + placeholder( + "providers", + serviceProviders.isEmpty() + ? "No providers found " + : Utils.formatListMessage( + serviceProviders.stream() + .map(provider -> provider.registrar().getName()) + .collect(Collectors.toList())) + )) + ); return; } - Collection> serviceProviders = main.getServer().getServicesManager().getRegistrations(EconomyProvider.class); - RegisteredServiceProvider from = null; - RegisteredServiceProvider to = null; + ProviderEconomy from = null; + ProviderEconomy to = null; - if(serviceProviders.size() < 2) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.migrate.requires-two-providers"), Collections.singletonList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true) - )); + if (serviceProviders.size() < 2) { + sender.sendMessage(Message.of(MessageKey.MIGRATE_REQUIRES_TWO_PROVIDERS)); return; } - final HashSet serviceProvidersNames = new HashSet<>(); + final Set serviceProvidersNames = new HashSet<>(); - for(RegisteredServiceProvider serviceProvider : serviceProviders) { - serviceProvidersNames.add(serviceProvider.getPlugin().getName()); - if(debugEnabled) { - main.debugHandler.log(DebugCategory.MIGRATE_SUBCOMMAND, "Found service provider: " + serviceProvider.getPlugin().getName()); + for (ProviderEconomy serviceProvider : serviceProviders) { + serviceProvidersNames.add(serviceProvider.registrar().getName()); + if (debugEnabled) { + DebugHandler.log(DebugCategory.MIGRATE_SUBCOMMAND, "Found service provider: " + serviceProvider.registrar().getName()); } } - if(args[1].equalsIgnoreCase(args[2])) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.migrate.providers-match"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("providers", Utils.formatListMessage(main, new ArrayList<>(serviceProvidersNames)), false) - )); + if (args[0].equalsIgnoreCase(args[1])) { + sender.sendMessage(Message.of( + MessageKey.MIGRATE_PROVIDERS_MATCH, + placeholder("providers", Utils.formatListMessage(serviceProvidersNames))) + ); return; } - for(RegisteredServiceProvider serviceProvider : serviceProviders) { - final String serviceProviderPluginName = serviceProvider.getPlugin().getName(); + for (ProviderEconomy serviceProvider : serviceProviders) { + final String serviceProviderPluginName = serviceProvider.registrar().getName(); - if(args[1].equalsIgnoreCase(serviceProviderPluginName)) { + if (args[0].equalsIgnoreCase(serviceProviderPluginName)) { from = serviceProvider; - } else if(args[2].equalsIgnoreCase(serviceProviderPluginName)) { + } else if (args[1].equalsIgnoreCase(serviceProviderPluginName)) { to = serviceProvider; } } - if(from == null) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.migrate.requires-valid-from"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("providers", Utils.formatListMessage(main, new ArrayList<>(serviceProvidersNames)), false) - )); + if (from == null) { + sender.sendMessage(Message.of( + MessageKey.MIGRATE_REQUIRES_VALID_FROM, + placeholder("providers", Utils.formatListMessage(serviceProvidersNames))) + ); return; } - if(to == null) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.migrate.requires-valid-to"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("providers", Utils.formatListMessage(main, new ArrayList<>(serviceProvidersNames)), false) - )); + if (to == null) { + sender.sendMessage(Message.of( + MessageKey.MIGRATE_REQUIRES_VALID_TO, + placeholder("providers", Utils.formatListMessage(serviceProvidersNames))) + ); return; } - if(debugEnabled) { - main.debugHandler.log(DebugCategory.MIGRATE_SUBCOMMAND, "Migrating from '&b" + from.getPlugin().getName() + "&7' to '&b" + to.getPlugin().getName() + "&7'."); + if (debugEnabled) { + DebugHandler.log(DebugCategory.MIGRATE_SUBCOMMAND, "Migrating from '&b" + from.registrar().getName() + "&7' to '&b" + to.registrar().getName() + "&7'."); } - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.migrate.starting-migration"), Collections.singletonList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true) - )); + sender.sendMessage(Message.of(MessageKey.MIGRATE_STARTING_MIGRATION)); // Override economies with dummy economy that doesn't support any operations. - MigrationEconomy dummyEconomy = new MigrationEconomy(main); - main.getServer().getServicesManager().register(EconomyProvider.class, dummyEconomy, main, ServicePriority.Highest); + MigrationEconomy dummyEconomy = new MigrationEconomy(); + TreasuryPlugin.getInstance().registerProvider(dummyEconomy); // Re-register economies to ensure target economy will override migrated economy. - reregister(from, ServicePriority.Low); - reregister(to, ServicePriority.High); + TreasuryPlugin.getInstance().reregisterProvider(from, true); + TreasuryPlugin.getInstance().reregisterProvider(to, false); - MigrationData migration = new MigrationData(main, from.getProvider(), to.getProvider(), debugEnabled); + MigrationData migration = new MigrationData(from, to, debugEnabled); - main.getServer().getScheduler().runTaskAsynchronously(main, () -> { + TreasuryPlugin.getInstance().scheduler().runAsync(() -> { // Block until currencies have been populated. establishCurrencies(migration).arriveAndAwaitAdvance(); @@ -151,12 +156,14 @@ public void run(@NotNull CommandSender sender, @NotNull String label, @NotNull S // Initialize account migration. Phaser playerMigration = migrateAccounts(migration, new PlayerAccountMigrator()); - if (migration.from().hasBankAccountSupport()) { - if (migration.to().hasBankAccountSupport()) { + EconomyProvider fromProvider = migration.from().provide(); + EconomyProvider toProvider = migration.to().provide(); + if (fromProvider.hasBankAccountSupport()) { + if (toProvider.hasBankAccountSupport()) { Phaser bankMigration = migrateAccounts(migration, new BankAccountMigrator()); bankMigration.arriveAndAwaitAdvance(); } else { - migration.debug(() -> "'&b" + migration.to().getProvider().getName() + "&7' does not offer bank support, cannot transfer accounts."); + migration.debug(() -> "'&b" + migration.to().registrar().getName() + "&7' does not offer bank support, cannot transfer accounts."); } } @@ -164,34 +171,37 @@ public void run(@NotNull CommandSender sender, @NotNull String label, @NotNull S playerMigration.arriveAndAwaitAdvance(); // Unregister economy override. - main.getServer().getServicesManager().unregister(dummyEconomy); + TreasuryPlugin.getInstance().unregisterProvider(dummyEconomy); sendMigrationMessage(sender, migration); }); } - private void reregister(RegisteredServiceProvider serviceProvider, ServicePriority priority) { - if (serviceProvider.getPriority() == priority) { - return; + @Override + @Nullable + public List complete(@NotNull CommandSource source, @NotNull String label, @NotNull String[] args) { + if (args.length == 0) { + return Collections.emptyList(); } - - Plugin plugin = serviceProvider.getPlugin(); - ServicesManager servicesManager = plugin.getServer().getServicesManager(); - EconomyProvider provider = serviceProvider.getProvider(); - - servicesManager.unregister(provider); - servicesManager.register(EconomyProvider.class, provider, plugin, priority); + if ((args.length == 1 || args.length == 2) && source.hasPermission("treasury.command.treasury.migrate")) { + String lastArg = args[args.length - 1].toLowerCase(Locale.ROOT); + return TreasuryPlugin.getInstance().pluginsListRegisteringProvider() + .stream() + .filter(name -> name.toLowerCase(Locale.ROOT).startsWith(lastArg)) + .collect(Collectors.toList()); + } + return Collections.emptyList(); } - private void sendMigrationMessage(@NotNull CommandSender sender, @NotNull MigrationData migration) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.migrate.finished-migration"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("time", migration.timer().getTimer() + "", false), - new MultiMessage.Placeholder("player-accounts", migration.playerAccountsProcessed().toString(), false), - new MultiMessage.Placeholder("bank-accounts", migration.bankAccountsProcessed().toString(), false), - new MultiMessage.Placeholder("migrated-currencies", Utils.formatListMessage(main, migration.migratedCurrencies().keySet().stream().map(Currency::getCurrencyName).collect(Collectors.toList())), false), - new MultiMessage.Placeholder("non-migrated-currencies", Utils.formatListMessage(main, migration.nonMigratedCurrencies()), false) - )).send(sender); + private void sendMigrationMessage(@NotNull CommandSource sender, @NotNull MigrationData migration) { + sender.sendMessage(Message.of( + MessageKey.MIGRATE_FINISHED_MIGRATION, + placeholder("time", migration.timer().getTimer()), + placeholder("player-accounts", migration.playerAccountsProcessed().toString()), + placeholder("bank-accounts", migration.bankAccountsProcessed().toString()), + placeholder("migrated-currencies", Utils.formatListMessage(migration.migratedCurrencies().keySet().stream().map(Currency::getCurrencyName).collect(Collectors.toList()))), + placeholder("non-migrated-currencies", Utils.formatListMessage(migration.nonMigratedCurrencies()))) + ); } private Phaser establishCurrencies(@NotNull MigrationData migration) { @@ -200,14 +210,14 @@ private Phaser establishCurrencies(@NotNull MigrationData migration) { // Initialize phaser with a single party: currency mapping completion. Phaser phaser = new Phaser(1); - migration.from().retrieveCurrencyIds(new PhasedFutureSubscriber<>(phaser, fromCurrencyIdsFuture)); + migration.from().provide().retrieveCurrencyIds(new PhasedFutureSubscriber<>(phaser, fromCurrencyIdsFuture)); fromCurrencyIdsFuture.thenAccept(fromCurrencyIds -> { for (UUID fromCurrencyId : fromCurrencyIds) { // Fetch from currency. CompletableFuture fromCurrencyFuture = new CompletableFuture<>(); - migration.from().retrieveCurrency(fromCurrencyId, new PhasedFutureSubscriber<>(phaser, fromCurrencyFuture)); + migration.from().provide().retrieveCurrency(fromCurrencyId, new PhasedFutureSubscriber<>(phaser, fromCurrencyFuture)); fromCurrencyFuture.whenComplete(((currency, throwable) -> { if (throwable != null) { migration.debug(() -> "Unable to locate reported currency with ID '&b" + fromCurrencyId + "&7'."); @@ -218,7 +228,7 @@ private Phaser establishCurrencies(@NotNull MigrationData migration) { // Fetch to currency. CompletableFuture toCurrencyFuture = new CompletableFuture<>(); - migration.to().retrieveCurrency(fromCurrencyId, new PhasedFutureSubscriber<>(phaser, toCurrencyFuture)); + migration.to().provide().retrieveCurrency(fromCurrencyId, new PhasedFutureSubscriber<>(phaser, toCurrencyFuture)); toCurrencyFuture.whenComplete(((toCurrency, throwable) -> { if (toCurrency == null) { // Currency not found. @@ -242,7 +252,7 @@ private Phaser migrateAccounts(@NotNull MigrationData migrat // Initialize phaser with a single party: migration completion. Phaser phaser = new Phaser(1); - migrator.requestAccountIds().accept(migration.from(), new PhasedSubscriber>(phaser) { + migrator.requestAccountIds().accept(migration.from().provide(), new PhasedSubscriber>(phaser) { @Override public void phaseAccept(@NotNull Collection uuids) { for (UUID uuid : uuids) { @@ -276,18 +286,18 @@ private void migrateAccount( }; CompletableFuture fromAccountFuture = new CompletableFuture<>(); - migrator.requestAccount().accept(migration.from(), uuid, new PhasedFutureSubscriber<>(phaser, fromAccountFuture)); + migrator.requestAccount().accept(migration.from().provide(), uuid, new PhasedFutureSubscriber<>(phaser, fromAccountFuture)); fromAccountFuture.whenComplete(failureConsumer); CompletableFuture toAccountFuture = new CompletableFuture<>(); - migrator.checkAccountExistence().accept(migration.to(), uuid, new PhasedSubscriber(phaser) { + migrator.checkAccountExistence().accept(migration.to().provide(), uuid, new PhasedSubscriber(phaser) { @Override public void phaseAccept(@NotNull Boolean hasAccount) { PhasedFutureSubscriber subscription = new PhasedFutureSubscriber<>(phaser, toAccountFuture); if (hasAccount) { - migrator.requestAccount().accept(migration.to(), uuid, subscription); + migrator.requestAccount().accept(migration.to().provide(), uuid, subscription); } else { - migrator.createAccount().accept(migration.to(), uuid, subscription); + migrator.createAccount().accept(migration.to().provide(), uuid, subscription); } } diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrationData.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrationData.java similarity index 71% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrationData.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrationData.java index cfc8cdcd..d7cf8b89 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrationData.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrationData.java @@ -1,10 +1,11 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; -import me.lokka30.microlib.maths.QuickTimer; import me.lokka30.treasury.api.economy.EconomyProvider; import me.lokka30.treasury.api.economy.currency.Currency; -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.debug.DebugCategory; +import me.lokka30.treasury.plugin.core.ProviderEconomy; +import me.lokka30.treasury.plugin.core.debug.DebugCategory; +import me.lokka30.treasury.plugin.core.debug.DebugHandler; +import me.lokka30.treasury.plugin.core.utils.QuickTimer; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -19,9 +20,8 @@ */ class MigrationData { - private final @NotNull Treasury treasury; - private final @NotNull EconomyProvider from; - private final @NotNull EconomyProvider to; + private final @NotNull ProviderEconomy from; + private final @NotNull ProviderEconomy to; private final boolean debugEnabled; private final @NotNull QuickTimer timer = new QuickTimer(); private final @NotNull Map migratedCurrencies = new ConcurrentHashMap<>(); @@ -30,11 +30,9 @@ class MigrationData { private final @NotNull AtomicInteger bankAccountsProcessed = new AtomicInteger(); MigrationData( - @NotNull Treasury treasury, - @NotNull EconomyProvider from, - @NotNull EconomyProvider to, + @NotNull ProviderEconomy from, + @NotNull ProviderEconomy to, boolean debugEnabled) { - this.treasury = treasury; this.from = from; this.to = to; this.debugEnabled = debugEnabled; @@ -42,15 +40,15 @@ class MigrationData { void debug(Supplier supplier) { if (debugEnabled) { - treasury.debugHandler.log(DebugCategory.MIGRATE_SUBCOMMAND, supplier.get()); + DebugHandler.log(DebugCategory.MIGRATE_SUBCOMMAND, supplier.get()); } } - @NotNull EconomyProvider from() { + @NotNull ProviderEconomy from() { return from; } - @NotNull EconomyProvider to() { + @NotNull ProviderEconomy to() { return to; } diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrationEconomy.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrationEconomy.java similarity index 91% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrationEconomy.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrationEconomy.java index 7593b0e4..0db5b80e 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/MigrationEconomy.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/MigrationEconomy.java @@ -1,4 +1,4 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; import me.lokka30.treasury.api.economy.EconomyProvider; import me.lokka30.treasury.api.economy.account.BankAccount; @@ -8,8 +8,7 @@ import me.lokka30.treasury.api.economy.response.EconomyException; import me.lokka30.treasury.api.economy.response.EconomySubscriber; import me.lokka30.treasury.api.economy.response.FailureReason; -import me.lokka30.treasury.plugin.Treasury; -import org.bukkit.plugin.Plugin; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,12 +23,10 @@ */ class MigrationEconomy implements EconomyProvider { - private final @NotNull Plugin plugin; private final @NotNull Currency currency; private final @NotNull EconomyException migrationException; - MigrationEconomy(@NotNull Plugin plugin) { - this.plugin = plugin; + MigrationEconomy() { this.currency = new Currency() { private final UUID uuid = UUID.randomUUID(); @@ -61,14 +58,9 @@ public double getStartingBalance(@Nullable UUID playerUUID) { this.migrationException = new EconomyException(FailureReason.MIGRATION, "Economy unavailable during migration process."); } - @Override - public @NotNull Plugin getProvider() { - return plugin; - } - @Override public @NotNull EconomyAPIVersion getSupportedAPIVersion() { - return Treasury.ECONOMY_API_VERSION; + return TreasuryPlugin.getInstance().getEconomyAPIVersion(); } @Override diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PhasedFutureSubscriber.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PhasedFutureSubscriber.java similarity index 90% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PhasedFutureSubscriber.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PhasedFutureSubscriber.java index cb00b35c..4cd706ed 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PhasedFutureSubscriber.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PhasedFutureSubscriber.java @@ -1,4 +1,4 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; import me.lokka30.treasury.api.economy.response.EconomyException; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PhasedSubscriber.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PhasedSubscriber.java similarity index 92% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PhasedSubscriber.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PhasedSubscriber.java index 944c8125..5041a8ca 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PhasedSubscriber.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PhasedSubscriber.java @@ -1,4 +1,4 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; import me.lokka30.treasury.api.economy.response.EconomyException; import me.lokka30.treasury.api.economy.response.EconomySubscriber; diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PlayerAccountMigrator.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PlayerAccountMigrator.java similarity index 96% rename from src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PlayerAccountMigrator.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PlayerAccountMigrator.java index e5c2eaee..dc678ed1 100644 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/PlayerAccountMigrator.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/PlayerAccountMigrator.java @@ -1,4 +1,4 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; import me.lokka30.treasury.api.economy.EconomyProvider; import me.lokka30.treasury.api.economy.account.PlayerAccount; diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/TriConsumer.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/TriConsumer.java new file mode 100644 index 00000000..973be740 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/migrate/TriConsumer.java @@ -0,0 +1,7 @@ +package me.lokka30.treasury.plugin.core.command.subcommand.migrate; + +interface TriConsumer { + + void accept(T t, U u, V v); + +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/config/ConfigAdapter.java b/core/src/main/java/me/lokka30/treasury/plugin/core/config/ConfigAdapter.java new file mode 100644 index 00000000..9645a3b1 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/config/ConfigAdapter.java @@ -0,0 +1,28 @@ +package me.lokka30.treasury.plugin.core.config; + +import me.lokka30.treasury.plugin.core.config.messaging.Messages; +import me.lokka30.treasury.plugin.core.config.settings.Settings; +import org.jetbrains.annotations.NotNull; + +/** + * A config adapter, providing {@link Messages} and {@link Settings} + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public interface ConfigAdapter { + + /** + * Returns a {@link Messages} object, which contains all the messages. + * + * @return messages + */ + @NotNull Messages getMessages(); + + /** + * Returns a {@link Settings} object, which contains all the settings. + * + * @return settings + */ + @NotNull Settings getSettings(); +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/Message.java b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/Message.java new file mode 100644 index 00000000..bb5f57e7 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/Message.java @@ -0,0 +1,96 @@ +package me.lokka30.treasury.plugin.core.config.messaging; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a message, holding a {@link MessageKey} and potential {@link MessagePlaceholder placeholders}. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public final class Message { + + @NotNull + public static Message of(@NotNull MessageKey messageKey, @Nullable MessagePlaceholder... placeholders) { + return new Message(messageKey, placeholders); + } + + private final MessageKey key; + private final MessagePlaceholder[] placeholders; + + private Message(@NotNull MessageKey key, @Nullable MessagePlaceholder... placeholders) { + this.key = key; + this.placeholders = placeholders; + } + + @NotNull + public MessageKey getKey() { + return key; + } + + /** + * Replaces the placeholders onto the given message, if any specified. + * + * @param message message + * @return message with replaced placeholders + * @author MrIvanPlays + * @since v1.0.0 + */ + @NotNull + public String handlePlaceholders(@NotNull String message) { + Objects.requireNonNull(message, "message"); + if (placeholders == null) { + return message.replaceAll( + "%prefix%", + TreasuryPlugin.getInstance().configAdapter().getMessages().getSingleMessage(MessageKey.PREFIX) + ); + } + boolean prefixHandled = false; + for (MessagePlaceholder placeholder : placeholders) { + String toReplace = String.valueOf(placeholder.getToReplace()); + if (!toReplace.startsWith("%")) { + toReplace = "%" + toReplace; + } + if (!toReplace.endsWith("%")) { + toReplace = toReplace + "%"; + } + message = message.replaceAll(toReplace, String.valueOf(placeholder.getReplacement())); + if (toReplace.equalsIgnoreCase("%prefix%")) { + prefixHandled = true; + } + } + if (!prefixHandled) { + message = message.replaceAll( + "%prefix%", + TreasuryPlugin.getInstance().configAdapter().getMessages().getSingleMessage(MessageKey.PREFIX) + ); + } + return message; + } + + /** + * Replaces the placeholders onto the given messages, if any specified. + * + * @param message the messages to handle placeholders + * @return messages with replaced placeholders + * @author MrIvanPlays + * @since v1.0.0 + */ + @NotNull + public List handlePlaceholders(@NotNull List message) { + Objects.requireNonNull(message, "message"); + if (message.isEmpty()) { + return message; + } + if (message.size() == 1) { + return Collections.singletonList(handlePlaceholders(message.get(0))); + } + return message.stream().map(this::handlePlaceholders).collect(Collectors.toList()); + } +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/MessageKey.java b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/MessageKey.java new file mode 100644 index 00000000..9371fa43 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/MessageKey.java @@ -0,0 +1,83 @@ +package me.lokka30.treasury.plugin.core.config.messaging; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a key of a message. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public enum MessageKey { + // Common + PREFIX("common.prefix"), + NO_PERMISSION("common.no-permission"), + STATE_YES("common.states.does"), + STATE_NO("common.states.does-not"), + LIST_DELIMITER("common.list-delimiter"), + + // Commands + INVALID_USAGE_UNSPECIFIED("commands.treasury.invalid-usage-unspecified"), + INVALID_USAGE_SPECIFIED("commands.treasury.invalid-usage-specified"), + + // Subcommands + HELP_INVALID_USAGE("commands.treasury.subcommands.help.invalid-usage"), + HELP_AVAILABLE_COMMANDS("commands.treasury.subcommands.help.available-commands"), + INFO_INVALID_USAGE("commands.treasury.subcommands.info.invalid-usage"), + INFO_TREASURY("commands.treasury.subcommands.info.treasury"), + INFO_ECONOMY_PROVIDER_UNAVAILABLE("commands.treasury.subcommands.info.economy-provider-unavailable"), + INFO_ECONOMY_PROVIDER_AVAILABLE("commands.treasury.subcommands.info.economy-provider-available"), + INFO_MISC_INFO("commands.treasury.subcommands.info.misc-info"), + MIGRATE_INVALID_USAGE("commands.treasury.subcommands.migrate.invalid-usage"), + MIGRATE_REQUIRES_TWO_PROVIDERS("commands.treasury.subcommands.migrate.requires-two-providers"), + MIGRATE_PROVIDERS_MATCH("commands.treasury.subcommands.migrate.providers-match"), + MIGRATE_REQUIRES_VALID_FROM("commands.treasury.subcommands.migrate.requires-valid-from"), + MIGRATE_REQUIRES_VALID_TO("commands.treasury.subcommands.migrate.requires-valid-to"), + MIGRATE_STARTING_MIGRATION("commands.treasury.subcommands.migrate.starting-migration"), + MIGRATE_INTERNAL_ERROR("commands.treasury.subcommands.migrate.internal-error"), + MIGRATE_FINISHED_MIGRATION("commands.treasury.subcommands.migrate.finished-migration"), + RELOAD_INVALID_USAGE("commands.treasury.subcommands.reload.invalid-usage"), + RELOAD_START("commands.treasury.subcommands.reload.reload-start"), + RELOAD_COMPLETE("commands.treasury.subcommands.reload.reload-complete"); + + private static Map BY_CONFIG_KEY = new HashMap<>(); + + static { + for (MessageKey key : MessageKey.values()) { + BY_CONFIG_KEY.put(key.asConfigKey(), key); + } + } + + /** + * Returns a message key by the specified config {@code key} + * + * @param key the config key you want a message key for + * @return message key or null + */ + @Nullable + public static MessageKey getByConfigKey(@NotNull String key) { + Objects.requireNonNull(key, "key"); + return BY_CONFIG_KEY.get(key); + } + + private final String configKey; + + MessageKey(@NotNull String configKey) { + this.configKey = Objects.requireNonNull(configKey, "configKey"); + } + + /** + * Returns the config key of this message key. + * + * @return config key + */ + @NotNull + public String asConfigKey() { + return configKey; + } + +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/MessagePlaceholder.java b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/MessagePlaceholder.java new file mode 100644 index 00000000..a0f292bd --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/MessagePlaceholder.java @@ -0,0 +1,41 @@ +package me.lokka30.treasury.plugin.core.config.messaging; + +import java.beans.ConstructorProperties; +import java.util.Objects; +import org.jetbrains.annotations.NotNull; + +/** + * Represents a message placeholder + * + * @since v1.0.0 + */ +public final class MessagePlaceholder { + + /** + * Creates a new {@link MessagePlaceholder} + * + * @param a to replace + * @param b replacement + * @return message placeholder instance + */ + public static MessagePlaceholder placeholder(@NotNull Object a, @NotNull Object b) { + return new MessagePlaceholder(a, b); + } + + private Object a; + private Object b; + + @ConstructorProperties({"a", "b"}) + private MessagePlaceholder(@NotNull Object a, @NotNull Object b) { + this.a = Objects.requireNonNull(a, "null toReplace"); + this.b = Objects.requireNonNull(b, "null replacement"); + } + + public Object getToReplace() { + return a; + } + + public Object getReplacement() { + return b; + } +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/Messages.java b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/Messages.java new file mode 100644 index 00000000..c1b89ebc --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/config/messaging/Messages.java @@ -0,0 +1,396 @@ +package me.lokka30.treasury.plugin.core.config.messaging; + +import com.mrivanplays.annotationconfig.core.annotations.ConfigObject; +import com.mrivanplays.annotationconfig.core.annotations.Ignore; +import com.mrivanplays.annotationconfig.core.annotations.Key; +import com.mrivanplays.annotationconfig.core.annotations.comment.Comment; +import com.mrivanplays.annotationconfig.core.utils.AnnotationUtils; +import com.mrivanplays.annotationconfig.yaml.YamlConfig; +import java.io.File; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import org.jetbrains.annotations.NotNull; + +/** + * All Treasury plugin messages. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +@Comment("## Treasury") +@Comment("Treasury is a modern code library for plugins.") +@Comment("GitHub Repository: ") +@Comment(" ") +@Comment("## About this File") +@Comment("Welcome to the messages.yml file, here you may translate") +@Comment("and customise all of Treasury's messages (except for those") +@Comment("logged to the console). Standard color codes are supported") +@Comment("(e.g &a, &b, &c) and also hex color codes (e.g.") +@Comment("&#FF0000, &#ABCDEF). All messages are configured in terms") +@Comment("of lines, so you can add multiple lines to most messages") +@Comment("if you wish.") +@Comment(" ") +@Comment("## Applying changes") +@Comment("Whenever you have finished making your changes to this") +@Comment("configuration file, please save it, then run") +@Comment("`/treasury reload` if your server is already running.") +@SuppressWarnings({"unused", "FieldMayBeFinal"}) +public class Messages { + + @ConfigObject + private CommonMessages common = new CommonMessages(); + + @Comment("These messages are used across multiple other messages,") + @Comment("so they have been grouped together in the 'common' category.") + public static class CommonMessages { + + @Comment("This text replaces the `%prefix%` placeholder in all applicable messages.") + private String prefix = "&b&lTreasury:&7"; + + @Comment("This message is sent when a user does not have permission to access something within Treasury,") + @Comment("i.e., a command like `/treasury migrate`.") + @Comment(" ") + @Comment("Placeholders: %prefix%, %permission%") + @Key("no-permission") + private List noPermission = Collections.singletonList( + "%prefix% You don't have access to that &8(&7requires permission &b%permission%&8)&7." + ); + + @ConfigObject + private States states = new States(); + + @Comment("These states are used in various messages.") + public static class States { + + private String does = "&aYes"; + + @Key("does-not") + private String doesNot = "&cNo"; + } + + @Comment("The delimiter used in lists of things - this separates each list term.") + @Comment("For example, the non-colored version of a list can look like:") + @Comment("'List item 1&7, &bList item 2&7, &bList item 3'") + @Comment("Notice how the list delimiter is used to separate each term in the list.") + @Key("list-delimiter") + private String listDelimiter = "&7, &b"; + } + + @ConfigObject + private Commands commands = new Commands(); + + @Comment("These messages are sent by running certain commands.") + public static class Commands { + + @ConfigObject + private TreasuryCommand treasury = new TreasuryCommand(); + + @Comment("Messages from `/treasury`") + public static class TreasuryCommand { + + @Comment("Placeholders: %prefix%, %label%") + @Key("invalid-usage-unspecified") + private List invalidUsageUnspecified = Arrays.asList( + "%prefix% Invalid usage - please specify a subcommand.", + "%prefix% For a list of available subcommands, try ''&b/%label% help&7''." + ); + + @Comment("Placeholders: %prefix%, %label%, %subcomand%") + @Key("invalid-usage-specified") + private List invalidUsageSpecified = Arrays.asList( + "%prefix% Invalid subcommand ''&b%subcommand%&7''.", + "%prefix% For a list of available subcommands, try ''&b/%label% help&7''." + ); + + @Comment("Placeholders: %prefix%, %label%") + @Key("subcommands.help.invalid-usage") + private List helpInvalidUsage = Collections.singletonList( + "%prefix% Invalid usage, try ''&b/%label% help&7''." + ); + + @Comment("Placeholders: %prefix%") + @Key("subcommands.help.available-commands") + private List helpAvailableCommands = Arrays.asList( + "%prefix% Available commands:", + " &8&m->&b /treasury help &8- &7view a list of Treasury''s commands.", + " &8&m->&b /treasury info &8- &7view info about Treasury.", + " &8&m->&b /treasury migrate &8- &7migrate from one economy provider to another.", + " &8&m->&b /treasury reload &8- &7re-load all of Treasury''s configuration files.'" + ); + + @Comment("Placeholders: %prefix%, %label%") + @Key("subcommands.info.invalid-usage") + private List infoInvalidUsage = Collections.singletonList( + "%prefix% Invalid usage, try ''&b/%label% info&7''." + ); + + @Comment("Placeholders: %prefix%, %version%, %description%, %credits%,") + @Comment(" %latest-api-version%, %repository%") + @Key("subcommands.info.treasury") + private List infoTreasury = Arrays.asList( + "&f&nAbout Treasury", + "&8 &m->&7 Running &bTreasury v%version%", + "&8 &m->&7 Description: &b%description%", + "&8 &m->&7 Made possible by: &bSee &n%credits%", + "&8 &m->&7 Latest API Version: &b%latest-api-version%", + "&8 &m->&7 Learn more at: &b&n%repository%", + " " + ); + + @Comment("Placeholders: %prefix%") + @Key("subcommands.info.economy-provider-unavailable") + private List infoEconomyProviderUnavailable = Arrays.asList( + "&f&nEconomy Provider", + "&8 &m->&7 You don''t have an Economy Provider installed.'", + " " + ); + + @Comment("Placeholders: %prefix, %name%, %priority%, %api-version%") + @Comment(" %supports-bank-accounts%, %primary-currency%,") + @Comment(" %supports-transaction-events%") + @Key("subcommands.info.economy-provider-available") + private List infoEconomyProviderAvailable = Arrays.asList( + "&f&nEconomy Provider", + "&8 &m->&7 Name: &b%name%", + "&8 &m->&7 Priority: &b%priority%", + "&8 &m->&7 API Version: &b%api-version%", + "&8 &m->&7 Supports bank accounts: &b%supports-bank-accounts%", + "&8 &m->&7 Supports transaction events: &b%supports-transaction-events%", + "&8 &m->&7 Primary currency: &b%primary-currency%", + " " + ); + + @Comment("Placeholders: %prefix%") + @Key("subcommands.info.misc-info") + private List infoMiscInfo = Arrays.asList( + "&f&nMiscellaneous Info:", + "&8 &m->&7 For a list of commands, run ''&b/treasury help&7''." + ); + + @Comment("Placeholders: %prefix%, %label%, %providers%") + @Key("subcommands.migrate.invalid-usage") + private List migrateInvalidUsage = Arrays.asList( + "%prefix% Invalid usage, try ''&b/%label% migrate &7''.", + "%prefix% Valid economy providers: &b%providers%&7." + ); + + @Comment("Placeholders: %prefix%") + @Key("subcommands.migrate.requires-two-providers") + private List migrateRequiresTwoProviders = Collections.singletonList( + "%prefix% You can''t use this subcommand unless you have 2 economy providers set up." + ); + + @Comment("Placeholders: %prefix%, %providers%") + @Key("subcommands.migrate.providers-match") + private List migrateProvidersMatch = Arrays.asList( + "%prefix% You must specify two different economy providers.", + "%prefix% Valid economy providers: &b%providers%&7." + ); + + @Comment("Placeholders: %prefix%, %providers%") + @Key("subcommands.migrate.requires-valid-from") + private List migrateRequiresValidFrom = Arrays.asList( + "%prefix% You must specify a valid economy provider to migrate from.", + "%prefix% Valid economy providers: &b%providers%&7." + ); + + @Comment("Placeholders: %prefix%, %providers%") + @Key("subcommands.migrate.requires-valid-to") + private List migrateRequiresValidTo = Arrays.asList( + "%prefix% You must specify a valid economy provider to migrate to.'", + "%prefix% Valid economy providers: &b%providers%&7." + ); + + @Comment("Placeholders: %prefix%") + @Key("subcommands.migrate.starting-migration") + private List migrateStartingMigration = Arrays.asList( + "%prefix% Starting migration, please wait...", + "%prefix% (This may briefly freeze the server)" + ); + + @Comment("Placeholders: %prefix%") + @Key("subcommands.migrate.internal-error") + private List migrateInternalError = Collections.singletonList( + "%prefix% An internal error occurred whilst attempting to migrate. Please check console for more information." + ); + + @Comment("Placeholders: %prefix%, %time%, %player-accounts%,") + @Comment(" %migrated-currencies%, %non-migrated-currencies%") + @Key("subcommands.migrate.finished-migration") + private List migrateFinishedMigration = Arrays.asList( + "%prefix% Migration complete! Statistics:", + "&8 &m->&7 Took &b%time%ms&7.", + "&8 &m->&7 Processed &b%player-accounts%&7 player accounts.", + "&8 &m->&7 Processed &b%bank-accounts%&7 bank accounts.", + "&8 &m->&7 Migrated currencies: &b%migrated-currencies%&7.", + "&8 &m->&7 Non-migrated currencies: &b%non-migrated-currencies%&7." + ); + + @Comment("Placeholders: %prefix%, %label%") + @Key("subcommands.reload.invalid-usage") + private List reloadInvalidUsage = Collections.singletonList( + "%prefix% Invalid usage, try '&b/%label% reload&7'." + ); + + @Comment("Placeholders: %prefix%") + @Key("subcommands.reload.reload-start") + private List reloadStart = Collections.singletonList( + "%prefix% Reloading Treasury..." + ); + + @Comment("Placeholders: %prefix%, %time%") + @Key("subcommands.reload.reload-complete") + private List reloadComplete = Collections.singletonList( + "%prefix% Reload successful &8(&7took &b%time%ms&8)&7." + ); + + } + } + + // now for accessing them all easily + private static final class MessageHolder { + + private final List message; + + public MessageHolder(@NotNull List message) { + this.message = Objects.requireNonNull(message, "message"); + } + + public MessageHolder(@NotNull String message) { + this.message = Collections.singletonList(Objects.requireNonNull(message, "message")); + } + + @NotNull + public List getMessage() { + return message; + } + } + + public static Messages load(File file) { + Messages messages = new Messages(); + YamlConfig.getConfigResolver().loadOrDump(messages, file); + messages.initMessagesMap(); + return messages; + } + + @Ignore + private Map messagesMap = new HashMap<>(); + + /** + * Returns the messages held by the specified {@link MessageKey} {@code key} + * + * @param key the key you want the messages for + * @return messages of the specified key + */ + @NotNull + public List getMessage(@NotNull MessageKey key) { + Objects.requireNonNull(key, "key"); + if (messagesMap.isEmpty()) { + throw new IllegalArgumentException("initMessagesMap not called!"); + } + return messagesMap.get(key).getMessage(); + } + + /** + * Returns the single message held by the specified {@link MessageKey} {@code key} + * + * @param key the key you want the message of + * @return message of the specified key + */ + @NotNull + public String getSingleMessage(@NotNull MessageKey key) { + Objects.requireNonNull(key, "key"); + if (messagesMap.isEmpty()) { + throw new IllegalArgumentException("initMessagesMap not called!"); + } + return messagesMap.get(key).getMessage().get(0); + } + + /** + * Inits the messages map. The messages map is the easier way of accessing all the messages. + */ + public void initMessagesMap() { + for (Field field : this.getClass().getDeclaredFields()) { + field.setAccessible(true); + if (AnnotationUtils.isIgnored(field)) { + continue; + } + if (AnnotationUtils.isConfigObject(field)) { + try { + Map deep = getDeepMessages(field, null); + for (Map.Entry entry : deep.entrySet()) { + MessageKey key = MessageKey.getByConfigKey(entry.getKey()); + if (key == null) { + TreasuryPlugin.getInstance().logger().error( + "The key '" + entry.getKey() + "' has not been registered " + + "into MessageKey! Tell a developer right now!!!" + ); + continue; + } + messagesMap.put(key, entry.getValue()); + } + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("A field became inaccessible."); + } + continue; + } + String configKey = AnnotationUtils.getKey(field); + MessageKey key = MessageKey.getByConfigKey(configKey); + if (key == null) { + TreasuryPlugin.getInstance().logger().error( + "The key '" + configKey + "' has not been registered " + + "into MessageKey! Tell a developer right now!!!" + ); + continue; + } + messagesMap.put(key, getMessageHolder(field, null)); + } + } + + private Map getDeepMessages(Field field, Object parent) throws IllegalAccessException { + String key = AnnotationUtils.getKey(field); + Object toAccess = field.get(parent == null ? this : parent); + Map map = new HashMap<>(); + for (Field fToAccess : toAccess.getClass().getDeclaredFields()) { + fToAccess.setAccessible(true); + if (AnnotationUtils.isIgnored(fToAccess)) { + continue; + } + if (AnnotationUtils.isConfigObject(fToAccess)) { + Map obj = getDeepMessages(fToAccess, toAccess); + for (Map.Entry entry : obj.entrySet()) { + map.put(key + "." + entry.getKey(), entry.getValue()); + } + continue; + } + map.put(key + "." + AnnotationUtils.getKey(fToAccess), getMessageHolder(fToAccess, toAccess)); + } + return map; + } + + private MessageHolder getMessageHolder(Field field, Object toAccess) { + Object getPass = toAccess == null ? this : toAccess; + MessageHolder holder; + if (String.class.isAssignableFrom(field.getType())) { + try { + holder = new MessageHolder(String.class.cast(field.get(getPass))); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Somehow field became inaccessible ; " + field.getName()); + } + } else { + try { + holder = new MessageHolder((List) field.get(getPass)); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Somehow field became inaccessible ; " + field.getName()); + } + } + return holder; + } + +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/config/settings/DebugCategorySerializer.java b/core/src/main/java/me/lokka30/treasury/plugin/core/config/settings/DebugCategorySerializer.java new file mode 100644 index 00000000..f374993f --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/config/settings/DebugCategorySerializer.java @@ -0,0 +1,52 @@ +package me.lokka30.treasury.plugin.core.config.settings; + +import com.mrivanplays.annotationconfig.core.serialization.DataObject; +import com.mrivanplays.annotationconfig.core.serialization.FieldTypeSerializer; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.debug.DebugCategory; + +/** + * A serializer of debug categories + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public class DebugCategorySerializer implements FieldTypeSerializer> { + + public static final DebugCategorySerializer INSTANCE = new DebugCategorySerializer(); + + private DebugCategorySerializer() {} + + @Override + public List deserialize(DataObject data, Field field) { + List stringList = data.getList(String.class); + List ret = new ArrayList<>(); + for (String val : stringList) { + try { + ret.add(DebugCategory.valueOf(val.toUpperCase(Locale.ROOT))); + } catch (IllegalArgumentException e) { + TreasuryPlugin.getInstance().logger().error( + "Invalid DebugCategory '&b" + val + "&7' specified in &bsettings.yml&7 at location " + + "'&bdebug.enabled-categories.list&7'! Please fix this ASAP." + ); + } + } + return ret; + } + + @Override + public DataObject serialize(List value, Field field) { + List values = new ArrayList<>(); + if (value.isEmpty()) { + return new DataObject(values); + } + for (DebugCategory category : value) { + values.add(category.name().toLowerCase(Locale.ROOT)); + } + return new DataObject(values); + } +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/config/settings/Settings.java b/core/src/main/java/me/lokka30/treasury/plugin/core/config/settings/Settings.java new file mode 100644 index 00000000..1ceac6c0 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/config/settings/Settings.java @@ -0,0 +1,156 @@ +package me.lokka30.treasury.plugin.core.config.settings; + +import com.google.common.reflect.TypeToken; +import com.mrivanplays.annotationconfig.core.annotations.ConfigObject; +import com.mrivanplays.annotationconfig.core.annotations.Ignore; +import com.mrivanplays.annotationconfig.core.annotations.Key; +import com.mrivanplays.annotationconfig.core.annotations.comment.Comment; +import com.mrivanplays.annotationconfig.core.serialization.SerializerRegistry; +import com.mrivanplays.annotationconfig.yaml.YamlConfig; +import java.io.File; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.debug.DebugCategory; +import me.lokka30.treasury.plugin.core.debug.DebugCategoryMode; + +/** + * Represents the settings file of treasury. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +@Comment("## Treasury") +@Comment("Treasury is a modern code library for plugins.") +@Comment("GitHub Repository: ") +@Comment(" ") +@Comment("## About this File") +@Comment("Welcome to the settings.yml file, here you may configure") +@Comment("parts of the plugin. For most servers, this file can be") +@Comment("left alone as it usually contains settings tailored to") +@Comment("more experienced server owners.") +@Comment(" ") +@Comment("## Applying Changes") +@Comment("Whenever you have finished making your changes to this") +@Comment("configuration file, please save it, then run") +@Comment("`/treasury reload` if your server is already running.") +@SuppressWarnings("FieldMayBeFinal") +public class Settings { + + public static Settings load(File file) { + Type debugCategoryList = new TypeToken>() {}.getType(); + if (!SerializerRegistry.INSTANCE.hasSerializer(debugCategoryList)) { + SerializerRegistry.INSTANCE.registerSerializer(debugCategoryList, DebugCategorySerializer.INSTANCE); + } + Settings settings = new Settings(); + YamlConfig.getConfigResolver().loadOrDump(settings, file); + return settings; + } + + @Key("update-checker") + @ConfigObject + private UpdateCheckerSettings updateChecker = new UpdateCheckerSettings(); + + @Comment("## Settings regarding the update checker.") + @Comment("It is recommended you leave this enabled.") + @Comment("The update checker makes a single check to the SpigotMC") + @Comment("website to see if you are running the latest version of") + @Comment("Treasury. It is asynchronous, and only sends a message") + @Comment("if there is a new version available.") + public static class UpdateCheckerSettings { + + @Comment("## Should the update checker be enabled?") + @Comment("This setting allows you to enable/disable the update checker.") + @Comment("Type: Boolean | Default: `true`") + private boolean enabled = true; + + public boolean isEnabled() { + return enabled; + } + } + + @ConfigObject + private DebugSettings debug = new DebugSettings(); + + @Comment("## Settings regarding the debug logger.") + @Comment("The debug logger is a system in Treasury only accessible") + @Comment("to server administrators by default. It is used by Treasury") + @Comment("developers on their test servers to assist in diagnosing any") + @Comment("issues that may be present. It is recommended that all server") + @Comment("owners leave this area alone as it will send a lot of spam to") + @Comment("your console. Developers can configure what categories of debug") + @Comment("logs they want to see to filter out all the messages.") + public static class DebugSettings { + + @ConfigObject + @Key("enabled-categories") + private EnabledCategories enabledCategories = new EnabledCategories(); + + @Comment("## What debug-categories should be sent to the console?") + @Comment("This setting allows you to tune what categories of debug messages") + @Comment("will be sent to the server's console. The list functions as a") + @Comment("blacklist or whitelist, as set by the `mode`.") + public static class EnabledCategories { + + @Comment("## What list mode should the debug logger use?") + @Comment("`WHITELIST` - only the specified categories in the list") + @Comment(" will be enabled.") + @Comment("`BLACKLIST` - only the non-specified categories in the list") + @Comment(" will be enabled.") + @Comment("Type: `String` (DebugCategoryMode constants) | Default: `WHITELIST`") + private DebugCategoryMode mode = DebugCategoryMode.WHITELIST; + + @Comment("## Contents of the debug logger categories list.") + @Comment("Add entries to the whitelist/blacklist here.") + @Comment("Use debug categories from the `DebugCategory` enum, available at GitHub.") + @Comment("Type: `List` (DebugCategory constants) | Default: `[]` (empty)") + private List list = Collections.emptyList(); + + public DebugCategoryMode getMode() { + return mode; + } + + public List getList() { + return list; + } + } + + public EnabledCategories getEnabledCategories() { + return enabledCategories; + } + } + + public boolean checkForUpdates() { + return updateChecker.isEnabled(); + } + + @Ignore + private List enabledCategories; + + public List getDebugCategories() { + if (enabledCategories != null) { + return enabledCategories; + } + enabledCategories = new ArrayList<>(); + List specified = debug.getEnabledCategories().getList(); + DebugCategoryMode mode = debug.getEnabledCategories().getMode(); + switch (mode) { + case WHITELIST: + enabledCategories.addAll(specified); + break; + case BLACKLIST: + enabledCategories.addAll(Arrays.asList(DebugCategory.values())); + break; + default: + TreasuryPlugin.getInstance().logger().error( + "Invalid mode specified in &bsettings.yml&7 at location " + + "'&bdebug.enabled-categories.mode&7'! " + + "You can only use '&bWHITELIST&7' or '&bBLACKLIST&7'. Please fix this ASAP" + ); + } + return enabledCategories; + } +} diff --git a/src/main/java/me/lokka30/treasury/plugin/debug/DebugCategory.java b/core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugCategory.java similarity index 96% rename from src/main/java/me/lokka30/treasury/plugin/debug/DebugCategory.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugCategory.java index 29252713..7d0fed30 100644 --- a/src/main/java/me/lokka30/treasury/plugin/debug/DebugCategory.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugCategory.java @@ -10,19 +10,21 @@ * 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 me.lokka30.treasury.plugin.debug; +package me.lokka30.treasury.plugin.core.debug; /** - * @author lokka30 - * @since v1.0.0 * Contains constants that describe different 'categories' of debug messages * that can be sent to the server's console, when enabled in `settings.yml`. + * + * @author lokka30 + * @since v1.0.0 */ public enum DebugCategory { /** - * @since v1.0.0 * Various information about the process in the Migrate subcommand. + * + * @since v1.0.0 */ MIGRATE_SUBCOMMAND diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugCategoryMode.java b/core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugCategoryMode.java new file mode 100644 index 00000000..d1863915 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugCategoryMode.java @@ -0,0 +1,20 @@ +package me.lokka30.treasury.plugin.core.debug; + +/** + * Represents a mode, which decides how the enabled debug categories are handled. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public enum DebugCategoryMode { + + /** + * Only the specified debug categories are going to be enabled. + */ + WHITELIST, + + /** + * The specified debug categories won't be enabled. + */ + BLACKLIST +} diff --git a/src/main/java/me/lokka30/treasury/plugin/file/FileHandler.java b/core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugHandler.java similarity index 55% rename from src/main/java/me/lokka30/treasury/plugin/file/FileHandler.java rename to core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugHandler.java index b3f8e931..d2ca1ec1 100644 --- a/src/main/java/me/lokka30/treasury/plugin/file/FileHandler.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/debug/DebugHandler.java @@ -10,48 +10,40 @@ * 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 me.lokka30.treasury.plugin.file; +package me.lokka30.treasury.plugin.core.debug; -import me.lokka30.microlib.files.YamlConfigFile; -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.misc.Utils; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; import org.jetbrains.annotations.NotNull; -import java.io.IOException; - -public class FileHandler { - - @NotNull private final Treasury main; - - public FileHandler(@NotNull final Treasury main) { - this.main = main; - } +/** + * Represents a handler for debugging. + * + * @author lokka30, MrIvanPlays + * @since v1.0.0 + */ +public class DebugHandler { /** - * @author lokka30 - * @since v1.0.0 - * (Re)loads all config files. + * Returns whether the specified debug category is enabled. + * + * @param debugCategory the debug category to check if enabled + * @return true if enabled, false otherwise */ - public void loadFiles() { - Utils.logger.info("Loading config files..."); - - loadFile(main.settingsCfg); - loadFile(main.messagesCfg); + public static boolean isCategoryEnabled(@NotNull final DebugCategory debugCategory) { + return TreasuryPlugin.getInstance() + .configAdapter() + .getSettings() + .getDebugCategories() + .contains(debugCategory); } /** - * @author lokka30 - * @since v1.0.0 - * (Re)load a particular config file. - * Notify the user if an IOException occured. - * @param cfg to be loaded + * Appends a prefix to the message you want to debug. + * + * @param debugCategory the debug category you want to log message for + * @param msg the message you want to log */ - public void loadFile(@NotNull final YamlConfigFile cfg) { - try { - Utils.logger.info("Loading file '&b" + cfg.getName() + "&7'..."); - cfg.load(); - } catch(IOException ex) { - Utils.logger.error("Unable to load &b" + cfg.getName() + "&7: " + ex.getMessage()); - } + public static void log(@NotNull final DebugCategory debugCategory, @NotNull final String msg) { + TreasuryPlugin.getInstance().logger().info("&8[&3DEBUG &8| &3" + debugCategory + "&8]: &7" + msg); } } diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/logging/Logger.java b/core/src/main/java/me/lokka30/treasury/plugin/core/logging/Logger.java new file mode 100644 index 00000000..bf57e5b0 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/logging/Logger.java @@ -0,0 +1,39 @@ +package me.lokka30.treasury.plugin.core.logging; + +/** + * Represents a logger interface, which is to be implemented by platforms. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public interface Logger { + + /** + * Logs an informative message. Can use legacy minecraft colors. + * + * @param message the message you want to log. + */ + void info(String message); + + /** + * Logs a warning message. Can use legacy minecraft colors. + * + * @param message the message you want to log. + */ + void warn(String message); + + /** + * Logs an error message. Can use legacy minecraft colors. + * + * @param message the message you want to log. + */ + void error(String message); + + /** + * Logs an error message with a {@link Throwable} appended. Can use legacy minecraft colors. + * + * @param message the message you want to log. + * @param t the exception to append to the message. + */ + void error(String message, Throwable t); +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/schedule/Scheduler.java b/core/src/main/java/me/lokka30/treasury/plugin/core/schedule/Scheduler.java new file mode 100644 index 00000000..8c9f7ec7 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/schedule/Scheduler.java @@ -0,0 +1,24 @@ +package me.lokka30.treasury.plugin.core.schedule; + +/** + * Represents a scheduler wrapper. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public interface Scheduler { + + /** + * Runs the specified task synchronously (on the main thread of the platform implemented) + * + * @param task the task you want to run + */ + void runSync(Runnable task); + + /** + * Runs the specified task asynchronously. + * + * @param task the task you want to run + */ + void runAsync(Runnable task); +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/utils/QuickTimer.java b/core/src/main/java/me/lokka30/treasury/plugin/core/utils/QuickTimer.java new file mode 100644 index 00000000..7142de0e --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/utils/QuickTimer.java @@ -0,0 +1,39 @@ +package me.lokka30.treasury.plugin.core.utils; + +/** + * This is a small class useful for timing simple things such as the time required to start-up a plugin or run a command. + *

+ * Mark the starting point of the timer with `QuickTimer timer = new QuickTimer()`, then get the time (in milliseconds) + * since it started using `QuickTimer#getTimer()`. + * + * @author lokka30 + * @see System#currentTimeMillis() + * @since v1.0.0 + */ +@SuppressWarnings("unused") +public class QuickTimer { + + private long startTime; + + public QuickTimer() { + start(); + } + + public QuickTimer(long startTime) { + this.startTime = startTime; + } + + /** + * Re/start the timer. + */ + public void start() { + startTime = System.currentTimeMillis(); + } + + /** + * @return time (millis) since start time + */ + public long getTimer() { + return System.currentTimeMillis() - startTime; + } +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/utils/UpdateChecker.java b/core/src/main/java/me/lokka30/treasury/plugin/core/utils/UpdateChecker.java new file mode 100644 index 00000000..171d8408 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/utils/UpdateChecker.java @@ -0,0 +1,55 @@ +package me.lokka30.treasury.plugin.core.utils; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; + +// TODO: This requires a Spigot Resource ID which can't be obtained before the resource is released. +/** + * Represents an update checker for spigot. + * + * @author MrIvanPlays + * @since v1.0.0 + */ +public final class UpdateChecker { + + private static final int RESOURCE_ID = 12345; + + private static final String REQUEST_URI = String.format( + "https://api.spigotmc.org/simple/0.2/index.php?action=getResource&id=%s", RESOURCE_ID + ); + + /** + * Runs an update check. + */ + public static void checkForUpdates() { + //noinspection ConstantConditions + if (true) return; + TreasuryPlugin plugin = TreasuryPlugin.getInstance(); + if (!plugin.configAdapter().getSettings().checkForUpdates()) { + return; + } + plugin.scheduler().runAsync(() -> { + try { + URL url = new URL(REQUEST_URI); + try (Reader in = new InputStreamReader(url.openStream())) { + JsonObject object = Utils.GSON.fromJson(in, JsonObject.class); + String latestVersion = object.get("current_version").getAsString(); + if (!plugin.getVersion().equalsIgnoreCase(latestVersion)) { + plugin.logger().warn( + "A new Treasury update is available - '&bv" + + latestVersion + + "&7' - please update as soon as possible." + + " &8(&7You're running '&bv" + plugin.getVersion() + "&7'&8)" + ); + } + } + } catch (IOException e) { + plugin.logger().error("IO whilst trying to request Spigot", e); + } + }); + } +} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/utils/Utils.java b/core/src/main/java/me/lokka30/treasury/plugin/core/utils/Utils.java new file mode 100644 index 00000000..73c91686 --- /dev/null +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/utils/Utils.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021-2021 lokka30. + * + * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. + * + * 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 me.lokka30.treasury.plugin.core.utils; + +import com.google.gson.Gson; +import java.util.Objects; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; +import me.lokka30.treasury.plugin.core.command.CommandSource; +import me.lokka30.treasury.plugin.core.config.messaging.Message; +import me.lokka30.treasury.plugin.core.config.messaging.MessageKey; +import me.lokka30.treasury.plugin.core.config.messaging.MessagePlaceholder; +import me.lokka30.treasury.plugin.core.config.messaging.Messages; +import org.jetbrains.annotations.NotNull; + +public class Utils { + + public static final Gson GSON = new Gson(); + + /** + * Checks if the player has permission for the command. + * If the player does not have permission then a notification + * will be sent to them regarding their lack of permission. + * + * @param source who ran a command and is being checked for the permission. + * @param permission to check. + * @return whether the sender has the specified permission. + * @author lokka30 + * @since v1.0.0 + */ + @SuppressWarnings({"BooleanMethodIsAlwaysInverted"}) + public static boolean checkPermissionForCommand(@NotNull CommandSource source, @NotNull String permission) { + Objects.requireNonNull(source, "source"); + Objects.requireNonNull(permission, "permission"); + if (source.hasPermission(permission)) { + return true; + } else { + source.sendMessage(Message.of( + MessageKey.NO_PERMISSION, + MessagePlaceholder.placeholder("%permission%", permission)) + ); + return false; + } + } + + @NotNull + public static String getYesNoStateMessage(final boolean state) { + Messages messages = TreasuryPlugin.getInstance().configAdapter().getMessages(); + return state + ? messages.getSingleMessage(MessageKey.STATE_YES) + : messages.getSingleMessage(MessageKey.STATE_NO); + } + + @NotNull + public static String formatListMessage(@NotNull final Iterable list) { + Objects.requireNonNull(list, "list"); + final String delimiter = TreasuryPlugin + .getInstance() + .configAdapter() + .getMessages() + .getSingleMessage(MessageKey.LIST_DELIMITER); + + return String.join(delimiter, list); + } + + private Utils() { + throw new IllegalArgumentException("Initialization of utility-type class."); + } + +} diff --git a/pom.xml b/pom.xml index 58204b9f..7d0162d4 100644 --- a/pom.xml +++ b/pom.xml @@ -17,103 +17,169 @@ 4.0.0 me.lokka30 - Treasury - 1.0.0 + treasury-parent + 1.0.0-SNAPSHOT + + api + api-bukkit + core + bukkit + - jar + pom - Treasury - A modern code library for SpigotMC plugins. + Treasury-Parent + A modern code library for different Minecraft platforms. Parent POM + + 2021 + https://github.com/lokka30/Treasury - 1.8 + 1.8 + 1.8 UTF-8 + + + 1.17.1-R0.1-SNAPSHOT + 22.0.0 + 4.13.1 + 2.8.0 + 21.0 + 2.2.1 + 2.1.0-SNAPSHOT + + + MIT License + http://www.opensource.org/licenses/mit-license.php + repo + + + + + scm:git:https://github.com/lokka30/Treasury.git + scm:git:git@github.com:lokka30/Treasury.git + https://github.com/lokka30/Treasury + + - clean package org.apache.maven.plugins - maven-compiler-plugin - 3.7.0 - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.4 + maven-surefire-plugin + 2.19.1 - false - - - org.bstats - me.lokka30.elementaleconomy.bstats - - - me.lokka30.microlib - me.lokka30.elementaleconomy.microlib - - + false + 1 - - - package - - shade - - - + + + org.junit.platform + junit-platform-surefire-provider + 1.1.0 + + + org.junit.jupiter + junit-jupiter-engine + 5.1.0 + + - - - src/main/resources - true - - - - - jitpack.io - https://jitpack.io - - - spigotmc-repo - https://hub.spigotmc.org/nexus/content/groups/public/ - - - CodeMC - https://repo.codemc.org/repository/maven-public - - + + + deployToCodeMC + + + + deployToMrIvanPlays + + + od-releases + https://repo.mrivanplays.com/repository/od-releases/ + + + od-snapshots + https://repo.mrivanplays.com/repository/od-snapshots/ + + + + clean package + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + false + false + + -parameters + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + false + 1 + + + + org.junit.platform + junit-platform-surefire-provider + 1.1.0 + + + org.junit.jupiter + junit-jupiter-engine + 5.1.0 + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + true + false + true + true + true + none + 8 + + + + attach-javadocs + + jar + + + + + + + + - - - org.spigotmc - spigot-api - 1.17.1-R0.1-SNAPSHOT - provided - - - org.bstats - bstats-bukkit - 2.2.1 - compile - - - com.github.lokka30 - MicroLib - 3.1.0 - - - org.jetbrains - annotations - 22.0.0 - - \ No newline at end of file diff --git a/src/main/java/me/lokka30/treasury/plugin/command/CommandHandler.java b/src/main/java/me/lokka30/treasury/plugin/command/CommandHandler.java deleted file mode 100644 index bf93f408..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/command/CommandHandler.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.command; - -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.command.treasury.TreasuryCommand; -import me.lokka30.treasury.plugin.misc.Utils; -import org.bukkit.command.PluginCommand; -import org.bukkit.command.TabExecutor; -import org.jetbrains.annotations.NotNull; - -public class CommandHandler { - - @NotNull private final Treasury main; - - public CommandHandler(@NotNull final Treasury main) { this.main = main; } - - /** - * @author lokka30 - * @since v1.0.0 - * @see CommandHandler#registerCommand(String, TabExecutor) - * Registers all commands from Treasury. - */ - public void registerCommands() { - Utils.logger.info("Registering commands..."); - - registerCommand("treasury", new TreasuryCommand(main)); - } - - /** - * @author lokka30 - * @since v1.0.0 - * Attempts to register the specified command. - * If unsuccessful, console is notified. - * The base command is probably case-sensitive. - * @param baseCommand defined in plugin.yml. - * @param executor handling the execution of the command. - */ - private void registerCommand(@SuppressWarnings("SameParameterValue") @NotNull final String baseCommand, @NotNull final TabExecutor executor) { - assert !baseCommand.isEmpty(); - - final PluginCommand pluginCommand = main.getCommand(baseCommand); - if(pluginCommand == null) { - Utils.logger.error("Unable to register command '&b/" + baseCommand + "&7'. Please notify a Treasury developer."); - } else { - pluginCommand.setExecutor(executor); - Utils.logger.info("Registered command '&b/" + baseCommand + "&7' successfully."); - } - } -} diff --git a/src/main/java/me/lokka30/treasury/plugin/command/Subcommand.java b/src/main/java/me/lokka30/treasury/plugin/command/Subcommand.java deleted file mode 100644 index ecd5fcdb..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/command/Subcommand.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2021-2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.command; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -/** - * @author lokka30 - * @since v1.0.0 - * A subcommand is a class handling the execution of - * a specific part of a command, which in turn makes - * the code cleaner and easier to understand. - * For example, '/example create' and '/example delete' - * can be their own separate subcommands 'create' and - * 'delete', to avoid cluttering the base command's - * executor class. - */ -public interface Subcommand { - - /** - * @author lokka30 - * @since v1.0.0 - * @see org.bukkit.command.TabExecutor - * Run the code executing the subcommand. - * @param sender who ran the subcommand. - * @param label of the base command (alias). - * @param args specified by the sender, INCLUDING the subcommand's argument. - */ - void run(@NotNull final CommandSender sender, @NotNull final String label, @NotNull final String[] args); - - /** - * @author lokka30 - * @since v1.0.0 - * @see Collections#emptyList() - * @see org.bukkit.command.TabExecutor#onTabComplete(CommandSender, Command, String, String[]) - * Get a list of suggestions to return for 1.13+'s tab completion system. - * @param sender who will receive the suggestions. - * @param label of the base command (alias). - * @param args specified by the sender, INCLUDING the subcommand's argument. - * @return a list of compiled suggestions - or, if none, `Collections.emptyList()` is returned. - */ - @SuppressWarnings("unused") - @NotNull - default List getTabSuggestions(@NotNull final CommandSender sender, @NotNull final String label, @NotNull final String[] args) { - return Collections.emptyList(); - } - -} diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/TreasuryCommand.java b/src/main/java/me/lokka30/treasury/plugin/command/treasury/TreasuryCommand.java deleted file mode 100644 index a4b5e7b7..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/TreasuryCommand.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2021-2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.command.treasury; - -import me.lokka30.microlib.messaging.MultiMessage; -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.command.treasury.subcommand.HelpSubcommand; -import me.lokka30.treasury.plugin.command.treasury.subcommand.InfoSubcommand; -import me.lokka30.treasury.plugin.command.treasury.subcommand.migrate.MigrateSubcommand; -import me.lokka30.treasury.plugin.command.treasury.subcommand.ReloadSubcommand; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabExecutor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -public class TreasuryCommand implements TabExecutor { - - @SuppressWarnings({"FieldCanBeLocal", "unused"}) - @NotNull private final Treasury main; - public TreasuryCommand(@NotNull final Treasury main) { - this.main = main; - - this.helpSubcommand = new HelpSubcommand(main); - this.infoSubcommand = new InfoSubcommand(main); - this.migrateSubcommand = new MigrateSubcommand(main); - this.reloadSubcommand = new ReloadSubcommand(main); - } - - @NotNull private final HelpSubcommand helpSubcommand; - @NotNull private final InfoSubcommand infoSubcommand; - @NotNull private final MigrateSubcommand migrateSubcommand; - @NotNull private final ReloadSubcommand reloadSubcommand; - - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) { - if(args.length == 0) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.invalid-usage-unspecified"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("label", label, false) - )); - return true; - } else { - switch(args[0].toUpperCase(Locale.ROOT)) { - case "HELP": - helpSubcommand.run(sender, label, args); - return true; - case "INFO": - infoSubcommand.run(sender, label, args); - return true; - case "MIGRATE": - migrateSubcommand.run(sender, label, args); - return true; - case "RELOAD": - reloadSubcommand.run(sender, label, args); - return true; - default: - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.invalid-usage-specified"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("label", label, false), - new MultiMessage.Placeholder("subcommand", args[0], false) - )); - return true; - } - } - } - - @NotNull private final List subcommands = Arrays.asList("help", "info", "migrate", "reload"); - - @Nullable - @Override - public List onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) { - if(args.length == 0) { - return Collections.emptyList(); - } else if(args.length == 1) { - return subcommands; - } else { - switch(args[0].toUpperCase(Locale.ROOT)) { - case "HELP": - return helpSubcommand.getTabSuggestions(sender, label, args); - case "INFO": - return infoSubcommand.getTabSuggestions(sender, label, args); - case "MIGRATE": - return migrateSubcommand.getTabSuggestions(sender, label, args); - case "RELOAD": - return reloadSubcommand.getTabSuggestions(sender, label, args); - default: - return Collections.emptyList(); - } - } - } -} diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/InfoSubcommand.java b/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/InfoSubcommand.java deleted file mode 100644 index 4bdf88e6..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/InfoSubcommand.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2021-2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.command.treasury.subcommand; - -import me.lokka30.microlib.messaging.MultiMessage; -import me.lokka30.treasury.api.economy.EconomyProvider; -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.command.Subcommand; -import me.lokka30.treasury.plugin.misc.Utils; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collections; - -public class InfoSubcommand implements Subcommand { - - /* - inf: Prints generic information about the plugin. - cmd: /treasury info - arg: | 0 - len: 0 1 - */ - - @NotNull private final Treasury main; - public InfoSubcommand(@NotNull final Treasury main) { this.main = main; } - - @Override - public void run(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { - if(!Utils.checkPermissionForCommand(main, sender, "treasury.command.treasury.info")) return; - - if(args.length != 1) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.info.invalid-usage"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("label", label, false) - )); - return; - } - - final RegisteredServiceProvider registeredServiceProvider = main.getServer().getServicesManager().getRegistration(EconomyProvider.class); - - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.info.treasury"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("version", main.getDescription().getVersion(), false), - new MultiMessage.Placeholder("description", main.getDescription().getDescription(), false), - new MultiMessage.Placeholder("credits", "https://github.com/lokka30/Treasury/wiki/Credits", false), - new MultiMessage.Placeholder("latest-api-version", Treasury.ECONOMY_API_VERSION.getNumber() + "", false), - new MultiMessage.Placeholder("repository", "https://github.com/lokka30/Treasury/", false) - )); - - - - if(registeredServiceProvider == null) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.info.economy-provider-unavailable"), Collections.singletonList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true) - )); - } else { - final EconomyProvider provider = registeredServiceProvider.getProvider(); - - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.info.economy-provider-available"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("name", provider.getProvider().getName(), false), - new MultiMessage.Placeholder("priority", registeredServiceProvider.getPriority().toString(), false), - new MultiMessage.Placeholder("api-version", provider.getSupportedAPIVersion() + "", false), - new MultiMessage.Placeholder("supports-bank-accounts", Utils.getYesNoStateMessage(main, provider.hasBankAccountSupport()), true), - new MultiMessage.Placeholder("supports-transaction-events", Utils.getYesNoStateMessage(main, provider.hasTransactionEventSupport()), true), - new MultiMessage.Placeholder("primary-currency", provider.getPrimaryCurrency().getCurrencyName(), true) - )); - } - - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.info.misc-info"), Collections.singletonList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true) - )); - } -} diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/ReloadSubcommand.java b/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/ReloadSubcommand.java deleted file mode 100644 index e465c6ea..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/ReloadSubcommand.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2021-2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.command.treasury.subcommand; - -import me.lokka30.microlib.maths.QuickTimer; -import me.lokka30.microlib.messaging.MultiMessage; -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.command.Subcommand; -import me.lokka30.treasury.plugin.misc.Utils; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collections; - -public class ReloadSubcommand implements Subcommand { - - /* - inf: View the plugin's available commands. - cmd: /treasury reload - arg: | 0 - len: 0 1 - */ - - @NotNull private final Treasury main; - public ReloadSubcommand(@NotNull final Treasury main) { this.main = main; } - - @Override - public void run(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { - if(!Utils.checkPermissionForCommand(main, sender, "treasury.command.treasury.reload")) return; - - if(args.length != 1) { - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.reload.invalid-usage"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("label", label, false) - )); - return; - } - - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.reload.reload-start"), Collections.singletonList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true) - )); - - final QuickTimer timer = new QuickTimer(); - - main.fileHandler.loadFiles(); - main.debugHandler.loadEnabledCategories(); - - new MultiMessage(main.messagesCfg.getConfig().getStringList("commands.treasury.subcommands.reload.reload-complete"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("time", timer.getTimer() + "", false) - )); - } -} diff --git a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/TriConsumer.java b/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/TriConsumer.java deleted file mode 100644 index 810a63a8..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/command/treasury/subcommand/migrate/TriConsumer.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.lokka30.treasury.plugin.command.treasury.subcommand.migrate; - -interface TriConsumer { - - void accept(T t, U u, V v); - -} diff --git a/src/main/java/me/lokka30/treasury/plugin/debug/DebugHandler.java b/src/main/java/me/lokka30/treasury/plugin/debug/DebugHandler.java deleted file mode 100644 index e49df771..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/debug/DebugHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.debug; - -import me.lokka30.treasury.plugin.Treasury; -import me.lokka30.treasury.plugin.misc.Utils; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Locale; - -public class DebugHandler { - - @NotNull - private final Treasury main; - - public DebugHandler(@NotNull final Treasury main) { this.main = main; } - - @NotNull - private final HashSet enabledCategories = new HashSet<>(); - - public void loadEnabledCategories() { - Utils.logger.info("Loading enabled debug logging categories..."); - - final HashSet listedCategories = new HashSet<>(); - for(String listedCategoryStr : main.settingsCfg.getConfig().getStringList("debug.enabled-categories.list")) { - try { - listedCategories.add(DebugCategory.valueOf(listedCategoryStr)); - } catch(IllegalArgumentException ex) { - Utils.logger.error("Invalid DebugCategory '&b" + listedCategoryStr + "&7' specified in &bsettings.yml&7 at location '&bdebug.enabled-categories.list&7'! Please fix this ASAP."); - } - } - - switch(main.settingsCfg.getConfig().getString("debug.enabled-categories.mode", "NOT_SPECIFIED").toUpperCase(Locale.ROOT)) { - case "WHITELIST": - enabledCategories.addAll(listedCategories); - break; - case "BLACKLIST": - enabledCategories.addAll(Arrays.asList(DebugCategory.values())); - enabledCategories.removeAll(listedCategories); - break; - default: - Utils.logger.error("Invalid mode specified in &bsettings.yml&7 at location '&bdebug.enabled-categories.mode&7'! You can only use '&bWHITELIST&7' or '&bBLACKLIST&7'. Please fix this ASAP."); - break; - } - } - - public boolean isCategoryEnabled(@NotNull final DebugCategory debugCategory) { - return enabledCategories.contains(debugCategory); - } - - public void log(@NotNull final DebugCategory debugCategory, @NotNull final String msg) { - Utils.logger.info("&8[&3DEBUG &8| &3" + debugCategory + "&8]: &7" + msg); - } -} diff --git a/src/main/java/me/lokka30/treasury/plugin/misc/UpdateCheckerHandler.java b/src/main/java/me/lokka30/treasury/plugin/misc/UpdateCheckerHandler.java deleted file mode 100644 index ae1b5081..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/misc/UpdateCheckerHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.misc; - -import me.lokka30.microlib.exceptions.OutdatedServerVersionException; -import me.lokka30.microlib.other.UpdateChecker; -import me.lokka30.treasury.plugin.Treasury; -import org.jetbrains.annotations.NotNull; - -public class UpdateCheckerHandler { - - @NotNull private final Treasury main; - public UpdateCheckerHandler(@NotNull final Treasury main) { - this.main = main; - } - - public void checkForUpdates() { - if(!main.settingsCfg.getConfig().getBoolean("update-checker.enabled", true)) return; - - //TODO This method requires a Spigot Resource ID which can't be obtained before the resource is released. This will be modified later. - //noinspection ConstantConditions - if(true) return; - - final UpdateChecker updateChecker = new UpdateChecker(main, 12345); - - try { - updateChecker.getLatestVersion(latestVersion -> { - if(latestVersion == null) { - Utils.logger.error("Unable to check for updates."); - return; - } - - if(latestVersion.equals(updateChecker.getCurrentVersion())) return; - - Utils.logger.warning("A new Treasury update is available - '&bv" + latestVersion + "&7' - please update as soon as possible." + - " &8(&7You're running '&bv" + updateChecker.getCurrentVersion() + "&7'&8)"); - }); - } catch(OutdatedServerVersionException ex) { - Utils.logger.warning("Treasury's update checker only functions on &b1.11+&7 servers, as older versions lack the code required to run it. " + - "Please disable the update checker in Treasury's &bsettings.yml&7 file."); - } - } -} diff --git a/src/main/java/me/lokka30/treasury/plugin/misc/Utils.java b/src/main/java/me/lokka30/treasury/plugin/misc/Utils.java deleted file mode 100644 index 55b2f282..00000000 --- a/src/main/java/me/lokka30/treasury/plugin/misc/Utils.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2021-2021 lokka30. - * - * This code is part of Treasury, an Economy API for Minecraft servers. Please see for more information on this resource. - * - * 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 me.lokka30.treasury.plugin.misc; - -import me.lokka30.microlib.messaging.MessageUtils; -import me.lokka30.microlib.messaging.MicroLogger; -import me.lokka30.microlib.messaging.MultiMessage; -import me.lokka30.treasury.plugin.Treasury; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; - -public class Utils { - - /** - * This stores Treasury's MicroLogger, facilitating all console logs. - */ - public static final MicroLogger logger = new MicroLogger("&b&lTreasury:&7 "); - - /** - * @author lokka30 - * @since v1.0.0 - * Checks if the player has permission for the command. - * If the player does not have permission then a notification - * will be sent to them regarding their lack of permission. - * @param main a link to the main class to access configuration files. - * @param sender who ran a command and is being checked for the permission. - * @param permission to check. - * @return whether the sender has the specified permission. - */ - @SuppressWarnings({"BooleanMethodIsAlwaysInverted", "unused"}) - public static boolean checkPermissionForCommand(@NotNull final Treasury main, @NotNull final CommandSender sender, @NotNull final String permission) { - if(sender.hasPermission(permission)) { - return true; - } else { - new MultiMessage(main.messagesCfg.getConfig().getStringList("common.no-permission"), Arrays.asList( - new MultiMessage.Placeholder("prefix", main.messagesCfg.getConfig().getString("common.prefix"), true), - new MultiMessage.Placeholder("permission", permission, false) - )); - return false; - } - } - - /** - * @author lokka30 - * @since v1.0.0 - * If the specified amount is less than zero - * then zero is returned. Otherwise, the amount - * is returned. This ensures an amount is at least zero - * since negative values are not allowed in the API. - * @param amount to check for. - * @return the unmodified or modified amount. - */ - public static double ensureAtLeastZero(final double amount) { - return Math.max(amount, 0.0d); - } - - @NotNull - public static String getYesNoStateMessage(@NotNull final Treasury main, final boolean state) { - if(state) { - return main.messagesCfg.getConfig().getString("common.states.yes", "&aYes"); - } else { - return main.messagesCfg.getConfig().getString("common.states.no", "&cNo"); - } - } - - @NotNull - public static String formatListMessage(@NotNull final Treasury main, @NotNull final Iterable list) { - final String delimiter = MessageUtils.colorizeAll(main.messagesCfg.getConfig().getString("common.list-delimiter", "&7, &b")); - - return String.join(delimiter, list); - } - -} diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml deleted file mode 100644 index a94f9a56..00000000 --- a/src/main/resources/messages.yml +++ /dev/null @@ -1,195 +0,0 @@ -### Treasury -# Treasury is a modern code library for SpigotMC plugins. -# GitHub Repository: -# -### About this File -# Welcome to the messages.yml file, here you may translate -# and customise all of Treasury's messages (except for those -# logged to the console). Standard color codes are supported -# (e.g. &a, &b, &c) and also hex color codes (e.g. -# &#FF0000, &#ABCDEF). All messages are configured in terms -# of lines, so you can add multiple lines to most messages -# if you wish. -# -### Applying Changes -# Whenever you have finished making your changes to this -# configuration file, please save it, then run -# `/treasury reload` if your server is already running. - -# These messages are used across multiple other messages, -# so they have been grouped together in the 'common' category. -common: - - # This text replaces the `%prefix%` placeholder in all applicable messages. - prefix: '&b&lTreasury:&7' - - # This message is sent when a user does not have permission to access something within Treasury, - # i.e., a command like `/treasury migrate`. - # - # Placeholders: %prefix%, %permission% - no-permission: - - '%prefix% You don''t have access to that &8(&7requires permission &b%permission%&8)&7.' - - # These states are used in various messages. - states: - yes: '&aYes' - no: '&cNo' - - # The delimiter used in lists of things - this separates each list term. - # For example, the non-colorized version of a list can look like: - # 'List item 1&7, &bList item 2&7, &bList item 3' - # Notice how the list delimiter is used to separate each term in the list. - list-delimiter: '&7, &b' - -# These messages are sent by running certain commands. -commands: - - # Messages from `/treasury` - treasury: - - # Placeholders: %prefix%, %label% - invalid-usage-unspecified: - - '%prefix% Invalid usage - please specify a subcommand.' - - '%prefix% For a list of available subcommands, try ''&b/%label% help&7''.' - - # Placeholders: %prefix%, %label%, %subcommand% - invalid-usage-specified: - - '%prefix% Invalid subcommand ''&b%subcommand%&7''.' - - '%prefix% For a list of available subcommands, try ''&b/%label% help&7''.' - - subcommands: - - help: - - # Placeholders: %prefix%, %label% - invalid-usage: - - '%prefix% Invalid usage, try ''&b/%label% help&7''.' - - # Placeholders: %prefix% - available-commands: - - '%prefix% Available commands:' - - ' &8&m->&b /treasury help &8- &7view a list of Treasury''s commands.' - - ' &8&m->&b /treasury info &8- &7view info about Treasury.' - - ' &8&m->&b /treasury migrate &8- &7migrate from one economy provider to another.' - - ' &8&m->&b /treasury reload &8- &7re-load all of Treasury''s configuration files.' - - info: - - # Placeholders: %prefix%, %label% - invalid-usage: - - '%prefix% Invalid usage, try ''&b/%label% info&7''.' - - # Placeholders: %prefix%, %version%, %description%, %credits%, - # %latest-api-version%, %repository% - treasury: - - '&f&nAbout Treasury' - - '&8 &m->&7 Running &bTreasury v%version%' - - '&8 &m->&7 Description: &b%description%' - - '&8 &m->&7 Made possible by: &bSee &n%credits%' - - '&8 &m->&7 Latest API Version: &b%latest-api-version%' - - '&8 &m->&7 Learn more at: &b&n%repository%' - - ' ' - - # Placeholders: %prefix% - economy-provider-unavailable: - - '&f&nEconomy Provider' - - '&8 &m->&7 You don''t have an Economy Provider installed.' - - ' ' - - # Placeholders: %prefix%, %name%, %priority%, %api-version%, - # %supports-bank-accounts%, %primary-currency%, - # %supports-transaction-events% - economy-provider-available: - - '&f&nEconomy Provider' - - '&8 &m->&7 Name: &b%name%' - - '&8 &m->&7 Priority: &b%priority%' - - '&8 &m->&7 API Version: &b%api-version%' - - '&8 &m->&7 Supports bank accounts: &b%supports-bank-accounts%' - - '&8 &m->&7 Supports transaction events: &b%supports-transaction-events%' - - '&8 &m->&7 Primary currency: &b%primary-currency%' - - ' ' - - # Placeholders: %prefix% - misc-info: - - '&f&nMiscellaneous Info:' - - '&8 &m->&7 For a list of commands, run ''&b/treasury help&7''.' - - migrate: - - # Placeholders: %prefix%, %label%, %providers% - invalid-usage: - - '%prefix% Invalid usage, try ''&b/%label% migrate &7''.' - - '%prefix% Valid economy providers: &b%providers%&7.' - - # Placeholders: %prefix% - requires-two-providers: - - '%prefix% You can''t use this subcommand unless you have 2 economy providers running.' - - # Placeholders: %prefix%, %providers% - providers-match: - - '%prefix% You must specify two different economy providers.' - - '%prefix% Valid economy providers: &b%providers%&7.' - - # Placeholders: %prefix%, %providers% - requires-valid-from: - - '%prefix% You must specify a valid economy provider to migrate from.' - - '%prefix% Valid economy providers: &b%providers%&7.' - - # Placeholders: %prefix%, %providers% - requires-valid-to: - - '%prefix% You must specify a valid economy provider to migrate to.' - - '%prefix% Valid economy providers: &b%providers%&7.' - - # Placeholders: %prefix% - starting-migration: - - '%prefix% Starting migration, please wait...' - - '%prefix% (This may briefly freeze the server)' - - # Placeholders: %prefix% - internal-error: - - '%prefix% An internal error occured whilst attempting to migrate. Please check console for more information.' - - # Placeholders: %prefix%, %time%, %player-accounts%, - # %migrated-currencies%, %non-migrated-currencies% - finished-migration: - - '%prefix% Migration complete! Statistics:' - - '&8 &m->&7 Took &b%time%ms&7.' - - '&8 &m->&7 Processed &b%player-accounts%&7 player accounts.' - - '&8 &m->&7 Processed &b%bank-accounts%&7 bank accounts.' - - '&8 &m->&7 Migrated currencies: &b%migrated-currencies%&7.' - - '&8 &m->&7 Non-migrated currencies: &b%non-migrated-currencies%&7.' - - reload: - - # Placeholders: %prefix%, %label% - invalid-usage: - - '%prefix% Invalid usage, try ''&b/%label% reload&7''.' - - # Placeholders: %prefix% - reload-start: - - '%prefix% Reloading Treasury...' - - # Placeholders: %prefix%, %time% - reload-complete: - - '%prefix% Reload successful &8(&7took &b%time%ms&8)&7.' - -### Settings regarding the messages.yml file specifically. -# DO NOT TOUCH THESE SETTINGS. These settings are analysed by -# Treasury's file system to ensure you have an up-to-date file, -# adjusting any of these values can cause a malfunction. -# As values of these settings will change over time, no Default -# values will be supplied in this file's documentation. -file: - - ### Version of messages.yml. - # DO NOT TOUCH THIS SETTING. - # Type: `Integer` - version: 1 - - ### Version of the plugin that this file was generated with. - # DO NOT TOUCH THIS SETTING. - # It doesn't actually make any difference to modify this, - # but it is useful for Treasury developers to see in case - # there is an issue with your file. - # Type: `String` - generated-with: '${project.version}' \ No newline at end of file diff --git a/src/main/resources/settings.yml b/src/main/resources/settings.yml deleted file mode 100644 index c722d7e5..00000000 --- a/src/main/resources/settings.yml +++ /dev/null @@ -1,79 +0,0 @@ -### Treasury -# Treasury is a modern code library for SpigotMC plugins. -# GitHub Repository: -# -### About this File -# Welcome to the settings.yml file, here you may configure -# parts of the plugin. For most servers, this file can be -# left alone as it usually contains settings tailored to -# more experienced server owners. -# -### Applying Changes -# Whenever you have finished making your changes to this -# configuration file, please save it, then run -# `/treasury reload` if your server is already running. - -### Settings regarding the update checker. -# It is recommended you leave this enabled. -# The update checker makes a single check to the SpigotMC -# website to see if you are running the latest version of -# Treasury. It is asynchronous, and only sends a message -# if there is a new version available. -update-checker: - - ### Should the update checker be enabled? - # This setting allows you to enable/disable the update checker. - # Type: Boolean | Default: `true` - enabled: true - -### Settings regarding the debug logger. -# The debug logger is a system in Treasury only accessible -# to server administrators by default. It is used by Treasury -# developers on their test servers to assist in diagnosing any -# issues that may be present. It is recommended that all server -# owners leave this area alone as it will send a lot of spam to -# your console. Developers can configure what categories of debug -# logs they want to see to filter out all of the other messages. -debug: - - ### What debug-categories should be sent to the console? - # This setting allows you to tune what categories of debug messages - # will be sent to the server's console. The list functions as a - # blacklist or whitelist, as set by the `mode`. - enabled-categories: - - ### What list mode should the debug logger use? - # `WHITELIST` - only the specified categories in the list - # will be enabled. - # `BLACKLIST` - only the non-specified categories in the list - # will be enabled. - # Type: `String` (DebugCategory constants) | Default: `WHITELIST` - mode: 'WHITELIST' - - ### Contents of the debug logger categories list. - # Add entries to the whitelist/blacklist here. - # Use debug categories from the `DebugCategory` enum, available at: - # - # Type: `List` (DebugCategory constants) | Default: `[ ]` (empty) - list: [ ] - -### Settings regarding the settings.yml file specifically. -# DO NOT TOUCH THESE SETTINGS. These settings are analysed by -# Treasury's file system to ensure you have an up-to-date file, -# adjusting any of these values can cause a malfunction. -# As values of these settings will change over time, no Default -# values will be supplied in this file's documentation. -file: - - ### Version of settings.yml. - # DO NOT TOUCH THIS SETTING. - # Type: `Integer` - version: 1 - - ### Version of the plugin that this file was generated with. - # DO NOT TOUCH THIS SETTING. - # It doesn't actually make any difference to modify this, - # but it is useful for Treasury developers to see in case - # there is an issue with your file. - # Type: `String` - generated-with: '${project.version}' \ No newline at end of file