mirror of
https://github.com/xHyroM/lighteco.git
synced 2024-11-12 18:38:07 +01:00
rebase
This commit is contained in:
commit
240b6a3f3f
156 changed files with 3050 additions and 1248 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
@ -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:
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
LightEco is licensed under the [Apache-2.0 License](./LICENSE).
|
||||
|
|
36
SECURITY.md
Normal file
36
SECURITY.md
Normal file
|
@ -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.
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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<MessagingService> getMessagingService();
|
||||
|
||||
/**
|
||||
* Gets the {@link PlayerAdapter} for a player class.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package dev.xhyrom.lighteco.api.exception;
|
||||
|
||||
public class CannotBeGreaterThan extends IllegalArgumentException {
|
||||
public CannotBeGreaterThan(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package dev.xhyrom.lighteco.api.exception;
|
||||
|
||||
public class CannotBeNegative extends IllegalArgumentException {
|
||||
public CannotBeNegative(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<User> loadUser(@NonNull UUID uniqueId);
|
||||
|
||||
@NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId, String username);
|
||||
|
||||
@NonNull CompletableFuture<Void> saveUser(@NonNull User user);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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() {}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -13,6 +13,20 @@ public interface Currency {
|
|||
*/
|
||||
String getIdentifier();
|
||||
|
||||
/**
|
||||
* Returns the identifier aliases of the currency.
|
||||
* <p>
|
||||
* Useful if you want multiple commands for the same currency.
|
||||
* For example, you can have a command `/hyrocoins` but also `/hc`.
|
||||
* </p>
|
||||
*
|
||||
* @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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -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<MavenPublication>("mavenJava") {
|
||||
repositories.maven {
|
||||
url = uri("https://repo.jopga.me/releases")
|
||||
|
||||
credentials(PasswordCredentials::class)
|
||||
authentication {
|
||||
create<BasicAuthentication>("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"))
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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<Player> 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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
44
bukkittest/.gitignore
vendored
44
bukkittest/.gitignore
vendored
|
@ -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/
|
|
@ -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")
|
||||
}
|
|
@ -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<MessagingService> getMessagingService() {
|
||||
return this.plugin.getMessagingService().map(ApiMessagingService::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull <T> PlayerAdapter<T> getPlayerAdapter(@NonNull Class<T> 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<T>) this.playerAdapter;
|
||||
|
|
|
@ -4,10 +4,10 @@ import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
|
|||
|
||||
public abstract class ApiAbstractManager<H> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<dev.xhyrom.lighteco.common.manager.command.CommandManager> implements CommandManager {
|
||||
public ApiCommandManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.command.CommandManager handler) {
|
||||
super(plugin, handler);
|
||||
public class ApiCommandManager
|
||||
extends ApiAbstractManager<dev.xhyrom.lighteco.common.command.CommandManager>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<dev.xhyrom.lighteco.common.manager.currency.CurrencyManager> implements CurrencyManager {
|
||||
public ApiCurrencyManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.currency.CurrencyManager handler) {
|
||||
super(plugin, handler);
|
||||
public class ApiCurrencyManager
|
||||
extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.currency.CurrencyManager>
|
||||
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<Currency> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<dev.xhyrom.lighteco.common.manager.user.UserManager> implements UserManager {
|
||||
public ApiUserManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.user.UserManager handler) {
|
||||
super(plugin, handler);
|
||||
public class ApiUserManager
|
||||
extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.user.UserManager>
|
||||
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<dev.xhyrom.lighteco.commo
|
|||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<User> 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<dev.xhyrom.lighteco.commo
|
|||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> saveUsers(@NotNull @NonNull User... users) {
|
||||
public @NonNull CompletableFuture<Void> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,7 @@ public class ExpiringSet<T> {
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,4 @@ package dev.xhyrom.lighteco.common.cache;
|
|||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class RedisBackedMap<T, U> extends HashMap<T, U> {
|
||||
|
||||
}
|
||||
public class RedisBackedMap<T, U> extends HashMap<T, U> {}
|
||||
|
|
|
@ -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<CommandSource> 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<String, CurrencyMessageConfig> config = plugin.getConfig().messages.currency;
|
||||
CurrencyMessageConfig currencyMessageConfig = config.get(currency.getIdentifier());
|
||||
|
||||
if (currencyMessageConfig == null) {
|
||||
return config.get("default");
|
||||
}
|
||||
|
||||
return currencyMessageConfig;
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> dispatcher = new CommandDispatcher<>();
|
||||
|
||||
@Getter
|
||||
private final Set<UUID> locks = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private final Map<UUID, UUID> 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<CommandSource> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {}
|
|
@ -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<String> 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<CommandSource> build();
|
||||
|
||||
protected LiteralArgumentBuilder<CommandSource> builder() {
|
||||
return LiteralArgumentBuilder.literal(name);
|
||||
}
|
||||
}
|
|
@ -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<String> {
|
||||
private OfflineUserArgument() {}
|
||||
|
||||
public static User getOfflineUser(CommandContext<CommandSource> 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();
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> {
|
||||
public static OfflineUserSuggestionProvider create() {
|
||||
return new OfflineUserSuggestionProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Suggestions> getSuggestions(
|
||||
CommandContext<CommandSource> 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();
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> build() {
|
||||
return builder()
|
||||
.then(RequiredArgumentBuilder.<CommandSource, String>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();
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> build() {
|
||||
LiteralArgumentBuilder<CommandSource> 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();
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> 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<CommandSource> build() {
|
||||
if (currency.fractionalDigits() > 0) {
|
||||
return builder()
|
||||
.requires((source) -> source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.give"))
|
||||
.then(RequiredArgumentBuilder.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Double>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.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Integer>argument(
|
||||
"amount", IntegerArgumentType.integer(1))
|
||||
.requires((source) -> source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.give"))
|
||||
.executes(c -> {
|
||||
execute(c);
|
||||
return SINGLE_SUCCESS;
|
||||
})))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> 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><bold>LightEco</bold></#fa5246> <dark_gray>(<#d6766f>v<version><dark_gray>) <white>on <#d6766f><platform>",
|
||||
Placeholder.parsed(
|
||||
"version", plugin.getBootstrap().getVersion()),
|
||||
Placeholder.parsed(
|
||||
"platform", plugin.getPlatformType().getName())));
|
||||
|
||||
return SINGLE_SUCCESS;
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> 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<CommandSource> build() {
|
||||
if (currency.fractionalDigits() > 0) {
|
||||
return builder()
|
||||
.requires((source) -> !source.sender().isConsole()
|
||||
&& source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.pay"))
|
||||
.then(RequiredArgumentBuilder.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Double>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.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Integer>argument(
|
||||
"amount", IntegerArgumentType.integer(1))
|
||||
.requires((source) -> source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.pay"))
|
||||
.executes(c -> {
|
||||
execute(c);
|
||||
return SINGLE_SUCCESS;
|
||||
})))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> 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<CommandSource> build() {
|
||||
if (currency.fractionalDigits() > 0) {
|
||||
return builder()
|
||||
.requires((source) -> source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.set"))
|
||||
.then(RequiredArgumentBuilder.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Double>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.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Integer>argument(
|
||||
"amount", IntegerArgumentType.integer(1))
|
||||
.requires((source) -> source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.set"))
|
||||
.executes(c -> {
|
||||
execute(c);
|
||||
return SINGLE_SUCCESS;
|
||||
})))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -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<CommandSource> 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<CommandSource> build() {
|
||||
if (currency.fractionalDigits() > 0) {
|
||||
return builder()
|
||||
.requires((source) -> source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.take"))
|
||||
.then(RequiredArgumentBuilder.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Double>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.<CommandSource, String>argument(
|
||||
"target", StringArgumentType.word())
|
||||
.suggests(OfflineUserSuggestionProvider.create())
|
||||
.then(RequiredArgumentBuilder.<CommandSource, Integer>argument(
|
||||
"amount", IntegerArgumentType.integer(1))
|
||||
.requires((source) -> source.sender()
|
||||
.eligible("lighteco.currency." + currency.getIdentifier()
|
||||
+ ".command.take"))
|
||||
.executes(c -> {
|
||||
execute(c);
|
||||
return SINGLE_SUCCESS;
|
||||
})))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -4,18 +4,30 @@ import eu.okaeri.configs.OkaeriConfig;
|
|||
import eu.okaeri.configs.annotation.Variable;
|
||||
|
||||
public class CurrencyMessageConfig extends OkaeriConfig {
|
||||
public String balance = "<currency> <dark_gray>| <gray>Your balance: <yellow><balance> </yellow></gray>";
|
||||
public String balance =
|
||||
"<currency> <dark_gray>| <gray>Your balance: <yellow><balance> </yellow></gray>";
|
||||
|
||||
@Variable("balance-others")
|
||||
public String balanceOthers = "<currency> <dark_gray>| <gray>Balance of <yellow><target> <dark_gray>| <gray><yellow><balance> </yellow></gray>";
|
||||
public String balanceOthers =
|
||||
"<currency> <dark_gray>| <gray>Balance of <yellow><target> <dark_gray>| <gray><yellow><balance> </yellow></gray>";
|
||||
|
||||
public String set = "<currency> <dark_gray>| <gray>Set balance of <gold><target> <yellow>to <gold><amount>";
|
||||
public String give = "<currency> <dark_gray>| <gray>Gave <gold><target> <gold><amount> <dark_gray>| <gold><balance>";
|
||||
public String take = "<currency> <dark_gray>| <gray>Took <gold><amount> <yellow>from <gold><target>";
|
||||
public String set =
|
||||
"<currency> <dark_gray>| <gray>Set balance of <gold><target> <yellow>to <gold><amount>";
|
||||
public String give =
|
||||
"<currency> <dark_gray>| <gray>Gave <gold><target> <gold><amount> <dark_gray>| <gold><balance>";
|
||||
public String take =
|
||||
"<currency> <dark_gray>| <gray>Took <gold><amount> <yellow>from <gold><target>";
|
||||
|
||||
public String pay = "<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target>";
|
||||
public String payWithTax = "<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target> <dark_gray>(<gold><taxed_amount> <yellow>after tax<dark_gray>)";
|
||||
public String pay =
|
||||
"<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target>";
|
||||
public String payWithTax =
|
||||
"<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target> <dark_gray>(<gold><taxed_amount> <yellow>after tax<dark_gray>)";
|
||||
public String payReceived =
|
||||
"<currency> <dark_gray>| <gray>Received <gold><amount> <yellow>from <gold><sender>";
|
||||
public String payReceivedWithTax =
|
||||
"<currency> <dark_gray>| <gray>Received <gold><amount> <yellow>from <gold><sender> <dark_gray>(<gold><taxed_amount> <yellow>after tax<dark_gray>)";
|
||||
|
||||
public String wait = "<red>Please wait a moment before using this command again.";
|
||||
public String notEnoughMoney = "<red>You don't have enough money!";
|
||||
public String cannotPaySelf = "<red>You cannot pay yourself!";
|
||||
public String cannotBeGreaterThan = "<red>Amount cannot be greater than <gold><max>";
|
||||
}
|
||||
|
|
|
@ -6,5 +6,9 @@ import java.util.Collections;
|
|||
import java.util.Map;
|
||||
|
||||
public class MessageConfig extends OkaeriConfig {
|
||||
public Map<String, CurrencyMessageConfig> currency = Collections.singletonMap("default", new CurrencyMessageConfig());
|
||||
public Map<String, CurrencyMessageConfig> currency =
|
||||
Collections.singletonMap("default", new CurrencyMessageConfig());
|
||||
|
||||
public String wait = "<red>Please wait a moment before using this command again.";
|
||||
public String userNotFound = "<red>User <username> not found.";
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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<Relocation> 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);
|
||||
|
|
|
@ -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<StorageType> types);
|
||||
|
||||
void loadMessagingDependencies(Set<MessagingType> types);
|
||||
|
||||
ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies);
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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<Dependency, Path> 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<Dependency> 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<MessagingType> types) {
|
||||
loadDependencies(this.registry.resolveMessagingDependencies(types));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies) {
|
||||
ImmutableSet<Dependency> set = ImmutableSet.copyOf(dependencies);
|
||||
|
|
|
@ -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<StorageType, Dependency> STORAGE_DEPENDENCIES = ImmutableSetMultimap.<StorageType, Dependency>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<StorageType, Dependency> STORAGE_DEPENDENCIES =
|
||||
ImmutableSetMultimap.<StorageType, Dependency>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<MessagingType, Dependency> MESSAGING_DEPENDENCIES =
|
||||
ImmutableSetMultimap.<MessagingType, Dependency>builder()
|
||||
.putAll(
|
||||
MessagingType.REDIS,
|
||||
Dependency.COMMONS_POOL_2,
|
||||
Dependency.JEDIS,
|
||||
Dependency.SLF4J_API,
|
||||
Dependency.SLF4J_SIMPLE)
|
||||
.build();
|
||||
|
||||
public Set<Dependency> resolveStorageDependencies(Set<StorageType> types) {
|
||||
Set<Dependency> dependencies = new LinkedHashSet<>();
|
||||
|
@ -26,6 +39,16 @@ public class DependencyRegistry {
|
|||
return dependencies;
|
||||
}
|
||||
|
||||
public Set<Dependency> resolveMessagingDependencies(Set<MessagingType> types) {
|
||||
Set<Dependency> 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;
|
||||
|
|
|
@ -11,5 +11,4 @@ public class IsolatedClassLoader extends URLClassLoader {
|
|||
public IsolatedClassLoader(URL[] urls) {
|
||||
super(urls, ClassLoader.getSystemClassLoader().getParent());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
// Copyright (c) contributors
|
||||
// Under MIT License
|
||||
|
||||
package dev.xhyrom.lighteco.common.dependencies;
|
||||
package dev.xhyrom.lighteco.common.dependencies;
|
||||
|
|
|
@ -17,5 +17,4 @@ public class Relocation {
|
|||
this.pattern = pattern;
|
||||
this.relocatedPattern = relocatedPattern;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ import java.nio.file.Path;
|
|||
import java.util.*;
|
||||
|
||||
public class RelocationHandler {
|
||||
public static final Set<Dependency> DEPENDENCIES = EnumSet.of(Dependency.ASM, Dependency.ASM_COMMONS, Dependency.JAR_RELOCATOR);
|
||||
public static final Set<Dependency> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ public interface Manager<I, T> {
|
|||
T apply(I identifier);
|
||||
|
||||
Collection<I> keys();
|
||||
|
||||
Collection<T> values();
|
||||
|
||||
T getOrMake(I identifier);
|
||||
|
|
|
@ -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<String, CurrencyMessageConfig> config;
|
||||
private final ArrayList<UUID> 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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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<String, Currency> implements CurrencyManager {
|
||||
public class StandardCurrencyManager extends SingleManager<String, Currency>
|
||||
implements CurrencyManager {
|
||||
private final LightEcoPlugin plugin;
|
||||
|
||||
public StandardCurrencyManager(LightEcoPlugin plugin) {
|
||||
|
@ -32,10 +34,14 @@ public class StandardCurrencyManager extends SingleManager<String, Currency> 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);
|
||||
|
|
|
@ -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<UUID, User> 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<UUID, User> implement
|
|||
|
||||
@Override
|
||||
public CompletableFuture<Void> saveUser(User user) {
|
||||
return this.plugin.getStorage().saveUser(user.getProxy());
|
||||
return this.plugin.getStorage().saveUser(user.getProxy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ public class UserHousekeeper implements Runnable {
|
|||
|
||||
private final ExpiringSet<UUID> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,10 @@ public interface UserManager extends Manager<UUID, User> {
|
|||
UserHousekeeper getHousekeeper();
|
||||
|
||||
CompletableFuture<Void> saveUser(User user);
|
||||
|
||||
CompletableFuture<Void> saveUsers(User... users);
|
||||
|
||||
CompletableFuture<User> loadUser(UUID uniqueId);
|
||||
|
||||
CompletableFuture<User> loadUser(UUID uniqueId, String username);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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<UUID> 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();
|
||||
}
|
||||
}
|
|
@ -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<MessagingType> 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;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package dev.xhyrom.lighteco.common.messaging;
|
||||
|
||||
public enum MessagingType {
|
||||
NONE,
|
||||
REDIS
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package dev.xhyrom.lighteco.common.messaging.message;
|
||||
|
||||
public enum MessageType {
|
||||
USER_UPDATE;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package dev.xhyrom.lighteco.common.model.chat;
|
||||
|
||||
public abstract class AbstractCommandSender<T> implements CommandSender {
|
||||
protected final T delegate;
|
||||
protected final T delegate;
|
||||
|
||||
protected AbstractCommandSender(T delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
protected AbstractCommandSender(T delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<InternalMessagingService> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
* Common classes used by all platform-specific implementations.
|
||||
*/
|
||||
package dev.xhyrom.lighteco.common;
|
||||
package dev.xhyrom.lighteco.common;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue