1
0
Fork 0
mirror of https://github.com/xHyroM/lighteco.git synced 2024-11-26 00:21:04 +01:00

Merge branch 'main' into feat/better-command-abstraction

This commit is contained in:
Jozef Steinhübl 2023-11-01 15:14:58 +01:00 committed by GitHub
commit 723fd6abd4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 328 additions and 63 deletions

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/lightecp) - **Open-source** - LightEco is open-source, and is available on [GitHub](https://github.com/xHyroM/lighteco)
## Development ## Development
@ -23,4 +23,4 @@ Monorepo structure:
## License ## License
LightEco is licensed under the [Apache-2.0 License](./LICENSE). LightEco is licensed under the [Apache-2.0 License](./LICENSE).

36
SECURITY.md Normal file
View file

@ -0,0 +1,36 @@
# Security Policy
## Supported Versions
LightEco is currently in alpha version, which means it's still not done. As such, it may contain bugs or other issues. We are working hard to improve the plugin and fix any problems that are found, but we encourage users to report any issues they encounter to us so that we can address them as quickly as possible.
| Version | Supported |
| ------- | ------------------ |
| 0.x.x | :white_check_mark: |
## Reporting a Vulnerability
If you find a security vulnerability, please report it to us as soon as possible. We take security very seriously and we appreciate your help in keeping our plugin safe.
**How to report a vulnerability**
You can report a vulnerability to us by:
* **Discord:** Contact me on Discord at [`xhyrom`](https://s.xhyrom.dev/discord-user).
* **Email:** Send an email to `github@xhyrom.dev`.
**What to expect when reporting a vulnerability**
We will investigate your report as soon as possible. We will typically provide you with an update within 24 hours.
If the vulnerability is accepted, we will work to fix it as quickly as possible. We will notify you when the fix is released.
If the vulnerability is declined, we will provide you with a reason for the decision.
**What to include in your report**
When reporting a vulnerability, please include the following information:
* **A detailed description of the vulnerability.** This should include how the vulnerability can be exploited and what impact it could have.
* **Steps to reproduce the vulnerability.** This will help us to quickly investigate the issue.
* **Any additional information that you think may be helpful.** This could include screenshots, code samples, or other relevant data.

View file

@ -3,6 +3,12 @@ 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

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

View file

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

View file

@ -13,6 +13,19 @@ 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}
* *

View file

@ -1,6 +1,7 @@
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;
@ -59,4 +60,12 @@ public interface User {
* @throws IllegalArgumentException if the amount is negative * @throws IllegalArgumentException if the amount is negative
*/ */
void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException; void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException;
/**
* Send a message to this user.
* Message will be silently dropped if the user is offline.
*
* @param message the message
*/
void sendMessage(Component message);
} }

View file

@ -13,9 +13,11 @@ val commitHash = determineCommitHash(project)
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)
} }
} }
@ -54,5 +56,5 @@ fun determineCommitHash(project: Project): String {
standardOutput = commitHashInfo standardOutput = commitHashInfo
} }
return commitHashInfo.toString() return commitHashInfo.toString().strip()
} }

View file

