1
0
Fork 0
mirror of https://github.com/xHyroM/lighteco.git synced 2024-11-23 23:31:05 +01:00

Compare commits

..

No commits in common. "5b8045236d40da1d28fde8477b81b08fcf30225b" and "15e23dd047d4eb6bc54e4e7f7515918342b94e8a" have entirely different histories.

161 changed files with 1247 additions and 3128 deletions

View file

@ -12,7 +12,8 @@ jobs:
distribution: 'adopt' distribution: 'adopt'
- name: Build with Gradle - name: Build with Gradle
run: | run: |
./gradlew shadowJar -p paper ./gradlew shadowJar -p bukkittest
./gradlew shadowJar -p bukkit
./gradlew shadowJar -p currency-money ./gradlew shadowJar -p currency-money
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:

1
.gitignore vendored
View file

@ -7,7 +7,6 @@
### ForgeGradle ### ### ForgeGradle ###
# Minecraft client/server files # Minecraft client/server files
run/ run/
runServer/
### Intellij ### ### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider

View file

@ -11,7 +11,7 @@
- **Multi-currency** - LightEco supports creating your own currencies and using them in your server - **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. - **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. - **Storage** - LightEco offers support for multiple storage types.
- **Open-source** - LightEco is open-source, and is available on [GitHub](https://github.com/xHyroM/lighteco) - **Open-source** - LightEco is open-source, and is available on [GitHub](https://github.com/xHyroM/lightecp)
## Development ## Development

View file

@ -1,36 +0,0 @@
# 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.

View file

@ -3,12 +3,6 @@ plugins {
} }
dependencies { 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") compileOnly("org.projectlombok:lombok:1.18.28")
annotationProcessor("org.projectlombok:lombok:1.18.28") annotationProcessor("org.projectlombok:lombok:1.18.28")

View file

@ -3,14 +3,10 @@ package dev.xhyrom.lighteco.api;
import dev.xhyrom.lighteco.api.manager.CommandManager; import dev.xhyrom.lighteco.api.manager.CommandManager;
import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.manager.CurrencyManager;
import dev.xhyrom.lighteco.api.manager.UserManager; 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.Platform;
import dev.xhyrom.lighteco.api.platform.PlayerAdapter; import dev.xhyrom.lighteco.api.platform.PlayerAdapter;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Optional;
public interface LightEco { public interface LightEco {
/** /**
* Gets the {@link Platform}, which represents the current platform the * Gets the {@link Platform}, which represents the current platform the
@ -41,13 +37,6 @@ public interface LightEco {
*/ */
@NonNull CommandManager getCommandManager(); @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. * Gets the {@link PlayerAdapter} for a player class.
* *

View file

@ -1,11 +1,10 @@
package dev.xhyrom.lighteco.api; package dev.xhyrom.lighteco.api;
import static org.jetbrains.annotations.ApiStatus.Internal;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import static org.jetbrains.annotations.ApiStatus.Internal;
@UtilityClass @UtilityClass
public final class LightEcoProvider { public final class LightEcoProvider {
private static LightEco instance; private static LightEco instance;

View file

@ -1,7 +0,0 @@
package dev.xhyrom.lighteco.api.exception;
public class CannotBeGreaterThan extends IllegalArgumentException {
public CannotBeGreaterThan(String message) {
super(message);
}
}

View file

@ -1,7 +0,0 @@
package dev.xhyrom.lighteco.api.exception;
public class CannotBeNegative extends IllegalArgumentException {
public CannotBeNegative(String message) {
super(message);
}
}

View file

@ -1,7 +1,6 @@
package dev.xhyrom.lighteco.api.manager; package dev.xhyrom.lighteco.api.manager;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public interface CommandManager { public interface CommandManager {

View file

@ -1,7 +1,6 @@
package dev.xhyrom.lighteco.api.manager; package dev.xhyrom.lighteco.api.manager;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;

View file

@ -1,7 +1,6 @@
package dev.xhyrom.lighteco.api.manager; package dev.xhyrom.lighteco.api.manager;
import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.model.user.User;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -10,7 +9,6 @@ import java.util.concurrent.CompletableFuture;
public interface UserManager { public interface UserManager {
@NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId); @NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId);
@NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId, String username); @NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId, String username);
@NonNull CompletableFuture<Void> saveUser(@NonNull User user); @NonNull CompletableFuture<Void> saveUser(@NonNull User user);

View file

@ -1,8 +0,0 @@
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);
}

View file

@ -1,11 +0,0 @@
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);
}

View file

@ -1,12 +0,0 @@
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() {}
}

View file

@ -1,7 +0,0 @@
package dev.xhyrom.lighteco.api.messenger;
import org.checkerframework.checker.nullness.qual.NonNull;
public interface MessengerProvider {
@NonNull Messenger obtain(@NonNull IncomingMessageConsumer consumer);
}

View file

@ -1,12 +0,0 @@
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();
}

View file

@ -1,15 +0,0 @@
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();
}

View file

@ -1,24 +0,0 @@
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();
}

View file

@ -13,20 +13,6 @@ public interface Currency {
*/ */
String getIdentifier(); 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} * Returns the type of the currency, either {@link Type#LOCAL} or {@link Type#GLOBAL}
* *
@ -80,8 +66,7 @@ public interface Currency {
*/ */
default BigDecimal calculateTax(User user, BigDecimal amount) { default BigDecimal calculateTax(User user, BigDecimal amount) {
return BigDecimal.ZERO; return BigDecimal.ZERO;
} };
;
/** /**
* Represents the type of currency * Represents the type of currency

View file

@ -1,9 +1,6 @@
package dev.xhyrom.lighteco.api.model.user; package dev.xhyrom.lighteco.api.model.user;
import dev.xhyrom.lighteco.api.model.currency.Currency; 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.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -52,8 +49,7 @@ public interface User {
* @param amount the amount * @param amount the amount
* @throws IllegalArgumentException if the amount is negative * @throws IllegalArgumentException if the amount is negative
*/ */
void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException;
throws IllegalArgumentException;
/** /**
* Subtract the specified amount from the balance of this user for the specified currency. * Subtract the specified amount from the balance of this user for the specified currency.
@ -62,14 +58,5 @@ public interface User {
* @param amount the amount * @param amount the amount
* @throws IllegalArgumentException if the amount is negative * @throws IllegalArgumentException if the amount is negative
*/ */
void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException;
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);
} }

View file

@ -11,7 +11,7 @@ public interface Platform {
@NonNull Type getType(); @NonNull Type getType();
enum Type { enum Type {
PAPER("Paper"), BUKKIT("Bukkit"),
SPONGE("Sponge"), SPONGE("Sponge"),
VELOCITY("Velocity"), VELOCITY("Velocity"),
BUNGEECORD("BungeeCord"); BUNGEECORD("BungeeCord");
@ -27,7 +27,7 @@ public interface Platform {
} }
public boolean isLocal() { public boolean isLocal() {
return this == PAPER || this == SPONGE; return this == BUKKIT || this == SPONGE;
} }
public boolean isProxy() { public boolean isProxy() {

View file

@ -1,7 +1,6 @@
package dev.xhyrom.lighteco.api.platform; package dev.xhyrom.lighteco.api.platform;
import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.model.user.User;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;

View file

@ -2,7 +2,6 @@ package dev.xhyrom.lighteco.api.storage;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;
import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.model.user.User;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -24,10 +23,7 @@ public interface StorageProvider {
void shutdown() throws Exception; void shutdown() throws Exception;
default void registerCurrency(@NonNull Currency currency) throws Exception {} default void registerCurrency(@NonNull Currency currency) throws Exception {}
@NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception; @NonNull User loadUser(@NonNull UUID uniqueId, @Nullable String username) throws Exception;
void saveUser(@NonNull User user) throws Exception; void saveUser(@NonNull User user) throws Exception;
void saveUsers(@NonNull User... users) throws Exception; void saveUsers(@NonNull User... users) throws Exception;
} }

View file

@ -3,7 +3,6 @@ import java.io.ByteArrayOutputStream
plugins { plugins {
id("java") id("java")
id("org.sonarqube") version "4.2.1.3168" id("org.sonarqube") version "4.2.1.3168"
id("com.diffplug.spotless") version "6.25.0"
} }
val majorVersion = 0 val majorVersion = 0
@ -11,20 +10,12 @@ val minorVersion = 1
val patchVersion = determinePatchVersion(project) val patchVersion = determinePatchVersion(project)
val commitHash = determineCommitHash(project) val commitHash = determineCommitHash(project)
defaultTasks("spotlessApply")
repositories {
mavenCentral()
}
allprojects { allprojects {
group = "dev.xhyrom" group = "dev.xhyrom"
version = "$majorVersion.$minorVersion.$patchVersion" version = "$majorVersion.$minorVersion.$patchVersion"
description = "Incredibly fast, lightweight, and modular plugin that excels across multiple platforms."
ext { ext {
set("version", "$majorVersion.$minorVersion.$patchVersion+$commitHash") set("version", "$majorVersion.$minorVersion.$patchVersion+$commitHash")
set("description", description)
} }
} }
@ -35,19 +26,6 @@ subprojects {
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://storehouse.okaeri.eu/repository/maven-public/") 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/**")
} }
} }
@ -76,5 +54,5 @@ fun determineCommitHash(project: Project): String {
standardOutput = commitHashInfo standardOutput = commitHashInfo
} }
return commitHashInfo.toString().strip() return commitHashInfo.toString()
} }

View file

@ -4,12 +4,7 @@ plugins {
} }
java { java {
targetCompatibility = JavaVersion.VERSION_17 // toolchain.languageVersion.set(JavaLanguageVersion.of(17))
sourceCompatibility = JavaVersion.VERSION_17
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
withSourcesJar() withSourcesJar()
} }
@ -18,7 +13,6 @@ tasks {
filesMatching(listOf("plugin.yml")) { filesMatching(listOf("plugin.yml")) {
expand( expand(
"name" to project.name, "name" to project.name,
"coreName" to "LightEco",
"version" to project.version, "version" to project.version,
"description" to project.description, "description" to project.description,
"author" to "xHyroM" "author" to "xHyroM"
@ -30,62 +24,3 @@ tasks {
options.encoding = Charsets.UTF_8.name() 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"))
}
}

View file

@ -5,7 +5,7 @@ plugins {
repositories { repositories {
maven("https://repo.extendedclip.com/content/repositories/placeholderapi") maven("https://repo.extendedclip.com/content/repositories/placeholderapi")
maven("https://repo.papermc.io/repository/maven-public/") maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://oss.sonatype.org/content/repositories/snapshots") maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://oss.sonatype.org/content/repositories/central") maven("https://oss.sonatype.org/content/repositories/central")
} }
@ -13,10 +13,10 @@ repositories {
dependencies { dependencies {
implementation(project(":lighteco-common")) implementation(project(":lighteco-common"))
implementation("dev.jorel:commandapi-bukkit-shade:9.1.0")
implementation("net.kyori:adventure-platform-bukkit:4.2.0") implementation("net.kyori:adventure-platform-bukkit:4.2.0")
compileOnly("io.papermc.paper:paper-api:1.19.1-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-mojangapi:1.19.1-R0.1-SNAPSHOT")
// PlaceholderAPI // PlaceholderAPI
compileOnly("me.clip:placeholderapi:2.11.3") compileOnly("me.clip:placeholderapi:2.11.3")
@ -29,9 +29,7 @@ dependencies {
} }
tasks.shadowJar { tasks.shadowJar {
dependencies { relocate("dev.jorel.commandapi", "dev.xhyrom.lighteco.libraries.commandapi")
exclude(dependency("com.mojang:brigadier"))
}
// common // common
relocate("eu.okaeri.configs", "dev.xhyrom.lighteco.libraries.okaeri.configs") relocate("eu.okaeri.configs", "dev.xhyrom.lighteco.libraries.okaeri.configs")

View file

@ -1,17 +1,13 @@
package dev.xhyrom.lighteco.paper; package dev.xhyrom.lighteco.bukkit;
import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.CommandAPIBukkitConfig;
import dev.xhyrom.lighteco.bukkit.logger.BukkitLogger;
import dev.xhyrom.lighteco.common.plugin.bootstrap.LightEcoBootstrap; import dev.xhyrom.lighteco.common.plugin.bootstrap.LightEcoBootstrap;
import dev.xhyrom.lighteco.common.plugin.bootstrap.LoaderBootstrap; import dev.xhyrom.lighteco.common.plugin.bootstrap.LoaderBootstrap;
import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger;
import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter;
import dev.xhyrom.lighteco.paper.logger.PaperLogger;
import lombok.Getter; import lombok.Getter;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@ -19,45 +15,42 @@ import org.bukkit.plugin.java.JavaPlugin;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@Getter @Getter
public class PaperLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstrap { public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstrap {
private final PaperLightEcoPlugin plugin = new PaperLightEcoPlugin(this); private final BukkitLightEcoPlugin plugin = new BukkitLightEcoPlugin(this);
@Getter @Getter
private final JavaPlugin loader; private final JavaPlugin loader;
@Getter @Getter
private final PluginLogger logger; private final PluginLogger logger;
@Getter @Getter
private final SchedulerAdapter scheduler; private final SchedulerAdapter scheduler;
@Getter public BukkitLightEcoBootstrap(JavaPlugin loader) {
private BukkitAudiences audience;
public PaperLightEcoBootstrap(JavaPlugin loader) {
this.loader = loader; this.loader = loader;
this.logger = new PaperLogger(this.plugin, loader.getLogger()); this.logger = new BukkitLogger(loader.getLogger());
this.scheduler = new PaperSchedulerAdapter(this); this.scheduler = new BukkitSchedulerAdapter(this);
} }
@Override @Override
public void onLoad() { public void onLoad() {
this.plugin.load(); this.plugin.load();
CommandAPI.onLoad(new CommandAPIBukkitConfig(this.loader)
.verboseOutput(this.getPlugin().getConfig().debug)
);
} }
@Override @Override
public void onEnable() { public void onEnable() {
CommandAPI.onEnable();
this.plugin.enable(); this.plugin.enable();
this.audience = BukkitAudiences.create(this.loader);
} }
@Override @Override
public void onDisable() { public void onDisable() {
CommandAPI.onDisable();
this.plugin.disable(); this.plugin.disable();
} }
@ -66,17 +59,6 @@ public class PaperLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstra
return this.loader.getDataFolder().toPath(); return this.loader.getDataFolder().toPath();
} }
@Override
public String getVersion() {
return this.loader.getDescription().getVersion();
}
@Override
public Optional<UUID> lookupUniqueId(String username) {
return Optional.of(this.loader.getServer().getOfflinePlayer(username))
.map(OfflinePlayer::getUniqueId);
}
@Override @Override
public boolean isPlayerOnline(UUID uniqueId) { public boolean isPlayerOnline(UUID uniqueId) {
Player player = this.loader.getServer().getPlayer(uniqueId); Player player = this.loader.getServer().getPlayer(uniqueId);
@ -94,9 +76,4 @@ public class PaperLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstra
public InputStream getResourceStream(String filename) { public InputStream getResourceStream(String filename) {
return this.loader.getResource(filename); return this.loader.getResource(filename);
} }
@Override
public Audience getPlayerAudience(UUID uniqueId) {
return audience.player(uniqueId);
}
} }

View file

@ -0,0 +1,35 @@
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();
}
}

View file

@ -0,0 +1,67 @@
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;
}
}

View file

@ -1,26 +1,25 @@
package dev.xhyrom.lighteco.paper; package dev.xhyrom.lighteco.bukkit;
import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerAdapter;
import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerTask; import dev.xhyrom.lighteco.common.plugin.scheduler.SchedulerTask;
import lombok.Getter;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class PaperSchedulerAdapter implements SchedulerAdapter { public class BukkitSchedulerAdapter implements SchedulerAdapter {
private final Executor async; private final Executor async;
private final PaperLightEcoBootstrap bootstrap; private final BukkitLightEcoBootstrap bootstrap;
private final BukkitScheduler scheduler; private final BukkitScheduler scheduler;
public PaperSchedulerAdapter(PaperLightEcoBootstrap bootstrap) { public BukkitSchedulerAdapter(BukkitLightEcoBootstrap bootstrap) {
this.bootstrap = bootstrap; this.bootstrap = bootstrap;
this.scheduler = bootstrap.getLoader().getServer().getScheduler(); this.scheduler = bootstrap.getLoader().getServer().getScheduler();
this.async = runnable -> this.async = runnable -> this.scheduler.runTaskAsynchronously(this.bootstrap.getLoader(), runnable);
this.scheduler.runTaskAsynchronously(this.bootstrap.getLoader(), runnable);
} }
public Executor async() { public Executor async() {
@ -29,19 +28,29 @@ public class PaperSchedulerAdapter implements SchedulerAdapter {
@Override @Override
public SchedulerTask asyncLater(Runnable runnable, long delay, TimeUnit unit) { public SchedulerTask asyncLater(Runnable runnable, long delay, TimeUnit unit) {
return new Task(this.scheduler.runTaskLaterAsynchronously( return new Task(
this.bootstrap.getLoader(), runnable, unit.toSeconds(delay) * 20)); this.scheduler.runTaskLaterAsynchronously(
this.bootstrap.getLoader(),
runnable,
unit.toSeconds(delay) * 20
)
);
} }
@Override @Override
public SchedulerTask asyncRepeating(Runnable runnable, long interval, TimeUnit unit) { public SchedulerTask asyncRepeating(Runnable runnable, long interval, TimeUnit unit) {
return new Task(this.scheduler.runTaskTimerAsynchronously( return new Task(
this.bootstrap.getLoader(), runnable, 0, unit.toSeconds(interval) * 20)); this.scheduler.runTaskTimerAsynchronously(
this.bootstrap.getLoader(),
runnable,
0,
unit.toSeconds(interval) * 20
)
);
} }
public class Task implements SchedulerTask { public class Task implements SchedulerTask {
private final BukkitTask task; private final BukkitTask task;
public Task(BukkitTask task) { public Task(BukkitTask task) {
this.task = task; this.task = task;
} }

View file

@ -1,17 +1,21 @@
package dev.xhyrom.lighteco.paper.chat; package dev.xhyrom.lighteco.bukkit.chat;
import dev.xhyrom.lighteco.common.model.chat.AbstractCommandSender; import dev.xhyrom.lighteco.common.model.chat.AbstractCommandSender;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.UUID; import java.util.UUID;
public class PaperCommandSender extends AbstractCommandSender<CommandSender> { public class BukkitCommandSender extends AbstractCommandSender<CommandSender> {
public PaperCommandSender(CommandSender sender) { private final Audience audience;
public BukkitCommandSender(CommandSender sender, BukkitAudiences audienceFactory) {
super(sender); super(sender);
this.audience = audienceFactory.sender(sender);
} }
@Override @Override
@ -28,13 +32,8 @@ public class PaperCommandSender extends AbstractCommandSender<CommandSender> {
return null; return null;
} }
@Override
public boolean eligible(String permission) {
return this.delegate.hasPermission(permission);
}
@Override @Override
public void sendMessage(Component message) { public void sendMessage(Component message) {
this.delegate.sendMessage(message); this.audience.sendMessage(message);
} }
} }

View file

@ -0,0 +1,59 @@
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);
});
}
}

View file

@ -0,0 +1,13 @@
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];
}
}

View file

@ -0,0 +1,54 @@
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);
});
}
}

View file

@ -0,0 +1,57 @@
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);
});
}
}

View file

@ -0,0 +1,54 @@
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);
});
}
}

View file

@ -0,0 +1,54 @@
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);
});
}
}

View file

@ -1,16 +1,14 @@
package dev.xhyrom.lighteco.paper.hooks; package dev.xhyrom.lighteco.bukkit.hooks;
import dev.xhyrom.lighteco.paper.PaperLightEcoPlugin;
import dev.xhyrom.lighteco.bukkit.BukkitLightEcoPlugin;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@UtilityClass @UtilityClass
public class Hooks { public class Hooks {
private static PlaceholderAPIExpansion placeholderAPIExpansion; private static PlaceholderAPIExpansion placeholderAPIExpansion;
public static void register(PaperLightEcoPlugin plugin) { public static void register(BukkitLightEcoPlugin plugin) {
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
placeholderAPIExpansion = new PlaceholderAPIExpansion(plugin); placeholderAPIExpansion = new PlaceholderAPIExpansion(plugin);
placeholderAPIExpansion.register(); placeholderAPIExpansion.register();

View file

@ -1,43 +1,36 @@
package dev.xhyrom.lighteco.paper.hooks; package dev.xhyrom.lighteco.bukkit.hooks;
import dev.xhyrom.lighteco.bukkit.BukkitLightEcoPlugin;
import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.model.currency.Currency;
import dev.xhyrom.lighteco.common.model.user.User; import dev.xhyrom.lighteco.common.model.user.User;
import dev.xhyrom.lighteco.paper.PaperLightEcoPlugin;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import me.clip.placeholderapi.expansion.PlaceholderExpansion; import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.checkerframework.checker.nullness.qual.NonNull; import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.Nullable; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@RequiredArgsConstructor @RequiredArgsConstructor
public class PlaceholderAPIExpansion extends PlaceholderExpansion { public class PlaceholderAPIExpansion extends PlaceholderExpansion {
private final PaperLightEcoPlugin plugin; private final BukkitLightEcoPlugin plugin;
@Override @Override
public @NonNull String getIdentifier() { public @NotNull String getIdentifier() {
return "lighteco"; return "lighteco";
} }
@Override @Override
public @NonNull String getAuthor() { public @NotNull String getAuthor() {
return this.plugin return this.plugin.getBootstrap().getLoader().getDescription().getAuthors().toString();
.getBootstrap()
.getLoader()
.getDescription()
.getAuthors()
.toString();
} }
@Override @Override
public @NonNull String getVersion() { public @NotNull String getVersion() {
return this.plugin.getBootstrap().getLoader().getDescription().getVersion(); return this.plugin.getBootstrap().getLoader().getDescription().getVersion();
} }
@Override @Override
public @Nullable String onRequest(OfflinePlayer player, @NonNull String params) { public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
String[] args = params.split("_"); String[] args = params.split("_");
if (args.length < 2) return null; if (args.length < 2) return null;

View file

@ -1,13 +1,11 @@
package dev.xhyrom.lighteco.paper.listeners; package dev.xhyrom.lighteco.bukkit.listeners;
import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.bukkit.BukkitLightEcoPlugin;
import dev.xhyrom.lighteco.common.model.user.User; import dev.xhyrom.lighteco.common.model.user.User;
import dev.xhyrom.lighteco.paper.PaperLightEcoPlugin;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@ -16,11 +14,11 @@ import org.bukkit.event.player.PlayerQuitEvent;
import java.util.UUID; import java.util.UUID;
public class PaperConnectionListener implements Listener { public class BukkitConnectionListener implements Listener {
private final PaperLightEcoPlugin plugin; private final BukkitLightEcoPlugin plugin;
private final MiniMessage miniMessage = MiniMessage.miniMessage(); private final MiniMessage miniMessage = MiniMessage.miniMessage();
public PaperConnectionListener(PaperLightEcoPlugin plugin) { public BukkitConnectionListener(BukkitLightEcoPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
} }
@ -31,24 +29,21 @@ public class PaperConnectionListener implements Listener {
} }
try { try {
this.plugin this.plugin.getStorage().loadUser(event.getUniqueId(), event.getName()).join();
.getStorage()
.loadUser(event.getUniqueId(), event.getName())
.join();
} catch (Exception e) { } catch (Exception e) {
this.plugin this.plugin.getBootstrap().getLogger()
.getBootstrap() .error("Failed to load user data for %s (%s)", e, event.getName(), event.getUniqueId());
.getLogger()
.error(
"Failed to load user data for %s (%s)",
e, event.getName(), event.getUniqueId());
Component reason = miniMessage.deserialize( Component reason = miniMessage.deserialize(
"<bold>LightEco</bold> <red>Failed to load your data. Contact a staff member for assistance."); "<bold>LightEco</bold> <red>Failed to load your data. Contact a staff member for assistance."
);
event.disallow( event.disallow(
AsyncPlayerPreLoginEvent.Result.KICK_OTHER, AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
LegacyComponentSerializer.legacySection().serialize(reason)); LegacyComponentSerializer.legacySection().serialize(
reason
)
);
} }
} }
@ -62,13 +57,12 @@ public class PaperConnectionListener implements Listener {
return; return;
} }
this.plugin.getUserManager().saveUser(user).thenAccept(v -> this.plugin this.plugin.getUserManager().saveUser(user)
.getMessagingService() .thenAccept(v -> {
.ifPresent(service -> { // make sure the player is offline before unloading
for (Currency currency : if (Bukkit.getPlayer(uniqueId) != null) return;
this.plugin.getCurrencyManager().getRegisteredCurrencies()) {
service.pushUserUpdate(user, currency); this.plugin.getUserManager().unload(uniqueId);
} });
}));
} }
} }

View file

@ -1,17 +1,14 @@
package dev.xhyrom.lighteco.paper.logger; package dev.xhyrom.lighteco.bukkit.logger;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class PaperLogger implements PluginLogger { public class BukkitLogger implements PluginLogger {
private final LightEcoPlugin plugin;
private final Logger logger; private final Logger logger;
public PaperLogger(LightEcoPlugin plugin, Logger logger) { public BukkitLogger(Logger logger) {
this.plugin = plugin;
this.logger = logger; this.logger = logger;
} }
@ -25,20 +22,6 @@ public class PaperLogger implements PluginLogger {
this.logger.info(String.format(message, args)); this.logger.info(String.format(message, args));
} }
@Override
public void debug(String message) {
if (!this.plugin.getConfig().debug) return;
info(message);
}
@Override
public void debug(String message, Object... args) {
if (!this.plugin.getConfig().debug) return;
info(message, args);
}
@Override @Override
public void warn(String message) { public void warn(String message) {
this.logger.log(Level.WARNING, message); this.logger.log(Level.WARNING, message);

View file

@ -0,0 +1,74 @@
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();
}
}
}

View file

@ -1,13 +1,12 @@
package dev.xhyrom.lighteco.paper.manager; package dev.xhyrom.lighteco.bukkit.manager;
import dev.xhyrom.lighteco.api.manager.ContextManager; import dev.xhyrom.lighteco.api.manager.ContextManager;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.UUID; import java.util.UUID;
public class PaperContextManager implements ContextManager<Player> { public class BukkitContextManager implements ContextManager<Player> {
@Override @Override
public @NonNull UUID getPlayerUniqueId(@NonNull Player player) { public @NonNull UUID getPlayerUniqueId(@NonNull Player player) {
return player.getUniqueId(); return player.getUniqueId();

View file

@ -1,9 +1,9 @@
name: ${coreName} name: ${name}
description: ${description} description: ${description}
version: ${version} version: ${version}
main: dev.xhyrom.lighteco.paper.PaperLightEcoLoader main: dev.xhyrom.lighteco.bukkit.BukkitLightEcoLoader
author: ${author} author: ${author}
api-version: 1.17 api-version: 1.16
load: STARTUP load: STARTUP
softdepend: softdepend:

44
bukkittest/.gitignore vendored Normal file
View file

@ -0,0 +1,44 @@
.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/

View file

@ -6,17 +6,8 @@ plugins {
} }
server { server {
version = "1.20.6" version = "1.20.1"
type = "purpur" type = "paper"
// Minecraft 1.20.6 requires java 21
java {
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_21
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
} }
repositories { repositories {

View file

@ -1,4 +1,4 @@
package dev.xhyrom.lighteco.test.paper; package dev.xhyrom.lighteco.bukkittest;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;

View file

@ -1,4 +1,4 @@
package dev.xhyrom.lighteco.test.paper; package dev.xhyrom.lighteco.bukkittest;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;
import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.model.user.User;
@ -18,7 +18,7 @@ public class TestCurrency2 implements Currency {
@Override @Override
public boolean isPayable() { public boolean isPayable() {
return false; return true;
} }
@Override @Override

View file

@ -1,9 +1,8 @@
package dev.xhyrom.lighteco.test.paper; package dev.xhyrom.lighteco.bukkittest;
import dev.xhyrom.lighteco.api.LightEco; import dev.xhyrom.lighteco.api.LightEco;
import dev.xhyrom.lighteco.api.LightEcoProvider; import dev.xhyrom.lighteco.api.LightEcoProvider;
import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.manager.CurrencyManager;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@ -20,9 +19,7 @@ public class TestPlugin extends JavaPlugin implements Listener {
getLogger().info("TestCurrency registered!"); getLogger().info("TestCurrency registered!");
currencyManager.getRegisteredCurrencies().forEach(currency -> getLogger() currencyManager.getRegisteredCurrencies().forEach(currency -> getLogger().info("Currency: " + currency.getIdentifier() + " (" + currency.getType() + ", " + currency.fractionalDigits() + ", " + currency.isPayable() + ")"));
.info("Currency: " + currency.getIdentifier() + " (" + currency.getType() + ", "
+ currency.fractionalDigits() + ", " + currency.isPayable() + ")"));
provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test")); provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test"));
provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test2")); provider.getCommandManager().registerCurrencyCommand(currencyManager.getCurrency("test2"));

View file

@ -1,10 +1,10 @@
name: ${name} name: ${name}
description: ${description} description: ${description}
version: ${version} version: ${version}
main: dev.xhyrom.lighteco.test.paper.TestPlugin main: dev.xhyrom.lighteco.bukkittest.TestPlugin
author: ${author} author: ${author}
api-version: 1.20 api-version: 1.20
softdepend: softdepend:
- Vault - Vault
- LightEco - lighteco-bukkit

View file

@ -4,7 +4,6 @@ plugins {
dependencies { dependencies {
api(project(":lighteco-api")) api(project(":lighteco-api"))
api("org.checkerframework:checker-qual:3.8.0")
api("net.kyori:adventure-api:4.12.0") { api("net.kyori:adventure-api:4.12.0") {
exclude(module = "adventure-bom") exclude(module = "adventure-bom")
exclude(module = "checker-qual") exclude(module = "checker-qual")
@ -19,13 +18,11 @@ dependencies {
implementation("eu.okaeri:okaeri-configs-yaml-snakeyaml:5.0.0-beta.5") implementation("eu.okaeri:okaeri-configs-yaml-snakeyaml:5.0.0-beta.5")
implementation("eu.okaeri:okaeri-configs-validator-okaeri: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("com.zaxxer:HikariCP:5.0.1")
compileOnly("redis.clients:jedis:5.1.0")
compileOnly("org.projectlombok:lombok:1.18.28") compileOnly("org.projectlombok:lombok:1.18.28")
annotationProcessor("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") compileOnly("org.jetbrains:annotations:20.1.0")
} }

View file

@ -4,16 +4,12 @@ import dev.xhyrom.lighteco.api.LightEco;
import dev.xhyrom.lighteco.api.manager.CommandManager; import dev.xhyrom.lighteco.api.manager.CommandManager;
import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.manager.CurrencyManager;
import dev.xhyrom.lighteco.api.manager.UserManager; 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.Platform;
import dev.xhyrom.lighteco.api.platform.PlayerAdapter; import dev.xhyrom.lighteco.api.platform.PlayerAdapter;
import dev.xhyrom.lighteco.common.api.impl.*; import dev.xhyrom.lighteco.common.api.impl.*;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Optional;
public class LightEcoApi implements LightEco { public class LightEcoApi implements LightEco {
private final LightEcoPlugin plugin; private final LightEcoPlugin plugin;
@ -53,18 +49,12 @@ public class LightEcoApi implements LightEco {
return this.commandManager; return this.commandManager;
} }
@Override
public @NonNull Optional<MessagingService> getMessagingService() {
return this.plugin.getMessagingService().map(ApiMessagingService::new);
}
@Override @Override
public @NonNull <T> PlayerAdapter<T> getPlayerAdapter(@NonNull Class<T> playerClass) { public @NonNull <T> PlayerAdapter<T> getPlayerAdapter(@NonNull Class<T> playerClass) {
Class<?> expected = this.plugin.getContextManager().getPlayerClass(); Class<?> expected = this.plugin.getContextManager().getPlayerClass();
if (!expected.equals(playerClass)) { if (!expected.equals(playerClass)) {
throw new IllegalArgumentException("Expected player class " + expected.getName() throw new IllegalArgumentException("Expected player class " + expected.getName() + ", got " + playerClass.getName());
+ ", got " + playerClass.getName());
} }
return (PlayerAdapter<T>) this.playerAdapter; return (PlayerAdapter<T>) this.playerAdapter;

View file

@ -4,10 +4,10 @@ import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
public abstract class ApiAbstractManager<H> { public abstract class ApiAbstractManager<H> {
protected final LightEcoPlugin plugin; protected final LightEcoPlugin plugin;
protected final H handle; protected final H handler;
protected ApiAbstractManager(LightEcoPlugin plugin, H handle) { protected ApiAbstractManager(LightEcoPlugin plugin, H handler) {
this.plugin = plugin; this.plugin = plugin;
this.handle = handle; this.handler = handler;
} }
} }

View file

@ -3,30 +3,26 @@ package dev.xhyrom.lighteco.common.api.impl;
import dev.xhyrom.lighteco.api.manager.CommandManager; import dev.xhyrom.lighteco.api.manager.CommandManager;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public class ApiCommandManager public class ApiCommandManager extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.command.CommandManager> implements CommandManager {
extends ApiAbstractManager<dev.xhyrom.lighteco.common.command.CommandManager> public ApiCommandManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.command.CommandManager handler) {
implements CommandManager { super(plugin, handler);
public ApiCommandManager(
LightEcoPlugin plugin, dev.xhyrom.lighteco.common.command.CommandManager handle) {
super(plugin, handle);
} }
@Override @Override
public void registerCurrencyCommand(@NonNull Currency currency) { public void registerCurrencyCommand(@NonNull Currency currency) {
dev.xhyrom.lighteco.common.model.currency.Currency internal = dev.xhyrom.lighteco.common.model.currency.Currency internal = this.plugin.getCurrencyManager()
this.plugin.getCurrencyManager().getIfLoaded(currency.getIdentifier()); .getIfLoaded(currency.getIdentifier());
this.handle.register(internal, false); this.handler.registerCurrencyCommand(internal);
} }
@Override @Override
public void registerCurrencyCommand(@NonNull Currency currency, boolean main) { public void registerCurrencyCommand(@NonNull Currency currency, boolean main) {
dev.xhyrom.lighteco.common.model.currency.Currency internal = dev.xhyrom.lighteco.common.model.currency.Currency internal = this.plugin.getCurrencyManager()
this.plugin.getCurrencyManager().getIfLoaded(currency.getIdentifier()); .getIfLoaded(currency.getIdentifier());
this.handle.register(internal, main); this.handler.registerCurrencyCommand(internal, main);
} }
} }

View file

@ -3,38 +3,34 @@ package dev.xhyrom.lighteco.common.api.impl;
import dev.xhyrom.lighteco.api.manager.CurrencyManager; import dev.xhyrom.lighteco.api.manager.CurrencyManager;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection; import java.util.Collection;
public class ApiCurrencyManager public class ApiCurrencyManager extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.currency.CurrencyManager> implements CurrencyManager {
extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.currency.CurrencyManager> public ApiCurrencyManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.currency.CurrencyManager handler) {
implements CurrencyManager { super(plugin, handler);
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 handle) { private Currency wrap(dev.xhyrom.lighteco.common.model.currency.Currency handler) {
return handle.getProxy(); return handler.getProxy();
} }
@Override @Override
public @NonNull Collection<Currency> getRegisteredCurrencies() { public @NonNull Collection<Currency> getRegisteredCurrencies() {
return this.handle.values().stream().map(this::wrap).toList(); return this.handler.values()
.stream().map(this::wrap)
.toList();
} }
@Override @Override
public Currency getCurrency(@NonNull String identifier) { public Currency getCurrency(@NonNull String identifier) {
return wrap(this.handle.getIfLoaded(identifier)); return wrap(this.handler.getIfLoaded(identifier));
} }
@Override @Override
public void registerCurrency(@NonNull Currency currency) { public void registerCurrency(@NonNull Currency currency) {
dev.xhyrom.lighteco.common.model.currency.Currency internal = dev.xhyrom.lighteco.common.model.currency.Currency internal = new dev.xhyrom.lighteco.common.model.currency.Currency(currency);
new dev.xhyrom.lighteco.common.model.currency.Currency(currency); this.handler.registerCurrency(internal);
this.handle.registerCurrency(internal);
} }
} }

View file

@ -1,22 +0,0 @@
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);
}
}

View file

@ -2,7 +2,6 @@ package dev.xhyrom.lighteco.common.api.impl;
import dev.xhyrom.lighteco.api.platform.Platform; import dev.xhyrom.lighteco.api.platform.Platform;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public class ApiPlatform implements Platform { public class ApiPlatform implements Platform {

View file

@ -1,10 +1,9 @@
package dev.xhyrom.lighteco.common.api.impl; package dev.xhyrom.lighteco.common.api.impl;
import dev.xhyrom.lighteco.api.manager.ContextManager; import dev.xhyrom.lighteco.api.manager.ContextManager;
import dev.xhyrom.lighteco.api.manager.UserManager;
import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.model.user.User;
import dev.xhyrom.lighteco.api.manager.UserManager;
import dev.xhyrom.lighteco.api.platform.PlayerAdapter; import dev.xhyrom.lighteco.api.platform.PlayerAdapter;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.UUID; import java.util.UUID;

View file

@ -2,9 +2,6 @@ package dev.xhyrom.lighteco.common.api.impl;
import dev.xhyrom.lighteco.api.model.currency.Currency; import dev.xhyrom.lighteco.api.model.currency.Currency;
import dev.xhyrom.lighteco.api.model.user.User; 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.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -12,65 +9,55 @@ import java.math.BigDecimal;
import java.util.UUID; import java.util.UUID;
public class ApiUser implements User { public class ApiUser implements User {
public static dev.xhyrom.lighteco.common.model.user.User cast(User u) { private final dev.xhyrom.lighteco.common.model.user.User handler;
if (u instanceof ApiUser) {
return ((ApiUser) u).handle;
}
throw new IllegalArgumentException( public ApiUser(dev.xhyrom.lighteco.common.model.user.User handler) {
"Cannot cast " + u.getClass().getName() + " to " + ApiUser.class.getName()); this.handler = handler;
}
private final dev.xhyrom.lighteco.common.model.user.User handle;
public ApiUser(dev.xhyrom.lighteco.common.model.user.User handle) {
this.handle = handle;
} }
@Override @Override
public @NonNull UUID getUniqueId() { public @NonNull UUID getUniqueId() {
return this.handle.getUniqueId(); return this.handler.getUniqueId();
} }
@Override @Override
public @Nullable String getUsername() { public @Nullable String getUsername() {
return this.handle.getUsername(); return this.handler.getUsername();
} }
@Override @Override
public @NonNull BigDecimal getBalance(@NonNull Currency currency) { public @NonNull BigDecimal getBalance(@NonNull Currency currency) {
dev.xhyrom.lighteco.common.model.currency.Currency internal = dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin()
this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); .getCurrencyManager()
.getIfLoaded(currency.getIdentifier());
return this.handle.getBalance(internal); return this.handler.getBalance(internal);
} }
@Override @Override
public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) { public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) {
dev.xhyrom.lighteco.common.model.currency.Currency internal = dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin()
this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); .getCurrencyManager()
.getIfLoaded(currency.getIdentifier());
this.handle.setBalance(internal, balance); this.handler.setBalance(internal, balance);
} }
@Override @Override
public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) { public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) {
dev.xhyrom.lighteco.common.model.currency.Currency internal = dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin()
this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); .getCurrencyManager()
.getIfLoaded(currency.getIdentifier());
this.handle.deposit(internal, amount); this.handler.deposit(internal, amount);
} }
@Override @Override
public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) { public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) {
dev.xhyrom.lighteco.common.model.currency.Currency internal = dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin()
this.handle.getPlugin().getCurrencyManager().getIfLoaded(currency.getIdentifier()); .getCurrencyManager()
.getIfLoaded(currency.getIdentifier());
this.handle.withdraw(internal, amount); this.handler.withdraw(internal, amount);
}
@Override
public void sendMessage(Component message) {
this.handle.sendMessage(message);
} }
} }

View file

@ -3,24 +3,21 @@ package dev.xhyrom.lighteco.common.api.impl;
import dev.xhyrom.lighteco.api.manager.UserManager; import dev.xhyrom.lighteco.api.manager.UserManager;
import dev.xhyrom.lighteco.api.model.user.User; import dev.xhyrom.lighteco.api.model.user.User;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class ApiUserManager public class ApiUserManager extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.user.UserManager> implements UserManager {
extends ApiAbstractManager<dev.xhyrom.lighteco.common.manager.user.UserManager> public ApiUserManager(LightEcoPlugin plugin, dev.xhyrom.lighteco.common.manager.user.UserManager handler) {
implements UserManager { super(plugin, handler);
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 handle) { private User wrap(dev.xhyrom.lighteco.common.model.user.User handler) {
this.plugin.getUserManager().getHousekeeper().registerUsage(handle.getUniqueId()); this.plugin.getUserManager().getHousekeeper().registerUsage(handler.getUniqueId());
return handle.getProxy(); return handler.getProxy();
} }
@Override @Override
@ -30,7 +27,8 @@ public class ApiUserManager
@Override @Override
public @NonNull CompletableFuture<User> loadUser(@NonNull UUID uniqueId, String username) { 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 @Override
@ -39,17 +37,17 @@ public class ApiUserManager
} }
@Override @Override
public @NonNull CompletableFuture<Void> saveUsers(@NonNull User... users) { public @NonNull CompletableFuture<Void> saveUsers(@NotNull @NonNull User... users) {
return this.plugin.getStorage().saveUsers(users); return this.plugin.getStorage().saveUsers(users);
} }
@Override @Override
public @Nullable User getUser(@NonNull UUID uniqueId) { public @Nullable User getUser(@NonNull UUID uniqueId) {
return wrap(this.handle.getIfLoaded(uniqueId)); return wrap(this.handler.getIfLoaded(uniqueId));
} }
@Override @Override
public boolean isLoaded(@NonNull UUID uniqueId) { public boolean isLoaded(@NonNull UUID uniqueId) {
return this.handle.isLoaded(uniqueId); return this.handler.isLoaded(uniqueId);
} }
} }

View file

@ -10,7 +10,9 @@ public class ExpiringSet<T> {
private final long lifetime; private final long lifetime;
public ExpiringSet(long duration, TimeUnit unit) { 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); this.lifetime = unit.toMillis(duration);
} }

View file

@ -2,4 +2,6 @@ package dev.xhyrom.lighteco.common.cache;
import java.util.HashMap; import java.util.HashMap;
public class RedisBackedMap<T, U> extends HashMap<T, U> {} public class RedisBackedMap<T, U> extends HashMap<T, U> {
}

View file

@ -1,58 +0,0 @@
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;
}
}

