diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eeb29cd..37ad61d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,7 @@ jobs: distribution: 'adopt' - name: Build with Gradle run: | - ./gradlew shadowJar -p bukkittest - ./gradlew shadowJar -p bukkit + ./gradlew shadowJar -p paper ./gradlew shadowJar -p currency-money - uses: actions/upload-artifact@v3 with: diff --git a/.gitignore b/.gitignore index 1285e0e..2698b5a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ ### ForgeGradle ### # Minecraft client/server files run/ +runServer/ ### Intellij ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider diff --git a/README.md b/README.md index 7029583..04969e7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - **Multi-currency** - LightEco supports creating your own currencies and using them in your server - **Local and global currencies** - LightEco offers support for both local and global currencies, enabling you to create server-specific or proxy-wide currencies. - **Storage** - LightEco offers support for multiple storage types. -- **Open-source** - LightEco is open-source, and is available on [GitHub](https://github.com/xHyroM/lightecp) +- **Open-source** - LightEco is open-source, and is available on [GitHub](https://github.com/xHyroM/lighteco) ## Development @@ -23,4 +23,4 @@ Monorepo structure: ## License -LightEco is licensed under the [Apache-2.0 License](./LICENSE). \ No newline at end of file +LightEco is licensed under the [Apache-2.0 License](./LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..885d902 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,36 @@ +# Security Policy + +## Supported Versions + +LightEco is currently in alpha version, which means it's still not done. As such, it may contain bugs or other issues. We are working hard to improve the plugin and fix any problems that are found, but we encourage users to report any issues they encounter to us so that we can address them as quickly as possible. + +| Version | Supported | +| ------- | ------------------ | +| 0.x.x | :white_check_mark: | + +## Reporting a Vulnerability + +If you find a security vulnerability, please report it to us as soon as possible. We take security very seriously and we appreciate your help in keeping our plugin safe. + +**How to report a vulnerability** + +You can report a vulnerability to us by: + +* **Discord:** Contact me on Discord at [`xhyrom`](https://s.xhyrom.dev/discord-user). +* **Email:** Send an email to `github@xhyrom.dev`. + +**What to expect when reporting a vulnerability** + +We will investigate your report as soon as possible. We will typically provide you with an update within 24 hours. + +If the vulnerability is accepted, we will work to fix it as quickly as possible. We will notify you when the fix is released. + +If the vulnerability is declined, we will provide you with a reason for the decision. + +**What to include in your report** + +When reporting a vulnerability, please include the following information: + +* **A detailed description of the vulnerability.** This should include how the vulnerability can be exploited and what impact it could have. +* **Steps to reproduce the vulnerability.** This will help us to quickly investigate the issue. +* **Any additional information that you think may be helpful.** This could include screenshots, code samples, or other relevant data. diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 5c0dfcb..23c986e 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -3,6 +3,12 @@ plugins { } dependencies { + api("net.kyori:adventure-api:4.12.0") { + exclude(module = "adventure-bom") + exclude(module = "checker-qual") + exclude(module = "annotations") + } + compileOnly("org.projectlombok:lombok:1.18.28") annotationProcessor("org.projectlombok:lombok:1.18.28") diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/LightEco.java b/api/src/main/java/dev/xhyrom/lighteco/api/LightEco.java index 451c6e7..8d781d4 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/LightEco.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/LightEco.java @@ -3,10 +3,14 @@ package dev.xhyrom.lighteco.api; import dev.xhyrom.lighteco.api.manager.CommandManager; import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.manager.UserManager; +import dev.xhyrom.lighteco.api.messaging.MessagingService; import dev.xhyrom.lighteco.api.platform.Platform; import dev.xhyrom.lighteco.api.platform.PlayerAdapter; + import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.Optional; + public interface LightEco { /** * Gets the {@link Platform}, which represents the current platform the @@ -37,6 +41,13 @@ public interface LightEco { */ @NonNull CommandManager getCommandManager(); + /** + * Gets the {@link MessagingService}, which manages the messaging. + * + * @return the messaging service + */ + @NonNull Optional getMessagingService(); + /** * Gets the {@link PlayerAdapter} for a player class. * diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/LightEcoProvider.java b/api/src/main/java/dev/xhyrom/lighteco/api/LightEcoProvider.java index b321054..7960d40 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/LightEcoProvider.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/LightEcoProvider.java @@ -1,10 +1,11 @@ package dev.xhyrom.lighteco.api; -import lombok.experimental.UtilityClass; -import org.checkerframework.checker.nullness.qual.NonNull; - import static org.jetbrains.annotations.ApiStatus.Internal; +import lombok.experimental.UtilityClass; + +import org.checkerframework.checker.nullness.qual.NonNull; + @UtilityClass public final class LightEcoProvider { private static LightEco instance; diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/exception/CannotBeGreaterThan.java b/api/src/main/java/dev/xhyrom/lighteco/api/exception/CannotBeGreaterThan.java new file mode 100644 index 0000000..45d6b92 --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/exception/CannotBeGreaterThan.java @@ -0,0 +1,7 @@ +package dev.xhyrom.lighteco.api.exception; + +public class CannotBeGreaterThan extends IllegalArgumentException { + public CannotBeGreaterThan(String message) { + super(message); + } +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/exception/CannotBeNegative.java b/api/src/main/java/dev/xhyrom/lighteco/api/exception/CannotBeNegative.java new file mode 100644 index 0000000..4373dd9 --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/exception/CannotBeNegative.java @@ -0,0 +1,7 @@ +package dev.xhyrom.lighteco.api.exception; + +public class CannotBeNegative extends IllegalArgumentException { + public CannotBeNegative(String message) { + super(message); + } +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/manager/CommandManager.java b/api/src/main/java/dev/xhyrom/lighteco/api/manager/CommandManager.java index 9d7401f..f003212 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/manager/CommandManager.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/manager/CommandManager.java @@ -1,6 +1,7 @@ package dev.xhyrom.lighteco.api.manager; import dev.xhyrom.lighteco.api.model.currency.Currency; + import org.checkerframework.checker.nullness.qual.NonNull; public interface CommandManager { diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/manager/CurrencyManager.java b/api/src/main/java/dev/xhyrom/lighteco/api/manager/CurrencyManager.java index b9113e9..adbf759 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/manager/CurrencyManager.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/manager/CurrencyManager.java @@ -1,6 +1,7 @@ package dev.xhyrom.lighteco.api.manager; import dev.xhyrom.lighteco.api.model.currency.Currency; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/manager/UserManager.java b/api/src/main/java/dev/xhyrom/lighteco/api/manager/UserManager.java index eb02103..c8b6217 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/manager/UserManager.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/manager/UserManager.java @@ -1,6 +1,7 @@ package dev.xhyrom.lighteco.api.manager; import dev.xhyrom.lighteco.api.model.user.User; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -9,6 +10,7 @@ import java.util.concurrent.CompletableFuture; public interface UserManager { @NonNull CompletableFuture loadUser(@NonNull UUID uniqueId); + @NonNull CompletableFuture loadUser(@NonNull UUID uniqueId, String username); @NonNull CompletableFuture saveUser(@NonNull User user); diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/messaging/MessagingService.java b/api/src/main/java/dev/xhyrom/lighteco/api/messaging/MessagingService.java new file mode 100644 index 0000000..72cfdc1 --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/messaging/MessagingService.java @@ -0,0 +1,8 @@ +package dev.xhyrom.lighteco.api.messaging; + +import dev.xhyrom.lighteco.api.model.currency.Currency; +import dev.xhyrom.lighteco.api.model.user.User; + +public interface MessagingService { + void pushUserUpdate(User user, Currency currency); +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/messenger/IncomingMessageConsumer.java b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/IncomingMessageConsumer.java new file mode 100644 index 0000000..4f62243 --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/IncomingMessageConsumer.java @@ -0,0 +1,11 @@ +package dev.xhyrom.lighteco.api.messenger; + +import dev.xhyrom.lighteco.api.messenger.message.Message; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public interface IncomingMessageConsumer { + void consumeIncomingMessage(@NonNull Message message); + + void consumeRawIncomingMessage(@NonNull String message); +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/messenger/Messenger.java b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/Messenger.java new file mode 100644 index 0000000..29f296b --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/Messenger.java @@ -0,0 +1,12 @@ +package dev.xhyrom.lighteco.api.messenger; + +import dev.xhyrom.lighteco.api.messenger.message.OutgoingMessage; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public interface Messenger extends AutoCloseable { + void sendOutgoingMessage(@NonNull OutgoingMessage message, boolean global); + + @Override + default void close() {} +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/messenger/MessengerProvider.java b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/MessengerProvider.java new file mode 100644 index 0000000..86cee89 --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/MessengerProvider.java @@ -0,0 +1,7 @@ +package dev.xhyrom.lighteco.api.messenger; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public interface MessengerProvider { + @NonNull Messenger obtain(@NonNull IncomingMessageConsumer consumer); +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/Message.java b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/Message.java new file mode 100644 index 0000000..a1b9d67 --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/Message.java @@ -0,0 +1,12 @@ +package dev.xhyrom.lighteco.api.messenger.message; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.UUID; + +/** + * Represents a message that can be received by a {@link dev.xhyrom.lighteco.api.messenger.Messenger}. + */ +public interface Message { + @NonNull UUID getId(); +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/OutgoingMessage.java b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/OutgoingMessage.java new file mode 100644 index 0000000..bd7007e --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/OutgoingMessage.java @@ -0,0 +1,15 @@ +package dev.xhyrom.lighteco.api.messenger.message; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Represents a message that can be sent via a {@link dev.xhyrom.lighteco.api.messenger.Messenger}. + */ +public interface OutgoingMessage extends Message { + /** + * Serializes message into a string. + * + * @return serialized message + */ + @NonNull String serialize(); +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/type/UserUpdateMessage.java b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/type/UserUpdateMessage.java new file mode 100644 index 0000000..54a7fc0 --- /dev/null +++ b/api/src/main/java/dev/xhyrom/lighteco/api/messenger/message/type/UserUpdateMessage.java @@ -0,0 +1,24 @@ +package dev.xhyrom.lighteco.api.messenger.message.type; + +import dev.xhyrom.lighteco.api.messenger.message.Message; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; +import java.util.UUID; + +/** + * Represents a message that is sent when a user updates their profile. + */ +public interface UserUpdateMessage extends Message { + /** + * Gets the unique id of the user that updated their profile. + * + * @return the user's unique id + */ + @NonNull UUID getUserUniqueId(); + + @NonNull String getCurrencyIdentifier(); + + @NonNull BigDecimal getNewBalance(); +} diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/model/currency/Currency.java b/api/src/main/java/dev/xhyrom/lighteco/api/model/currency/Currency.java index 8f06741..e6f3ed0 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/model/currency/Currency.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/model/currency/Currency.java @@ -13,6 +13,20 @@ public interface Currency { */ String getIdentifier(); + /** + * Returns the identifier aliases of the currency. + *

+ * Useful if you want multiple commands for the same currency. + * For example, you can have a command `/hyrocoins` but also `/hc`. + *

+ * + * @return the aliases + */ + default String[] getIdentifierAliases() { + return new String[0]; + } + ; + /** * Returns the type of the currency, either {@link Type#LOCAL} or {@link Type#GLOBAL} * @@ -66,7 +80,8 @@ public interface Currency { */ default BigDecimal calculateTax(User user, BigDecimal amount) { return BigDecimal.ZERO; - }; + } + ; /** * Represents the type of currency diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java b/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java index 715dada..3814c59 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java @@ -1,6 +1,9 @@ package dev.xhyrom.lighteco.api.model.user; import dev.xhyrom.lighteco.api.model.currency.Currency; + +import net.kyori.adventure.text.Component; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -49,7 +52,8 @@ public interface User { * @param amount the amount * @throws IllegalArgumentException if the amount is negative */ - void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException; + void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) + throws IllegalArgumentException; /** * Subtract the specified amount from the balance of this user for the specified currency. @@ -58,5 +62,14 @@ public interface User { * @param amount the amount * @throws IllegalArgumentException if the amount is negative */ - void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException; + void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) + throws IllegalArgumentException; + + /** + * Send a message to this user. + * Message will be silently dropped if the user is offline. + * + * @param message the message + */ + void sendMessage(Component message); } diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/platform/Platform.java b/api/src/main/java/dev/xhyrom/lighteco/api/platform/Platform.java index 0ede153..ed89fdf 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/platform/Platform.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/platform/Platform.java @@ -11,7 +11,7 @@ public interface Platform { @NonNull Type getType(); enum Type { - BUKKIT("Bukkit"), + PAPER("Paper"), SPONGE("Sponge"), VELOCITY("Velocity"), BUNGEECORD("BungeeCord"); @@ -27,7 +27,7 @@ public interface Platform { } public boolean isLocal() { - return this == BUKKIT || this == SPONGE; + return this == PAPER || this == SPONGE; } public boolean isProxy() { diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/platform/PlayerAdapter.java b/api/src/main/java/dev/xhyrom/lighteco/api/platform/PlayerAdapter.java index ddd8efc..6f3f8ee 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/platform/PlayerAdapter.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/platform/PlayerAdapter.java @@ -1,6 +1,7 @@ package dev.xhyrom.lighteco.api.platform; import dev.xhyrom.lighteco.api.model.user.User; + import org.checkerframework.checker.nullness.qual.NonNull; import java.util.concurrent.CompletableFuture; diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/storage/StorageProvider.java b/api/src/main/java/dev/xhyrom/lighteco/api/storage/StorageProvider.java index e4c199b..bda6b33 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/storage/StorageProvider.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/storage/StorageProvider.java @@ -2,6 +2,7 @@ package dev.xhyrom.lighteco.api.storage; import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.user.User; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -23,7 +24,10 @@ public interface StorageProvider { void shutdown() throws Exception; default void registerCurrency(@NonNull Currency currency) throws Exception {} + @NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception; + void saveUser(@NonNull User user) throws Exception; + void saveUsers(@NonNull User... users) throws Exception; } diff --git a/build.gradle.kts b/build.gradle.kts index 4335316..5beb692 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,7 @@ import java.io.ByteArrayOutputStream plugins { id("java") id("org.sonarqube") version "4.2.1.3168" + id("com.diffplug.spotless") version "6.25.0" } val majorVersion = 0 @@ -10,12 +11,20 @@ val minorVersion = 1 val patchVersion = determinePatchVersion(project) val commitHash = determineCommitHash(project) +defaultTasks("spotlessApply") + +repositories { + mavenCentral() +} + allprojects { group = "dev.xhyrom" version = "$majorVersion.$minorVersion.$patchVersion" + description = "Incredibly fast, lightweight, and modular plugin that excels across multiple platforms." ext { set("version", "$majorVersion.$minorVersion.$patchVersion+$commitHash") + set("description", description) } } @@ -26,6 +35,19 @@ subprojects { repositories { mavenCentral() maven("https://storehouse.okaeri.eu/repository/maven-public/") + maven("https://libraries.minecraft.net") + } +} + +spotless { + java { + importOrder() + removeUnusedImports() + + palantirJavaFormat().style("AOSP") + formatAnnotations() + + target("api/src/main/java/**", "common/src/main/java/**", "currency-money/src/main/java/**", "paper/src/main/java/**", "sponge-8/src/main/java/**", "test/**/src/main/java/**") } } @@ -54,5 +76,5 @@ fun determineCommitHash(project: Project): String { standardOutput = commitHashInfo } - return commitHashInfo.toString() + return commitHashInfo.toString().strip() } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/lighteco.base-logic.gradle.kts b/buildSrc/src/main/kotlin/lighteco.base-logic.gradle.kts index a799e87..d50789b 100644 --- a/buildSrc/src/main/kotlin/lighteco.base-logic.gradle.kts +++ b/buildSrc/src/main/kotlin/lighteco.base-logic.gradle.kts @@ -4,7 +4,12 @@ plugins { } java { - // toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_17 + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } + withSourcesJar() } @@ -13,6 +18,7 @@ tasks { filesMatching(listOf("plugin.yml")) { expand( "name" to project.name, + "coreName" to "LightEco", "version" to project.version, "description" to project.description, "author" to "xHyroM" @@ -23,4 +29,63 @@ tasks { compileJava { options.encoding = Charsets.UTF_8.name() } +} + +publishing { + // Publishing to repo.jopga.me + publications.create("mavenJava") { + repositories.maven { + url = uri("https://repo.jopga.me/releases") + + credentials(PasswordCredentials::class) + authentication { + create("basic") + } + } + + groupId = rootProject.group as String + artifactId = project.name + version = rootProject.version as String + + pom { + name.set("LightEco") + url.set("https://github.com/xHyroM/lighteco") + description.set(project.description) + organization { + name.set("xHyroM") + url.set("https://xhyrom.dev") + } + developers { + developer { + id.set("xHyroM") + name.set("xHyroM") + email.set("lol@xhyrom.dev") + timezone.set("Europe/Bratislava") + url.set("https://xhyrom.dev") + } + } + scm { + connection.set("scm:git:https://github.com/xHyroM/lighteco.git") + developerConnection.set("scm:git:git@github.com:xHyroM/lighteco.git") + url.set("https://github.com/xHyroM/lighteco") + } + licenses { + license { + name.set("Apache License 2.0") + url.set("https://github.com/xHyroM/lighteco/blob/main/LICENSE") + distribution.set("repo") + } + } + ciManagement { + system.set("GitHub Actions") + url.set("https://github.com/xHyroM/lighteco/actions") + } + } + + artifact(tasks.named("jar")) { + classifier = "" + } + + artifact(tasks.named("sourcesJar")) + } } \ No newline at end of file diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoLoader.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoLoader.java deleted file mode 100644 index da91c69..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoLoader.java +++ /dev/null @@ -1,35 +0,0 @@ -package dev.xhyrom.lighteco.bukkit; - -import dev.jorel.commandapi.CommandAPI; -import dev.jorel.commandapi.CommandAPIBukkitConfig; -import org.bukkit.plugin.java.JavaPlugin; - -// Used inside plugin.yml -@SuppressWarnings("unused") -public class BukkitLightEcoLoader extends JavaPlugin { - private final BukkitLightEcoBootstrap bootstrap; - - public BukkitLightEcoLoader() { - this.bootstrap = new BukkitLightEcoBootstrap(this); - } - - @Override - public void onLoad() { - this.bootstrap.onLoad(); - CommandAPI.onLoad(new CommandAPIBukkitConfig(this) - .verboseOutput(this.bootstrap.getPlugin().getConfig().debug) - ); - } - - @Override - public void onEnable() { - CommandAPI.onEnable(); - this.bootstrap.onEnable(); - } - - @Override - public void onDisable() { - CommandAPI.onDisable(); - this.bootstrap.onDisable(); - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoPlugin.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoPlugin.java deleted file mode 100644 index 63b5ce3..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoPlugin.java +++ /dev/null @@ -1,67 +0,0 @@ -package dev.xhyrom.lighteco.bukkit; - -import dev.xhyrom.lighteco.api.LightEco; -import dev.xhyrom.lighteco.api.manager.ContextManager; -import dev.xhyrom.lighteco.api.platform.Platform; -import dev.xhyrom.lighteco.bukkit.hooks.Hooks; -import dev.xhyrom.lighteco.bukkit.listeners.BukkitConnectionListener; -import dev.xhyrom.lighteco.bukkit.manager.BukkitCommandManager; -import dev.xhyrom.lighteco.bukkit.manager.BukkitContextManager; -import dev.xhyrom.lighteco.common.manager.currency.StandardCurrencyManager; -import dev.xhyrom.lighteco.common.plugin.AbstractLightEcoPlugin; -import dev.xhyrom.lighteco.common.manager.user.StandardUserManager; -import lombok.Getter; -import org.bukkit.entity.Player; -import org.bukkit.plugin.ServicePriority; -import org.checkerframework.checker.nullness.qual.NonNull; - -@Getter -public class BukkitLightEcoPlugin extends AbstractLightEcoPlugin { - private final BukkitLightEcoBootstrap bootstrap; - - @Getter - private StandardUserManager userManager; - @Getter - private StandardCurrencyManager currencyManager; - @Getter - private BukkitCommandManager commandManager; - @Getter - private ContextManager contextManager; - - public BukkitLightEcoPlugin(BukkitLightEcoBootstrap bootstrap) { - this.bootstrap = bootstrap; - } - - @Override - protected void registerListeners() { - this.bootstrap.getLoader().getServer().getPluginManager().registerEvents(new BukkitConnectionListener(this), this.bootstrap.getLoader()); - } - - @Override - public void setupManagers() { - this.userManager = new StandardUserManager(this); - this.currencyManager = new StandardCurrencyManager(this); - this.commandManager = new BukkitCommandManager(this); - this.contextManager = new BukkitContextManager(); - } - - @Override - protected void registerApiOnPlatform(LightEco api) { - this.getBootstrap().getLoader().getServer().getServicesManager().register(LightEco.class, api, this.getBootstrap().getLoader(), ServicePriority.Normal); - } - - @Override - protected void registerPlatformHooks() { - Hooks.register(this); - } - - @Override - protected void removePlatformHooks() { - Hooks.unregister(); - } - - @Override - public Platform.@NonNull Type getPlatformType() { - return Platform.Type.BUKKIT; - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/BalanceCommand.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/BalanceCommand.java deleted file mode 100644 index 3c9e295..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/BalanceCommand.java +++ /dev/null @@ -1,59 +0,0 @@ -package dev.xhyrom.lighteco.bukkit.commands; - -import dev.jorel.commandapi.CommandAPICommand; -import dev.jorel.commandapi.arguments.OfflinePlayerArgument; -import dev.jorel.commandapi.executors.CommandArguments; -import dev.xhyrom.lighteco.bukkit.chat.BukkitCommandSender; -import dev.xhyrom.lighteco.bukkit.manager.BukkitCommandManager; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import lombok.RequiredArgsConstructor; -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; - -@RequiredArgsConstructor -public class BalanceCommand implements Command { - private final BukkitCommandManager manager; - private final String name; - private final Currency currency; - private final String permissionBase; - - @Override - public CommandAPICommand[] multipleBuild() { - return new CommandAPICommand[]{ - new CommandAPICommand(name) - .withPermission(permissionBase + "balance.others") - .withArguments(new OfflinePlayerArgument("target")) - .executes((sender, args) -> { - this.handleBalance(sender, args, currency); - }), - new CommandAPICommand(name) - .withPermission(permissionBase + "balance") - .executesPlayer((sender, args) -> { - this.handleBalance(sender, args, currency); - }) - }; - } - - private void handleBalance(CommandSender originalSender, CommandArguments args, Currency currency) { - BukkitCommandSender sender = new BukkitCommandSender(originalSender, this.manager.audienceFactory); - OfflinePlayer target = (OfflinePlayer) args.get("target"); - - if (target == null) { - this.manager.onBalance(sender, currency); - - return; - } - - this.manager.plugin.getUserManager().loadUser(target.getUniqueId()) - .thenAccept(result -> { - String username = result.getUsername() == null ? - target.getName() != null - ? target.getName() - : args.getRaw("target") - : result.getUsername(); - result.setUsername(username); - - this.manager.onBalance(sender, currency, result); - }); - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/Command.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/Command.java deleted file mode 100644 index 30f56b6..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/Command.java +++ /dev/null @@ -1,13 +0,0 @@ -package dev.xhyrom.lighteco.bukkit.commands; - -import dev.jorel.commandapi.CommandAPICommand; - -public interface Command { - default CommandAPICommand build() { - return null; - } - - default CommandAPICommand[] multipleBuild() { - return new CommandAPICommand[0]; - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/GiveCommand.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/GiveCommand.java deleted file mode 100644 index e138c0d..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/GiveCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -package dev.xhyrom.lighteco.bukkit.commands; - -import dev.jorel.commandapi.CommandAPICommand; -import dev.jorel.commandapi.arguments.DoubleArgument; -import dev.jorel.commandapi.arguments.IntegerArgument; -import dev.jorel.commandapi.arguments.OfflinePlayerArgument; -import dev.jorel.commandapi.executors.CommandArguments; -import dev.xhyrom.lighteco.bukkit.chat.BukkitCommandSender; -import dev.xhyrom.lighteco.bukkit.manager.BukkitCommandManager; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import lombok.RequiredArgsConstructor; -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; - -import java.math.BigDecimal; - -@RequiredArgsConstructor -public class GiveCommand implements Command { - private final BukkitCommandManager manager; - private final Currency currency; - private final String permissionBase; - - @Override - public CommandAPICommand build() { - return new CommandAPICommand("give") - .withPermission(permissionBase + "give") - .withArguments( - new OfflinePlayerArgument("target"), - currency.getProxy().fractionalDigits() > 0 - ? new DoubleArgument("amount", 1) - : new IntegerArgument("amount", 1) - ) - .executes((sender, args) -> { - this.handleGive(sender, args, currency); - }); - } - - - private void handleGive(CommandSender originalSender, CommandArguments args, Currency currency) { - BukkitCommandSender sender = new BukkitCommandSender(originalSender, this.manager.audienceFactory); - OfflinePlayer target = (OfflinePlayer) args.get("target"); - BigDecimal amount = BigDecimal.valueOf(Double.parseDouble(args.getRaw("amount"))); - - if (!this.manager.canUse(sender, currency)) return; - - this.manager.plugin.getUserManager().loadUser(target.getUniqueId()) - .thenAccept(result -> { - String name = target.getName() != null ? target.getName() : args.getRaw("target"); - result.setUsername(name); - - this.manager.onGive(sender, currency, result, amount); - }); - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/PayCommand.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/PayCommand.java deleted file mode 100644 index 4e07a94..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/PayCommand.java +++ /dev/null @@ -1,57 +0,0 @@ -package dev.xhyrom.lighteco.bukkit.commands; - -import dev.jorel.commandapi.CommandAPICommand; -import dev.jorel.commandapi.arguments.DoubleArgument; -import dev.jorel.commandapi.arguments.IntegerArgument; -import dev.jorel.commandapi.arguments.OfflinePlayerArgument; -import dev.jorel.commandapi.executors.CommandArguments; -import dev.xhyrom.lighteco.bukkit.chat.BukkitCommandSender; -import dev.xhyrom.lighteco.bukkit.manager.BukkitCommandManager; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import lombok.RequiredArgsConstructor; -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; - -import java.math.BigDecimal; - -@RequiredArgsConstructor -public class PayCommand implements Command { - private final BukkitCommandManager manager; - private final Currency currency; - private final String permissionBase; - - @Override - public CommandAPICommand build() { - return new CommandAPICommand("pay") - .withPermission(permissionBase + "pay") - .withArguments( - new OfflinePlayerArgument("target"), - currency.getProxy().fractionalDigits() > 0 - ? new DoubleArgument("amount", 1) - : new IntegerArgument("amount", 1) - ) - .executesPlayer((sender, args) -> { - this.handlePay(sender, args, currency); - }); - } - - private void handlePay(CommandSender originalSender, CommandArguments args, Currency currency) { - BukkitCommandSender sender = new BukkitCommandSender(originalSender, this.manager.audienceFactory); - OfflinePlayer target = (OfflinePlayer) args.get("target"); - BigDecimal amount = BigDecimal.valueOf(Double.parseDouble(args.getRaw("amount"))); - - if (!this.manager.canUse(sender, currency)) return; - - this.manager.plugin.getUserManager().loadUser(target.getUniqueId()) - .thenAccept(result -> { - String username = result.getUsername() == null ? - target.getName() != null - ? target.getName() - : args.getRaw("target") - : result.getUsername(); - result.setUsername(username); - - this.manager.onPay(sender, currency, result, amount); - }); - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/SetCommand.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/SetCommand.java deleted file mode 100644 index c45f9ff..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/SetCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -package dev.xhyrom.lighteco.bukkit.commands; - -import dev.jorel.commandapi.CommandAPICommand; -import dev.jorel.commandapi.arguments.DoubleArgument; -import dev.jorel.commandapi.arguments.IntegerArgument; -import dev.jorel.commandapi.arguments.OfflinePlayerArgument; -import dev.jorel.commandapi.executors.CommandArguments; -import dev.xhyrom.lighteco.bukkit.chat.BukkitCommandSender; -import dev.xhyrom.lighteco.bukkit.manager.BukkitCommandManager; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import lombok.RequiredArgsConstructor; -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; - -import java.math.BigDecimal; - -@RequiredArgsConstructor -public class SetCommand implements Command { - private final BukkitCommandManager manager; - private final Currency currency; - private final String permissionBase; - - @Override - public CommandAPICommand build() { - return new CommandAPICommand("set") - .withPermission(permissionBase + "set") - .withArguments( - new OfflinePlayerArgument("target"), - currency.getProxy().fractionalDigits() > 0 - ? new DoubleArgument("amount", 0) - : new IntegerArgument("amount", 0) - ) - .executes((sender, args) -> { - this.handleSet(sender, args, currency); - }); - } - - - private void handleSet(CommandSender originalSender, CommandArguments args, Currency currency) { - BukkitCommandSender sender = new BukkitCommandSender(originalSender, this.manager.audienceFactory); - OfflinePlayer target = (OfflinePlayer) args.get("target"); - BigDecimal amount = BigDecimal.valueOf(Double.parseDouble(args.getRaw("amount"))); - - if (!this.manager.canUse(sender, currency)) return; - - this.manager.plugin.getUserManager().loadUser(target.getUniqueId()) - .thenAccept(result -> { - String name = target.getName() != null ? target.getName() : args.getRaw("target"); - result.setUsername(name); - - this.manager.onSet(sender, currency, result, amount); - }); - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/TakeCommand.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/TakeCommand.java deleted file mode 100644 index 3f25263..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/commands/TakeCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -package dev.xhyrom.lighteco.bukkit.commands; - -import dev.jorel.commandapi.CommandAPICommand; -import dev.jorel.commandapi.arguments.DoubleArgument; -import dev.jorel.commandapi.arguments.IntegerArgument; -import dev.jorel.commandapi.arguments.OfflinePlayerArgument; -import dev.jorel.commandapi.executors.CommandArguments; -import dev.xhyrom.lighteco.bukkit.chat.BukkitCommandSender; -import dev.xhyrom.lighteco.bukkit.manager.BukkitCommandManager; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import lombok.RequiredArgsConstructor; -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; - -import java.math.BigDecimal; - -@RequiredArgsConstructor -public class TakeCommand implements Command { - private final BukkitCommandManager manager; - private final Currency currency; - private final String permissionBase; - - @Override - public CommandAPICommand build() { - return new CommandAPICommand("take") - .withPermission(permissionBase + "take") - .withArguments( - new OfflinePlayerArgument("target"), - currency.getProxy().fractionalDigits() > 0 - ? new DoubleArgument("amount", 1) - : new IntegerArgument("amount", 1) - ) - .executes((sender, args) -> { - this.handleTake(sender, args, currency); - }); - } - - - private void handleTake(CommandSender originalSender, CommandArguments args, Currency currency) { - BukkitCommandSender sender = new BukkitCommandSender(originalSender, this.manager.audienceFactory); - OfflinePlayer target = (OfflinePlayer) args.get("target"); - BigDecimal amount = BigDecimal.valueOf(Double.parseDouble(args.getRaw("amount"))); - - if (!this.manager.canUse(sender, currency)) return; - - this.manager.plugin.getUserManager().loadUser(target.getUniqueId()) - .thenAccept(result -> { - String name = target.getName() != null ? target.getName() : args.getRaw("target"); - result.setUsername(name); - - this.manager.onTake(sender, currency, result, amount); - }); - } -} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitCommandManager.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitCommandManager.java deleted file mode 100644 index 9b78ab5..0000000 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitCommandManager.java +++ /dev/null @@ -1,74 +0,0 @@ -package dev.xhyrom.lighteco.bukkit.manager; - -import dev.jorel.commandapi.CommandAPICommand; -import dev.xhyrom.lighteco.bukkit.commands.*; -import dev.xhyrom.lighteco.common.manager.command.AbstractCommandManager; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; -import org.bukkit.plugin.java.JavaPlugin; -import org.checkerframework.checker.nullness.qual.NonNull; - -public class BukkitCommandManager extends AbstractCommandManager { - public final BukkitAudiences audienceFactory; - - public BukkitCommandManager(LightEcoPlugin plugin) { - super(plugin); - - this.audienceFactory = BukkitAudiences.create((JavaPlugin) this.plugin.getBootstrap().getLoader()); - } - - @Override - public void registerCurrencyCommand(@NonNull Currency currency) { - String permissionBase = "lighteco.currency." + currency.getIdentifier() + ".command."; - - // Balance - for (CommandAPICommand cmd : new BalanceCommand( - this, - currency.getIdentifier(), - currency, - permissionBase - ).multipleBuild()) { - cmd.register(); - } - - CommandAPICommand cmd = new CommandAPICommand(currency.getIdentifier()) - .withSubcommand(new SetCommand(this, currency, permissionBase).build()) - .withSubcommand(new GiveCommand(this, currency, permissionBase).build()) - .withSubcommand(new TakeCommand(this, currency, permissionBase).build()) - .withSubcommands(new BalanceCommand(this, "balance", currency, permissionBase).multipleBuild()); - - if (currency.isPayable()) - cmd = cmd.withSubcommand(new PayCommand(this, currency, permissionBase).build()); - - cmd.register(); - } - - @Override - public void registerCurrencyCommand(@NonNull Currency currency, boolean main) { - if (!main) { - registerCurrencyCommand(currency); - return; - } - - String permissionBase = "lighteco.currency." + currency.getIdentifier() + ".command."; - - // Register main command - registerCurrencyCommand(currency); - - // Expose pay as main command - if (currency.isPayable()) - new PayCommand(this, currency, permissionBase).build().register(); - - // Expose balance as main command - for (CommandAPICommand cmd : new BalanceCommand( - this, - "balance", - currency, - permissionBase - ).multipleBuild()) { - cmd.register(); - } - - } -} diff --git a/bukkittest/.gitignore b/bukkittest/.gitignore deleted file mode 100644 index 72a0aec..0000000 --- a/bukkittest/.gitignore +++ /dev/null @@ -1,44 +0,0 @@ -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ - -### IntelliJ IDEA ### -.idea/modules.xml -.idea/jarRepositories.xml -.idea/compiler.xml -.idea/libraries/ -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### Eclipse ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ - -### Mac OS ### -.DS_Store - -runServer/ \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 91998ab..f01959a 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -4,6 +4,7 @@ plugins { dependencies { api(project(":lighteco-api")) + api("org.checkerframework:checker-qual:3.8.0") api("net.kyori:adventure-api:4.12.0") { exclude(module = "adventure-bom") exclude(module = "checker-qual") @@ -18,11 +19,13 @@ dependencies { implementation("eu.okaeri:okaeri-configs-yaml-snakeyaml:5.0.0-beta.5") implementation("eu.okaeri:okaeri-configs-validator-okaeri:5.0.0-beta.5") + compileOnly("com.mojang:brigadier:1.0.18") + compileOnly("com.zaxxer:HikariCP:5.0.1") + compileOnly("redis.clients:jedis:5.1.0") compileOnly("org.projectlombok:lombok:1.18.28") annotationProcessor("org.projectlombok:lombok:1.18.28") - compileOnly("org.checkerframework:checker-qual:3.8.0") compileOnly("org.jetbrains:annotations:20.1.0") } \ No newline at end of file diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/LightEcoApi.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/LightEcoApi.java index dbf396b..3ffce80 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/LightEcoApi.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/LightEcoApi.java @@ -4,12 +4,16 @@ import dev.xhyrom.lighteco.api.LightEco; import dev.xhyrom.lighteco.api.manager.CommandManager; import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.manager.UserManager; +import dev.xhyrom.lighteco.api.messaging.MessagingService; import dev.xhyrom.lighteco.api.platform.Platform; import dev.xhyrom.lighteco.api.platform.PlayerAdapter; import dev.xhyrom.lighteco.common.api.impl.*; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.Optional; + public class LightEcoApi implements LightEco { private final LightEcoPlugin plugin; @@ -49,12 +53,18 @@ public class LightEcoApi implements LightEco { return this.commandManager; } + @Override + public @NonNull Optional getMessagingService() { + return this.plugin.getMessagingService().map(ApiMessagingService::new); + } + @Override public @NonNull PlayerAdapter getPlayerAdapter(@NonNull Class playerClass) { Class expected = this.plugin.getContextManager().getPlayerClass(); if (!expected.equals(playerClass)) { - throw new IllegalArgumentException("Expected player class " + expected.getName() + ", got " + playerClass.getName()); + throw new IllegalArgumentException("Expected player class " + expected.getName() + + ", got " + playerClass.getName()); } return (PlayerAdapter) this.playerAdapter; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiAbstractManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiAbstractManager.java index 026b2a7..8c9e118 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiAbstractManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiAbstractManager.java @@ -4,10 +4,10 @@ import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; public abstract class ApiAbstractManager { protected final LightEcoPlugin plugin; - protected final H handler; + protected final H handle; - protected ApiAbstractManager(LightEcoPlugin plugin, H handler) { + protected ApiAbstractManager(LightEcoPlugin plugin, H handle) { this.plugin = plugin; - this.handler = handler; + this.handle = handle; } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCommandManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCommandManager.java index 0954065..5b75167 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCommandManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCommandManager.java @@ -3,26 +3,30 @@ package dev.xhyrom.lighteco.common.api.impl; import dev.xhyrom.lighteco.api.manager.CommandManager; import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import org.checkerframework.checker.nullness.qual.NonNull; -public class ApiCommandManager extends ApiAbstractManager implements CommandManager { - public ApiCommandManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.command.CommandManager handler) { - super(plugin, handler); +public class ApiCommandManager + extends ApiAbstractManager + implements CommandManager { + public ApiCommandManager( + LightEcoPlugin plugin, dev.xhyrom.lighteco.common.command.CommandManager handle) { + super(plugin, handle); } @Override public void registerCurrencyCommand(@NonNull Currency currency) { - dev.xhyrom.lighteco.common.model.currency.Currency internal = this.plugin.getCurrencyManager() - .getIfLoaded(currency.getIdentifier()); + dev.xhyrom.lighteco.common.model.currency.Currency internal = + this.plugin.getCurrencyManager().getIfLoaded(currency.getIdentifier()); - this.handler.registerCurrencyCommand(internal); + this.handle.register(internal, false); } @Override public void registerCurrencyCommand(@NonNull Currency currency, boolean main) { - dev.xhyrom.lighteco.common.model.currency.Currency internal = this.plugin.getCurrencyManager() - .getIfLoaded(currency.getIdentifier()); + dev.xhyrom.lighteco.common.model.currency.Currency internal = + this.plugin.getCurrencyManager().getIfLoaded(currency.getIdentifier()); - this.handler.registerCurrencyCommand(internal, main); + this.handle.register(internal, main); } -} \ No newline at end of file +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCurrencyManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCurrencyManager.java index 00cedf7..b77c662 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCurrencyManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiCurrencyManager.java @@ -3,34 +3,38 @@ package dev.xhyrom.lighteco.common.api.impl; import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Collection; -public class ApiCurrencyManager extends ApiAbstractManager implements CurrencyManager { - public ApiCurrencyManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.currency.CurrencyManager handler) { - super(plugin, handler); +public class ApiCurrencyManager + extends ApiAbstractManager + implements CurrencyManager { + public ApiCurrencyManager( + LightEcoPlugin plugin, + dev.xhyrom.lighteco.common.manager.currency.CurrencyManager handle) { + super(plugin, handle); } - private Currency wrap(dev.xhyrom.lighteco.common.model.currency.Currency handler) { - return handler.getProxy(); + private Currency wrap(dev.xhyrom.lighteco.common.model.currency.Currency handle) { + return handle.getProxy(); } @Override public @NonNull Collection getRegisteredCurrencies() { - return this.handler.values() - .stream().map(this::wrap) - .toList(); + return this.handle.values().stream().map(this::wrap).toList(); } @Override public Currency getCurrency(@NonNull String identifier) { - return wrap(this.handler.getIfLoaded(identifier)); + return wrap(this.handle.getIfLoaded(identifier)); } @Override public void registerCurrency(@NonNull Currency currency) { - dev.xhyrom.lighteco.common.model.currency.Currency internal = new dev.xhyrom.lighteco.common.model.currency.Currency(currency); - this.handler.registerCurrency(internal); + dev.xhyrom.lighteco.common.model.currency.Currency internal = + new dev.xhyrom.lighteco.common.model.currency.Currency(currency); + this.handle.registerCurrency(internal); } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiMessagingService.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiMessagingService.java new file mode 100644 index 0000000..862d8c5 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiMessagingService.java @@ -0,0 +1,22 @@ +package dev.xhyrom.lighteco.common.api.impl; + +import dev.xhyrom.lighteco.api.messaging.MessagingService; +import dev.xhyrom.lighteco.api.model.currency.Currency; +import dev.xhyrom.lighteco.api.model.user.User; +import dev.xhyrom.lighteco.common.messaging.InternalMessagingService; + +public class ApiMessagingService implements MessagingService { + private final InternalMessagingService handle; + + public ApiMessagingService(InternalMessagingService handle) { + this.handle = handle; + } + + @Override + public void pushUserUpdate(User user, Currency currency) { + dev.xhyrom.lighteco.common.model.currency.Currency internalCurrency = + this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); + + this.handle.pushUserUpdate(ApiUser.cast(user), internalCurrency); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlatform.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlatform.java index ff613d1..0910f99 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlatform.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlatform.java @@ -2,6 +2,7 @@ package dev.xhyrom.lighteco.common.api.impl; import dev.xhyrom.lighteco.api.platform.Platform; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import org.checkerframework.checker.nullness.qual.NonNull; public class ApiPlatform implements Platform { diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlayerAdapter.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlayerAdapter.java index a60f2ac..4eb4876 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlayerAdapter.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiPlayerAdapter.java @@ -1,9 +1,10 @@ package dev.xhyrom.lighteco.common.api.impl; import dev.xhyrom.lighteco.api.manager.ContextManager; -import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.manager.UserManager; +import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.platform.PlayerAdapter; + import org.checkerframework.checker.nullness.qual.NonNull; import java.util.UUID; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java index afc0f5c..5d11449 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java @@ -2,6 +2,9 @@ package dev.xhyrom.lighteco.common.api.impl; import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.user.User; + +import net.kyori.adventure.text.Component; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -9,55 +12,65 @@ import java.math.BigDecimal; import java.util.UUID; public class ApiUser implements User { - private final dev.xhyrom.lighteco.common.model.user.User handler; + public static dev.xhyrom.lighteco.common.model.user.User cast(User u) { + if (u instanceof ApiUser) { + return ((ApiUser) u).handle; + } - public ApiUser(dev.xhyrom.lighteco.common.model.user.User handler) { - this.handler = handler; + throw new IllegalArgumentException( + "Cannot cast " + u.getClass().getName() + " to " + ApiUser.class.getName()); + } + + private final dev.xhyrom.lighteco.common.model.user.User handle; + + public ApiUser(dev.xhyrom.lighteco.common.model.user.User handle) { + this.handle = handle; } @Override public @NonNull UUID getUniqueId() { - return this.handler.getUniqueId(); + return this.handle.getUniqueId(); } @Override public @Nullable String getUsername() { - return this.handler.getUsername(); + return this.handle.getUsername(); } @Override public @NonNull BigDecimal getBalance(@NonNull Currency currency) { - dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin() - .getCurrencyManager() - .getIfLoaded(currency.getIdentifier()); + dev.xhyrom.lighteco.common.model.currency.Currency internal = + this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); - return this.handler.getBalance(internal); + return this.handle.getBalance(internal); } @Override public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) { - dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin() - .getCurrencyManager() - .getIfLoaded(currency.getIdentifier()); + dev.xhyrom.lighteco.common.model.currency.Currency internal = + this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); - this.handler.setBalance(internal, balance); + this.handle.setBalance(internal, balance); } @Override public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) { - dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin() - .getCurrencyManager() - .getIfLoaded(currency.getIdentifier()); + dev.xhyrom.lighteco.common.model.currency.Currency internal = + this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); - this.handler.deposit(internal, amount); + this.handle.deposit(internal, amount); } @Override public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) { - dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin() - .getCurrencyManager() - .getIfLoaded(currency.getIdentifier()); + dev.xhyrom.lighteco.common.model.currency.Currency internal = + this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); - this.handler.withdraw(internal, amount); + this.handle.withdraw(internal, amount); + } + + @Override + public void sendMessage(Component message) { + this.handle.sendMessage(message); } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUserManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUserManager.java index 89098d2..a04a02f 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUserManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUserManager.java @@ -3,21 +3,24 @@ package dev.xhyrom.lighteco.common.api.impl; import dev.xhyrom.lighteco.api.manager.UserManager; import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.jetbrains.annotations.NotNull; import java.util.UUID; import java.util.concurrent.CompletableFuture; -public class ApiUserManager extends ApiAbstractManager implements UserManager { - public ApiUserManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.user.UserManager handler) { - super(plugin, handler); +public class ApiUserManager + extends ApiAbstractManager + implements UserManager { + public ApiUserManager( + LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.user.UserManager handle) { + super(plugin, handle); } - private User wrap(dev.xhyrom.lighteco.common.model.user.User handler) { - this.plugin.getUserManager().getHousekeeper().registerUsage(handler.getUniqueId()); - return handler.getProxy(); + private User wrap(dev.xhyrom.lighteco.common.model.user.User handle) { + this.plugin.getUserManager().getHousekeeper().registerUsage(handle.getUniqueId()); + return handle.getProxy(); } @Override @@ -27,8 +30,7 @@ public class ApiUserManager extends ApiAbstractManager loadUser(@NonNull UUID uniqueId, String username) { - return this.plugin.getStorage().loadUser(uniqueId, username) - .thenApply(this::wrap); + return this.plugin.getStorage().loadUser(uniqueId, username).thenApply(this::wrap); } @Override @@ -37,17 +39,17 @@ public class ApiUserManager extends ApiAbstractManager saveUsers(@NotNull @NonNull User... users) { + public @NonNull CompletableFuture saveUsers(@NonNull User... users) { return this.plugin.getStorage().saveUsers(users); } @Override public @Nullable User getUser(@NonNull UUID uniqueId) { - return wrap(this.handler.getIfLoaded(uniqueId)); + return wrap(this.handle.getIfLoaded(uniqueId)); } @Override public boolean isLoaded(@NonNull UUID uniqueId) { - return this.handler.isLoaded(uniqueId); + return this.handle.isLoaded(uniqueId); } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/cache/ExpiringSet.java b/common/src/main/java/dev/xhyrom/lighteco/common/cache/ExpiringSet.java index 22c95e3..032a60f 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/cache/ExpiringSet.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/cache/ExpiringSet.java @@ -10,9 +10,7 @@ public class ExpiringSet { private final long lifetime; public ExpiringSet(long duration, TimeUnit unit) { - this.cache = CacheBuilder.newBuilder() - .expireAfterWrite(duration, unit) - .build(); + this.cache = CacheBuilder.newBuilder().expireAfterWrite(duration, unit).build(); this.lifetime = unit.toMillis(duration); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/cache/RedisBackedMap.java b/common/src/main/java/dev/xhyrom/lighteco/common/cache/RedisBackedMap.java index 7fd2df8..5b965c1 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/cache/RedisBackedMap.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/cache/RedisBackedMap.java @@ -2,6 +2,4 @@ package dev.xhyrom.lighteco.common.cache; import java.util.HashMap; -public class RedisBackedMap extends HashMap { - -} +public class RedisBackedMap extends HashMap {} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandHelper.java b/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandHelper.java new file mode 100644 index 0000000..73b3894 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandHelper.java @@ -0,0 +1,58 @@ +package dev.xhyrom.lighteco.common.command; + +import com.mojang.brigadier.context.CommandContext; + +import dev.xhyrom.lighteco.common.command.argument.type.OfflineUserArgument; +import dev.xhyrom.lighteco.common.command.exception.LockedUserException; +import dev.xhyrom.lighteco.common.config.message.CurrencyMessageConfig; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import lombok.experimental.UtilityClass; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import java.util.Map; + +@UtilityClass +public class CommandHelper { + public static User getUser(CommandContext context) { + LightEcoPlugin plugin = context.getSource().plugin(); + CommandSender sender = context.getSource().sender(); + + User target = null; + try { + target = OfflineUserArgument.getOfflineUser(context, "target"); + } catch (LockedUserException e) { + sender.sendMessage( + MiniMessage.miniMessage().deserialize(plugin.getConfig().messages.wait)); + } + + if (target == null || target.getUsername() == null) { + String userName = context.getArgument("target", String.class); + + sender.sendMessage(MiniMessage.miniMessage() + .deserialize( + plugin.getConfig().messages.userNotFound, + Placeholder.parsed("username", userName))); + return null; + } + + return target; + } + + public static CurrencyMessageConfig getCurrencyMessageConfig( + LightEcoPlugin plugin, Currency currency) { + Map config = plugin.getConfig().messages.currency; + CurrencyMessageConfig currencyMessageConfig = config.get(currency.getIdentifier()); + + if (currencyMessageConfig == null) { + return config.get("default"); + } + + return currencyMessageConfig; + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandManager.java new file mode 100644 index 0000000..aa6c2cd --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandManager.java @@ -0,0 +1,146 @@ +package dev.xhyrom.lighteco.common.command; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.ParseResults; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.commands.BalanceCommand; +import dev.xhyrom.lighteco.common.commands.CurrencyParentCommand; +import dev.xhyrom.lighteco.common.commands.InfoCommand; +import dev.xhyrom.lighteco.common.commands.PayCommand; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import lombok.Getter; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.MiniMessage; + +import java.util.*; +import java.util.concurrent.*; + +public class CommandManager { + protected final LightEcoPlugin plugin; + private final ExecutorService executor = + Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() + .setDaemon(true) + .setNameFormat("lighteco-command-executor") + .build()); + + @Getter + private final CommandDispatcher dispatcher = new CommandDispatcher<>(); + + @Getter + private final Set locks = ConcurrentHashMap.newKeySet(); + + private final Map locksMappings = new ConcurrentHashMap<>(); + + public CommandManager(LightEcoPlugin plugin) { + this.plugin = plugin; + } + + // Register built-in commands + public void register() { + register(new InfoCommand()); + } + + public void register(Currency currency, boolean main) { + register(new CurrencyParentCommand(currency)); + + if (main) { + register(BalanceCommand.create(currency)); + register(PayCommand.create(currency)); + } + } + + protected void register(Command command) { + dispatcher.getRoot().addChild(command.build()); + } + + public void execute(CommandSender sender, String name, String[] args) { + if (!sender.isConsole() && locks.contains(sender.getUniqueId())) { + sender.sendMessage( + MiniMessage.miniMessage().deserialize(this.plugin.getConfig().messages.wait)); + return; + } + + final CommandSource source = new CommandSource(this.plugin, sender); + final ParseResults parseResults = dispatcher.parse( + name + (args.length > 0 ? " " + String.join(" ", args) : ""), source); + + if (!sender.isConsole()) locks.add(sender.getUniqueId()); + + CompletableFuture.runAsync( + () -> { + try { + dispatcher.execute(parseResults); + } catch (CommandSyntaxException e) { + this.sendError(sender, name, e); + } finally { + if (!source.sender().isConsole()) { + this.plugin + .getBootstrap() + .getLogger() + .debug("Removing lock for " + sender.getUsername()); + + UUID target = locksMappings.get(sender.getUniqueId()); + if (target != null) { + locks.remove(target); + locksMappings.remove(sender.getUniqueId()); + + this.plugin + .getBootstrap() + .getLogger() + .debug("Removing lock caused by " + sender.getUsername() + + " for " + target); + } + + locks.remove(sender.getUniqueId()); + } + } + }, + executor); + } + + public void lockBySender(CommandSender sender, UUID target) { + locks.add(target); + locksMappings.put(sender.getUniqueId(), target); + } + + private void sendError(CommandSender sender, String name, CommandSyntaxException e) { + sender.sendMessage(Component.text(e.getRawMessage().getString(), NamedTextColor.RED)); + + if (e.getInput() != null && e.getCursor() >= 0) { + int j = Math.min(e.getInput().length(), e.getCursor()); + + Component msg = Component.empty() + .color(NamedTextColor.GRAY) + .clickEvent( + ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + name)); + + if (j > 10) { + msg = msg.append(Component.text("...")); + } + + msg = msg.append(Component.text(e.getInput().substring(Math.max(0, j - 10), j))); + + if (j < e.getInput().length()) { + Component component = Component.text(e.getInput().substring(j)) + .color(NamedTextColor.RED) + .decorate(TextDecoration.UNDERLINED); + msg = msg.append(component); + } + + msg = msg.append(Component.translatable("command.context.here") + .color(NamedTextColor.RED) + .decorate(TextDecoration.ITALIC)); + sender.sendMessage(msg); + } + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandSource.java b/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandSource.java new file mode 100644 index 0000000..a0095ac --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/command/CommandSource.java @@ -0,0 +1,8 @@ +package dev.xhyrom.lighteco.common.command; + +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public record CommandSource(@NonNull LightEcoPlugin plugin, @NonNull CommandSender sender) {} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/command/abstraction/Command.java b/common/src/main/java/dev/xhyrom/lighteco/common/command/abstraction/Command.java new file mode 100644 index 0000000..b915fb1 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/command/abstraction/Command.java @@ -0,0 +1,36 @@ +package dev.xhyrom.lighteco.common.command.abstraction; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.common.command.CommandSource; + +import lombok.Getter; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Getter +public abstract class Command { + @NonNull protected final String name; + + @NonNull private final String description; + + @NonNull private final List aliases = new ArrayList<>(); + + public Command(@NonNull String name, @NonNull String description, String... aliases) { + this.name = name; + this.description = description; + + Collections.addAll(this.aliases, aliases); + } + + public abstract CommandNode build(); + + protected LiteralArgumentBuilder builder() { + return LiteralArgumentBuilder.literal(name); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/command/argument/type/OfflineUserArgument.java b/common/src/main/java/dev/xhyrom/lighteco/common/command/argument/type/OfflineUserArgument.java new file mode 100644 index 0000000..8177ead --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/command/argument/type/OfflineUserArgument.java @@ -0,0 +1,46 @@ +package dev.xhyrom.lighteco.common.command.argument.type; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.exception.LockedUserException; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import java.util.UUID; + +public class OfflineUserArgument implements ArgumentType { + private OfflineUserArgument() {} + + public static User getOfflineUser(CommandContext context, String name) + throws LockedUserException { + String userName = context.getArgument(name, String.class); + LightEcoPlugin plugin = context.getSource().plugin(); + CommandSender sender = context.getSource().sender(); + + UUID uniqueId = plugin.getBootstrap().lookupUniqueId(userName).orElse(null); + if (uniqueId == null) { + return null; + } + + if (sender.getUniqueId() != uniqueId + && plugin.getCommandManager().getLocks().contains(uniqueId)) { + throw new LockedUserException(uniqueId); + } + + // Lock the user to prevent race conditions + if (!sender.isConsole()) + plugin.getCommandManager().lockBySender(context.getSource().sender(), uniqueId); + + return plugin.getUserManager().loadUser(uniqueId).join(); + } + + @Override + public String parse(StringReader reader) throws CommandSyntaxException { + return reader.readString(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/command/exception/LockedUserException.java b/common/src/main/java/dev/xhyrom/lighteco/common/command/exception/LockedUserException.java new file mode 100644 index 0000000..994d0d1 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/command/exception/LockedUserException.java @@ -0,0 +1,9 @@ +package dev.xhyrom.lighteco.common.command.exception; + +import java.util.UUID; + +public class LockedUserException extends Exception { + public LockedUserException(UUID uniqueId) { + super("User with uuid " + uniqueId + " is currently locked thus cannot be modified"); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/command/suggestion/type/OfflineUserSuggestionProvider.java b/common/src/main/java/dev/xhyrom/lighteco/common/command/suggestion/type/OfflineUserSuggestionProvider.java new file mode 100644 index 0000000..cef1398 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/command/suggestion/type/OfflineUserSuggestionProvider.java @@ -0,0 +1,36 @@ +package dev.xhyrom.lighteco.common.command.suggestion.type; + +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.SuggestionProvider; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; + +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class OfflineUserSuggestionProvider implements SuggestionProvider { + public static OfflineUserSuggestionProvider create() { + return new OfflineUserSuggestionProvider(); + } + + @Override + public CompletableFuture getSuggestions( + CommandContext context, SuggestionsBuilder builder) { + LightEcoPlugin plugin = context.getSource().plugin(); + + String remaining = builder.getRemaining(); + + for (UUID uniqueId : plugin.getBootstrap().getOnlinePlayers()) { + User user = plugin.getUserManager().getIfLoaded(uniqueId); + if (user == null) continue; + + builder.suggest(user.getUsername()); + } + + return builder.buildFuture(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/commands/BalanceCommand.java b/common/src/main/java/dev/xhyrom/lighteco/common/commands/BalanceCommand.java new file mode 100644 index 0000000..57c2d10 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/commands/BalanceCommand.java @@ -0,0 +1,89 @@ +package dev.xhyrom.lighteco.common.commands; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; + +import static dev.xhyrom.lighteco.common.command.CommandHelper.*; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.command.suggestion.type.OfflineUserSuggestionProvider; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; + +public class BalanceCommand extends Command { + private final Currency currency; + + public static BalanceCommand create(@NonNull Currency currency) { + return new BalanceCommand(currency); + } + + public BalanceCommand(@NonNull Currency currency) { + super("balance", "Check your balance"); + + this.currency = currency; + } + + @Override + public CommandNode build() { + return builder() + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.balance.others")) + .executes(context -> { + LightEcoPlugin plugin = context.getSource().plugin(); + CommandSender sender = context.getSource().sender(); + + final User target = getUser(context); + if (target == null) return SINGLE_SUCCESS; + + BigDecimal balance = target.getBalance(currency); + + sender.sendMessage(MiniMessage.miniMessage() + .deserialize( + getCurrencyMessageConfig(plugin, currency) + .balanceOthers, + Placeholder.parsed( + "currency", currency.getIdentifier()), + Placeholder.parsed("target", target.getUsername()), + Placeholder.parsed( + "balance", balance.toPlainString()))); + + return SINGLE_SUCCESS; + })) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.balance")) + .executes(context -> { + LightEcoPlugin plugin = context.getSource().plugin(); + CommandSender sender = context.getSource().sender(); + + User user = plugin.getUserManager().getIfLoaded(sender.getUniqueId()); + BigDecimal balance = user.getBalance(currency); + + sender.sendMessage(MiniMessage.miniMessage() + .deserialize( + getCurrencyMessageConfig(plugin, currency).balance, + Placeholder.parsed("currency", currency.getIdentifier()), + Placeholder.parsed("balance", balance.toPlainString()))); + + return SINGLE_SUCCESS; + }) + .build(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/commands/CurrencyParentCommand.java b/common/src/main/java/dev/xhyrom/lighteco/common/commands/CurrencyParentCommand.java new file mode 100644 index 0000000..2da1974 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/commands/CurrencyParentCommand.java @@ -0,0 +1,61 @@ +package dev.xhyrom.lighteco.common.commands; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; + +import static dev.xhyrom.lighteco.common.command.CommandHelper.getCurrencyMessageConfig; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; + +public class CurrencyParentCommand extends Command { + private final Currency currency; + + public CurrencyParentCommand(@NonNull Currency currency) { + super(currency.getIdentifier(), currency.getIdentifier()); + + this.currency = currency; + } + + @Override + public CommandNode build() { + LiteralArgumentBuilder builder = builder() + .then(BalanceCommand.create(currency).build()) + .then(SetCommand.create(currency).build()) + .then(GiveCommand.create(currency).build()) + .then(TakeCommand.create(currency).build()) + .executes(context -> { + LightEcoPlugin plugin = context.getSource().plugin(); + CommandSender sender = context.getSource().sender(); + + User user = plugin.getUserManager().getIfLoaded(sender.getUniqueId()); + BigDecimal balance = user.getBalance(currency); + + sender.sendMessage(MiniMessage.miniMessage() + .deserialize( + getCurrencyMessageConfig(plugin, currency).balance, + Placeholder.parsed("currency", currency.getIdentifier()), + Placeholder.parsed("balance", balance.toPlainString()))); + + return SINGLE_SUCCESS; + }); + + if (currency.isPayable()) + builder = builder.then(PayCommand.create(currency).build()); + + return builder.build(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/commands/GiveCommand.java b/common/src/main/java/dev/xhyrom/lighteco/common/commands/GiveCommand.java new file mode 100644 index 0000000..34d8237 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/commands/GiveCommand.java @@ -0,0 +1,116 @@ +package dev.xhyrom.lighteco.common.commands; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; + +import static dev.xhyrom.lighteco.common.command.CommandHelper.*; + +import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan; +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.command.suggestion.type.OfflineUserSuggestionProvider; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class GiveCommand extends Command { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private final Currency currency; + + public static GiveCommand create(@NonNull Currency currency) { + return new GiveCommand(currency); + } + + public GiveCommand(@NonNull Currency currency) { + super("give", "Give a player some money"); + + this.currency = currency; + } + + private void execute(CommandContext context) { + final LightEcoPlugin plugin = context.getSource().plugin(); + final CommandSender sender = context.getSource().sender(); + + final User target = getUser(context); + if (target == null) return; + + BigDecimal amount = BigDecimal.valueOf( + currency.fractionalDigits() > 0 + ? context.getArgument("amount", Double.class) + : context.getArgument("amount", Integer.class)); + + amount = amount.setScale(currency.fractionalDigits(), RoundingMode.DOWN); + + try { + target.deposit(currency, amount); + } catch (CannotBeGreaterThan e) { + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).cannotBeGreaterThan, + Placeholder.parsed("max", plugin.getConfig().maximumBalance.toPlainString()))); + + return; + } + + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).set, + Placeholder.parsed("currency", currency.getIdentifier()), + Placeholder.parsed("target", target.getUsername()), + Placeholder.parsed("amount", amount.toPlainString()))); + } + + @Override + public CommandNode build() { + if (currency.fractionalDigits() > 0) { + return builder() + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.give")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", DoubleArgumentType.doubleArg(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + + currency.getIdentifier() + ".command.give")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } + + return builder() + .requires((source) -> source.sender() + .eligible( + "lighteco.currency." + currency.getIdentifier() + ".command.give")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", IntegerArgumentType.integer(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.give")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/commands/InfoCommand.java b/common/src/main/java/dev/xhyrom/lighteco/common/commands/InfoCommand.java new file mode 100644 index 0000000..03ad1cd --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/commands/InfoCommand.java @@ -0,0 +1,40 @@ +package dev.xhyrom.lighteco.common.commands; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; + +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +public class InfoCommand extends Command { + public InfoCommand() { + super("lighteco", "LightEco information"); + } + + @Override + public CommandNode build() { + return builder() + .requires(source -> source.sender().eligible("lighteco.command.info")) + .executes(context -> { + LightEcoPlugin plugin = context.getSource().plugin(); + CommandSender sender = context.getSource().sender(); + + sender.sendMessage(MiniMessage.miniMessage() + .deserialize( + "<#fa5246>LightEco (<#d6766f>v) on <#d6766f>", + Placeholder.parsed( + "version", plugin.getBootstrap().getVersion()), + Placeholder.parsed( + "platform", plugin.getPlatformType().getName()))); + + return SINGLE_SUCCESS; + }) + .build(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/commands/PayCommand.java b/common/src/main/java/dev/xhyrom/lighteco/common/commands/PayCommand.java new file mode 100644 index 0000000..44148cc --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/commands/PayCommand.java @@ -0,0 +1,160 @@ +package dev.xhyrom.lighteco.common.commands; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; + +import static dev.xhyrom.lighteco.common.command.CommandHelper.*; + +import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan; +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.command.suggestion.type.OfflineUserSuggestionProvider; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class PayCommand extends Command { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private final Currency currency; + + public static PayCommand create(@NonNull Currency currency) { + return new PayCommand(currency); + } + + public PayCommand(@NonNull Currency currency) { + super("pay", "Pay a player"); + + this.currency = currency; + } + + private void execute(CommandContext context) { + final LightEcoPlugin plugin = context.getSource().plugin(); + final CommandSender sender = context.getSource().sender(); + + final User target = getUser(context); + if (target == null) return; + + BigDecimal amount = BigDecimal.valueOf( + currency.fractionalDigits() > 0 + ? context.getArgument("amount", Double.class) + : context.getArgument("amount", Integer.class)); + + amount = amount.setScale(currency.fractionalDigits(), RoundingMode.DOWN); + + final User user = plugin.getUserManager().getIfLoaded(sender.getUniqueId()); + if (user == null) { + return; + } + + if (user.getBalance(this.currency).compareTo(amount) < 0) { + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).notEnoughMoney)); + + return; + } + + // calculate tax using Currency#calculateTax + BigDecimal tax = currency.getProxy().calculateTax(user.getProxy(), amount); + tax = tax.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); + + // subtract tax from amount + BigDecimal taxedAmount = amount.subtract(tax); + + try { + target.deposit(currency, taxedAmount); + user.withdraw(currency, amount); + } catch (CannotBeGreaterThan e) { + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).cannotBeGreaterThan, + Placeholder.parsed("max", plugin.getConfig().maximumBalance.toPlainString()))); + + return; + } + + String template = tax.compareTo(BigDecimal.ZERO) > 0 + ? getCurrencyMessageConfig(plugin, this.currency).payWithTax + : getCurrencyMessageConfig(plugin, this.currency).pay; + + String templateReceived = tax.compareTo(BigDecimal.ZERO) > 0 + ? getCurrencyMessageConfig(plugin, this.currency).payReceivedWithTax + : getCurrencyMessageConfig(plugin, this.currency).payReceived; + + sender.sendMessage(miniMessage.deserialize( + template, + Placeholder.parsed("currency", currency.getIdentifier()), + Placeholder.parsed("target", target.getUsername()), + Placeholder.parsed("amount", amount.toPlainString()), + Placeholder.parsed("taxed_amount", taxedAmount.toPlainString()), + Placeholder.parsed("sender_balance", user.getBalance(currency).toPlainString()), + Placeholder.parsed( + "receiver_balance", target.getBalance(currency).toPlainString()))); + + target.sendMessage(miniMessage.deserialize( + templateReceived, + Placeholder.parsed("currency", currency.getIdentifier()), + Placeholder.parsed("sender", user.getUsername()), + Placeholder.parsed("amount", amount.toPlainString()), + Placeholder.parsed("taxed_amount", taxedAmount.toPlainString()), + Placeholder.parsed("sender_balance", user.getBalance(currency).toPlainString()), + Placeholder.parsed( + "receiver_balance", target.getBalance(currency).toPlainString()))); + } + + @Override + public CommandNode build() { + if (currency.fractionalDigits() > 0) { + return builder() + .requires((source) -> !source.sender().isConsole() + && source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.pay")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", DoubleArgumentType.doubleArg(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + + currency.getIdentifier() + ".command.pay")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } + + return builder() + .requires((source) -> !source.sender().isConsole() + && source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.pay")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", IntegerArgumentType.integer(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.pay")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/commands/SetCommand.java b/common/src/main/java/dev/xhyrom/lighteco/common/commands/SetCommand.java new file mode 100644 index 0000000..7bca726 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/commands/SetCommand.java @@ -0,0 +1,115 @@ +package dev.xhyrom.lighteco.common.commands; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; + +import static dev.xhyrom.lighteco.common.command.CommandHelper.*; + +import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan; +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.command.suggestion.type.OfflineUserSuggestionProvider; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class SetCommand extends Command { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private final Currency currency; + + public static SetCommand create(@NonNull Currency currency) { + return new SetCommand(currency); + } + + public SetCommand(@NonNull Currency currency) { + super("set", "Set a player's balance"); + + this.currency = currency; + } + + private void execute(CommandContext context) { + final LightEcoPlugin plugin = context.getSource().plugin(); + final CommandSender sender = context.getSource().sender(); + + final User target = getUser(context); + if (target == null) return; + + BigDecimal amount = BigDecimal.valueOf( + currency.fractionalDigits() > 0 + ? context.getArgument("amount", Double.class) + : context.getArgument("amount", Integer.class)); + + amount = amount.setScale(currency.fractionalDigits(), RoundingMode.DOWN); + + try { + target.setBalance(currency, amount); + } catch (CannotBeGreaterThan e) { + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).cannotBeGreaterThan, + Placeholder.parsed("max", plugin.getConfig().maximumBalance.toPlainString()))); + + return; + } + + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).set, + Placeholder.parsed("currency", currency.getIdentifier()), + Placeholder.parsed("target", target.getUsername()), + Placeholder.parsed("amount", amount.toPlainString()))); + } + + @Override + public CommandNode build() { + if (currency.fractionalDigits() > 0) { + return builder() + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.set")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", DoubleArgumentType.doubleArg(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + + currency.getIdentifier() + ".command.set")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } + + return builder() + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + ".command.set")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", IntegerArgumentType.integer(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.set")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/commands/TakeCommand.java b/common/src/main/java/dev/xhyrom/lighteco/common/commands/TakeCommand.java new file mode 100644 index 0000000..aa03ef0 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/commands/TakeCommand.java @@ -0,0 +1,116 @@ +package dev.xhyrom.lighteco.common.commands; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; + +import static dev.xhyrom.lighteco.common.command.CommandHelper.*; + +import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.tree.CommandNode; + +import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan; +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.command.suggestion.type.OfflineUserSuggestionProvider; +import dev.xhyrom.lighteco.common.model.chat.CommandSender; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class TakeCommand extends Command { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private final Currency currency; + + public static TakeCommand create(@NonNull Currency currency) { + return new TakeCommand(currency); + } + + public TakeCommand(@NonNull Currency currency) { + super("take", "Take money from a player"); + + this.currency = currency; + } + + private void execute(CommandContext context) { + final LightEcoPlugin plugin = context.getSource().plugin(); + final CommandSender sender = context.getSource().sender(); + + final User target = getUser(context); + if (target == null) return; + + BigDecimal amount = BigDecimal.valueOf( + currency.fractionalDigits() > 0 + ? context.getArgument("amount", Double.class) + : context.getArgument("amount", Integer.class)); + + amount = amount.setScale(currency.fractionalDigits(), RoundingMode.DOWN); + + try { + target.withdraw(currency, amount); + } catch (CannotBeGreaterThan e) { + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).cannotBeGreaterThan, + Placeholder.parsed("max", plugin.getConfig().maximumBalance.toPlainString()))); + + return; + } + + sender.sendMessage(miniMessage.deserialize( + getCurrencyMessageConfig(plugin, this.currency).set, + Placeholder.parsed("currency", currency.getIdentifier()), + Placeholder.parsed("target", target.getUsername()), + Placeholder.parsed("amount", amount.toPlainString()))); + } + + @Override + public CommandNode build() { + if (currency.fractionalDigits() > 0) { + return builder() + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.take")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", DoubleArgumentType.doubleArg(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + + currency.getIdentifier() + ".command.take")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } + + return builder() + .requires((source) -> source.sender() + .eligible( + "lighteco.currency." + currency.getIdentifier() + ".command.take")) + .then(RequiredArgumentBuilder.argument( + "target", StringArgumentType.word()) + .suggests(OfflineUserSuggestionProvider.create()) + .then(RequiredArgumentBuilder.argument( + "amount", IntegerArgumentType.integer(1)) + .requires((source) -> source.sender() + .eligible("lighteco.currency." + currency.getIdentifier() + + ".command.take")) + .executes(c -> { + execute(c); + return SINGLE_SUCCESS; + }))) + .build(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/Config.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/Config.java index 7f1e85a..8f21694 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/config/Config.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/Config.java @@ -2,25 +2,38 @@ package dev.xhyrom.lighteco.common.config; import dev.xhyrom.lighteco.common.config.housekeeper.HousekeeperConfig; import dev.xhyrom.lighteco.common.config.message.MessageConfig; +import dev.xhyrom.lighteco.common.config.messaging.MessagingConfig; import dev.xhyrom.lighteco.common.config.storage.StorageConfig; + import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.annotation.Header; +import java.math.BigDecimal; + @Header("LightEco configuration file.") @Header("") public class Config extends OkaeriConfig { @Comment("This property must be unique for each server.") - @Comment("If you have multiple servers, you must set this property to a different value for each server.") + @Comment( + "If you have multiple servers, you must set this property to a different value for each server.") @Comment("Used for local currencies.") public String server = "none"; @Comment("Storage settings.") public StorageConfig storage = new StorageConfig(); + @Comment("Messaging settings.") + public MessagingConfig messaging = new MessagingConfig(); + @Comment("Save interval to storage in seconds.") public long saveInterval = 5L; + @Comment("Maximum allowed balance.") + @Comment( + "If you want to change this value, you must also change the data type in the database.") + public BigDecimal maximumBalance = BigDecimal.valueOf(999999999999999.99); + @Comment("Messages") public MessageConfig messages = new MessageConfig(); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/housekeeper/HousekeeperConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/housekeeper/HousekeeperConfig.java index f15e82f..0e652e6 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/config/housekeeper/HousekeeperConfig.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/housekeeper/HousekeeperConfig.java @@ -8,9 +8,11 @@ import java.util.concurrent.TimeUnit; public class HousekeeperConfig extends OkaeriConfig { @Comment("How long should the cache be kept after the last write") public int expireAfterWrite = 300; + public TimeUnit expireAfterWriteUnit = TimeUnit.SECONDS; @Comment("How often should housekeeper run") public int runInterval = 60; + public TimeUnit runIntervalUnit = TimeUnit.SECONDS; } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/message/CurrencyMessageConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/message/CurrencyMessageConfig.java index 3bc4c4b..87f745e 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/config/message/CurrencyMessageConfig.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/message/CurrencyMessageConfig.java @@ -4,18 +4,30 @@ import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Variable; public class CurrencyMessageConfig extends OkaeriConfig { - public String balance = " | Your balance: "; + public String balance = + " | Your balance: "; + @Variable("balance-others") - public String balanceOthers = " | Balance of | "; + public String balanceOthers = + " | Balance of | "; - public String set = " | Set balance of to "; - public String give = " | Gave | "; - public String take = " | Took from "; + public String set = + " | Set balance of to "; + public String give = + " | Gave | "; + public String take = + " | Took from "; - public String pay = " | Paid to "; - public String payWithTax = " | Paid to ( after tax)"; + public String pay = + " | Paid to "; + public String payWithTax = + " | Paid to ( after tax)"; + public String payReceived = + " | Received from "; + public String payReceivedWithTax = + " | Received from ( after tax)"; - public String wait = "Please wait a moment before using this command again."; public String notEnoughMoney = "You don't have enough money!"; public String cannotPaySelf = "You cannot pay yourself!"; + public String cannotBeGreaterThan = "Amount cannot be greater than "; } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/message/MessageConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/message/MessageConfig.java index 88be91a..7a080e4 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/config/message/MessageConfig.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/message/MessageConfig.java @@ -6,5 +6,9 @@ import java.util.Collections; import java.util.Map; public class MessageConfig extends OkaeriConfig { - public Map currency = Collections.singletonMap("default", new CurrencyMessageConfig()); + public Map currency = + Collections.singletonMap("default", new CurrencyMessageConfig()); + + public String wait = "Please wait a moment before using this command again."; + public String userNotFound = "User not found."; } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/messaging/MessagingConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/messaging/MessagingConfig.java new file mode 100644 index 0000000..2989b07 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/messaging/MessagingConfig.java @@ -0,0 +1,16 @@ +package dev.xhyrom.lighteco.common.config.messaging; + +import dev.xhyrom.lighteco.common.messaging.MessagingType; + +import eu.okaeri.configs.OkaeriConfig; +import eu.okaeri.configs.annotation.Comment; + +public class MessagingConfig extends OkaeriConfig { + @Comment("Messaging provider.") + @Comment("Available providers: redis") + public MessagingType provider = MessagingType.NONE; + + @Comment("Data storage settings.") + @Comment("You don't need to worry about this if you're using plugin message.") + public MessagingDataConfig data = new MessagingDataConfig(); +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/messaging/MessagingDataConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/messaging/MessagingDataConfig.java new file mode 100644 index 0000000..d3a880e --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/messaging/MessagingDataConfig.java @@ -0,0 +1,17 @@ +package dev.xhyrom.lighteco.common.config.messaging; + +import eu.okaeri.configs.OkaeriConfig; +import eu.okaeri.configs.annotation.Comment; + +public class MessagingDataConfig extends OkaeriConfig { + @Comment("Define the address and port of the messaging service.") + public String address = "localhost"; + + @Comment("Credentials for connecting to the messaging service.") + public String username = "root"; + + public String password = "password"; + + @Comment("Whether to use SSL to connect to the messaging service.") + public boolean ssl = false; +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java index 12897ce..7746351 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java @@ -1,6 +1,7 @@ package dev.xhyrom.lighteco.common.config.storage; import dev.xhyrom.lighteco.common.storage.StorageType; + import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageDataConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageDataConfig.java index 614eef6..80174e6 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageDataConfig.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageDataConfig.java @@ -12,6 +12,7 @@ public class StorageDataConfig extends OkaeriConfig { @Comment("Credentials for connecting to the database.") public String username = "root"; + public String password = "password"; @Comment("Maximum number of connections in the pool.") diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/Dependency.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/Dependency.java index 7939c8c..856ca2d 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/Dependency.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/Dependency.java @@ -1,7 +1,9 @@ package dev.xhyrom.lighteco.common.dependencies; import com.google.common.collect.ImmutableList; + import dev.xhyrom.lighteco.common.dependencies.relocation.Relocation; + import lombok.Getter; import java.util.List; @@ -12,59 +14,40 @@ public enum Dependency { * Somewhere we use brackets instad of dots, so we need to rewrite them * This is because gradle's shadow plugin relocates using replacing full paths (dots) */ - - ASM( - "org.ow2.asm", - "asm", - "9.1" - ), - ASM_COMMONS( - "org.ow2.asm", - "asm-commons", - "9.1" - ), - JAR_RELOCATOR( - "me.lucko", - "jar-relocator", - "1.7" - ), - HIKARI( - "com{}zaxxer", - "HikariCP", - "5.0.1", - Relocation.of("hikari", "com{}zaxxer{}hikari") - ), - H2_DRIVER( - "com.h2database", - "h2", - "2.1.214" - ), - SQLITE_DRIVER( - "org.xerial", - "sqlite-jdbc", - "3.28.0" - ), + ASM("org.ow2.asm", "asm", "9.1"), + ASM_COMMONS("org.ow2.asm", "asm-commons", "9.1"), + JAR_RELOCATOR("me.lucko", "jar-relocator", "1.7"), + HIKARI("com{}zaxxer", "HikariCP", "5.0.1", Relocation.of("hikari", "com{}zaxxer{}hikari")), + H2_DRIVER("com.h2database", "h2", "2.1.214"), + SQLITE_DRIVER("org.xerial", "sqlite-jdbc", "3.28.0"), MARIADB_DRIVER( "org{}mariadb{}jdbc", "mariadb-java-client", "3.1.3", - Relocation.of("mariadb", "org{}mariadb{}jdbc") - ), - MYSQL_DRIVER( - "mysql", - "mysql-connector-java", - "8.0.23", - Relocation.of("mysql", "com{}mysql") - ), + Relocation.of("mariadb", "org{}mariadb{}jdbc")), + MYSQL_DRIVER("mysql", "mysql-connector-java", "8.0.23", Relocation.of("mysql", "com{}mysql")), POSTGRESQL_DRIVER( "org{}postgresql", "postgresql", "42.6.0", - Relocation.of("postgresql", "org{}postgresql") - ); + Relocation.of("postgresql", "org{}postgresql")), + JEDIS( + "redis.clients", + "jedis", + "5.1.0", + Relocation.of("jedis", "redis{}clients{}jedis"), + Relocation.of("commonspool2", "org{}apache{}commons{}pool2")), + SLF4J_SIMPLE("org.slf4j", "slf4j-simple", "1.7.30"), + SLF4J_API("org.slf4j", "slf4j-api", "1.7.30"), + COMMONS_POOL_2( + "org.apache.commons", + "commons-pool2", + "2.9.0", + Relocation.of("commonspool2", "org{}apache{}commons{}pool2")); private final String fullPath; private final String version; + @Getter private final List relocations; @@ -75,13 +58,13 @@ public enum Dependency { } Dependency(String groupId, String artifactId, String version, Relocation... relocations) { - this.fullPath = String.format(MAVEN_FORMAT, + this.fullPath = String.format( + MAVEN_FORMAT, rewriteEscape(groupId).replace('.', '/'), rewriteEscape(artifactId), version, rewriteEscape(artifactId), - version - ); + version); this.version = version; this.relocations = ImmutableList.copyOf(relocations); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManager.java index c81b6a1..ad4ad1a 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManager.java @@ -1,5 +1,6 @@ package dev.xhyrom.lighteco.common.dependencies; +import dev.xhyrom.lighteco.common.messaging.MessagingType; import dev.xhyrom.lighteco.common.storage.StorageType; import java.util.Set; @@ -9,6 +10,8 @@ public interface DependencyManager extends AutoCloseable { void loadStorageDependencies(Set types); + void loadMessagingDependencies(Set types); + ClassLoader obtainClassLoaderWith(Set dependencies); @Override diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManagerImpl.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManagerImpl.java index b2bfc39..24c1a75 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManagerImpl.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyManagerImpl.java @@ -2,13 +2,16 @@ package dev.xhyrom.lighteco.common.dependencies; import com.google.common.collect.ImmutableSet; import com.google.common.io.MoreFiles; + import dev.xhyrom.lighteco.common.config.Config; import dev.xhyrom.lighteco.common.dependencies.relocation.Relocation; import dev.xhyrom.lighteco.common.dependencies.relocation.RelocationHandler; +import dev.xhyrom.lighteco.common.messaging.MessagingType; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; -import dev.xhyrom.lighteco.common.util.URLClassLoaderAccess; import dev.xhyrom.lighteco.common.storage.StorageType; +import dev.xhyrom.lighteco.common.util.URLClassLoaderAccess; + import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import java.io.IOException; @@ -17,8 +20,6 @@ import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; public class DependencyManagerImpl implements DependencyManager { private final EnumMap loaded = new EnumMap<>(Dependency.class); @@ -36,7 +37,8 @@ public class DependencyManagerImpl implements DependencyManager { this.logger = plugin.getBootstrap().getLogger(); this.registry = new DependencyRegistry(); this.cacheDirectory = setupCacheDirectory(plugin); - this.classLoader = URLClassLoaderAccess.create((URLClassLoader) plugin.getBootstrap().getClass().getClassLoader()); + this.classLoader = URLClassLoaderAccess.create( + (URLClassLoader) plugin.getBootstrap().getClass().getClassLoader()); } private synchronized RelocationHandler getRelocationHandler() { @@ -49,42 +51,25 @@ public class DependencyManagerImpl implements DependencyManager { @Override public void loadDependencies(Set dependencies) { - CountDownLatch latch = new CountDownLatch(dependencies.size()); - - if (this.config.debug) - this.logger.info("Loading dependencies: " + dependencies); + if (this.config.debug) this.logger.info("Loading dependencies: " + dependencies); for (Dependency dependency : dependencies) { if (this.loaded.containsKey(dependency)) { - latch.countDown(); continue; } - CompletableFuture.runAsync(() -> { - if (this.config.debug) - this.logger.info("Loading dependency " + dependency); + if (this.config.debug) this.logger.info("Loading dependency " + dependency); - try { - loadDependency(dependency); - } catch (Exception e) { - throw new RuntimeException("Failed to load dependency " + dependency, e); - } finally { - latch.countDown(); - - if (this.config.debug) - this.logger.info("Loaded dependency " + dependency); - } - }); + try { + loadDependency(dependency); + } catch (Exception e) { + throw new RuntimeException("Failed to load dependency " + dependency, e); + } finally { + if (this.config.debug) this.logger.info("Loaded dependency " + dependency); + } } - try { - latch.await(); - - if (this.config.debug) - this.logger.info("Loaded dependencies: " + dependencies); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + if (this.config.debug) this.logger.info("Loaded dependencies: " + dependencies); } private void loadDependency(Dependency dependency) throws Exception { @@ -142,6 +127,11 @@ public class DependencyManagerImpl implements DependencyManager { loadDependencies(this.registry.resolveStorageDependencies(types)); } + @Override + public void loadMessagingDependencies(Set types) { + loadDependencies(this.registry.resolveMessagingDependencies(types)); + } + @Override public ClassLoader obtainClassLoaderWith(Set dependencies) { ImmutableSet set = ImmutableSet.copyOf(dependencies); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyRegistry.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyRegistry.java index b948bcb..afd229a 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyRegistry.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/DependencyRegistry.java @@ -2,19 +2,32 @@ package dev.xhyrom.lighteco.common.dependencies; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.SetMultimap; + +import dev.xhyrom.lighteco.common.messaging.MessagingType; import dev.xhyrom.lighteco.common.storage.StorageType; import java.util.LinkedHashSet; import java.util.Set; public class DependencyRegistry { - private static final SetMultimap STORAGE_DEPENDENCIES = ImmutableSetMultimap.builder() - .putAll(StorageType.SQLITE, Dependency.SQLITE_DRIVER) - .putAll(StorageType.H2, Dependency.H2_DRIVER) - .putAll(StorageType.MYSQL, Dependency.MYSQL_DRIVER, Dependency.HIKARI) - .putAll(StorageType.MARIADB, Dependency.MARIADB_DRIVER, Dependency.HIKARI) - .putAll(StorageType.POSTGRESQL, Dependency.POSTGRESQL_DRIVER, Dependency.HIKARI) - .build(); + private static final SetMultimap STORAGE_DEPENDENCIES = + ImmutableSetMultimap.builder() + .putAll(StorageType.SQLITE, Dependency.SQLITE_DRIVER) + .putAll(StorageType.H2, Dependency.H2_DRIVER) + .putAll(StorageType.MYSQL, Dependency.MYSQL_DRIVER, Dependency.HIKARI) + .putAll(StorageType.MARIADB, Dependency.MARIADB_DRIVER, Dependency.HIKARI) + .putAll(StorageType.POSTGRESQL, Dependency.POSTGRESQL_DRIVER, Dependency.HIKARI) + .build(); + + private static final SetMultimap MESSAGING_DEPENDENCIES = + ImmutableSetMultimap.builder() + .putAll( + MessagingType.REDIS, + Dependency.COMMONS_POOL_2, + Dependency.JEDIS, + Dependency.SLF4J_API, + Dependency.SLF4J_SIMPLE) + .build(); public Set resolveStorageDependencies(Set types) { Set dependencies = new LinkedHashSet<>(); @@ -26,6 +39,16 @@ public class DependencyRegistry { return dependencies; } + public Set resolveMessagingDependencies(Set types) { + Set dependencies = new LinkedHashSet<>(); + + for (MessagingType type : types) { + dependencies.addAll(MESSAGING_DEPENDENCIES.get(type)); + } + + return dependencies; + } + public boolean shouldAutoLoad(Dependency dependency) { return switch (dependency) { case H2_DRIVER, SQLITE_DRIVER -> false; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/IsolatedClassLoader.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/IsolatedClassLoader.java index e9568ed..21f060d 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/IsolatedClassLoader.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/IsolatedClassLoader.java @@ -11,5 +11,4 @@ public class IsolatedClassLoader extends URLClassLoader { public IsolatedClassLoader(URL[] urls) { super(urls, ClassLoader.getSystemClassLoader().getParent()); } - -} \ No newline at end of file +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/package-info.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/package-info.java index c4a2b90..42fb8da 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/package-info.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/package-info.java @@ -4,4 +4,4 @@ // Copyright (c) contributors // Under MIT License -package dev.xhyrom.lighteco.common.dependencies; \ No newline at end of file +package dev.xhyrom.lighteco.common.dependencies; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/Relocation.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/Relocation.java index e1679a0..a738532 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/Relocation.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/Relocation.java @@ -17,5 +17,4 @@ public class Relocation { this.pattern = pattern; this.relocatedPattern = relocatedPattern; } - } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/RelocationHandler.java b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/RelocationHandler.java index 15ff554..7e21f3e 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/RelocationHandler.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/dependencies/relocation/RelocationHandler.java @@ -12,7 +12,8 @@ import java.nio.file.Path; import java.util.*; public class RelocationHandler { - public static final Set DEPENDENCIES = EnumSet.of(Dependency.ASM, Dependency.ASM_COMMONS, Dependency.JAR_RELOCATOR); + public static final Set DEPENDENCIES = + EnumSet.of(Dependency.ASM, Dependency.ASM_COMMONS, Dependency.JAR_RELOCATOR); private static final String JAR_RELOCATOR_CLASS = "me.lucko.jarrelocator.JarRelocator"; private static final String JAR_RELOCATOR_RUN_METHOD = "run"; @@ -31,10 +32,12 @@ public class RelocationHandler { Class jarRelocatorClass = classLoader.loadClass(JAR_RELOCATOR_CLASS); // prepare the reflected constructor & method instances - this.jarRelocatorConstructor = jarRelocatorClass.getDeclaredConstructor(File.class, File.class, Map.class); + this.jarRelocatorConstructor = + jarRelocatorClass.getDeclaredConstructor(File.class, File.class, Map.class); this.jarRelocatorConstructor.setAccessible(true); - this.jarRelocatorRunMethod = jarRelocatorClass.getDeclaredMethod(JAR_RELOCATOR_RUN_METHOD); + this.jarRelocatorRunMethod = + jarRelocatorClass.getDeclaredMethod(JAR_RELOCATOR_RUN_METHOD); this.jarRelocatorRunMethod.setAccessible(true); } catch (Exception e) { try { @@ -56,8 +59,8 @@ public class RelocationHandler { } // create and invoke a new relocator - Object relocator = this.jarRelocatorConstructor.newInstance(input.toFile(), output.toFile(), mappings); + Object relocator = + this.jarRelocatorConstructor.newInstance(input.toFile(), output.toFile(), mappings); this.jarRelocatorRunMethod.invoke(relocator); } - } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/Manager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/Manager.java index 7734c22..0cc55b7 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/Manager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/manager/Manager.java @@ -6,6 +6,7 @@ public interface Manager { T apply(I identifier); Collection keys(); + Collection values(); T getOrMake(I identifier); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/AbstractCommandManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/AbstractCommandManager.java deleted file mode 100644 index 3fef971..0000000 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/AbstractCommandManager.java +++ /dev/null @@ -1,211 +0,0 @@ -package dev.xhyrom.lighteco.common.manager.command; - -import dev.xhyrom.lighteco.common.config.message.CurrencyMessageConfig; -import dev.xhyrom.lighteco.common.model.chat.CommandSender; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import dev.xhyrom.lighteco.common.model.user.User; -import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.Map; -import java.util.UUID; - -public abstract class AbstractCommandManager implements CommandManager { - public final LightEcoPlugin plugin; - private final MiniMessage miniMessage = MiniMessage.miniMessage(); - private final Map config; - private final ArrayList mustWait = new ArrayList<>(); - - protected AbstractCommandManager(LightEcoPlugin plugin) { - this.plugin = plugin; - this.config = this.plugin.getConfig().messages.currency; - } - - @Override - public boolean canUse(CommandSender sender, Currency currency) { - // Console doesn't need to wait - if (sender.getUniqueId() == null) return true; - - if (mustWait.contains(sender.getUniqueId())) { - sender.sendMessage( - miniMessage.deserialize( - this.getConfig(currency).wait - ) - ); - - return false; - } - - return true; - } - - private void addToMustWait(UUID ...uuids) { - for (UUID uuid : uuids) { - if (uuid != null) - mustWait.add(uuid); - } - } - - private void removeFromMustWait(UUID ...uuids) { - for (UUID uuid : uuids) { - if (uuid != null) - mustWait.remove(uuid); - } - } - - private CurrencyMessageConfig getConfig(Currency currency) { - CurrencyMessageConfig currencyMessageConfig = this.config.get(currency.getIdentifier()); - - if (currencyMessageConfig == null) { - return this.config.get("default"); - } - - return currencyMessageConfig; - } - - @Override - public void onBalance(CommandSender sender, Currency currency) { - User user = this.plugin.getUserManager().getIfLoaded(sender.getUniqueId()); - BigDecimal balance = user.getBalance(currency); - - sender.sendMessage( - miniMessage.deserialize( - getConfig(currency).balance, - Placeholder.parsed("currency", currency.getIdentifier()), - Placeholder.parsed("balance", balance.toPlainString()) - ) - ); - } - - @Override - public void onBalance(CommandSender sender, Currency currency, User target) { - BigDecimal balance = target.getBalance(currency); - - sender.sendMessage( - miniMessage.deserialize( - getConfig(currency).balanceOthers, - Placeholder.parsed("currency", currency.getIdentifier()), - Placeholder.parsed("target", target.getUsername()), - Placeholder.parsed("balance", balance.toPlainString()) - ) - - ); - } - - @Override - public void onSet(CommandSender sender, Currency currency, User target, BigDecimal amount) { - addToMustWait(sender.getUniqueId(), target.getUniqueId()); - amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - - target.setBalance(currency, amount); - - sender.sendMessage( - miniMessage.deserialize( - this.getConfig(currency).set, - Placeholder.parsed("currency", currency.getIdentifier()), - Placeholder.parsed("target", target.getUsername()), - Placeholder.parsed("amount", amount.toPlainString()) - ) - ); - - removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); - } - - @Override - public void onGive(CommandSender sender, Currency currency, User target, BigDecimal amount) { - addToMustWait(sender.getUniqueId(), target.getUniqueId()); - amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - - target.deposit(currency, amount); - - sender.sendMessage( - miniMessage.deserialize( - this.getConfig(currency).give, - Placeholder.parsed("currency", currency.getIdentifier()), - Placeholder.parsed("target", target.getUsername()), - Placeholder.parsed("amount", amount.toPlainString()), - Placeholder.parsed("balance", target.getBalance(currency).toPlainString()) - ) - ); - - removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); - } - - @Override - public void onTake(CommandSender sender, Currency currency, User target, BigDecimal amount) { - addToMustWait(sender.getUniqueId(), target.getUniqueId()); - amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - - target.withdraw(currency, amount); - - sender.sendMessage( - miniMessage.deserialize( - this.getConfig(currency).take, - Placeholder.parsed("currency", currency.getIdentifier()), - Placeholder.parsed("target", target.getUsername()), - Placeholder.parsed("amount", amount.toPlainString()), - Placeholder.parsed("balance", target.getBalance(currency).toPlainString()) - ) - ); - - removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); - } - - @Override - public void onPay(CommandSender sender, Currency currency, User target, BigDecimal amount) { - if (sender.getUniqueId() != null && (sender.getUniqueId() == target.getUniqueId())) { - sender.sendMessage( - miniMessage.deserialize(this.getConfig(currency).cannotPaySelf) - ); - - return; - } - - amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - - User user = this.plugin.getUserManager().getIfLoaded(sender.getUniqueId()); - - if (user.getBalance(currency).compareTo(amount) < 0) { - sender.sendMessage( - miniMessage.deserialize(this.getConfig(currency).notEnoughMoney) - ); - - return; - } - - addToMustWait(sender.getUniqueId(), target.getUniqueId()); - - // calculate tax using Currency#calculateTax - BigDecimal tax = currency.getProxy().calculateTax(user.getProxy(), amount); - tax = tax.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - - // subtract tax from amount - BigDecimal taxedAmount = amount.subtract(tax); - - target.deposit(currency, taxedAmount); - user.withdraw(currency, amount); - - String template = tax.compareTo(BigDecimal.ZERO) > 0 - ? this.getConfig(currency).payWithTax - : this.getConfig(currency).pay; - - - sender.sendMessage( - miniMessage.deserialize( - template, - Placeholder.parsed("currency", currency.getIdentifier()), - Placeholder.parsed("target", target.getUsername()), - Placeholder.parsed("amount", amount.toPlainString()), - Placeholder.parsed("taxed_amount", taxedAmount.toPlainString()), - Placeholder.parsed("sender_balance", user.getBalance(currency).toPlainString()), - Placeholder.parsed("receiver_balance", target.getBalance(currency).toPlainString()) - ) - ); - - removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); - } -} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/CommandManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/CommandManager.java deleted file mode 100644 index bcb3c5d..0000000 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/CommandManager.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.xhyrom.lighteco.common.manager.command; - -import dev.xhyrom.lighteco.common.model.chat.CommandSender; -import dev.xhyrom.lighteco.common.model.currency.Currency; -import dev.xhyrom.lighteco.common.model.user.User; -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.math.BigDecimal; - -public interface CommandManager { - void registerCurrencyCommand(@NonNull Currency currency); - void registerCurrencyCommand(@NonNull Currency currency, boolean main); - - boolean canUse(CommandSender sender, Currency currency); - - void onBalance(CommandSender sender, Currency currency); - void onBalance(CommandSender sender, Currency currency, User target); - - void onSet(CommandSender sender, Currency currency, User target, BigDecimal amount); - void onGive(CommandSender sender, Currency currency, User target, BigDecimal amount); - void onTake(CommandSender sender, Currency currency, User target, BigDecimal amount); - void onPay(CommandSender sender, Currency currency, User target, BigDecimal amount); -} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/CurrencyManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/CurrencyManager.java index c2675f9..ba1274e 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/CurrencyManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/CurrencyManager.java @@ -2,6 +2,7 @@ package dev.xhyrom.lighteco.common.manager.currency; import dev.xhyrom.lighteco.common.manager.Manager; import dev.xhyrom.lighteco.common.model.currency.Currency; + import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Collection; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/StandardCurrencyManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/StandardCurrencyManager.java index f15f5d8..80f3058 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/StandardCurrencyManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/manager/currency/StandardCurrencyManager.java @@ -3,11 +3,13 @@ package dev.xhyrom.lighteco.common.manager.currency; import dev.xhyrom.lighteco.common.manager.SingleManager; import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Collection; -public class StandardCurrencyManager extends SingleManager implements CurrencyManager { +public class StandardCurrencyManager extends SingleManager + implements CurrencyManager { private final LightEcoPlugin plugin; public StandardCurrencyManager(LightEcoPlugin plugin) { @@ -32,10 +34,14 @@ public class StandardCurrencyManager extends SingleManager imp @Override public void registerCurrency(@NonNull Currency currency) { if (this.isLoaded(currency.getIdentifier())) - throw new IllegalArgumentException("Currency with identifier " + currency.getIdentifier() + " already registered"); + throw new IllegalArgumentException( + "Currency with identifier " + currency.getIdentifier() + " already registered"); if (this.plugin.getConfig().debug) - this.plugin.getBootstrap().getLogger().info("Registering currency " + currency.getIdentifier()); + this.plugin + .getBootstrap() + .getLogger() + .info("Registering currency " + currency.getIdentifier()); this.plugin.getStorage().registerCurrencySync(currency.getProxy()); this.map.put(currency.getIdentifier(), currency); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/StandardUserManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/StandardUserManager.java index deff464..11610b2 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/StandardUserManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/StandardUserManager.java @@ -3,6 +3,7 @@ package dev.xhyrom.lighteco.common.manager.user; import dev.xhyrom.lighteco.common.manager.ConcurrentManager; import dev.xhyrom.lighteco.common.model.user.User; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import lombok.Getter; import java.util.Arrays; @@ -11,21 +12,26 @@ import java.util.concurrent.CompletableFuture; public class StandardUserManager extends ConcurrentManager implements UserManager { private final LightEcoPlugin plugin; + @Getter private final UserHousekeeper housekeeper; public StandardUserManager(LightEcoPlugin plugin) { this.plugin = plugin; - this.housekeeper = new UserHousekeeper(plugin, this, UserHousekeeper.timeoutSettings( - this.plugin.getConfig().housekeeper.expireAfterWrite, - this.plugin.getConfig().housekeeper.expireAfterWriteUnit - )); + this.housekeeper = new UserHousekeeper( + plugin, + this, + UserHousekeeper.timeoutSettings( + this.plugin.getConfig().housekeeper.expireAfterWrite, + this.plugin.getConfig().housekeeper.expireAfterWriteUnit)); - this.plugin.getBootstrap().getScheduler().asyncRepeating( - this.housekeeper, - this.plugin.getConfig().housekeeper.runInterval, - this.plugin.getConfig().housekeeper.runIntervalUnit - ); + this.plugin + .getBootstrap() + .getScheduler() + .asyncRepeating( + this.housekeeper, + this.plugin.getConfig().housekeeper.runInterval, + this.plugin.getConfig().housekeeper.runIntervalUnit); } @Override @@ -49,15 +55,15 @@ public class StandardUserManager extends ConcurrentManager implement @Override public CompletableFuture saveUser(User user) { - return this.plugin.getStorage().saveUser(user.getProxy()); + return this.plugin.getStorage().saveUser(user.getProxy()); } @Override public CompletableFuture saveUsers(User... users) { - return this.plugin.getStorage().saveUsers( - Arrays.stream(users) + return this.plugin + .getStorage() + .saveUsers(Arrays.stream(users) .map(User::getProxy) - .toArray(dev.xhyrom.lighteco.api.model.user.User[]::new) - ); + .toArray(dev.xhyrom.lighteco.api.model.user.User[]::new)); } -} \ No newline at end of file +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserHousekeeper.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserHousekeeper.java index 3b5c080..806cbc7 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserHousekeeper.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserHousekeeper.java @@ -13,7 +13,8 @@ public class UserHousekeeper implements Runnable { private final ExpiringSet recentlyUsed; - public UserHousekeeper(LightEcoPlugin plugin, UserManager userManager, TimeoutSettings timeoutSettings) { + public UserHousekeeper( + LightEcoPlugin plugin, UserManager userManager, TimeoutSettings timeoutSettings) { this.plugin = plugin; this.userManager = userManager; this.recentlyUsed = new ExpiringSet<>(timeoutSettings.duration, timeoutSettings.unit); @@ -41,8 +42,7 @@ public class UserHousekeeper implements Runnable { } // If the user is dirty (has unsaved changes), don't unload - if (user.isDirty()) - return; + if (user.isDirty()) return; if (this.plugin.getConfig().debug) { this.plugin.getBootstrap().getLogger().info("Unloading data for " + uuid); @@ -64,4 +64,4 @@ public class UserHousekeeper implements Runnable { this.unit = unit; } } -} \ No newline at end of file +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserManager.java index 3d50fcc..f1f4837 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/manager/user/UserManager.java @@ -10,8 +10,10 @@ public interface UserManager extends Manager { UserHousekeeper getHousekeeper(); CompletableFuture saveUser(User user); + CompletableFuture saveUsers(User... users); CompletableFuture loadUser(UUID uniqueId); + CompletableFuture loadUser(UUID uniqueId, String username); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/InternalMessagingService.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/InternalMessagingService.java new file mode 100644 index 0000000..a778455 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/InternalMessagingService.java @@ -0,0 +1,13 @@ +package dev.xhyrom.lighteco.common.messaging; + +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +public interface InternalMessagingService { + LightEcoPlugin getPlugin(); + + void pushUserUpdate(User user, Currency currency); + + void shutdown(); +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/LightEcoMessagingService.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/LightEcoMessagingService.java new file mode 100644 index 0000000..876fee2 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/LightEcoMessagingService.java @@ -0,0 +1,163 @@ +package dev.xhyrom.lighteco.common.messaging; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import dev.xhyrom.lighteco.api.messenger.IncomingMessageConsumer; +import dev.xhyrom.lighteco.api.messenger.Messenger; +import dev.xhyrom.lighteco.api.messenger.MessengerProvider; +import dev.xhyrom.lighteco.api.messenger.message.Message; +import dev.xhyrom.lighteco.api.messenger.message.type.UserUpdateMessage; +import dev.xhyrom.lighteco.common.cache.ExpiringSet; +import dev.xhyrom.lighteco.common.messaging.message.MessageType; +import dev.xhyrom.lighteco.common.messaging.message.UserUpdateMessageImpl; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; +import dev.xhyrom.lighteco.common.util.gson.GsonProvider; + +import lombok.Getter; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class LightEcoMessagingService implements InternalMessagingService, IncomingMessageConsumer { + @Getter + private final LightEcoPlugin plugin; + + private final ExpiringSet receivedMessages; + + private final Messenger messenger; + private final MessengerProvider provider; + + public LightEcoMessagingService(LightEcoPlugin plugin, MessengerProvider provider) { + this.plugin = plugin; + + this.provider = provider; + this.messenger = provider.obtain(this); + this.receivedMessages = new ExpiringSet<>(30, TimeUnit.MINUTES); + } + + private UUID generateMessageId() { + UUID id = UUID.randomUUID(); + + this.receivedMessages.add(id); + return id; + } + + @Override + public void pushUserUpdate(User user, Currency currency) { + this.plugin + .getBootstrap() + .getScheduler() + .async() + .execute(() -> this.messenger.sendOutgoingMessage( + new UserUpdateMessageImpl( + generateMessageId(), + user.getUniqueId(), + currency.getIdentifier(), + user.getBalance(currency)), + currency.getType() + == dev.xhyrom.lighteco.api.model.currency.Currency.Type.GLOBAL)); + } + + public static @NonNull String serialize(MessageType type, UUID id, JsonElement content) { + JsonObject data = new JsonObject(); + + data.add("i", new JsonPrimitive(id.toString())); + data.add("t", new JsonPrimitive(type.name())); + data.add("c", content); + + return GsonProvider.get().toJson(data); + } + + @Override + public void consumeIncomingMessage(@NonNull Message message) { + if (!this.receivedMessages.add(message.getId())) { + return; + } + + this.processIncomingMessage(message); + } + + @Override + public void consumeRawIncomingMessage(@NonNull String message) { + try { + deserializeAndConsumeRawIncomingMessage(message); + } catch (Exception e) { + this.plugin + .getBootstrap() + .getLogger() + .warn("Failed to deserialize incoming message: " + message, e); + } + } + + private void deserializeAndConsumeRawIncomingMessage(@NonNull String message) { + JsonObject parsed = GsonProvider.get().fromJson(message, JsonObject.class); + + JsonElement idElement = parsed.get("i"); + if (idElement == null) { + throw new IllegalStateException("Missing message id: " + message); + } + + UUID id = UUID.fromString(idElement.getAsString()); + + if (!this.receivedMessages.add(id)) { + return; + } + + JsonElement typeElement = parsed.get("t"); + if (typeElement == null) { + throw new IllegalStateException("Missing message type: " + message); + } + + MessageType type = MessageType.valueOf(typeElement.getAsString()); + + @Nullable JsonElement contentElement = parsed.get("c"); + + Message deserialized; + switch (type) { + case USER_UPDATE: + deserialized = UserUpdateMessageImpl.deserialize(id, contentElement); + break; + default: + return; + } + + this.processIncomingMessage(deserialized); + } + + private void processIncomingMessage(Message message) { + if (message instanceof UserUpdateMessage userUpdateMessage) { + this.plugin.getBootstrap().getScheduler().async().execute(() -> { + User user = this.plugin + .getUserManager() + .getIfLoaded(userUpdateMessage.getUserUniqueId()); + if (user == null) { + return; + } + + Currency currency = this.plugin + .getCurrencyManager() + .getIfLoaded(userUpdateMessage.getCurrencyIdentifier()); + if (currency == null) { + return; + } + + user.setBalance(currency, userUpdateMessage.getNewBalance(), false, false); + }); + } else { + throw new IllegalStateException( + "Unknown message type: " + message.getClass().getName()); + } + } + + @Override + public void shutdown() { + this.messenger.close(); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/MessagingFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/MessagingFactory.java new file mode 100644 index 0000000..155d600 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/MessagingFactory.java @@ -0,0 +1,38 @@ +package dev.xhyrom.lighteco.common.messaging; + +import dev.xhyrom.lighteco.api.messenger.MessengerProvider; +import dev.xhyrom.lighteco.common.messaging.type.redis.RedisMessengerProvider; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import java.util.Set; + +public class MessagingFactory { + private final LightEcoPlugin plugin; + + public MessagingFactory(LightEcoPlugin plugin) { + this.plugin = plugin; + } + + protected LightEcoPlugin getPlugin() { + return this.plugin; + } + + public Set getRequiredTypes() { + return Set.of(this.plugin.getConfig().messaging.provider); + } + + public InternalMessagingService get() { + MessagingType type = this.plugin.getConfig().messaging.provider; + MessengerProvider provider = this.createProvider(type); + if (provider == null) return null; + + return new LightEcoMessagingService(this.plugin, provider); + } + + private MessengerProvider createProvider(MessagingType type) { + return switch (type) { + case REDIS -> new RedisMessengerProvider(this.plugin); + default -> null; + }; + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/MessagingType.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/MessagingType.java new file mode 100644 index 0000000..7eb1dd9 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/MessagingType.java @@ -0,0 +1,6 @@ +package dev.xhyrom.lighteco.common.messaging; + +public enum MessagingType { + NONE, + REDIS +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/AbstractMessage.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/AbstractMessage.java new file mode 100644 index 0000000..7fa5059 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/AbstractMessage.java @@ -0,0 +1,21 @@ +package dev.xhyrom.lighteco.common.messaging.message; + +import dev.xhyrom.lighteco.api.messenger.message.Message; +import dev.xhyrom.lighteco.api.messenger.message.OutgoingMessage; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.UUID; + +public abstract class AbstractMessage implements Message, OutgoingMessage { + private final UUID id; + + protected AbstractMessage(UUID id) { + this.id = id; + } + + @Override + public @NonNull UUID getId() { + return this.id; + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/MessageType.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/MessageType.java new file mode 100644 index 0000000..e25af3c --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/MessageType.java @@ -0,0 +1,5 @@ +package dev.xhyrom.lighteco.common.messaging.message; + +public enum MessageType { + USER_UPDATE; +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/UserUpdateMessageImpl.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/UserUpdateMessageImpl.java new file mode 100644 index 0000000..cdadf8d --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/message/UserUpdateMessageImpl.java @@ -0,0 +1,55 @@ +package dev.xhyrom.lighteco.common.messaging.message; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import dev.xhyrom.lighteco.api.messenger.message.type.UserUpdateMessage; +import dev.xhyrom.lighteco.common.messaging.LightEcoMessagingService; + +import lombok.Getter; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.math.BigDecimal; +import java.util.UUID; + +public class UserUpdateMessageImpl extends AbstractMessage implements UserUpdateMessage { + private static final MessageType TYPE = MessageType.USER_UPDATE; + + @Getter + private final UUID userUniqueId; + + @Getter + private final String currencyIdentifier; + + @Getter + private final BigDecimal newBalance; + + public static UserUpdateMessage deserialize(UUID id, @NonNull JsonElement data) { + JsonObject obj = data.getAsJsonObject(); + UUID userUniqueId = UUID.fromString(obj.get("u").getAsString()); + String currencyIdentifier = obj.get("c").getAsString(); + BigDecimal newBalance = obj.get("b").getAsBigDecimal(); + + return new UserUpdateMessageImpl(id, userUniqueId, currencyIdentifier, newBalance); + } + + public UserUpdateMessageImpl( + UUID id, UUID userUniqueId, String currencyIdentifier, BigDecimal newBalance) { + super(id); + this.userUniqueId = userUniqueId; + this.currencyIdentifier = currencyIdentifier; + this.newBalance = newBalance; + } + + @Override + public @NonNull String serialize() { + JsonObject data = new JsonObject(); + data.add("u", new JsonPrimitive(this.userUniqueId.toString())); + data.add("c", new JsonPrimitive(this.currencyIdentifier)); + data.add("b", new JsonPrimitive(this.newBalance)); + + return LightEcoMessagingService.serialize(TYPE, getId(), data); + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/type/redis/RedisMessenger.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/type/redis/RedisMessenger.java new file mode 100644 index 0000000..3c5162d --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/type/redis/RedisMessenger.java @@ -0,0 +1,97 @@ +package dev.xhyrom.lighteco.common.messaging.type.redis; + +import dev.xhyrom.lighteco.api.messenger.IncomingMessageConsumer; +import dev.xhyrom.lighteco.api.messenger.Messenger; +import dev.xhyrom.lighteco.api.messenger.message.OutgoingMessage; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import lombok.Getter; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import redis.clients.jedis.*; + +public class RedisMessenger implements Messenger { + private static final String CHANNEL = "lighteco:{}:messages"; + + @Getter + private final String[] channels; + + private final LightEcoPlugin plugin; + private final IncomingMessageConsumer consumer; + + private UnifiedJedis jedis; + private Subscription sub; + + public RedisMessenger(LightEcoPlugin plugin, IncomingMessageConsumer consumer) { + this.plugin = plugin; + this.consumer = consumer; + + this.channels = new String[] { + CHANNEL.replace("{}:", ""), CHANNEL.replace("{}", this.plugin.getConfig().server) + }; + } + + public void init( + @Nullable String address, @Nullable String username, String password, boolean ssl) { + this.init(new JedisPooled(parseAddress(address), jedisConfig(username, password, ssl))); + } + + private void init(UnifiedJedis jedis) { + this.jedis = jedis; + this.sub = new Subscription(this); + + this.plugin.getBootstrap().getScheduler().async().execute(() -> { + this.jedis.subscribe(this.sub, this.getChannels()); + }); + } + + private static JedisClientConfig jedisConfig( + @Nullable String username, @Nullable String password, boolean ssl) { + return DefaultJedisClientConfig.builder() + .user(username) + .password(password) + .ssl(ssl) + .timeoutMillis(Protocol.DEFAULT_TIMEOUT) + .build(); + } + + private static HostAndPort parseAddress(String address) { + String[] addressSplit = address.split(":"); + String host = addressSplit[0]; + int port = + addressSplit.length > 1 ? Integer.parseInt(addressSplit[1]) : Protocol.DEFAULT_PORT; + + return new HostAndPort(host, port); + } + + @Override + public void sendOutgoingMessage(@NonNull OutgoingMessage message, boolean global) { + this.jedis.publish(global ? getChannels()[0] : getChannels()[1], message.serialize()); + } + + @Override + public void close() { + this.sub.unsubscribe(); + this.jedis.close(); + } + + private static class Subscription extends JedisPubSub { + private final RedisMessenger messenger; + + public Subscription(RedisMessenger messenger) { + this.messenger = messenger; + } + + @Override + public void onMessage(String channel, String message) { + String[] channels = this.messenger.getChannels(); + if (!channel.equals(channels[0]) && !channel.equals(channels[1])) { + return; + } + + this.messenger.consumer.consumeRawIncomingMessage(message); + } + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/messaging/type/redis/RedisMessengerProvider.java b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/type/redis/RedisMessengerProvider.java new file mode 100644 index 0000000..8448456 --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/messaging/type/redis/RedisMessengerProvider.java @@ -0,0 +1,34 @@ +package dev.xhyrom.lighteco.common.messaging.type.redis; + +import dev.xhyrom.lighteco.api.messenger.IncomingMessageConsumer; +import dev.xhyrom.lighteco.api.messenger.Messenger; +import dev.xhyrom.lighteco.api.messenger.MessengerProvider; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public class RedisMessengerProvider implements MessengerProvider { + private final LightEcoPlugin plugin; + + public RedisMessengerProvider(LightEcoPlugin plugin) { + this.plugin = plugin; + } + + @Override + public @NonNull Messenger obtain(@NonNull IncomingMessageConsumer consumer) { + RedisMessenger messenger = new RedisMessenger(this.plugin, consumer); + + String address = this.plugin.getConfig().messaging.data.address; + String username = this.plugin.getConfig().messaging.data.username; + String password = this.plugin.getConfig().messaging.data.password; + + if (password.isEmpty()) password = null; + if (username.isEmpty()) username = null; + + boolean ssl = this.plugin.getConfig().messaging.data.ssl; + + messenger.init(address, username, password, ssl); + + return messenger; + } +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/AbstractCommandSender.java b/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/AbstractCommandSender.java index b3f8cbd..8bec875 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/AbstractCommandSender.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/AbstractCommandSender.java @@ -1,9 +1,9 @@ package dev.xhyrom.lighteco.common.model.chat; public abstract class AbstractCommandSender implements CommandSender { - protected final T delegate; + protected final T delegate; - protected AbstractCommandSender(T delegate) { - this.delegate = delegate; - } + protected AbstractCommandSender(T delegate) { + this.delegate = delegate; + } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/CommandSender.java b/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/CommandSender.java index 9827b2b..4bda806 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/CommandSender.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/model/chat/CommandSender.java @@ -2,11 +2,20 @@ package dev.xhyrom.lighteco.common.model.chat; import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.UUID; public interface CommandSender { String getUsername(); - UUID getUniqueId(); + + @Nullable UUID getUniqueId(); + + boolean eligible(String permission); void sendMessage(Component message); + + default boolean isConsole() { + return getUniqueId() == null; + } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/model/currency/Currency.java b/common/src/main/java/dev/xhyrom/lighteco/common/model/currency/Currency.java index 8946d49..cb978a4 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/model/currency/Currency.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/model/currency/Currency.java @@ -16,6 +16,10 @@ public class Currency { return proxy.getIdentifier(); } + public String[] getIdentifierAliases() { + return proxy.getIdentifierAliases(); + } + public dev.xhyrom.lighteco.api.model.currency.Currency.Type getType() { return proxy.getType(); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java b/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java index bf0744b..6460d03 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java @@ -1,16 +1,24 @@ package dev.xhyrom.lighteco.common.model.user; +import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan; +import dev.xhyrom.lighteco.api.exception.CannotBeNegative; import dev.xhyrom.lighteco.common.api.impl.ApiUser; import dev.xhyrom.lighteco.common.cache.RedisBackedMap; +import dev.xhyrom.lighteco.common.messaging.InternalMessagingService; import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import lombok.Getter; import lombok.Setter; + +import net.kyori.adventure.text.Component; + import org.checkerframework.checker.nullness.qual.NonNull; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.HashMap; +import java.util.Optional; import java.util.UUID; @Getter @@ -26,6 +34,7 @@ public class User { @Getter @Setter private boolean dirty = false; + @Getter @Setter private String username; @@ -46,35 +55,65 @@ public class User { return balances.getOrDefault(currency, currency.getDefaultBalance()); } - public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) { - this.setBalance(currency, balance, false); + public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) + throws CannotBeNegative, CannotBeGreaterThan { + this.setBalance(currency, balance, false, true); } - public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance, boolean force) { + public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance, boolean force) + throws CannotBeNegative, CannotBeGreaterThan { + this.setBalance(currency, balance, force, true); + } + + public void setBalance( + @NonNull Currency currency, @NonNull BigDecimal balance, boolean force, boolean publish) + throws CannotBeNegative, CannotBeGreaterThan { if (balance.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException("Balance cannot be negative"); + throw new CannotBeNegative("Balance cannot be negative"); + } + + if (balance.compareTo(this.plugin.getConfig().maximumBalance) > 0) { + throw new CannotBeGreaterThan( + "Balance cannot be greater than " + this.plugin.getConfig().maximumBalance); } balance = balance.setScale(currency.fractionalDigits(), RoundingMode.DOWN); balances.put(currency, balance); - if (!force) - this.setDirty(true); + if (!force) this.setDirty(true); + + if (publish) { + @NonNull Optional messagingService = this.plugin.getMessagingService(); + messagingService.ifPresent(internalMessagingService -> + internalMessagingService.pushUserUpdate(this, currency)); + } } - public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException { + public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) + throws CannotBeNegative, CannotBeGreaterThan { if (amount.compareTo(BigDecimal.ZERO) < 0) { throw new IllegalArgumentException("Amount cannot be negative"); } + if (amount.compareTo(this.plugin.getConfig().maximumBalance) > 0) { + throw new CannotBeGreaterThan( + "Amount cannot be greater than " + this.plugin.getConfig().maximumBalance); + } + this.setBalance(currency, this.getBalance(currency).add(amount)); } - public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException { + public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) + throws CannotBeNegative, CannotBeGreaterThan { if (amount.compareTo(BigDecimal.ZERO) < 0) { throw new IllegalArgumentException("Amount cannot be negative"); } + if (amount.compareTo(this.plugin.getConfig().maximumBalance) > 0) { + throw new CannotBeGreaterThan( + "Amount cannot be greater than " + this.plugin.getConfig().maximumBalance); + } + if (this.getBalance(currency).compareTo(amount) < 0) { // Withdraw all amount = this.getBalance(currency); @@ -82,4 +121,8 @@ public class User { this.setBalance(currency, this.getBalance(currency).subtract(amount)); } + + public void sendMessage(@NonNull Component message) { + this.plugin.getBootstrap().getPlayerAudience(this.getUniqueId()).sendMessage(message); + } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/package-info.java b/common/src/main/java/dev/xhyrom/lighteco/common/package-info.java index 38a7213..0b5a2b2 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/package-info.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/package-info.java @@ -1,4 +1,4 @@ /** * Common classes used by all platform-specific implementations. */ -package dev.xhyrom.lighteco.common; \ No newline at end of file +package dev.xhyrom.lighteco.common; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/AbstractLightEcoPlugin.java b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/AbstractLightEcoPlugin.java index 4908b9c..7c1fa09 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/AbstractLightEcoPlugin.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/AbstractLightEcoPlugin.java @@ -6,23 +6,33 @@ import dev.xhyrom.lighteco.common.api.LightEcoApi; import dev.xhyrom.lighteco.common.config.Config; import dev.xhyrom.lighteco.common.dependencies.DependencyManager; import dev.xhyrom.lighteco.common.dependencies.DependencyManagerImpl; +import dev.xhyrom.lighteco.common.messaging.InternalMessagingService; +import dev.xhyrom.lighteco.common.messaging.MessagingFactory; import dev.xhyrom.lighteco.common.storage.Storage; import dev.xhyrom.lighteco.common.storage.StorageFactory; import dev.xhyrom.lighteco.common.task.UserSaveTask; + import eu.okaeri.configs.ConfigManager; import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer; + import lombok.Getter; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Optional; import java.util.concurrent.TimeUnit; @Getter public abstract class AbstractLightEcoPlugin implements LightEcoPlugin { private DependencyManager dependencyManager; + @Getter private Config config; @Getter private Storage storage; + + private InternalMessagingService messagingService; private LightEcoApi api; private UserSaveTask userSaveTask; @@ -41,10 +51,14 @@ public abstract class AbstractLightEcoPlugin implements LightEcoPlugin { public final void enable() { // setup storage - StorageFactory factory = new StorageFactory(this); - this.dependencyManager.loadStorageDependencies(factory.getRequiredTypes()); + StorageFactory storageFactory = new StorageFactory(this); + this.dependencyManager.loadStorageDependencies(storageFactory.getRequiredTypes()); - this.storage = factory.get(); + MessagingFactory messagingFactory = this.getMessagingFactory(); + this.dependencyManager.loadMessagingDependencies(messagingFactory.getRequiredTypes()); + + this.storage = storageFactory.get(); + this.messagingService = messagingFactory.get(); // register listeners this.registerListeners(); @@ -52,6 +66,9 @@ public abstract class AbstractLightEcoPlugin implements LightEcoPlugin { // setup managers this.setupManagers(); + // register built-in commands + this.getCommandManager().register(); + // register platform hooks this.registerPlatformHooks(); @@ -61,7 +78,9 @@ public abstract class AbstractLightEcoPlugin implements LightEcoPlugin { this.registerApiOnPlatform(this.api); this.userSaveTask = new UserSaveTask(this); - this.getBootstrap().getScheduler().asyncRepeating(userSaveTask, this.config.saveInterval, TimeUnit.SECONDS); + this.getBootstrap() + .getScheduler() + .asyncRepeating(userSaveTask, this.config.saveInterval, TimeUnit.SECONDS); } public final void disable() { @@ -74,6 +93,8 @@ public abstract class AbstractLightEcoPlugin implements LightEcoPlugin { // shutdown storage this.storage.shutdown(); + if (this.messagingService != null) this.messagingService.shutdown(); + // close isolated class loaders this.dependencyManager.close(); } @@ -81,8 +102,17 @@ public abstract class AbstractLightEcoPlugin implements LightEcoPlugin { protected abstract void registerListeners(); protected abstract void setupManagers(); + + protected abstract MessagingFactory getMessagingFactory(); + protected abstract void registerApiOnPlatform(LightEco api); protected abstract void registerPlatformHooks(); + protected abstract void removePlatformHooks(); + + @Override + public @NonNull Optional getMessagingService() { + return Optional.ofNullable(this.messagingService); + } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/LightEcoPlugin.java b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/LightEcoPlugin.java index fe96969..ee2f0c6 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/LightEcoPlugin.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/LightEcoPlugin.java @@ -2,27 +2,37 @@ package dev.xhyrom.lighteco.common.plugin; import dev.xhyrom.lighteco.api.manager.ContextManager; import dev.xhyrom.lighteco.api.platform.Platform; +import dev.xhyrom.lighteco.common.command.CommandManager; import dev.xhyrom.lighteco.common.config.Config; import dev.xhyrom.lighteco.common.dependencies.DependencyManager; -import dev.xhyrom.lighteco.common.manager.command.CommandManager; import dev.xhyrom.lighteco.common.manager.currency.CurrencyManager; import dev.xhyrom.lighteco.common.manager.user.UserManager; +import dev.xhyrom.lighteco.common.messaging.InternalMessagingService; import dev.xhyrom.lighteco.common.plugin.bootstrap.LightEcoBootstrap; import dev.xhyrom.lighteco.common.storage.Storage; + import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.Optional; + public interface LightEcoPlugin { Platform.@NonNull Type getPlatformType(); @NonNull LightEcoBootstrap getBootstrap(); @NonNull Config getConfig(); + @NonNull UserManager getUserManager(); + @NonNull CurrencyManager getCurrencyManager(); + @NonNull CommandManager getCommandManager(); + @NonNull ContextManager getContextManager(); @NonNull DependencyManager getDependencyManager(); + @NonNull Optional getMessagingService(); + @NonNull Storage getStorage(); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LightEcoBootstrap.java b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LightEcoBootstrap.java index ac16413..4bb69ed 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LightEcoBootstrap.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LightEcoBootstrap.java @@ -3,17 +3,32 @@ package dev.xhyrom.lighteco.common.plugin.bootstrap; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter; +import net.kyori.adventure.audience.Audience; + import java.io.InputStream; import java.nio.file.Path; import java.util.List; +import java.util.Optional; import java.util.UUID; public interface LightEcoBootstrap { Object getLoader(); + PluginLogger getLogger(); + SchedulerAdapter getScheduler(); + Path getDataDirectory(); + + String getVersion(); + + Optional lookupUniqueId(String username); + boolean isPlayerOnline(UUID uniqueId); + List getOnlinePlayers(); + InputStream getResourceStream(String filename); + + Audience getPlayerAudience(UUID uniqueId); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LoaderBootstrap.java b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LoaderBootstrap.java index b2c7858..a05e4d3 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LoaderBootstrap.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/bootstrap/LoaderBootstrap.java @@ -2,6 +2,8 @@ package dev.xhyrom.lighteco.common.plugin.bootstrap; public interface LoaderBootstrap { void onLoad(); + void onEnable(); + void onDisable(); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/logger/PluginLogger.java b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/logger/PluginLogger.java index ca1ab93..83f2f84 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/plugin/logger/PluginLogger.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/plugin/logger/PluginLogger.java @@ -2,17 +2,26 @@ package dev.xhyrom.lighteco.common.plugin.logger; public interface PluginLogger { void info(String message); - void info(String message, Object ...args); + + void info(String message, Object... args); + + void debug(String message); + + void debug(String message, Object... args); void warn(String message); - void warn(String message, Object ...args); + + void warn(String message, Object... args); void warn(String message, Throwable throwable); - void warn(String message, Throwable throwable, Object ...args); + + void warn(String message, Throwable throwable, Object... args); void error(String message); - void error(String message, Object ...args); + + void error(String message, Object... args); void error(String message, Throwable throwable); - void error(String message, Throwable throwable, Object ...args); + + void error(String message, Throwable throwable, Object... args); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/Storage.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/Storage.java index 8faae9a..f397c9a 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/Storage.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/Storage.java @@ -75,7 +75,8 @@ public class Storage { } return future(() -> this.provider.loadUser(uniqueId, username)) - .thenApply(apiUser -> this.plugin.getUserManager().getIfLoaded(apiUser.getUniqueId())); + .thenApply( + apiUser -> this.plugin.getUserManager().getIfLoaded(apiUser.getUniqueId())); } public CompletableFuture saveUser(dev.xhyrom.lighteco.api.model.user.User user) { diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java index fce72c5..e2d51d0 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java @@ -1,6 +1,5 @@ package dev.xhyrom.lighteco.common.storage; -import com.google.common.collect.ImmutableSet; import dev.xhyrom.lighteco.api.storage.StorageProvider; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.storage.provider.memory.MemoryStorageProvider; @@ -21,7 +20,7 @@ public class StorageFactory { } public Set getRequiredTypes() { - return ImmutableSet.of(this.plugin.getConfig().storage.provider); + return Set.of(this.plugin.getConfig().storage.provider); } public Storage get() { @@ -38,25 +37,27 @@ public class StorageFactory { case MEMORY -> new MemoryStorageProvider(this.plugin); case H2 -> new SqlStorageProvider( this.plugin, - new H2ConnectionFactory(this.plugin.getBootstrap().getDataDirectory().resolve("lighteco-h2").toAbsolutePath()) - ); + new H2ConnectionFactory(this.plugin + .getBootstrap() + .getDataDirectory() + .resolve("lighteco-h2") + .toAbsolutePath())); case SQLITE -> new SqlStorageProvider( this.plugin, - new SqliteConnectionFactory(this.plugin.getBootstrap().getDataDirectory().resolve("lighteco-sqlite.db")) - ); + new SqliteConnectionFactory(this.plugin + .getBootstrap() + .getDataDirectory() + .resolve("lighteco-sqlite.db"))); case MYSQL -> new SqlStorageProvider( - this.plugin, - new MySQLConnectionFactory(this.plugin.getConfig().storage.data) - ); + this.plugin, new MySQLConnectionFactory(this.plugin.getConfig().storage.data)); case MARIADB -> new SqlStorageProvider( this.plugin, - new MariaDBConnectionFactory(this.plugin.getConfig().storage.data) - ); + new MariaDBConnectionFactory(this.plugin.getConfig().storage.data)); case POSTGRESQL -> new SqlStorageProvider( this.plugin, - new PostgreSQLConnectionFactory(this.plugin.getConfig().storage.data) - ); - default -> throw new IllegalArgumentException("Unknown storage provider: " + type.name()); + new PostgreSQLConnectionFactory(this.plugin.getConfig().storage.data)); + default -> throw new IllegalArgumentException( + "Unknown storage provider: " + type.name()); }; } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/memory/MemoryStorageProvider.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/memory/MemoryStorageProvider.java index bdea3e5..e6d9141 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/memory/MemoryStorageProvider.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/memory/MemoryStorageProvider.java @@ -3,9 +3,9 @@ package dev.xhyrom.lighteco.common.storage.provider.memory; import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.storage.StorageProvider; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.UUID; @@ -14,6 +14,7 @@ public class MemoryStorageProvider implements StorageProvider { private HashMap userDatabase; private final LightEcoPlugin plugin; + public MemoryStorageProvider(LightEcoPlugin plugin) { this.plugin = plugin; } @@ -43,16 +44,16 @@ public class MemoryStorageProvider implements StorageProvider { } @Override - public void saveUsers(@NotNull @NonNull User... users) { + public void saveUsers(@NonNull User... users) { for (User user : users) { this.userDatabase.put(user.getUniqueId(), user); } } private User createUser(UUID uniqueId, String username, User data) { - dev.xhyrom.lighteco.common.model.user.User user = this.plugin.getUserManager().getOrMake(uniqueId); - if (username != null) - user.setUsername(username); + dev.xhyrom.lighteco.common.model.user.User user = + this.plugin.getUserManager().getOrMake(uniqueId); + if (username != null) user.setUsername(username); return user.getProxy(); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/package-info.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/package-info.java index bf9dc2e..151237b 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/package-info.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/package-info.java @@ -4,4 +4,4 @@ // Copyright (c) contributors // Under MIT License -package dev.xhyrom.lighteco.common.storage.provider; \ No newline at end of file +package dev.xhyrom.lighteco.common.storage.provider; diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java index 1577d8c..f2b9075 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java @@ -7,26 +7,22 @@ public enum SqlStatements { "INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;", "INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON DUPLICATE KEY UPDATE balance=?2;", "INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?, ?) ON DUPLICATE KEY UPDATE balance=?;", - "INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;" - ), + "INSERT INTO '{prefix}_local_{context}_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;"), SAVE_USER_GLOBAL_CURRENCY( "INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;", "INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON DUPLICATE KEY UPDATE balance=?2;", "INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?, ?) ON DUPLICATE KEY UPDATE balance=?;", - "INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;" - ), + "INSERT INTO '{prefix}_global_{currency}_users' (uuid, balance) VALUES (?1, ?2) ON CONFLICT (uuid) DO UPDATE SET balance=?2;"), LOAD_LOCAL_CURRENCY_USER( "SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?1", "SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?1", "SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?", - "SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?1" - ), + "SELECT {identifier} AS name, balance FROM '{prefix}_local_{context}_{currency}_users' WHERE uuid = ?1"), LOAD_GLOBAL_CURRENCY_USER( "SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?1", "SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?1", "SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?", - "SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?1" - ); + "SELECT {identifier} AS name, balance FROM '{prefix}_global_{currency}_users' WHERE uuid = ?1"); public final String sqlite; public final String mysql; @@ -54,11 +50,13 @@ public enum SqlStatements { case POSTGRESQL -> { return this.postgresql; } - default -> throw new IllegalArgumentException("Unknown implementation: " + implementationName); + default -> throw new IllegalArgumentException( + "Unknown implementation: " + implementationName); } } public static boolean mustDuplicateParameters(StorageType implementationName) { - return implementationName == StorageType.MARIADB || implementationName == StorageType.POSTGRESQL; + return implementationName == StorageType.MARIADB + || implementationName == StorageType.POSTGRESQL; } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java index 94bbb89..d7a99a6 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java @@ -6,9 +6,9 @@ import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.storage.StorageType; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.ConnectionFactory; + import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.jetbrains.annotations.NotNull; import java.math.BigDecimal; import java.sql.Connection; @@ -26,15 +26,19 @@ public class SqlStorageProvider implements StorageProvider { private static String LOAD_LOCAL_CURRENCY_USER; private static String LOAD_GLOBAL_CRRENCY_USER; - private static final String DELETE_LOCAL_USER = "DELETE FROM {prefix}_local_{context}_{currency}_users WHERE uuid = ?;"; - private static final String DELETE_GLOBAL_USER = "DELETE FROM {prefix}_global_{currency}_users WHERE uuid = ?;"; - private static final String CREATE_TABLE = """ + private static final String DELETE_LOCAL_USER = + "DELETE FROM {prefix}_local_{context}_{currency}_users WHERE uuid = ?;"; + private static final String DELETE_GLOBAL_USER = + "DELETE FROM {prefix}_global_{currency}_users WHERE uuid = ?;"; + private static final String CREATE_TABLE = + """ CREATE TABLE IF NOT EXISTS '{prefix}_{table}' ( 'uuid' VARCHAR(36) NOT NULL, - 'balance' DECIMAL(10, 2) NOT NULL, + 'balance' DECIMAL(20, 2) NOT NULL, PRIMARY KEY (`uuid`) ); - """.trim(); + """ + .trim(); private final LightEcoPlugin plugin; private final ConnectionFactory connectionFactory; @@ -43,11 +47,9 @@ public class SqlStorageProvider implements StorageProvider { public SqlStorageProvider(LightEcoPlugin plugin, ConnectionFactory connectionFactory) { this.plugin = plugin; this.connectionFactory = connectionFactory; - this.statementProcessor = connectionFactory.getStatementProcessor().compose( - s -> s - .replace("{prefix}", plugin.getConfig().storage.tablePrefix) - .replace("{context}", plugin.getConfig().server) - ); + this.statementProcessor = connectionFactory.getStatementProcessor().compose(s -> s.replace( + "{prefix}", plugin.getConfig().storage.tablePrefix) + .replace("{context}", plugin.getConfig().server)); final StorageType implementationName = this.connectionFactory.getImplementationName(); SAVE_USER_LOCAL_CURRENCY = SqlStatements.SAVE_USER_LOCAL_CURRENCY.get(implementationName); @@ -67,7 +69,8 @@ public class SqlStorageProvider implements StorageProvider { } @Override - public void registerCurrency(dev.xhyrom.lighteco.api.model.currency.@NonNull Currency currency) throws Exception { + public void registerCurrency(dev.xhyrom.lighteco.api.model.currency.@NonNull Currency currency) + throws Exception { StringBuilder tableName = new StringBuilder(); if (currency.getType() == dev.xhyrom.lighteco.api.model.currency.Currency.Type.LOCAL) { @@ -81,41 +84,39 @@ public class SqlStorageProvider implements StorageProvider { tableName.append("_users"); try (Connection c = this.connectionFactory.getConnection()) { - try (PreparedStatement ps = c.prepareStatement( - this.statementProcessor.apply(CREATE_TABLE - .replace("{table}", tableName.toString()) - ) - )) { + try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply( + CREATE_TABLE.replace("{table}", tableName.toString())))) { ps.execute(); } } } @Override - public @NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception { + public @NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) + throws Exception { String uniqueIdString = uniqueId.toString(); - dev.xhyrom.lighteco.common.model.user.User user = this.plugin.getUserManager().getOrMake(uniqueId); - if (username != null) - user.setUsername(username); + dev.xhyrom.lighteco.common.model.user.User user = + this.plugin.getUserManager().getOrMake(uniqueId); + if (username != null) user.setUsername(username); StringBuilder query = new StringBuilder(); - List currencies = this.plugin.getCurrencyManager().getRegisteredCurrencies().stream().toList(); + List currencies = + this.plugin.getCurrencyManager().getRegisteredCurrencies().stream() + .toList(); int size = this.plugin.getCurrencyManager().getRegisteredCurrencies().size(); for (int i = 0; i < size; i++) { Currency currency = currencies.get(i); switch (currency.getType()) { - case GLOBAL -> query.append( - this.statementProcessor.apply(LOAD_GLOBAL_CRRENCY_USER - .replace("{currency}", currency.getIdentifier()) - ).replace("{identifier}", "'"+currency.getIdentifier()+"'") - ); - case LOCAL -> query.append( - this.statementProcessor.apply(LOAD_LOCAL_CURRENCY_USER - .replace("{currency}", currency.getIdentifier()) - ).replace("{identifier}", "'"+currency.getIdentifier()+"'") - ); + case GLOBAL -> query.append(this.statementProcessor + .apply(LOAD_GLOBAL_CRRENCY_USER.replace( + "{currency}", currency.getIdentifier())) + .replace("{identifier}", "'" + currency.getIdentifier() + "'")); + case LOCAL -> query.append(this.statementProcessor + .apply(LOAD_LOCAL_CURRENCY_USER.replace( + "{currency}", currency.getIdentifier())) + .replace("{identifier}", "'" + currency.getIdentifier() + "'")); } if (i != size - 1) { @@ -125,7 +126,8 @@ public class SqlStorageProvider implements StorageProvider { try (Connection c = this.connectionFactory.getConnection()) { try (PreparedStatement ps = c.prepareStatement(query.toString())) { - if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName())) { + if (SqlStatements.mustDuplicateParameters( + this.connectionFactory.getImplementationName())) { for (int i = 0; i < size; i++) { ps.setString(i + 1, uniqueIdString); } @@ -163,7 +165,7 @@ public class SqlStorageProvider implements StorageProvider { } @Override - public void saveUsers(@NotNull @NonNull User... users) throws Exception { + public void saveUsers(@NonNull User... users) throws Exception { // use transaction try (Connection c = this.connectionFactory.getConnection()) { try { @@ -187,9 +189,9 @@ public class SqlStorageProvider implements StorageProvider { saveBalances(c, user, uniqueIdString, true); } - private void saveBalances(Connection c, User user, String uniqueIdString, boolean transactions) throws SQLException { - if (transactions) - c.setAutoCommit(false); + private void saveBalances(Connection c, User user, String uniqueIdString, boolean transactions) + throws SQLException { + if (transactions) c.setAutoCommit(false); for (Currency currency : this.plugin.getCurrencyManager().getRegisteredCurrencies()) { BigDecimal balance = user.getBalance(currency.getProxy()); @@ -197,16 +199,18 @@ public class SqlStorageProvider implements StorageProvider { if (balance.compareTo(BigDecimal.ZERO) == 0) { switch (currency.getType()) { case GLOBAL -> { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(DELETE_GLOBAL_USER - .replace("{currency}", currency.getIdentifier())))) { + try (PreparedStatement ps = c.prepareStatement( + this.statementProcessor.apply(DELETE_GLOBAL_USER.replace( + "{currency}", currency.getIdentifier())))) { ps.setString(1, uniqueIdString); ps.execute(); } } case LOCAL -> { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(DELETE_LOCAL_USER - .replace("{currency}", currency.getIdentifier())))) { + try (PreparedStatement ps = c.prepareStatement( + this.statementProcessor.apply(DELETE_LOCAL_USER.replace( + "{currency}", currency.getIdentifier())))) { ps.setString(1, uniqueIdString); ps.execute(); @@ -219,22 +223,26 @@ public class SqlStorageProvider implements StorageProvider { switch (currency.getType()) { case GLOBAL -> { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(SAVE_USER_GLOBAL_CURRENCY - .replace("{currency}", currency.getIdentifier())))) { + try (PreparedStatement ps = c.prepareStatement( + this.statementProcessor.apply(SAVE_USER_GLOBAL_CURRENCY.replace( + "{currency}", currency.getIdentifier())))) { ps.setString(1, uniqueIdString); ps.setBigDecimal(2, balance); - if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName())) + if (SqlStatements.mustDuplicateParameters( + this.connectionFactory.getImplementationName())) ps.setBigDecimal(3, balance); ps.execute(); } } case LOCAL -> { - try (PreparedStatement psLocal = c.prepareStatement(this.statementProcessor.apply(SAVE_USER_LOCAL_CURRENCY - .replace("{currency}", currency.getIdentifier())))) { + try (PreparedStatement psLocal = c.prepareStatement( + this.statementProcessor.apply(SAVE_USER_LOCAL_CURRENCY.replace( + "{currency}", currency.getIdentifier())))) { psLocal.setString(1, uniqueIdString); psLocal.setBigDecimal(2, balance); - if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName())) + if (SqlStatements.mustDuplicateParameters( + this.connectionFactory.getImplementationName())) psLocal.setBigDecimal(3, balance); psLocal.execute(); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/ConnectionFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/ConnectionFactory.java index c44ebdc..cb09105 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/ConnectionFactory.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/ConnectionFactory.java @@ -10,6 +10,7 @@ public interface ConnectionFactory { StorageType getImplementationName(); void init(LightEcoPlugin plugin); + void shutdown() throws Exception; Function getStatementProcessor(); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/H2ConnectionFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/H2ConnectionFactory.java index 46b99b1..34739c3 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/H2ConnectionFactory.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/H2ConnectionFactory.java @@ -26,11 +26,13 @@ public class H2ConnectionFactory extends FileConnectionFactory { @Override public void init(LightEcoPlugin plugin) { - ClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER)); + ClassLoader classLoader = plugin.getDependencyManager() + .obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER)); try { Class connectionClass = classLoader.loadClass("org.h2.jdbc.JdbcConnection"); - this.connectionConstructor = connectionClass.getConstructor(String.class, Properties.class, String.class, Object.class, boolean.class); + this.connectionConstructor = connectionClass.getConstructor( + String.class, Properties.class, String.class, Object.class, boolean.class); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -42,8 +44,9 @@ public class H2ConnectionFactory extends FileConnectionFactory { return (Connection) this.connectionConstructor.newInstance( "jdbc:h2:" + file.toString() + ";MODE=MySQL;DATABASE_TO_LOWER=TRUE", new Properties(), - null, null, false - ); + null, + null, + false); } catch (Exception e) { if (e.getCause() instanceof SQLException) { throw (SQLException) e.getCause(); @@ -55,8 +58,7 @@ public class H2ConnectionFactory extends FileConnectionFactory { @Override public Function getStatementProcessor() { - return s -> s - .replace('\'', '`') + return s -> s.replace('\'', '`') .replace("LIKE", "ILIKE") .replace("value", "`value`") .replace("``value``", "`value`"); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/SqliteConnectionFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/SqliteConnectionFactory.java index 10fa8ba..3aeb891 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/SqliteConnectionFactory.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/file/SqliteConnectionFactory.java @@ -26,11 +26,13 @@ public class SqliteConnectionFactory extends FileConnectionFactory { @Override public void init(LightEcoPlugin plugin) { - ClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.SQLITE_DRIVER)); + ClassLoader classLoader = plugin.getDependencyManager() + .obtainClassLoaderWith(EnumSet.of(Dependency.SQLITE_DRIVER)); try { Class connectionClass = classLoader.loadClass("org.sqlite.jdbc4.JDBC4Connection"); - this.connectionConstructor = connectionClass.getConstructor(String.class, String.class, Properties.class); + this.connectionConstructor = + connectionClass.getConstructor(String.class, String.class, Properties.class); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -40,10 +42,7 @@ public class SqliteConnectionFactory extends FileConnectionFactory { protected Connection createConnection(Path file) throws SQLException { try { return (Connection) this.connectionConstructor.newInstance( - "jdbc:sqlite:" + file, - file.toString(), - new Properties() - ); + "jdbc:sqlite:" + file, file.toString(), new Properties()); } catch (Exception e) { if (e.getCause() instanceof SQLException) { throw (SQLException) e.getCause(); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/DriverBasedHikariConnectionFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/DriverBasedHikariConnectionFactory.java index 45bb553..319cb09 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/DriverBasedHikariConnectionFactory.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/DriverBasedHikariConnectionFactory.java @@ -1,6 +1,7 @@ package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari; import com.zaxxer.hikari.HikariConfig; + import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig; import java.sql.Driver; @@ -18,9 +19,16 @@ public abstract class DriverBasedHikariConnectionFactory extends HikariConnectio protected abstract String driverJdbcIdentifier(); @Override - protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) { + protected void configureDatabase( + HikariConfig config, + String address, + String port, + String databaseName, + String username, + String password) { config.setDriverClassName(driverClassName()); - config.setJdbcUrl(String.format("jdbc:%s://%s:%s/%s", driverJdbcIdentifier(), address, port, databaseName)); + config.setJdbcUrl(String.format( + "jdbc:%s://%s:%s/%s", driverJdbcIdentifier(), address, port, databaseName)); config.setUsername(username); config.setPassword(password); } @@ -39,7 +47,8 @@ public abstract class DriverBasedHikariConnectionFactory extends HikariConnectio if (driver.getClass().getName().equals(driverClassName)) { try { DriverManager.deregisterDriver(driver); - } catch (SQLException ignored) {} + } catch (SQLException ignored) { + } } } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/HikariConnectionFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/HikariConnectionFactory.java index 303b9cc..7d4c61e 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/HikariConnectionFactory.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/HikariConnectionFactory.java @@ -2,6 +2,7 @@ package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; + import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.ConnectionFactory; @@ -23,7 +24,13 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { protected abstract String defaultPort(); - protected abstract void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password); + protected abstract void configureDatabase( + HikariConfig config, + String address, + String port, + String databaseName, + String username, + String password); protected void overrideProperties(Map properties) { // https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery @@ -39,9 +46,7 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { /** * Called after the Hikari pool has been initialised */ - protected void postInitialize() { - - } + protected void postInitialize() {} @Override public void init(LightEcoPlugin plugin) { @@ -56,7 +61,13 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { String port = addressSplit.length > 1 ? addressSplit[1] : defaultPort(); // allow the implementation to configure the HikariConfig appropriately with these values - configureDatabase(config, address, port, this.configuration.database, this.configuration.username, this.configuration.password); + configureDatabase( + config, + address, + port, + this.configuration.database, + this.configuration.username, + this.configuration.password); Map properties = new HashMap<>(); @@ -91,7 +102,8 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { Connection connection = this.hikari.getConnection(); if (connection == null) { - throw new SQLException("Unable to get a connection from the pool. (getConnection returned null)"); + throw new SQLException( + "Unable to get a connection from the pool. (getConnection returned null)"); } return connection; @@ -101,4 +113,4 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { public Function getStatementProcessor() { return s -> s.replace('\'', '`'); } -} \ No newline at end of file +} diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/task/UserSaveTask.java b/common/src/main/java/dev/xhyrom/lighteco/common/task/UserSaveTask.java index ad99adc..c93406c 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/task/UserSaveTask.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/task/UserSaveTask.java @@ -30,11 +30,11 @@ public class UserSaveTask implements Runnable { user.setDirty(false); } - this.plugin.getStorage().saveUsersSync( - Arrays.stream(users) + this.plugin + .getStorage() + .saveUsersSync(Arrays.stream(users) .map(User::getProxy) - .toArray(dev.xhyrom.lighteco.api.model.user.User[]::new) - ); + .toArray(dev.xhyrom.lighteco.api.model.user.User[]::new)); } catch (RuntimeException e) { this.plugin.getBootstrap().getLogger().error("Failed to save users", e); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/util/ThrowableRunnable.java b/common/src/main/java/dev/xhyrom/lighteco/common/util/ThrowableRunnable.java index fcf57ba..3e70ca5 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/util/ThrowableRunnable.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/util/ThrowableRunnable.java @@ -4,4 +4,3 @@ package dev.xhyrom.lighteco.common.util; public interface ThrowableRunnable { void run() throws Exception; } - diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/util/URLClassLoaderAccess.java b/common/src/main/java/dev/xhyrom/lighteco/common/util/URLClassLoaderAccess.java index 0af4715..b17238d 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/util/URLClassLoaderAccess.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/util/URLClassLoaderAccess.java @@ -7,6 +7,7 @@ package dev.xhyrom.lighteco.common.util; import dev.xhyrom.lighteco.common.util.exception.UnableToInjectException; + import org.checkerframework.checker.nullness.qual.NonNull; import java.lang.reflect.Field; @@ -22,9 +23,10 @@ public abstract class URLClassLoaderAccess { } else if (Unsafe.isSupported()) { return new Unsafe(classLoader); } else { - throw new UnableToInjectException("LightEco is unable to inject dependencies into the plugin class loader.\n" + - "To fix this, please add '--add-opens java.base/java.lang=ALL-UNNAMED' to your JVM arguments." + - "If it still doesn't work, please report this on https://github.com/xHyroM/lighteco/issues"); + throw new UnableToInjectException( + "LightEco is unable to inject dependencies into the plugin class loader.\n" + + "To fix this, please add '--add-opens java.base/java.lang=ALL-UNNAMED' to your JVM arguments." + + "If it still doesn't work, please report this on https://github.com/xHyroM/lighteco/issues"); } } @@ -109,7 +111,9 @@ public abstract class URLClassLoaderAccess { this.pathURLs = pathURLs; } - private static Object fetchField(final Class clazz, final Object object, final String name) throws NoSuchFieldException { + private static Object fetchField( + final Class clazz, final Object object, final String name) + throws NoSuchFieldException { Field field = clazz.getDeclaredField(name); long offset = UNSAFE.objectFieldOffset(field); return UNSAFE.getObject(object, offset); @@ -121,7 +125,7 @@ public abstract class URLClassLoaderAccess { throw new NullPointerException("unopenedURLs or pathURLs"); } - synchronized (this.unopenedURLs) { + synchronized (this.unopenedURLs) { this.unopenedURLs.add(url); this.pathURLs.add(url); } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/util/gson/GsonProvider.java b/common/src/main/java/dev/xhyrom/lighteco/common/util/gson/GsonProvider.java new file mode 100644 index 0000000..be397dd --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/util/gson/GsonProvider.java @@ -0,0 +1,12 @@ +package dev.xhyrom.lighteco.common.util.gson; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public final class GsonProvider { + private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); + + public static Gson get() { + return GSON; + } +} diff --git a/currency-money/README.md b/currency-money/README.md index e788a02..0ea6d3b 100644 --- a/currency-money/README.md +++ b/currency-money/README.md @@ -15,8 +15,8 @@ - **Vault support** - Money supports Vault, allowing you to use other economy plugins with Money. - **Configurable** - Money is configurable, allowing you to change the currency's name, symbol, and more. - **Lightweight** - Money is lightweight, and is designed to be as efficient as possible. -- **Open-source** - Money is open-source, and is available on [GitHub](https://github.com/xHyroM/tree/main/currency-money) +- **Open-source** - Money is open-source, and is available on [GitHub](https://github.com/xHyroM/lighteco/tree/main/currency-money) ## License -Money is licensed under the [Apache-2.0 License](./LICENSE). \ No newline at end of file +Money is licensed under the [Apache-2.0 License](./LICENSE). diff --git a/currency-money/build.gradle.kts b/currency-money/build.gradle.kts index e63ef0b..7c721b7 100644 --- a/currency-money/build.gradle.kts +++ b/currency-money/build.gradle.kts @@ -2,6 +2,8 @@ plugins { id("lighteco.addon-logic") } +description = "Addon that adds main currency to LightEco that uses Vault to hook into other economy plugins." + repositories { maven("https://repo.papermc.io/repository/maven-public/") maven("https://jitpack.io") diff --git a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/AbstractPlugin.java b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/AbstractPlugin.java index ad483e1..c29dbb7 100644 --- a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/AbstractPlugin.java +++ b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/AbstractPlugin.java @@ -1,8 +1,10 @@ package dev.xhyrom.lighteco.currency.money.common; import dev.xhyrom.lighteco.currency.money.common.config.Config; + import eu.okaeri.configs.ConfigManager; import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer; + import lombok.Getter; import java.nio.file.Path; diff --git a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/config/Config.java b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/config/Config.java index 0134dc8..36e1d65 100644 --- a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/config/Config.java +++ b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/config/Config.java @@ -5,9 +5,9 @@ import eu.okaeri.configs.annotation.Comment; public class Config extends OkaeriConfig { @Comment("Currency name") - @Comment("In singular form") public String currencyNameSingular = "Dollar"; + @Comment("In plural form") public String currencyNamePlural = "Dollars"; diff --git a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/currency/MoneyCurrency.java b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/currency/MoneyCurrency.java index 5dbcef8..4a1ca80 100644 --- a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/currency/MoneyCurrency.java +++ b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/common/currency/MoneyCurrency.java @@ -17,6 +17,11 @@ public class MoneyCurrency implements Currency { return "money"; } + @Override + public String[] getIdentifierAliases() { + return new String[] {"eco"}; + } + @Override public Type getType() { return Type.LOCAL; @@ -34,6 +39,6 @@ public class MoneyCurrency implements Currency { @Override public int fractionalDigits() { - return this.plugin.getConfig().fractionalDigits; + return this.plugin.getConfig().fractionalDigits; } } diff --git a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/BukkitMCLoader.java b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/PaperMCLoader.java similarity index 88% rename from currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/BukkitMCLoader.java rename to currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/PaperMCLoader.java index f19dc8b..b2533d7 100644 --- a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/BukkitMCLoader.java +++ b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/PaperMCLoader.java @@ -1,23 +1,26 @@ -package dev.xhyrom.lighteco.currency.money.bukkit; +package dev.xhyrom.lighteco.currency.money.paper; import dev.xhyrom.lighteco.api.LightEco; import dev.xhyrom.lighteco.api.LightEcoProvider; import dev.xhyrom.lighteco.api.manager.CommandManager; import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.model.currency.Currency; -import dev.xhyrom.lighteco.currency.money.bukkit.hooks.vault.VaultFactory; import dev.xhyrom.lighteco.currency.money.common.AbstractPlugin; import dev.xhyrom.lighteco.currency.money.common.Plugin; import dev.xhyrom.lighteco.currency.money.common.currency.MoneyCurrency; +import dev.xhyrom.lighteco.currency.money.paper.hooks.vault.VaultFactory; + import lombok.Getter; + import org.bukkit.plugin.java.JavaPlugin; -public class BukkitMCLoader extends JavaPlugin { +public class PaperMCLoader extends JavaPlugin { private VaultFactory vaultFactory; + @Getter private final Plugin plugin; - public BukkitMCLoader() { + public PaperMCLoader() { this.plugin = new AbstractPlugin(this.getDataFolder().toPath()); } @@ -50,4 +53,3 @@ public class BukkitMCLoader extends JavaPlugin { this.vaultFactory.unhook(); } } - diff --git a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/Vault.java b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/hooks/vault/Vault.java similarity index 92% rename from currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/Vault.java rename to currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/hooks/vault/Vault.java index 1c19bd0..622c43b 100644 --- a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/Vault.java +++ b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/hooks/vault/Vault.java @@ -1,12 +1,16 @@ -package dev.xhyrom.lighteco.currency.money.bukkit.hooks.vault; +package dev.xhyrom.lighteco.currency.money.paper.hooks.vault; import dev.xhyrom.lighteco.api.LightEco; import dev.xhyrom.lighteco.api.LightEcoProvider; +import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan; +import dev.xhyrom.lighteco.api.exception.CannotBeNegative; import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.currency.money.common.Plugin; + import net.milkbowl.vault.economy.AbstractEconomy; import net.milkbowl.vault.economy.EconomyResponse; + import org.bukkit.Bukkit; import java.math.BigDecimal; @@ -50,7 +54,7 @@ public class Vault extends AbstractEconomy { NumberFormat format = NumberFormat.getInstance(); format.setCurrency(java.util.Currency.getInstance(this.plugin.getConfig().currencyCode)); - return format.format(BigDecimal.valueOf(amount)); + return format.format(amount); } @Override @@ -91,7 +95,7 @@ public class Vault extends AbstractEconomy { @Override public boolean has(String playerName, double amount) { - return has(playerName, null, amount); + return has(playerName, null, amount); } @Override @@ -114,21 +118,19 @@ public class Vault extends AbstractEconomy { try { user.withdraw(currency, BigDecimal.valueOf(amount)); - } catch (IllegalArgumentException e) { + } catch (CannotBeGreaterThan | CannotBeNegative e) { return new EconomyResponse( amount, bigDecimalToDouble(user.getBalance(currency)), EconomyResponse.ResponseType.FAILURE, - "Cannot withdraw negative funds" - ); + e.getMessage()); } return new EconomyResponse( amount, bigDecimalToDouble(user.getBalance(currency)), EconomyResponse.ResponseType.SUCCESS, - "" - ); + ""); } @Override @@ -143,21 +145,19 @@ public class Vault extends AbstractEconomy { try { user.deposit(currency, BigDecimal.valueOf(amount)); - } catch (IllegalArgumentException e) { + } catch (CannotBeGreaterThan | CannotBeNegative e) { return new EconomyResponse( amount, bigDecimalToDouble(user.getBalance(currency)), EconomyResponse.ResponseType.FAILURE, - "Cannot deposit negative funds" - ); + e.getMessage()); } return new EconomyResponse( amount, bigDecimalToDouble(user.getBalance(currency)), EconomyResponse.ResponseType.SUCCESS, - "" - ); + ""); } @Override diff --git a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/VaultFactory.java b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/hooks/vault/VaultFactory.java similarity index 66% rename from currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/VaultFactory.java rename to currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/hooks/vault/VaultFactory.java index 8a72208..5797080 100644 --- a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/VaultFactory.java +++ b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/paper/hooks/vault/VaultFactory.java @@ -1,22 +1,23 @@ -package dev.xhyrom.lighteco.currency.money.bukkit.hooks.vault; +package dev.xhyrom.lighteco.currency.money.paper.hooks.vault; + +import dev.xhyrom.lighteco.currency.money.paper.PaperMCLoader; -import dev.xhyrom.lighteco.currency.money.bukkit.BukkitMCLoader; import net.milkbowl.vault.economy.Economy; + import org.bukkit.Bukkit; import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.ServicesManager; public class VaultFactory { - private final BukkitMCLoader loader; + private final PaperMCLoader loader; private Vault vault; - public VaultFactory(BukkitMCLoader loader) { + public VaultFactory(PaperMCLoader loader) { this.loader = loader; } public void hook() { - if (this.vault == null) - vault = new Vault(this.loader.getPlugin()); + if (this.vault == null) vault = new Vault(this.loader.getPlugin()); ServicesManager manager = Bukkit.getServicesManager(); manager.register(Economy.class, vault, this.loader, ServicePriority.Highest); diff --git a/currency-money/src/main/resources/plugin.yml b/currency-money/src/main/resources/plugin.yml index b5bdfbb..e893415 100644 --- a/currency-money/src/main/resources/plugin.yml +++ b/currency-money/src/main/resources/plugin.yml @@ -1,10 +1,11 @@ name: ${name} description: ${description} version: ${version} -main: dev.xhyrom.lighteco.currency.money.bukkit.BukkitMCLoader +main: dev.xhyrom.lighteco.currency.money.paper.PaperMCLoader author: ${author} -api-version: 1.20 +api-version: 1.17 +load: STARTUP softdepend: - Vault - - lighteco-bukkit + - LightEco diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9b17899..daeda4e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Jul 30 15:47:43 CEST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/bukkit/.gitignore b/paper/.gitignore similarity index 100% rename from bukkit/.gitignore rename to paper/.gitignore diff --git a/bukkit/README.md b/paper/README.md similarity index 100% rename from bukkit/README.md rename to paper/README.md diff --git a/bukkit/build.gradle.kts b/paper/build.gradle.kts similarity index 81% rename from bukkit/build.gradle.kts rename to paper/build.gradle.kts index cbefc31..0456452 100644 --- a/bukkit/build.gradle.kts +++ b/paper/build.gradle.kts @@ -5,7 +5,7 @@ plugins { repositories { maven("https://repo.extendedclip.com/content/repositories/placeholderapi") - maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + maven("https://repo.papermc.io/repository/maven-public/") maven("https://oss.sonatype.org/content/repositories/snapshots") maven("https://oss.sonatype.org/content/repositories/central") } @@ -13,10 +13,10 @@ repositories { dependencies { implementation(project(":lighteco-common")) - implementation("dev.jorel:commandapi-bukkit-shade:9.1.0") implementation("net.kyori:adventure-platform-bukkit:4.2.0") - compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.19.1-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-mojangapi:1.19.1-R0.1-SNAPSHOT") // PlaceholderAPI compileOnly("me.clip:placeholderapi:2.11.3") @@ -29,7 +29,9 @@ dependencies { } tasks.shadowJar { - relocate("dev.jorel.commandapi", "dev.xhyrom.lighteco.libraries.commandapi") + dependencies { + exclude(dependency("com.mojang:brigadier")) + } // common relocate("eu.okaeri.configs", "dev.xhyrom.lighteco.libraries.okaeri.configs") diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoBootstrap.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoBootstrap.java similarity index 57% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoBootstrap.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoBootstrap.java index eafc476..e94451d 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitLightEcoBootstrap.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoBootstrap.java @@ -1,13 +1,17 @@ -package dev.xhyrom.lighteco.bukkit; +package dev.xhyrom.lighteco.paper; -import dev.jorel.commandapi.CommandAPI; -import dev.jorel.commandapi.CommandAPIBukkitConfig; -import dev.xhyrom.lighteco.bukkit.logger.BukkitLogger; import dev.xhyrom.lighteco.common.plugin.bootstrap.LightEcoBootstrap; import dev.xhyrom.lighteco.common.plugin.bootstrap.LoaderBootstrap; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter; +import dev.xhyrom.lighteco.paper.logger.PaperLogger; + import lombok.Getter; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; + +import org.bukkit.OfflinePlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; @@ -15,42 +19,45 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.InputStream; import java.nio.file.Path; import java.util.List; +import java.util.Optional; import java.util.UUID; @Getter -public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstrap { - private final BukkitLightEcoPlugin plugin = new BukkitLightEcoPlugin(this); +public class PaperLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstrap { + private final PaperLightEcoPlugin plugin = new PaperLightEcoPlugin(this); @Getter private final JavaPlugin loader; + @Getter private final PluginLogger logger; + @Getter private final SchedulerAdapter scheduler; - public BukkitLightEcoBootstrap(JavaPlugin loader) { + @Getter + private BukkitAudiences audience; + + public PaperLightEcoBootstrap(JavaPlugin loader) { this.loader = loader; - this.logger = new BukkitLogger(loader.getLogger()); - this.scheduler = new BukkitSchedulerAdapter(this); + this.logger = new PaperLogger(this.plugin, loader.getLogger()); + this.scheduler = new PaperSchedulerAdapter(this); } @Override public void onLoad() { this.plugin.load(); - CommandAPI.onLoad(new CommandAPIBukkitConfig(this.loader) - .verboseOutput(this.getPlugin().getConfig().debug) - ); } @Override public void onEnable() { - CommandAPI.onEnable(); this.plugin.enable(); + + this.audience = BukkitAudiences.create(this.loader); } @Override public void onDisable() { - CommandAPI.onDisable(); this.plugin.disable(); } @@ -59,6 +66,17 @@ public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr return this.loader.getDataFolder().toPath(); } + @Override + public String getVersion() { + return this.loader.getDescription().getVersion(); + } + + @Override + public Optional lookupUniqueId(String username) { + return Optional.of(this.loader.getServer().getOfflinePlayer(username)) + .map(OfflinePlayer::getUniqueId); + } + @Override public boolean isPlayerOnline(UUID uniqueId) { Player player = this.loader.getServer().getPlayer(uniqueId); @@ -76,4 +94,9 @@ public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr public InputStream getResourceStream(String filename) { return this.loader.getResource(filename); } + + @Override + public Audience getPlayerAudience(UUID uniqueId) { + return audience.player(uniqueId); + } } diff --git a/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoLoader.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoLoader.java new file mode 100644 index 0000000..73b8ae1 --- /dev/null +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoLoader.java @@ -0,0 +1,28 @@ +package dev.xhyrom.lighteco.paper; + +import org.bukkit.plugin.java.JavaPlugin; + +// Used inside plugin.yml +@SuppressWarnings("unused") +public class PaperLightEcoLoader extends JavaPlugin { + private final PaperLightEcoBootstrap bootstrap; + + public PaperLightEcoLoader() { + this.bootstrap = new PaperLightEcoBootstrap(this); + } + + @Override + public void onLoad() { + this.bootstrap.onLoad(); + } + + @Override + public void onEnable() { + this.bootstrap.onEnable(); + } + + @Override + public void onDisable() { + this.bootstrap.onDisable(); + } +} diff --git a/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoPlugin.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoPlugin.java new file mode 100644 index 0000000..f08cfe6 --- /dev/null +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperLightEcoPlugin.java @@ -0,0 +1,97 @@ +package dev.xhyrom.lighteco.paper; + +import dev.xhyrom.lighteco.api.LightEco; +import dev.xhyrom.lighteco.api.manager.ContextManager; +import dev.xhyrom.lighteco.api.platform.Platform; +import dev.xhyrom.lighteco.common.manager.currency.StandardCurrencyManager; +import dev.xhyrom.lighteco.common.manager.user.StandardUserManager; +import dev.xhyrom.lighteco.common.messaging.MessagingFactory; +import dev.xhyrom.lighteco.common.plugin.AbstractLightEcoPlugin; +import dev.xhyrom.lighteco.paper.hooks.Hooks; +import dev.xhyrom.lighteco.paper.listeners.PaperCommandSuggestionsListener; +import dev.xhyrom.lighteco.paper.listeners.PaperConnectionListener; +import dev.xhyrom.lighteco.paper.manager.PaperCommandManager; +import dev.xhyrom.lighteco.paper.manager.PaperContextManager; + +import lombok.Getter; + +import org.bukkit.entity.Player; +import org.bukkit.plugin.ServicePriority; +import org.checkerframework.checker.nullness.qual.NonNull; + +@Getter +public class PaperLightEcoPlugin extends AbstractLightEcoPlugin { + private final PaperLightEcoBootstrap bootstrap; + + @Getter + private StandardUserManager userManager; + + @Getter + private StandardCurrencyManager currencyManager; + + @Getter + private PaperCommandManager commandManager; + + @Getter + private ContextManager contextManager; + + public PaperLightEcoPlugin(PaperLightEcoBootstrap bootstrap) { + this.bootstrap = bootstrap; + } + + @Override + protected void registerListeners() { + this.bootstrap + .getLoader() + .getServer() + .getPluginManager() + .registerEvents(new PaperConnectionListener(this), this.bootstrap.getLoader()); + this.bootstrap + .getLoader() + .getServer() + .getPluginManager() + .registerEvents( + new PaperCommandSuggestionsListener(this), this.bootstrap.getLoader()); + } + + @Override + public void setupManagers() { + this.userManager = new StandardUserManager(this); + this.currencyManager = new StandardCurrencyManager(this); + this.commandManager = new PaperCommandManager(this); + this.contextManager = new PaperContextManager(); + } + + @Override + protected MessagingFactory getMessagingFactory() { + return new MessagingFactory(this); + } + + @Override + protected void registerApiOnPlatform(LightEco api) { + this.getBootstrap() + .getLoader() + .getServer() + .getServicesManager() + .register( + LightEco.class, + api, + this.getBootstrap().getLoader(), + ServicePriority.Normal); + } + + @Override + protected void registerPlatformHooks() { + Hooks.register(this); + } + + @Override + protected void removePlatformHooks() { + Hooks.unregister(); + } + + @Override + public Platform.@NonNull Type getPlatformType() { + return Platform.Type.PAPER; + } +} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitSchedulerAdapter.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperSchedulerAdapter.java similarity index 54% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitSchedulerAdapter.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/PaperSchedulerAdapter.java index 0312ffd..656216e 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/BukkitSchedulerAdapter.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/PaperSchedulerAdapter.java @@ -1,25 +1,26 @@ -package dev.xhyrom.lighteco.bukkit; +package dev.xhyrom.lighteco.paper; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerTask; -import lombok.Getter; + import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -public class BukkitSchedulerAdapter implements SchedulerAdapter { +public class PaperSchedulerAdapter implements SchedulerAdapter { private final Executor async; - private final BukkitLightEcoBootstrap bootstrap; + private final PaperLightEcoBootstrap bootstrap; private final BukkitScheduler scheduler; - public BukkitSchedulerAdapter(BukkitLightEcoBootstrap bootstrap) { + public PaperSchedulerAdapter(PaperLightEcoBootstrap bootstrap) { this.bootstrap = bootstrap; this.scheduler = bootstrap.getLoader().getServer().getScheduler(); - this.async = runnable -> this.scheduler.runTaskAsynchronously(this.bootstrap.getLoader(), runnable); + this.async = runnable -> + this.scheduler.runTaskAsynchronously(this.bootstrap.getLoader(), runnable); } public Executor async() { @@ -28,29 +29,19 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter { @Override public SchedulerTask asyncLater(Runnable runnable, long delay, TimeUnit unit) { - return new Task( - this.scheduler.runTaskLaterAsynchronously( - this.bootstrap.getLoader(), - runnable, - unit.toSeconds(delay) * 20 - ) - ); + return new Task(this.scheduler.runTaskLaterAsynchronously( + this.bootstrap.getLoader(), runnable, unit.toSeconds(delay) * 20)); } @Override public SchedulerTask asyncRepeating(Runnable runnable, long interval, TimeUnit unit) { - return new Task( - this.scheduler.runTaskTimerAsynchronously( - this.bootstrap.getLoader(), - runnable, - 0, - unit.toSeconds(interval) * 20 - ) - ); + return new Task(this.scheduler.runTaskTimerAsynchronously( + this.bootstrap.getLoader(), runnable, 0, unit.toSeconds(interval) * 20)); } public class Task implements SchedulerTask { private final BukkitTask task; + public Task(BukkitTask task) { this.task = task; } diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/chat/BukkitCommandSender.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/chat/PaperCommandSender.java similarity index 56% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/chat/BukkitCommandSender.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/chat/PaperCommandSender.java index 9bdce61..8678c2f 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/chat/BukkitCommandSender.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/chat/PaperCommandSender.java @@ -1,21 +1,17 @@ -package dev.xhyrom.lighteco.bukkit.chat; +package dev.xhyrom.lighteco.paper.chat; import dev.xhyrom.lighteco.common.model.chat.AbstractCommandSender; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; + import net.kyori.adventure.text.Component; + import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.UUID; -public class BukkitCommandSender extends AbstractCommandSender { - private final Audience audience; - - public BukkitCommandSender(CommandSender sender, BukkitAudiences audienceFactory) { +public class PaperCommandSender extends AbstractCommandSender { + public PaperCommandSender(CommandSender sender) { super(sender); - - this.audience = audienceFactory.sender(sender); } @Override @@ -33,7 +29,12 @@ public class BukkitCommandSender extends AbstractCommandSender { } @Override - public void sendMessage(Component message) { - this.audience.sendMessage(message); + public boolean eligible(String permission) { + return this.delegate.hasPermission(permission); } -} \ No newline at end of file + + @Override + public void sendMessage(Component message) { + this.delegate.sendMessage(message); + } +} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/Hooks.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/hooks/Hooks.java similarity index 77% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/Hooks.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/hooks/Hooks.java index a820a55..a8d3893 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/Hooks.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/hooks/Hooks.java @@ -1,14 +1,16 @@ -package dev.xhyrom.lighteco.bukkit.hooks; +package dev.xhyrom.lighteco.paper.hooks; + +import dev.xhyrom.lighteco.paper.PaperLightEcoPlugin; -import dev.xhyrom.lighteco.bukkit.BukkitLightEcoPlugin; import lombok.experimental.UtilityClass; + import org.bukkit.Bukkit; @UtilityClass public class Hooks { private static PlaceholderAPIExpansion placeholderAPIExpansion; - public static void register(BukkitLightEcoPlugin plugin) { + public static void register(PaperLightEcoPlugin plugin) { if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { placeholderAPIExpansion = new PlaceholderAPIExpansion(plugin); placeholderAPIExpansion.register(); diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/PlaceholderAPIExpansion.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/hooks/PlaceholderAPIExpansion.java similarity index 66% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/PlaceholderAPIExpansion.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/hooks/PlaceholderAPIExpansion.java index a4162ad..0471401 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/PlaceholderAPIExpansion.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/hooks/PlaceholderAPIExpansion.java @@ -1,36 +1,43 @@ -package dev.xhyrom.lighteco.bukkit.hooks; +package dev.xhyrom.lighteco.paper.hooks; -import dev.xhyrom.lighteco.bukkit.BukkitLightEcoPlugin; import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.paper.PaperLightEcoPlugin; + import lombok.RequiredArgsConstructor; + import me.clip.placeholderapi.expansion.PlaceholderExpansion; + import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; @RequiredArgsConstructor public class PlaceholderAPIExpansion extends PlaceholderExpansion { - private final BukkitLightEcoPlugin plugin; + private final PaperLightEcoPlugin plugin; @Override - public @NotNull String getIdentifier() { + public @NonNull String getIdentifier() { return "lighteco"; } @Override - public @NotNull String getAuthor() { - return this.plugin.getBootstrap().getLoader().getDescription().getAuthors().toString(); + public @NonNull String getAuthor() { + return this.plugin + .getBootstrap() + .getLoader() + .getDescription() + .getAuthors() + .toString(); } @Override - public @NotNull String getVersion() { + public @NonNull String getVersion() { return this.plugin.getBootstrap().getLoader().getDescription().getVersion(); } @Override - public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) { + public @Nullable String onRequest(OfflinePlayer player, @NonNull String params) { String[] args = params.split("_"); if (args.length < 2) return null; diff --git a/paper/src/main/java/dev/xhyrom/lighteco/paper/listeners/PaperCommandSuggestionsListener.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/listeners/PaperCommandSuggestionsListener.java new file mode 100644 index 0000000..9ed97cc --- /dev/null +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/listeners/PaperCommandSuggestionsListener.java @@ -0,0 +1,78 @@ +package dev.xhyrom.lighteco.paper.listeners; + +import com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent; +import com.mojang.brigadier.tree.CommandNode; +import com.mojang.brigadier.tree.LiteralCommandNode; + +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.paper.PaperLightEcoPlugin; +import dev.xhyrom.lighteco.paper.chat.PaperCommandSender; +import dev.xhyrom.lighteco.paper.util.PaperBrigadier; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class PaperCommandSuggestionsListener implements Listener { + private final PaperLightEcoPlugin plugin; + + public PaperCommandSuggestionsListener(PaperLightEcoPlugin plugin) { + this.plugin = plugin; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onPlayerSendCommandsEvent(AsyncPlayerSendCommandsEvent event) { + PaperCommandSender sender = new PaperCommandSender(event.getPlayer()); + CommandSource source = new CommandSource(this.plugin, sender); + if (event.isAsynchronous() || !event.hasFiredAsync()) { + for (CommandNode command : + this.plugin.getCommandManager().getDispatcher().getRoot().getChildren()) { + PaperBrigadier.removeChild(event.getCommandNode(), command.getName()); + PaperBrigadier.removeChild( + event.getCommandNode(), + this.plugin.getBootstrap().getLoader().getName().toLowerCase() + ":" + + command.getName()); + + if (!command.canUse(source)) continue; + + addChild(event, source, command, createClone(command)); + addChild( + event, + source, + command, + createClone( + this.plugin.getBootstrap().getLoader().getName().toLowerCase() + ":" + + command.getName(), + command)); + } + } + } + + @SuppressWarnings({"rawtypes", "unchecked", "deprecation"}) + private void addChild( + AsyncPlayerSendCommandsEvent event, + CommandSource source, + CommandNode command, + CommandNode clone) { + for (CommandNode child : command.getChildren()) { + if (child.canUse(source)) clone.addChild(child); + } + + event.getCommandNode().addChild((CommandNode) clone); + } + + private CommandNode createClone(CommandNode command) { + return createClone(command.getName(), command); + } + + private CommandNode createClone( + String name, CommandNode command) { + return new LiteralCommandNode<>( + name, + command.getCommand(), + command.getRequirement(), + command.getRedirect(), + command.getRedirectModifier(), + command.isFork()); + } +} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/listeners/BukkitConnectionListener.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/listeners/PaperConnectionListener.java similarity index 54% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/listeners/BukkitConnectionListener.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/listeners/PaperConnectionListener.java index c8176b2..5ec1797 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/listeners/BukkitConnectionListener.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/listeners/PaperConnectionListener.java @@ -1,11 +1,13 @@ -package dev.xhyrom.lighteco.bukkit.listeners; +package dev.xhyrom.lighteco.paper.listeners; -import dev.xhyrom.lighteco.bukkit.BukkitLightEcoPlugin; +import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.model.user.User; +import dev.xhyrom.lighteco.paper.PaperLightEcoPlugin; + import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Bukkit; + import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -14,11 +16,11 @@ import org.bukkit.event.player.PlayerQuitEvent; import java.util.UUID; -public class BukkitConnectionListener implements Listener { - private final BukkitLightEcoPlugin plugin; +public class PaperConnectionListener implements Listener { + private final PaperLightEcoPlugin plugin; private final MiniMessage miniMessage = MiniMessage.miniMessage(); - public BukkitConnectionListener(BukkitLightEcoPlugin plugin) { + public PaperConnectionListener(PaperLightEcoPlugin plugin) { this.plugin = plugin; } @@ -29,21 +31,24 @@ public class BukkitConnectionListener implements Listener { } try { - this.plugin.getStorage().loadUser(event.getUniqueId(), event.getName()).join(); + this.plugin + .getStorage() + .loadUser(event.getUniqueId(), event.getName()) + .join(); } catch (Exception e) { - this.plugin.getBootstrap().getLogger() - .error("Failed to load user data for %s (%s)", e, event.getName(), event.getUniqueId()); + this.plugin + .getBootstrap() + .getLogger() + .error( + "Failed to load user data for %s (%s)", + e, event.getName(), event.getUniqueId()); Component reason = miniMessage.deserialize( - "LightEco Failed to load your data. Contact a staff member for assistance." - ); + "LightEco Failed to load your data. Contact a staff member for assistance."); event.disallow( AsyncPlayerPreLoginEvent.Result.KICK_OTHER, - LegacyComponentSerializer.legacySection().serialize( - reason - ) - ); + LegacyComponentSerializer.legacySection().serialize(reason)); } } @@ -57,12 +62,13 @@ public class BukkitConnectionListener implements Listener { return; } - this.plugin.getUserManager().saveUser(user) - .thenAccept(v -> { - // make sure the player is offline before unloading - if (Bukkit.getPlayer(uniqueId) != null) return; - - this.plugin.getUserManager().unload(uniqueId); - }); + this.plugin.getUserManager().saveUser(user).thenAccept(v -> this.plugin + .getMessagingService() + .ifPresent(service -> { + for (Currency currency : + this.plugin.getCurrencyManager().getRegisteredCurrencies()) { + service.pushUserUpdate(user, currency); + } + })); } } diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/logger/BukkitLogger.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/logger/PaperLogger.java similarity index 72% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/logger/BukkitLogger.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/logger/PaperLogger.java index 7d4d6f7..a423c0b 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/logger/BukkitLogger.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/logger/PaperLogger.java @@ -1,14 +1,17 @@ -package dev.xhyrom.lighteco.bukkit.logger; +package dev.xhyrom.lighteco.paper.logger; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; import java.util.logging.Level; import java.util.logging.Logger; -public class BukkitLogger implements PluginLogger { +public class PaperLogger implements PluginLogger { + private final LightEcoPlugin plugin; private final Logger logger; - public BukkitLogger(Logger logger) { + public PaperLogger(LightEcoPlugin plugin, Logger logger) { + this.plugin = plugin; this.logger = logger; } @@ -22,6 +25,20 @@ public class BukkitLogger implements PluginLogger { this.logger.info(String.format(message, args)); } + @Override + public void debug(String message) { + if (!this.plugin.getConfig().debug) return; + + info(message); + } + + @Override + public void debug(String message, Object... args) { + if (!this.plugin.getConfig().debug) return; + + info(message, args); + } + @Override public void warn(String message) { this.logger.log(Level.WARNING, message); diff --git a/paper/src/main/java/dev/xhyrom/lighteco/paper/manager/PaperCommandManager.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/manager/PaperCommandManager.java new file mode 100644 index 0000000..ab1f3c2 --- /dev/null +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/manager/PaperCommandManager.java @@ -0,0 +1,64 @@ +package dev.xhyrom.lighteco.paper.manager; + +import com.mojang.brigadier.ParseResults; + +import dev.xhyrom.lighteco.common.command.CommandManager; +import dev.xhyrom.lighteco.common.command.CommandSource; +import dev.xhyrom.lighteco.common.command.abstraction.Command; +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; +import dev.xhyrom.lighteco.paper.chat.PaperCommandSender; +import dev.xhyrom.lighteco.paper.util.PaperCommandMapUtil; + +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.TabCompleter; + +import java.util.ArrayList; +import java.util.List; + +public class PaperCommandManager extends CommandManager { + private final PaperCommandMapUtil commandMapUtil; + + public PaperCommandManager(LightEcoPlugin plugin) { + super(plugin); + + this.commandMapUtil = new PaperCommandMapUtil(plugin); + } + + @Override + protected void register(Command command) { + super.register(command); + + CommandExecutor executor = (sender, bukkitCommand, s, args) -> { + if (s.startsWith("lighteco:")) { + s = s.substring(9); + } + + execute(new PaperCommandSender(sender), s, args); + return true; + }; + + TabCompleter completer = (sender, bukkitCommand, s, args) -> { + final List suggestions = new ArrayList<>(); + final CommandSource source = new CommandSource(plugin, new PaperCommandSender(sender)); + + final ParseResults parseResults = getDispatcher() + .parse( + command.getName() + + (args.length > 0 ? " " + String.join(" ", args) : ""), + source); + + getDispatcher() + .getCompletionSuggestions(parseResults) + .join() + .getList() + .forEach(suggestion -> suggestions.add(suggestion.getText())); + + return suggestions; + }; + + List aliases = new ArrayList<>(command.getAliases()); + aliases.add(command.getName()); + + this.commandMapUtil.register(executor, completer, aliases); + } +} diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitContextManager.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/manager/PaperContextManager.java similarity index 77% rename from bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitContextManager.java rename to paper/src/main/java/dev/xhyrom/lighteco/paper/manager/PaperContextManager.java index 1ec1a53..e93280d 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitContextManager.java +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/manager/PaperContextManager.java @@ -1,12 +1,13 @@ -package dev.xhyrom.lighteco.bukkit.manager; +package dev.xhyrom.lighteco.paper.manager; import dev.xhyrom.lighteco.api.manager.ContextManager; + import org.bukkit.entity.Player; import org.checkerframework.checker.nullness.qual.NonNull; import java.util.UUID; -public class BukkitContextManager implements ContextManager { +public class PaperContextManager implements ContextManager { @Override public @NonNull UUID getPlayerUniqueId(@NonNull Player player) { return player.getUniqueId(); diff --git a/paper/src/main/java/dev/xhyrom/lighteco/paper/util/PaperBrigadier.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/util/PaperBrigadier.java new file mode 100644 index 0000000..0feb412 --- /dev/null +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/util/PaperBrigadier.java @@ -0,0 +1,41 @@ +package dev.xhyrom.lighteco.paper.util; + +import com.mojang.brigadier.tree.CommandNode; +import com.mojang.brigadier.tree.RootCommandNode; + +import java.lang.reflect.Field; +import java.util.Map; + +public class PaperBrigadier { + private static final Field CHILDREN_FIELD; + private static final Field LITERALS_FIELD; + private static final Field ARGUMENTS_FIELD; + private static final Field[] CHILDREN_FIELDS; + + static { + try { + CHILDREN_FIELD = CommandNode.class.getDeclaredField("children"); + LITERALS_FIELD = CommandNode.class.getDeclaredField("literals"); + ARGUMENTS_FIELD = CommandNode.class.getDeclaredField("arguments"); + CHILDREN_FIELDS = new Field[] {CHILDREN_FIELD, LITERALS_FIELD, ARGUMENTS_FIELD}; + + for (Field field : CHILDREN_FIELDS) { + field.setAccessible(true); + } + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } + + @SuppressWarnings("unchecked") + public static void removeChild(RootCommandNode root, String name) { + try { + for (Field field : CHILDREN_FIELDS) { + Map children = (Map) field.get(root); + children.remove(name); + } + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } +} diff --git a/paper/src/main/java/dev/xhyrom/lighteco/paper/util/PaperCommandMapUtil.java b/paper/src/main/java/dev/xhyrom/lighteco/paper/util/PaperCommandMapUtil.java new file mode 100644 index 0000000..68a7464 --- /dev/null +++ b/paper/src/main/java/dev/xhyrom/lighteco/paper/util/PaperCommandMapUtil.java @@ -0,0 +1,61 @@ +package dev.xhyrom.lighteco.paper.util; + +import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; + +import org.bukkit.command.*; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import java.lang.reflect.Constructor; +import java.util.List; +import java.util.Map; + +public class PaperCommandMapUtil { + private static final Constructor COMMAND_CONSTRUCTOR; + + static { + try { + COMMAND_CONSTRUCTOR = + PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); + COMMAND_CONSTRUCTOR.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new ExceptionInInitializerError(e); + } + } + + private final LightEcoPlugin plugin; + + public PaperCommandMapUtil(LightEcoPlugin plugin) { + this.plugin = plugin; + } + + public void register(CommandExecutor executor, TabCompleter completer, List aliases) { + Plugin bukkitPlugin = (JavaPlugin) this.plugin.getBootstrap().getLoader(); + CommandMap commandMap = bukkitPlugin.getServer().getCommandMap(); + Map knownCommands = commandMap.getKnownCommands(); + + for (String name : aliases) { + if (!name.toLowerCase().equals(name)) { + throw new IllegalArgumentException( + "Command aliases must be lowercase! (name: " + name + ")"); + } + + try { + PluginCommand command = COMMAND_CONSTRUCTOR.newInstance(name, bukkitPlugin); + + commandMap.register(bukkitPlugin.getName().toLowerCase(), command); + knownCommands.put( + bukkitPlugin.getName().toLowerCase() + ":" + name.toLowerCase(), command); + knownCommands.put(name, command); + + command.setLabel(name); + command.setExecutor(executor); + command.setTabCompleter(completer); + + commandMap.register(bukkitPlugin.getName(), command); + } catch (ReflectiveOperationException e) { + this.plugin.getBootstrap().getLogger().error("Failed to register command: %s", e); + } + } + } +} diff --git a/bukkit/src/main/resources/plugin.yml b/paper/src/main/resources/plugin.yml similarity index 55% rename from bukkit/src/main/resources/plugin.yml rename to paper/src/main/resources/plugin.yml index 0d7f4be..6868c77 100644 --- a/bukkit/src/main/resources/plugin.yml +++ b/paper/src/main/resources/plugin.yml @@ -1,9 +1,9 @@ -name: ${name} +name: ${coreName} description: ${description} version: ${version} -main: dev.xhyrom.lighteco.bukkit.BukkitLightEcoLoader +main: dev.xhyrom.lighteco.paper.PaperLightEcoLoader author: ${author} -api-version: 1.16 +api-version: 1.17 load: STARTUP softdepend: diff --git a/settings.gradle.kts b/settings.gradle.kts index 327bd3f..1c0f551 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,15 +3,22 @@ rootProject.name = "lighteco-parent" sequenceOf( "api", "common", - "bukkit", - "bukkittest", - "sponge-9", - "currency-money" + "paper", + "sponge-8", + "currency-money", + "test" ).forEach { include("lighteco-$it") project(":lighteco-$it").projectDir = file(it) } +sequenceOf( + "paper" +).forEach { + include("lighteco-test-$it") + project(":lighteco-test-$it").projectDir = file("test/$it") +} + pluginManagement { repositories { mavenLocal() diff --git a/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoBootstrap.java b/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoBootstrap.java index 307e62e..960da94 100644 --- a/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoBootstrap.java +++ b/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoBootstrap.java @@ -1,31 +1,32 @@ package dev.xhyrom.lighteco.sponge; +import com.google.inject.Inject; + import dev.xhyrom.lighteco.common.plugin.bootstrap.LightEcoBootstrap; import dev.xhyrom.lighteco.common.plugin.bootstrap.LoaderBootstrap; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter; -import dev.xhyrom.lighteco.sponge.logger.SpongeLogger; -import lombok.Getter; + +import net.kyori.adventure.audience.Audience; + +import org.apache.logging.log4j.Logger; +import org.spongepowered.plugin.builtin.jvm.Plugin; import java.io.InputStream; import java.nio.file.Path; import java.util.List; +import java.util.Optional; import java.util.UUID; +@Plugin("lighteco-sponge") public class SpongeLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstrap { - private final SpongeLightEcoPlugin plugin = new SpongeLightEcoPlugin(this); + private final SpongeLightEcoPlugin plugin; - @Getter - private final SpongeLightEcoLoader loader; - @Getter - private final PluginLogger logger; - @Getter - private final SchedulerAdapter scheduler; + @Inject + private Logger logger; - public SpongeLightEcoBootstrap(SpongeLightEcoLoader loader) { - this.loader = loader; - this.logger = new SpongeLogger(loader.logger); - this.scheduler = new SpongeSchedulerAdapter(this); + public SpongeLightEcoBootstrap() { + this.plugin = new SpongeLightEcoPlugin(this); } @Override @@ -43,11 +44,36 @@ public class SpongeLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr this.plugin.disable(); } + @Override + public Object getLoader() { + return null; + } + + @Override + public PluginLogger getLogger() { + return null; + } + + @Override + public SchedulerAdapter getScheduler() { + return null; + } + @Override public Path getDataDirectory() { return null; } + @Override + public String getVersion() { + return null; + } + + @Override + public Optional lookupUniqueId(String username) { + return Optional.empty(); + } + @Override public boolean isPlayerOnline(UUID uniqueId) { return false; @@ -62,4 +88,9 @@ public class SpongeLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr public InputStream getResourceStream(String filename) { return null; } + + @Override + public Audience getPlayerAudience(UUID uniqueId) { + return null; + } } diff --git a/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoPlugin.java b/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoPlugin.java index ae1fef7..e1e55e1 100644 --- a/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoPlugin.java +++ b/sponge-9/src/main/java/dev/xhyrom/lighteco/sponge/SpongeLightEcoPlugin.java @@ -3,11 +3,14 @@ package dev.xhyrom.lighteco.sponge; import dev.xhyrom.lighteco.api.LightEco; import dev.xhyrom.lighteco.api.manager.ContextManager; import dev.xhyrom.lighteco.api.platform.Platform; -import dev.xhyrom.lighteco.common.manager.command.CommandManager; +import dev.xhyrom.lighteco.common.command.CommandManager; import dev.xhyrom.lighteco.common.manager.currency.StandardCurrencyManager; import dev.xhyrom.lighteco.common.manager.user.StandardUserManager; +import dev.xhyrom.lighteco.common.messaging.MessagingFactory; import dev.xhyrom.lighteco.common.plugin.AbstractLightEcoPlugin; + import lombok.Getter; + import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.entity.living.player.Player; @@ -17,10 +20,13 @@ public class SpongeLightEcoPlugin extends AbstractLightEcoPlugin { @Getter private StandardUserManager userManager; + @Getter private StandardCurrencyManager currencyManager; + @Getter private CommandManager commandManager; + @Getter private ContextManager contextManager; @@ -30,31 +36,34 @@ public class SpongeLightEcoPlugin extends AbstractLightEcoPlugin { @Override protected void registerListeners() { - //this.bootstrap.getServer().getPluginManager().registerEvents(new BukkitConnectionListener(this), this.bootstrap); + // this.bootstrap.getServer().getPluginManager().registerEvents(new + // BukkitConnectionListener(this), this.bootstrap); } @Override public void setupManagers() { this.userManager = new StandardUserManager(this); this.currencyManager = new StandardCurrencyManager(this); - //this.commandManager = new BukkitCommandManager(this); - //this.contextManager = new BukkitContextManager(); + // this.commandManager = new BukkitCommandManager(this); + // this.contextManager = new BukkitContextManager(); + } + + @Override + protected MessagingFactory getMessagingFactory() { + return new MessagingFactory(this); } @Override protected void registerApiOnPlatform(LightEco api) { - //this.getBootstrap().getServer().getServicesManager().register(LightEco.class, api, this.getBootstrap(), ServicePriority.Normal); + // this.getBootstrap().getServer().getServicesManager().register(LightEco.class, api, + // this.getBootstrap(), ServicePriority.Normal); } @Override - protected void registerPlatformHooks() { - - } + protected void registerPlatformHooks() {} @Override - protected void removePlatformHooks() { - - } + protected void removePlatformHooks() {} @Override public Platform.@NonNull Type getPlatformType() { diff --git a/bukkittest/build.gradle.kts b/test/paper/build.gradle.kts similarity index 61% rename from bukkittest/build.gradle.kts rename to test/paper/build.gradle.kts index 545c292..fa27896 100644 --- a/bukkittest/build.gradle.kts +++ b/test/paper/build.gradle.kts @@ -6,8 +6,17 @@ plugins { } server { - version = "1.20.1" - type = "paper" + version = "1.20.6" + type = "purpur" + + // Minecraft 1.20.6 requires java 21 + java { + targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_21 + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } + } } repositories { diff --git a/bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestCurrency.java b/test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestCurrency.java similarity index 92% rename from bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestCurrency.java rename to test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestCurrency.java index 4652c83..c5534af 100644 --- a/bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestCurrency.java +++ b/test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestCurrency.java @@ -1,4 +1,4 @@ -package dev.xhyrom.lighteco.bukkittest; +package dev.xhyrom.lighteco.test.paper; import dev.xhyrom.lighteco.api.model.currency.Currency; diff --git a/bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestCurrency2.java b/test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestCurrency2.java similarity index 89% rename from bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestCurrency2.java rename to test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestCurrency2.java index 63de38a..9730636 100644 --- a/bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestCurrency2.java +++ b/test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestCurrency2.java @@ -1,4 +1,4 @@ -package dev.xhyrom.lighteco.bukkittest; +package dev.xhyrom.lighteco.test.paper; import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.user.User; @@ -18,12 +18,12 @@ public class TestCurrency2 implements Currency { @Override public boolean isPayable() { - return true; + return false; } @Override public int fractionalDigits() { - return 2; + return 2; } @Override diff --git a/bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestPlugin.java b/test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestPlugin.java similarity index 79% rename from bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestPlugin.java rename to test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestPlugin.java index 26170e1..05e8c57 100644 --- a/bukkittest/src/main/java/dev/xhyrom/lighteco/bukkittest/TestPlugin.java +++ b/test/paper/src/main/java/dev/xhyrom/lighteco/test/paper/TestPlugin.java @@ -1,8 +1,9 @@ -package dev.xhyrom.lighteco.bukkittest; +package dev.xhyrom.lighteco.test.paper; import dev.xhyrom.lighteco.api.LightEco; import dev.xhyrom.lighteco.api.LightEcoProvider; import dev.xhyrom.lighteco.api.manager.CurrencyManager; + import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; @@ -19,7 +20,9 @@ public class TestPlugin extends JavaPlugin implements Listener { getLogger().info("TestCurrency registered!"); - currencyManager.getRegisteredCurrencies().forEach(currency -> getLogger().info("Currency: " + currency.getIdentifier() + " (" + currency.getType() + ", " + currency.fractionalDigits() + ", " + currency.isPayable() + ")")); + currencyManager.getRegisteredCurrencies().forEach(currency -> getLogger() + .info("Currency: " + currency.getIdentifier() + " (" + currency.getType() + ", " + + currency.fractionalDigits() + ", " + currency.isPayable() + ")")); provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test")); provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test2")); diff --git a/bukkittest/src/main/resources/plugin.yml b/test/paper/src/main/resources/plugin.yml similarity index 64% rename from bukkittest/src/main/resources/plugin.yml rename to test/paper/src/main/resources/plugin.yml index 0fdea7e..31d3857 100644 --- a/bukkittest/src/main/resources/plugin.yml +++ b/test/paper/src/main/resources/plugin.yml @@ -1,10 +1,10 @@ name: ${name} description: ${description} version: ${version} -main: dev.xhyrom.lighteco.bukkittest.TestPlugin +main: dev.xhyrom.lighteco.test.paper.TestPlugin author: ${author} api-version: 1.20 softdepend: - Vault - - lighteco-bukkit \ No newline at end of file + - LightEco \ No newline at end of file