@ -23,4 +23,63 @@ tasks {
compileJava { compileJava {
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

@ -13,7 +13,7 @@ repositories {
dependencies { dependencies {
implementation(project(":lighteco-common")) implementation(project(":lighteco-common"))
implementation("dev.jorel:commandapi-bukkit-shade:9.1.0") implementation("dev.jorel:commandapi-bukkit-shade:9.2.0")
implementation("net.kyori:adventure-platform-bukkit:4.2.0") implementation("net.kyori:adventure-platform-bukkit:4.2.0")
compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT")

View file

@ -9,6 +9,8 @@ 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 lombok.Getter; import lombok.Getter;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
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;
@ -29,6 +31,7 @@ public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr
private final PluginLogger logger; private final PluginLogger logger;
@Getter @Getter
private final SchedulerAdapter scheduler; private final SchedulerAdapter scheduler;
private BukkitAudiences audience;
public BukkitLightEcoBootstrap(JavaPlugin loader) { public BukkitLightEcoBootstrap(JavaPlugin loader) {
this.loader = loader; this.loader = loader;
@ -48,6 +51,8 @@ public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr
public void onEnable() { public void onEnable() {
CommandAPI.onEnable(); CommandAPI.onEnable();
this.plugin.enable(); this.plugin.enable();
this.audience = BukkitAudiences.create(loader);
} }
@Override @Override
@ -83,4 +88,9 @@ public class BukkitLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr
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

@ -1,7 +1,5 @@
package dev.xhyrom.lighteco.bukkit; package dev.xhyrom.lighteco.bukkit;
import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.CommandAPIBukkitConfig;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
// Used inside plugin.yml // Used inside plugin.yml
@ -16,20 +14,15 @@ public class BukkitLightEcoLoader extends JavaPlugin {
@Override @Override
public void onLoad() { public void onLoad() {
this.bootstrap.onLoad(); this.bootstrap.onLoad();
CommandAPI.onLoad(new CommandAPIBukkitConfig(this)
.verboseOutput(this.bootstrap.getPlugin().getConfig().debug)
);
} }
@Override @Override
public void onEnable() { public void onEnable() {
CommandAPI.onEnable();
this.bootstrap.onEnable(); this.bootstrap.onEnable();
} }
@Override @Override
public void onDisable() { public void onDisable() {
CommandAPI.onDisable();
this.bootstrap.onDisable(); this.bootstrap.onDisable();
} }
} }

View file

@ -6,31 +6,30 @@ import dev.xhyrom.lighteco.common.model.user.User;
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.bukkit.entity.Player; import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull; import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.Nullable;
@RequiredArgsConstructor @RequiredArgsConstructor
public class PlaceholderAPIExpansion extends PlaceholderExpansion { public class PlaceholderAPIExpansion extends PlaceholderExpansion {
private final BukkitLightEcoPlugin plugin; private final BukkitLightEcoPlugin plugin;
@Override @Override
public @NotNull String getIdentifier() { public @NonNull String getIdentifier() {
return "lighteco"; return "lighteco";
} }
@Override @Override
public @NotNull String getAuthor() { public @NonNull String getAuthor() {
return this.plugin.getBootstrap().getLoader().getDescription().getAuthors().toString(); return this.plugin.getBootstrap().getLoader().getDescription().getAuthors().toString();
} }
@Override @Override
public @NotNull String getVersion() { public @NonNull String getVersion() {
return this.plugin.getBootstrap().getLoader().getDescription().getVersion(); return this.plugin.getBootstrap().getLoader().getDescription().getVersion();
} }
@Override @Override
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) { public @Nullable String onRequest(OfflinePlayer player, @NonNull String params) {
String[] args = params.split("_"); String[] args = params.split("_");
if (args.length < 2) return null; if (args.length < 2) return null;

View file

@ -20,28 +20,11 @@ public class BukkitCommandManager extends AbstractCommandManager {
@Override @Override
public void registerCurrencyCommand(@NonNull Currency currency) { public void registerCurrencyCommand(@NonNull Currency currency) {
String permissionBase = "lighteco.currency." + currency.getIdentifier() + ".command."; registerCommands(currency.getIdentifier(), currency);
// Balance for (String alias : currency.getIdentifierAliases()) {
for (CommandAPICommand cmd : new BalanceCommand( registerCommands(alias, currency);
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 @Override
@ -69,6 +52,30 @@ public class BukkitCommandManager extends AbstractCommandManager {
).multipleBuild()) { ).multipleBuild()) {
cmd.register(); cmd.register();
} }
}
private void registerCommands(@NonNull String name, @NonNull Currency currency) {
String permissionBase = "lighteco.currency." + currency.getIdentifier() + ".command.";
// Balance
for (CommandAPICommand cmd : new BalanceCommand(
this,
name,
currency,
permissionBase
).multipleBuild()) {
cmd.register();
}
CommandAPICommand cmd = new CommandAPICommand(name)
.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();
} }
} }

View file

@ -4,6 +4,7 @@ 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")
@ -23,6 +24,5 @@ dependencies {
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

@ -2,6 +2,7 @@ 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;
@ -60,4 +61,9 @@ public class ApiUser implements User {
this.handler.withdraw(internal, amount); this.handler.withdraw(internal, amount);
} }
@Override
public void sendMessage(Component message) {
this.handler.sendMessage(message);
}
} }

View file

@ -5,7 +5,6 @@ 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;
@ -37,7 +36,7 @@ public class ApiUserManager extends ApiAbstractManager<dev.xhyrom.lighteco.commo
} }
@Override @Override
public @NonNull CompletableFuture<Void> saveUsers(@NotNull @NonNull User... users) { public @NonNull CompletableFuture<Void> saveUsers(@NonNull User... users) {
return this.plugin.getStorage().saveUsers(users); return this.plugin.getStorage().saveUsers(users);
} }

View file

@ -7,6 +7,8 @@ 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 {
@ -21,6 +23,10 @@ public class Config extends OkaeriConfig {
@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

@ -14,8 +14,11 @@ public class CurrencyMessageConfig extends OkaeriConfig {
public String pay = "<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target>"; public String pay = "<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target>";
public String payWithTax = "<currency> <dark_gray>| <gray>Paid <gold><amount> <yellow>to <gold><target> <dark_gray>(<gold><taxed_amount> <yellow>after tax<dark_gray>)"; public String 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 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

@ -1,5 +1,6 @@
package dev.xhyrom.lighteco.common.manager.command; package dev.xhyrom.lighteco.common.manager.command;
import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan;
import dev.xhyrom.lighteco.common.config.message.CurrencyMessageConfig; import dev.xhyrom.lighteco.common.config.message.CurrencyMessageConfig;
import dev.xhyrom.lighteco.common.model.chat.CommandSender; import dev.xhyrom.lighteco.common.model.chat.CommandSender;
import dev.xhyrom.lighteco.common.model.currency.Currency; import dev.xhyrom.lighteco.common.model.currency.Currency;
@ -101,7 +102,19 @@ public abstract class AbstractCommandManager implements CommandManager {
addToMustWait(sender.getUniqueId(), target.getUniqueId()); addToMustWait(sender.getUniqueId(), target.getUniqueId());
amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN);
target.setBalance(currency, amount); try {
target.setBalance(currency, amount);
} catch (CannotBeGreaterThan e) {
removeFromMustWait(target.getUniqueId(), sender.getUniqueId());
sender.sendMessage(
miniMessage.deserialize(
this.getConfig(currency).cannotBeGreaterThan,
Placeholder.parsed("max", this.plugin.getConfig().maximumBalance.toPlainString())
)
);
return;
}
sender.sendMessage( sender.sendMessage(
miniMessage.deserialize( miniMessage.deserialize(
@ -120,7 +133,19 @@ public abstract class AbstractCommandManager implements CommandManager {
addToMustWait(sender.getUniqueId(), target.getUniqueId()); addToMustWait(sender.getUniqueId(), target.getUniqueId());
amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN);
target.deposit(currency, amount); try {
target.deposit(currency, amount);
} catch (CannotBeGreaterThan e) {
removeFromMustWait(target.getUniqueId(), sender.getUniqueId());
sender.sendMessage(
miniMessage.deserialize(
this.getConfig(currency).cannotBeGreaterThan,
Placeholder.parsed("max", this.plugin.getConfig().maximumBalance.toPlainString())
)
);
return;
}
sender.sendMessage( sender.sendMessage(
miniMessage.deserialize( miniMessage.deserialize(
@ -140,7 +165,19 @@ public abstract class AbstractCommandManager implements CommandManager {
addToMustWait(sender.getUniqueId(), target.getUniqueId()); addToMustWait(sender.getUniqueId(), target.getUniqueId());
amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN);
target.withdraw(currency, amount); try {
target.withdraw(currency, amount);
} catch (CannotBeGreaterThan e) {
removeFromMustWait(target.getUniqueId(), sender.getUniqueId());
sender.sendMessage(
miniMessage.deserialize(
this.getConfig(currency).cannotBeGreaterThan,
Placeholder.parsed("max", this.plugin.getConfig().maximumBalance.toPlainString())
)
);
return;
}
sender.sendMessage( sender.sendMessage(
miniMessage.deserialize( miniMessage.deserialize(
@ -186,13 +223,28 @@ public abstract class AbstractCommandManager implements CommandManager {
// subtract tax from amount // subtract tax from amount
BigDecimal taxedAmount = amount.subtract(tax); BigDecimal taxedAmount = amount.subtract(tax);
target.deposit(currency, taxedAmount); try {
user.withdraw(currency, amount); target.deposit(currency, taxedAmount);
user.withdraw(currency, amount);
} catch (CannotBeGreaterThan e) {
removeFromMustWait(target.getUniqueId(), sender.getUniqueId());
sender.sendMessage(
miniMessage.deserialize(
this.getConfig(currency).cannotBeGreaterThan,
Placeholder.parsed("max", this.plugin.getConfig().maximumBalance.toPlainString())
)
);
return;
}
String template = tax.compareTo(BigDecimal.ZERO) > 0 String template = tax.compareTo(BigDecimal.ZERO) > 0
? this.getConfig(currency).payWithTax ? this.getConfig(currency).payWithTax
: this.getConfig(currency).pay; : this.getConfig(currency).pay;
String templateReceived = tax.compareTo(BigDecimal.ZERO) > 0
? this.getConfig(currency).payReceivedWithTax
: this.getConfig(currency).payReceived;
sender.sendMessage( sender.sendMessage(
miniMessage.deserialize( miniMessage.deserialize(
@ -206,6 +258,18 @@ public abstract class AbstractCommandManager implements CommandManager {
) )
); );
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())
)
);
removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); removeFromMustWait(target.getUniqueId(), sender.getUniqueId());
} }
} }

View file

@ -16,6 +16,10 @@ public class Currency {
return proxy.getIdentifier(); return proxy.getIdentifier();
} }
public String[] getIdentifierAliases() {
return proxy.getIdentifierAliases();
}
public dev.xhyrom.lighteco.api.model.currency.Currency.Type getType() { public dev.xhyrom.lighteco.api.model.currency.Currency.Type getType() {
return proxy.getType(); return proxy.getType();
} }

View file

@ -1,11 +1,14 @@
package dev.xhyrom.lighteco.common.model.user; package dev.xhyrom.lighteco.common.model.user;
import dev.xhyrom.lighteco.api.exception.CannotBeGreaterThan;
import dev.xhyrom.lighteco.api.exception.CannotBeNegative;
import dev.xhyrom.lighteco.common.api.impl.ApiUser; import dev.xhyrom.lighteco.common.api.impl.ApiUser;
import dev.xhyrom.lighteco.common.cache.RedisBackedMap; import dev.xhyrom.lighteco.common.cache.RedisBackedMap;
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 lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -46,13 +49,17 @@ public class User {
return balances.getOrDefault(currency, currency.getDefaultBalance()); return balances.getOrDefault(currency, currency.getDefaultBalance());
} }
public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) { public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) throws CannotBeNegative, CannotBeGreaterThan {
this.setBalance(currency, balance, false); this.setBalance(currency, balance, false);
} }
public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance, boolean force) { public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance, boolean force) throws CannotBeNegative, CannotBeGreaterThan {
if (balance.compareTo(BigDecimal.ZERO) < 0) { if (balance.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("Balance cannot be negative"); throw new CannotBeNegative("Balance cannot be negative");
}
if (balance.compareTo(this.plugin.getConfig().maximumBalance) > 0) {
throw new CannotBeGreaterThan("Balance cannot be greater than " + this.plugin.getConfig().maximumBalance);
} }
balance = balance.setScale(currency.fractionalDigits(), RoundingMode.DOWN); balance = balance.setScale(currency.fractionalDigits(), RoundingMode.DOWN);
@ -62,19 +69,27 @@ public class User {
this.setDirty(true); this.setDirty(true);
} }
public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException { public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws CannotBeNegative, CannotBeGreaterThan {
if (amount.compareTo(BigDecimal.ZERO) < 0) { if (amount.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("Amount cannot be negative"); throw new IllegalArgumentException("Amount cannot be negative");
} }
if (amount.compareTo(this.plugin.getConfig().maximumBalance) > 0) {
throw new CannotBeGreaterThan("Amount cannot be greater than " + this.plugin.getConfig().maximumBalance);
}
this.setBalance(currency, this.getBalance(currency).add(amount)); this.setBalance(currency, this.getBalance(currency).add(amount));
} }
public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException { public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws CannotBeNegative, CannotBeGreaterThan {
if (amount.compareTo(BigDecimal.ZERO) < 0) { if (amount.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("Amount cannot be negative"); throw new IllegalArgumentException("Amount cannot be negative");
} }
if (amount.compareTo(this.plugin.getConfig().maximumBalance) > 0) {
throw new CannotBeGreaterThan("Amount cannot be greater than " + this.plugin.getConfig().maximumBalance);
}
if (this.getBalance(currency).compareTo(amount) < 0) { if (this.getBalance(currency).compareTo(amount) < 0) {
// Withdraw all // Withdraw all
amount = this.getBalance(currency); amount = this.getBalance(currency);
@ -82,4 +97,8 @@ public class User {
this.setBalance(currency, this.getBalance(currency).subtract(amount)); this.setBalance(currency, this.getBalance(currency).subtract(amount));
} }
public void sendMessage(@NonNull Component message) {
this.plugin.getBootstrap().getPlayerAudience(this.getUniqueId()).sendMessage(message);
}
} }

View file

@ -2,6 +2,7 @@ package dev.xhyrom.lighteco.common.plugin.bootstrap;
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 net.kyori.adventure.audience.Audience;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Path; import java.nio.file.Path;
@ -20,4 +21,5 @@ public interface LightEcoBootstrap {
List<UUID> getOnlinePlayers(); List<UUID> getOnlinePlayers();
InputStream getResourceStream(String filename); InputStream getResourceStream(String filename);
Audience getPlayerAudience(UUID uniqueId);
} }

View file

@ -5,7 +5,6 @@ import dev.xhyrom.lighteco.api.storage.StorageProvider;
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.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
@ -43,7 +42,7 @@ public class MemoryStorageProvider implements StorageProvider {
} }
@Override @Override
public void saveUsers(@NotNull @NonNull User... users) { public void saveUsers(@NonNull User... users) {
for (User user : users) { for (User user : users) {
this.userDatabase.put(user.getUniqueId(), user); this.userDatabase.put(user.getUniqueId(), user);
} }

View file

@ -8,7 +8,6 @@ import dev.xhyrom.lighteco.common.storage.StorageType;
import dev.xhyrom.lighteco.common.storage.provider.sql.connection.ConnectionFactory; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.ConnectionFactory;
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.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Connection; import java.sql.Connection;
@ -31,7 +30,7 @@ public class SqlStorageProvider implements StorageProvider {
private static final String CREATE_TABLE = """ private static final String CREATE_TABLE = """
CREATE TABLE IF NOT EXISTS '{prefix}_{table}' ( CREATE TABLE IF NOT EXISTS '{prefix}_{table}' (
'uuid' VARCHAR(36) NOT NULL, 'uuid' VARCHAR(36) NOT NULL,
'balance' DECIMAL(10, 2) NOT NULL, 'balance' DECIMAL(20, 2) NOT NULL,
PRIMARY KEY (`uuid`) PRIMARY KEY (`uuid`)
); );
""".trim(); """.trim();
@ -163,7 +162,7 @@ public class SqlStorageProvider implements StorageProvider {
} }
@Override @Override
public void saveUsers(@NotNull @NonNull User... users) throws Exception { public void saveUsers(@NonNull User... users) throws Exception {
// use transaction // use transaction
try (Connection c = this.connectionFactory.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try { try {

View file

@ -15,8 +15,8 @@
- **Vault support** - Money supports Vault, allowing you to use other economy plugins with Money. - **Vault support** - Money supports Vault, allowing you to use other economy plugins with Money.
- **Configurable** - Money is configurable, allowing you to change the currency's name, symbol, and more. - **Configurable** - Money is configurable, allowing you to change the currency's name, symbol, and more.
- **Lightweight** - Money is lightweight, and is designed to be as efficient as possible. - **Lightweight** - Money is lightweight, and is designed to be as efficient as possible.
- **Open-source** - Money is open-source, and is available on [GitHub](https://github.com/xHyroM/tree/main/currency-money) - **Open-source** - Money is open-source, and is available on [GitHub](https://github.com/xHyroM/lighteco/tree/main/currency-money)
## License ## License
Money is licensed under the [Apache-2.0 License](./LICENSE). Money is licensed under the [Apache-2.0 License](./LICENSE).

View file

@ -2,6 +2,8 @@ plugins {
id("lighteco.addon-logic") id("lighteco.addon-logic")
} }
description = "Addon that adds main currency to LightEco that uses Vault to hook into other economy plugins."
repositories { repositories {
maven("https://repo.papermc.io/repository/maven-public/") maven("https://repo.papermc.io/repository/maven-public/")
maven("https://jitpack.io") maven("https://jitpack.io")

View file

@ -2,6 +2,8 @@ package dev.xhyrom.lighteco.currency.money.bukkit.hooks.vault;
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.exception.CannotBeGreaterThan;
import dev.xhyrom.lighteco.api.exception.CannotBeNegative;
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 dev.xhyrom.lighteco.currency.money.common.Plugin; import dev.xhyrom.lighteco.currency.money.common.Plugin;
@ -50,7 +52,7 @@ public class Vault extends AbstractEconomy {
NumberFormat format = NumberFormat.getInstance(); NumberFormat format = NumberFormat.getInstance();
format.setCurrency(java.util.Currency.getInstance(this.plugin.getConfig().currencyCode)); format.setCurrency(java.util.Currency.getInstance(this.plugin.getConfig().currencyCode));
return format.format(BigDecimal.valueOf(amount)); return format.format(amount);
} }
@Override @Override
@ -114,12 +116,12 @@ public class Vault extends AbstractEconomy {
try { try {
user.withdraw(currency, BigDecimal.valueOf(amount)); user.withdraw(currency, BigDecimal.valueOf(amount));
} catch (IllegalArgumentException e) { } catch (CannotBeGreaterThan | CannotBeNegative e) {
return new EconomyResponse( return new EconomyResponse(
amount, amount,
bigDecimalToDouble(user.getBalance(currency)), bigDecimalToDouble(user.getBalance(currency)),
EconomyResponse.ResponseType.FAILURE, EconomyResponse.ResponseType.FAILURE,
"Cannot withdraw negative funds" e.getMessage()
); );
} }
@ -143,12 +145,12 @@ public class Vault extends AbstractEconomy {
try { try {
user.deposit(currency, BigDecimal.valueOf(amount)); user.deposit(currency, BigDecimal.valueOf(amount));
} catch (IllegalArgumentException e) { } catch (CannotBeGreaterThan | CannotBeNegative e) {
return new EconomyResponse( return new EconomyResponse(
amount, amount,
bigDecimalToDouble(user.getBalance(currency)), bigDecimalToDouble(user.getBalance(currency)),
EconomyResponse.ResponseType.FAILURE, EconomyResponse.ResponseType.FAILURE,
"Cannot deposit negative funds" e.getMessage()
); );
} }

View file

@ -17,6 +17,11 @@ public class MoneyCurrency implements Currency {
return "money"; return "money";
} }
@Override
public String[] getIdentifierAliases() {
return new String[]{"eco"};
}
@Override @Override
public Type getType() { public Type getType() {
return Type.LOCAL; return Type.LOCAL;

View file

@ -4,6 +4,7 @@ version: ${version}
main: dev.xhyrom.lighteco.currency.money.bukkit.BukkitMCLoader main: dev.xhyrom.lighteco.currency.money.bukkit.BukkitMCLoader
author: ${author} author: ${author}
api-version: 1.20 api-version: 1.20
load: STARTUP
softdepend: softdepend:
- Vault - Vault

View file

@ -5,6 +5,7 @@ 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 net.kyori.adventure.audience.Audience;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.spongepowered.plugin.builtin.jvm.Plugin; import org.spongepowered.plugin.builtin.jvm.Plugin;
@ -73,4 +74,9 @@ public class SpongeLightEcoBootstrap implements LightEcoBootstrap, LoaderBootstr
public InputStream getResourceStream(String filename) { public InputStream getResourceStream(String filename) {
return null; return null;
} }
@Override
public Audience getPlayerAudience(UUID uniqueId) {
return null;
}
} }