View file

@ -1,146 +0,0 @@
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);
}
}
}

View file

@ -1,8 +0,0 @@
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) {}

View file

@ -1,36 +0,0 @@
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);
}
}

View file

@ -1,46 +0,0 @@
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();
}
}

View file

@ -1,9 +0,0 @@
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");
}
}

View file

@ -1,36 +0,0 @@
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();
}
}

View file

@ -1,89 +0,0 @@
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();
}
}

View file

@ -1,61 +0,0 @@
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();
}
}

View file

@ -1,116 +0,0 @@
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();
}
}

View file

@ -1,40 +0,0 @@
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();
}
}

View file

@ -1,160 +0,0 @@
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();
}
}

View file

@ -1,115 +0,0 @@
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();
}
}

View file

@ -1,116 +0,0 @@
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();
}
}

View file

@ -2,38 +2,25 @@ package dev.xhyrom.lighteco.common.config;
import dev.xhyrom.lighteco.common.config.housekeeper.HousekeeperConfig; import dev.xhyrom.lighteco.common.config.housekeeper.HousekeeperConfig;
import dev.xhyrom.lighteco.common.config.message.MessageConfig; 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 dev.xhyrom.lighteco.common.config.storage.StorageConfig;
import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.annotation.Comment;
import eu.okaeri.configs.annotation.Header; import eu.okaeri.configs.annotation.Header;
import java.math.BigDecimal;
@Header("LightEco configuration file.") @Header("LightEco configuration file.")
@Header("") @Header("")
public class Config extends OkaeriConfig { public class Config extends OkaeriConfig {
@Comment("This property must be unique for each server.") @Comment("This property must be unique for each server.")
@Comment( @Comment("If you have multiple servers, you must set this property to a different value for each server.")
"If you have multiple servers, you must set this property to a different value for each server.")
@Comment("Used for local currencies.") @Comment("Used for local currencies.")
public String server = "none"; public String server = "none";
@Comment("Storage settings.") @Comment("Storage settings.")
public StorageConfig storage = new StorageConfig(); public StorageConfig storage = new StorageConfig();
@Comment("Messaging settings.")
public MessagingConfig messaging = new MessagingConfig();
@Comment("Save interval to storage in seconds.") @Comment("Save interval to storage in seconds.")
public long saveInterval = 5L; 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") @Comment("Messages")
public MessageConfig messages = new MessageConfig(); public MessageConfig messages = new MessageConfig();

View file

@ -8,11 +8,9 @@ import java.util.concurrent.TimeUnit;
public class HousekeeperConfig extends OkaeriConfig { public class HousekeeperConfig extends OkaeriConfig {
@Comment("How long should the cache be kept after the last write") @Comment("How long should the cache be kept after the last write")
public int expireAfterWrite = 300; public int expireAfterWrite = 300;
public TimeUnit expireAfterWriteUnit = TimeUnit.SECONDS; public TimeUnit expireAfterWriteUnit = TimeUnit.SECONDS;
@Comment("How often should housekeeper run") @Comment("How often should housekeeper run")
public int runInterval = 60; public int runInterval = 60;
public TimeUnit runIntervalUnit = TimeUnit.SECONDS; public TimeUnit runIntervalUnit = TimeUnit.SECONDS;
} }

View file

@ -4,30 +4,18 @@ import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Variable; import eu.okaeri.configs.annotation.Variable;
public class CurrencyMessageConfig extends OkaeriConfig { public class CurrencyMessageConfig extends OkaeriConfig {
public String balance = public String balance = "<currency> <dark_gray>| <gray>Your balance: <yellow><balance> </yellow></gray>";
"<currency> <dark_gray>| <gray>Your balance: <yellow><balance> </yellow></gray>";
@Variable("balance-others") @Variable("balance-others")
public String balanceOthers = public String balanceOthers = "<currency> <dark_gray>| <gray>Balance of <yellow><target> <dark_gray>| <gray><yellow><balance> </yellow></gray>";
"<currency> <dark_gray>| <gray>Balance of <yellow><target> <dark_gray>| <gray><yellow><balance> </yellow></gray>";
public String set = public String set = "<currency> <dark_gray>| <gray>Set balance of <gold><target> <yellow>to <gold><amount>";
"<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 give = public String take = "<currency> <dark_gray>| <gray>Took <gold><amount> <yellow>from <gold><target>";
"<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 = public String pay = "<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target>";
"<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 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 notEnoughMoney = "<red>You don't have enough money!";
public String cannotPaySelf = "<red>You cannot pay yourself!"; public String cannotPaySelf = "<red>You cannot pay yourself!";
public String cannotBeGreaterThan = "<red>Amount cannot be greater than <gold><max>";
} }

View file

@ -6,9 +6,5 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
public class MessageConfig extends OkaeriConfig { public class MessageConfig extends OkaeriConfig {
public Map<String, CurrencyMessageConfig> currency = public Map<String, CurrencyMessageConfig> currency = Collections.singletonMap("default", new CurrencyMessageConfig());
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.";
} }

View file

@ -1,16 +0,0 @@
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();
}

View file

@ -1,17 +0,0 @@
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;
}

View file

@ -1,7 +1,6 @@
package dev.xhyrom.lighteco.common.config.storage; package dev.xhyrom.lighteco.common.config.storage;
import dev.xhyrom.lighteco.common.storage.StorageType; import dev.xhyrom.lighteco.common.storage.StorageType;
import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.annotation.Comment;

View file

@ -12,7 +12,6 @@ public class StorageDataConfig extends OkaeriConfig {
@Comment("Credentials for connecting to the database.") @Comment("Credentials for connecting to the database.")
public String username = "root"; public String username = "root";
public String password = "password"; public String password = "password";
@Comment("Maximum number of connections in the pool.") @Comment("Maximum number of connections in the pool.")

View file

@ -1,9 +1,7 @@
package dev.xhyrom.lighteco.common.dependencies; package dev.xhyrom.lighteco.common.dependencies;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import dev.xhyrom.lighteco.common.dependencies.relocation.Relocation; import dev.xhyrom.lighteco.common.dependencies.relocation.Relocation;
import lombok.Getter; import lombok.Getter;
import java.util.List; import java.util.List;
@ -14,40 +12,59 @@ public enum Dependency {
* Somewhere we use brackets instad of dots, so we need to rewrite them * 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) * 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"), ASM(
JAR_RELOCATOR("me.lucko", "jar-relocator", "1.7"), "org.ow2.asm",
HIKARI("com{}zaxxer", "HikariCP", "5.0.1", Relocation.of("hikari", "com{}zaxxer{}hikari")), "asm",
H2_DRIVER("com.h2database", "h2", "2.1.214"), "9.1"
SQLITE_DRIVER("org.xerial", "sqlite-jdbc", "3.28.0"), ),
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( MARIADB_DRIVER(
"org{}mariadb{}jdbc", "org{}mariadb{}jdbc",
"mariadb-java-client", "mariadb-java-client",
"3.1.3", "3.1.3",
Relocation.of("mariadb", "org{}mariadb{}jdbc")), Relocation.of("mariadb", "org{}mariadb{}jdbc")
MYSQL_DRIVER("mysql", "mysql-connector-java", "8.0.23", Relocation.of("mysql", "com{}mysql")), ),
MYSQL_DRIVER(
"mysql",
"mysql-connector-java",
"8.0.23",
Relocation.of("mysql", "com{}mysql")
),
POSTGRESQL_DRIVER( POSTGRESQL_DRIVER(
"org{}postgresql", "org{}postgresql",
"postgresql", "postgresql",
"42.6.0", "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 fullPath;
private final String version; private final String version;
@Getter @Getter
private final List<Relocation> relocations; private final List<Relocation> relocations;
@ -58,13 +75,13 @@ public enum Dependency {
} }
Dependency(String groupId, String artifactId, String version, Relocation... relocations) { Dependency(String groupId, String artifactId, String version, Relocation... relocations) {
this.fullPath = String.format( this.fullPath = String.format(MAVEN_FORMAT,
MAVEN_FORMAT,
rewriteEscape(groupId).replace('.', '/'), rewriteEscape(groupId).replace('.', '/'),
rewriteEscape(artifactId), rewriteEscape(artifactId),
version, version,
rewriteEscape(artifactId), rewriteEscape(artifactId),
version); version
);
this.version = version; this.version = version;
this.relocations = ImmutableList.copyOf(relocations); this.relocations = ImmutableList.copyOf(relocations);

View file

@ -1,6 +1,5 @@
package dev.xhyrom.lighteco.common.dependencies; package dev.xhyrom.lighteco.common.dependencies;
import dev.xhyrom.lighteco.common.messaging.MessagingType;
import dev.xhyrom.lighteco.common.storage.StorageType; import dev.xhyrom.lighteco.common.storage.StorageType;
import java.util.Set; import java.util.Set;
@ -10,8 +9,6 @@ public interface DependencyManager extends AutoCloseable {
void loadStorageDependencies(Set<StorageType> types); void loadStorageDependencies(Set<StorageType> types);
void loadMessagingDependencies(Set<MessagingType> types);
ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies); ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies);
@Override @Override

View file

@ -2,16 +2,13 @@ package dev.xhyrom.lighteco.common.dependencies;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.io.MoreFiles; import com.google.common.io.MoreFiles;
import dev.xhyrom.lighteco.common.config.Config; import dev.xhyrom.lighteco.common.config.Config;
import dev.xhyrom.lighteco.common.dependencies.relocation.Relocation; import dev.xhyrom.lighteco.common.dependencies.relocation.Relocation;
import dev.xhyrom.lighteco.common.dependencies.relocation.RelocationHandler; 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.LightEcoPlugin;
import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger; import dev.xhyrom.lighteco.common.plugin.logger.PluginLogger;
import dev.xhyrom.lighteco.common.storage.StorageType;
import dev.xhyrom.lighteco.common.util.URLClassLoaderAccess; import dev.xhyrom.lighteco.common.util.URLClassLoaderAccess;
import dev.xhyrom.lighteco.common.storage.StorageType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import java.io.IOException; import java.io.IOException;
@ -20,6 +17,8 @@ import java.net.URLClassLoader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
public class DependencyManagerImpl implements DependencyManager { public class DependencyManagerImpl implements DependencyManager {
private final EnumMap<Dependency, Path> loaded = new EnumMap<>(Dependency.class); private final EnumMap<Dependency, Path> loaded = new EnumMap<>(Dependency.class);
@ -37,8 +36,7 @@ public class DependencyManagerImpl implements DependencyManager {
this.logger = plugin.getBootstrap().getLogger(); this.logger = plugin.getBootstrap().getLogger();
this.registry = new DependencyRegistry(); this.registry = new DependencyRegistry();
this.cacheDirectory = setupCacheDirectory(plugin); this.cacheDirectory = setupCacheDirectory(plugin);
this.classLoader = URLClassLoaderAccess.create( this.classLoader = URLClassLoaderAccess.create((URLClassLoader) plugin.getBootstrap().getClass().getClassLoader());
(URLClassLoader) plugin.getBootstrap().getClass().getClassLoader());
} }
private synchronized RelocationHandler getRelocationHandler() { private synchronized RelocationHandler getRelocationHandler() {
@ -51,25 +49,42 @@ public class DependencyManagerImpl implements DependencyManager {
@Override @Override
public void loadDependencies(Set<Dependency> dependencies) { public void loadDependencies(Set<Dependency> dependencies) {
if (this.config.debug) this.logger.info("Loading dependencies: " + dependencies); CountDownLatch latch = new CountDownLatch(dependencies.size());
if (this.config.debug)
this.logger.info("Loading dependencies: " + dependencies);
for (Dependency dependency : dependencies) { for (Dependency dependency : dependencies) {
if (this.loaded.containsKey(dependency)) { if (this.loaded.containsKey(dependency)) {
latch.countDown();
continue; continue;
} }
if (this.config.debug) this.logger.info("Loading dependency " + dependency); CompletableFuture.runAsync(() -> {
if (this.config.debug)
this.logger.info("Loading dependency " + dependency);
try { try {
loadDependency(dependency); loadDependency(dependency);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Failed to load dependency " + dependency, e); throw new RuntimeException("Failed to load dependency " + dependency, e);
} finally { } finally {
if (this.config.debug) this.logger.info("Loaded dependency " + dependency); latch.countDown();
if (this.config.debug)
this.logger.info("Loaded dependency " + dependency);
} }
});
} }
if (this.config.debug) this.logger.info("Loaded dependencies: " + dependencies); try {
latch.await();
if (this.config.debug)
this.logger.info("Loaded dependencies: " + dependencies);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} }
private void loadDependency(Dependency dependency) throws Exception { private void loadDependency(Dependency dependency) throws Exception {
@ -127,11 +142,6 @@ public class DependencyManagerImpl implements DependencyManager {
loadDependencies(this.registry.resolveStorageDependencies(types)); loadDependencies(this.registry.resolveStorageDependencies(types));
} }
@Override
public void loadMessagingDependencies(Set<MessagingType> types) {
loadDependencies(this.registry.resolveMessagingDependencies(types));
}
@Override @Override
public ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies) { public ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies) {
ImmutableSet<Dependency> set = ImmutableSet.copyOf(dependencies); ImmutableSet<Dependency> set = ImmutableSet.copyOf(dependencies);

View file

@ -2,16 +2,13 @@ package dev.xhyrom.lighteco.common.dependencies;
import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.SetMultimap; import com.google.common.collect.SetMultimap;
import dev.xhyrom.lighteco.common.messaging.MessagingType;
import dev.xhyrom.lighteco.common.storage.StorageType; import dev.xhyrom.lighteco.common.storage.StorageType;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
public class DependencyRegistry { public class DependencyRegistry {
private static final SetMultimap<StorageType, Dependency> STORAGE_DEPENDENCIES = private static final SetMultimap<StorageType, Dependency> STORAGE_DEPENDENCIES = ImmutableSetMultimap.<StorageType, Dependency>builder()
ImmutableSetMultimap.<StorageType, Dependency>builder()
.putAll(StorageType.SQLITE, Dependency.SQLITE_DRIVER) .putAll(StorageType.SQLITE, Dependency.SQLITE_DRIVER)
.putAll(StorageType.H2, Dependency.H2_DRIVER) .putAll(StorageType.H2, Dependency.H2_DRIVER)
.putAll(StorageType.MYSQL, Dependency.MYSQL_DRIVER, Dependency.HIKARI) .putAll(StorageType.MYSQL, Dependency.MYSQL_DRIVER, Dependency.HIKARI)
@ -19,16 +16,6 @@ public class DependencyRegistry {
.putAll(StorageType.POSTGRESQL, Dependency.POSTGRESQL_DRIVER, Dependency.HIKARI) .putAll(StorageType.POSTGRESQL, Dependency.POSTGRESQL_DRIVER, Dependency.HIKARI)
.build(); .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) { public Set<Dependency> resolveStorageDependencies(Set<StorageType> types) {
Set<Dependency> dependencies = new LinkedHashSet<>(); Set<Dependency> dependencies = new LinkedHashSet<>();
@ -39,16 +26,6 @@ public class DependencyRegistry {
return dependencies; 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) { public boolean shouldAutoLoad(Dependency dependency) {
return switch (dependency) { return switch (dependency) {
case H2_DRIVER, SQLITE_DRIVER -> false; case H2_DRIVER, SQLITE_DRIVER -> false;

View file

@ -11,4 +11,5 @@ public class IsolatedClassLoader extends URLClassLoader {
public IsolatedClassLoader(URL[] urls) { public IsolatedClassLoader(URL[] urls) {
super(urls, ClassLoader.getSystemClassLoader().getParent()); super(urls, ClassLoader.getSystemClassLoader().getParent());
} }
} }

View file

@ -17,4 +17,5 @@ public class Relocation {
this.pattern = pattern; this.pattern = pattern;
this.relocatedPattern = relocatedPattern; this.relocatedPattern = relocatedPattern;
} }
} }

View file

@ -12,8 +12,7 @@ import java.nio.file.Path;
import java.util.*; import java.util.*;
public class RelocationHandler { public class RelocationHandler {
public static final Set<Dependency> DEPENDENCIES = public static final Set<Dependency> DEPENDENCIES = EnumSet.of(Dependency.ASM, Dependency.ASM_COMMONS, Dependency.JAR_RELOCATOR);
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_CLASS = "me.lucko.jarrelocator.JarRelocator";
private static final String JAR_RELOCATOR_RUN_METHOD = "run"; private static final String JAR_RELOCATOR_RUN_METHOD = "run";
@ -32,12 +31,10 @@ public class RelocationHandler {
Class<?> jarRelocatorClass = classLoader.loadClass(JAR_RELOCATOR_CLASS); Class<?> jarRelocatorClass = classLoader.loadClass(JAR_RELOCATOR_CLASS);
// prepare the reflected constructor & method instances // prepare the reflected constructor & method instances
this.jarRelocatorConstructor = this.jarRelocatorConstructor = jarRelocatorClass.getDeclaredConstructor(File.class, File.class, Map.class);
jarRelocatorClass.getDeclaredConstructor(File.class, File.class, Map.class);
this.jarRelocatorConstructor.setAccessible(true); this.jarRelocatorConstructor.setAccessible(true);
this.jarRelocatorRunMethod = this.jarRelocatorRunMethod = jarRelocatorClass.getDeclaredMethod(JAR_RELOCATOR_RUN_METHOD);
jarRelocatorClass.getDeclaredMethod(JAR_RELOCATOR_RUN_METHOD);
this.jarRelocatorRunMethod.setAccessible(true); this.jarRelocatorRunMethod.setAccessible(true);
} catch (Exception e) { } catch (Exception e) {
try { try {
@ -59,8 +56,8 @@ public class RelocationHandler {
} }
// create and invoke a new relocator // create and invoke a new relocator
Object relocator = Object relocator = this.jarRelocatorConstructor.newInstance(input.toFile(), output.toFile(), mappings);
this.jarRelocatorConstructor.newInstance(input.toFile(), output.toFile(), mappings);
this.jarRelocatorRunMethod.invoke(relocator); this.jarRelocatorRunMethod.invoke(relocator);
} }
} }

View file

@ -6,7 +6,6 @@ public interface Manager<I, T> {
T apply(I identifier); T apply(I identifier);
Collection<I> keys(); Collection<I> keys();
Collection<T> values(); Collection<T> values();
T getOrMake(I identifier); T getOrMake(I identifier);

View file

@ -0,0 +1,211 @@
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());
}
}

View file

@ -0,0 +1,23 @@
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);
}

View file

@ -2,7 +2,6 @@ package dev.xhyrom.lighteco.common.manager.currency;
import dev.xhyrom.lighteco.common.manager.Manager; import dev.xhyrom.lighteco.common.manager.Manager;
import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.model.currency.Currency;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection; import java.util.Collection;

View file

@ -3,13 +3,11 @@ package dev.xhyrom.lighteco.common.manager.currency;
import dev.xhyrom.lighteco.common.manager.SingleManager; import dev.xhyrom.lighteco.common.manager.SingleManager;
import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.model.currency.Currency;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection; import java.util.Collection;
public class StandardCurrencyManager extends SingleManager<String, Currency> public class StandardCurrencyManager extends SingleManager<String, Currency> implements CurrencyManager {
implements CurrencyManager {
private final LightEcoPlugin plugin; private final LightEcoPlugin plugin;
public StandardCurrencyManager(LightEcoPlugin plugin) { public StandardCurrencyManager(LightEcoPlugin plugin) {
@ -34,14 +32,10 @@ public class StandardCurrencyManager extends SingleManager<String, Currency>
@Override @Override
public void registerCurrency(@NonNull Currency currency) { public void registerCurrency(@NonNull Currency currency) {
if (this.isLoaded(currency.getIdentifier())) if (this.isLoaded(currency.getIdentifier()))
throw new IllegalArgumentException( throw new IllegalArgumentException("Currency with identifier " + currency.getIdentifier() + " already registered");
"Currency with identifier " + currency.getIdentifier() + " already registered");
if (this.plugin.getConfig().debug) if (this.plugin.getConfig().debug)
this.plugin this.plugin.getBootstrap().getLogger().info("Registering currency " + currency.getIdentifier());
.getBootstrap()
.getLogger()
.info("Registering currency " + currency.getIdentifier());
this.plugin.getStorage().registerCurrencySync(currency.getProxy()); this.plugin.getStorage().registerCurrencySync(currency.getProxy());
this.map.put(currency.getIdentifier(), currency); this.map.put(currency.getIdentifier(), currency);

View file

@ -3,7 +3,6 @@ package dev.xhyrom.lighteco.common.manager.user;
import dev.xhyrom.lighteco.common.manager.ConcurrentManager; import dev.xhyrom.lighteco.common.manager.ConcurrentManager;
import dev.xhyrom.lighteco.common.model.user.User; import dev.xhyrom.lighteco.common.model.user.User;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays; import java.util.Arrays;
@ -12,26 +11,21 @@ import java.util.concurrent.CompletableFuture;
public class StandardUserManager extends ConcurrentManager<UUID, User> implements UserManager { public class StandardUserManager extends ConcurrentManager<UUID, User> implements UserManager {
private final LightEcoPlugin plugin; private final LightEcoPlugin plugin;
@Getter @Getter
private final UserHousekeeper housekeeper; private final UserHousekeeper housekeeper;
public StandardUserManager(LightEcoPlugin plugin) { public StandardUserManager(LightEcoPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
this.housekeeper = new UserHousekeeper( this.housekeeper = new UserHousekeeper(plugin, this, UserHousekeeper.timeoutSettings(
plugin,
this,
UserHousekeeper.timeoutSettings(
this.plugin.getConfig().housekeeper.expireAfterWrite, this.plugin.getConfig().housekeeper.expireAfterWrite,
this.plugin.getConfig().housekeeper.expireAfterWriteUnit)); this.plugin.getConfig().housekeeper.expireAfterWriteUnit
));
this.plugin this.plugin.getBootstrap().getScheduler().asyncRepeating(
.getBootstrap()
.getScheduler()
.asyncRepeating(
this.housekeeper, this.housekeeper,
this.plugin.getConfig().housekeeper.runInterval, this.plugin.getConfig().housekeeper.runInterval,
this.plugin.getConfig().housekeeper.runIntervalUnit); this.plugin.getConfig().housekeeper.runIntervalUnit
);
} }
@Override @Override
@ -60,10 +54,10 @@ public class StandardUserManager extends ConcurrentManager<UUID, User> implement
@Override @Override
public CompletableFuture<Void> saveUsers(User... users) { public CompletableFuture<Void> saveUsers(User... users) {
return this.plugin return this.plugin.getStorage().saveUsers(
.getStorage() Arrays.stream(users)
.saveUsers(Arrays.stream(users)
.map(User::getProxy) .map(User::getProxy)
.toArray(dev.xhyrom.lighteco.api.model.user.User[]::new)); .toArray(dev.xhyrom.lighteco.api.model.user.User[]::new)
);
} }
} }

Some files were not shown because too many files have changed in this diff Show more