Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
b5d1c21
Implement basic of paycheck management system with admin commands and…
Qbiterv Oct 11, 2025
2ec3945
Enhance paycheck system: add price argument resolver, improve paychec…
Qbiterv Oct 12, 2025
57297af
Refactor paycheck system to withdraw system: rename classes and updat…
Qbiterv Oct 12, 2025
a6c2134
Refactor withdraw system: rename classes, update dependencies, and im…
Qbiterv Oct 13, 2025
632c26b
Refactor withdraw system: update message handling, improve price argu…
Qbiterv Oct 13, 2025
dc22d8b
Refactor withdraw system: update plugin metadata handling, adjust ite…
Qbiterv Oct 13, 2025
de005b7
Fix price validation logic in PriceArgumentResolver: update threshold…
Qbiterv Oct 13, 2025
e84550c
Refactor command argument handling: update amount argument to use Pri…
Qbiterv Oct 13, 2025
e558053
Refactor AdminSetCommand: improve method parameter formatting for bet…
Qbiterv Oct 13, 2025
292a847
Refactor WithdrawItemService: ensure default item type is set to PAPE…
Qbiterv Oct 13, 2025
2aba885
Implement WithdrawItemService interface and create WithdrawItemServic…
Qbiterv Oct 15, 2025
40bf52c
Refactor PluginConfig and command classes: replace ItemStack with Con…
Qbiterv Oct 15, 2025
94d83d2
Refactor WithdrawService: update texture assignment to handle absence…
Qbiterv Oct 15, 2025
55aa9b6
Refactor command argument handling: replace PriceArgumentResolver wit…
Qbiterv Oct 17, 2025
df22aa5
Refactor message formatting: streamline chat notices for improved rea…
Qbiterv Oct 18, 2025
4b312cd
Review. Use proper paper-api loader, fix multiple bug's.
vLuckyyy Nov 4, 2025
43aed79
Fix tabulation. Remove useless changes.
vLuckyyy Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eternaleconomy-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies {
// okaeri configs
implementation("eu.okaeri:okaeri-configs-yaml-snakeyaml:${Versions.OKAERI_CONFIGS}")
implementation("eu.okaeri:okaeri-configs-serdes-commons:${Versions.OKAERI_CONFIGS}")
implementation("eu.okaeri:okaeri-configs-serdes-bukkit:${Versions.OKAERI_CONFIGS}")

compileOnly("me.clip:placeholderapi:${Versions.PLACEHOLDER_API}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,44 @@
import com.eternalcode.economy.account.database.AccountRepository;
import com.eternalcode.economy.account.database.AccountRepositoryImpl;
import com.eternalcode.economy.bridge.BridgeManager;
import com.eternalcode.economy.command.impl.admin.AdminAddCommand;
import com.eternalcode.economy.command.impl.admin.AdminBalanceCommand;
import com.eternalcode.economy.command.impl.admin.AdminRemoveCommand;
import com.eternalcode.economy.command.impl.admin.AdminResetCommand;
import com.eternalcode.economy.command.impl.admin.AdminSetCommand;
import com.eternalcode.economy.command.argument.AccountArgument;
import com.eternalcode.economy.command.argument.PriceArgumentResolver;
import com.eternalcode.economy.command.context.AccountContext;
import com.eternalcode.economy.command.cooldown.CommandCooldownEditor;
import com.eternalcode.economy.command.cooldown.CommandCooldownMessage;
import com.eternalcode.economy.command.handler.InvalidUsageHandlerImpl;
import com.eternalcode.economy.command.handler.MissingPermissionHandlerImpl;
import com.eternalcode.economy.command.message.InvalidBigDecimalMessage;
import com.eternalcode.economy.command.impl.MoneyBalanceCommand;
import com.eternalcode.economy.command.impl.MoneyTransferCommand;
import com.eternalcode.economy.database.DatabaseManager;
import com.eternalcode.economy.leaderboard.LeaderboardCommand;
import com.eternalcode.economy.command.impl.admin.*;
import com.eternalcode.economy.command.message.InvalidBigDecimalMessage;
import com.eternalcode.economy.command.validator.notsender.NotSender;
import com.eternalcode.economy.command.validator.notsender.NotSenderValidator;
import com.eternalcode.economy.config.ConfigService;
import com.eternalcode.economy.config.implementation.CommandsConfig;
import com.eternalcode.economy.config.implementation.PluginConfig;
import com.eternalcode.economy.config.implementation.messages.MessageConfig;
import com.eternalcode.economy.database.DatabaseManager;
import com.eternalcode.economy.format.DecimalFormatter;
import com.eternalcode.economy.format.DecimalFormatterImpl;
import com.eternalcode.economy.leaderboard.LeaderboardCommand;
import com.eternalcode.economy.multification.NoticeBroadcastHandler;
import com.eternalcode.economy.multification.NoticeHandler;
import com.eternalcode.economy.multification.NoticeService;
import com.eternalcode.economy.withdraw.WithdrawCommand;
import com.eternalcode.economy.withdraw.WithdrawListener;
import com.eternalcode.economy.withdraw.WithdrawManager;
import com.eternalcode.economy.withdraw.WithdrawTagger;
import com.eternalcode.economy.vault.VaultEconomyProvider;
import com.eternalcode.multification.notice.Notice;
import com.eternalcode.multification.notice.NoticeBroadcast;
import com.google.common.base.Stopwatch;
import dev.rollczi.litecommands.LiteCommands;
import dev.rollczi.litecommands.argument.ArgumentKey;
import dev.rollczi.litecommands.bukkit.LiteBukkitFactory;
import dev.rollczi.litecommands.jakarta.LiteJakartaExtension;
import dev.rollczi.litecommands.message.LiteMessages;
import jakarta.validation.constraints.Positive;
import java.io.File;
import java.math.BigDecimal;
import java.time.Duration;
import net.kyori.adventure.platform.AudienceProvider;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.minimessage.MiniMessage;
Expand All @@ -59,6 +58,10 @@
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.math.BigDecimal;
import java.time.Duration;

@SuppressWarnings("unused")
public class EconomyBukkitPlugin extends JavaPlugin {

Expand Down Expand Up @@ -101,6 +104,9 @@ public void onEnable() {
DecimalFormatter decimalFormatter = new DecimalFormatterImpl(pluginConfig);
AccountPaymentService accountPaymentService = new AccountPaymentService(accountManager, pluginConfig);

WithdrawTagger withdrawTagger = new WithdrawTagger(this);
WithdrawManager withdrawManager = new WithdrawManager(noticeService, pluginConfig, decimalFormatter, withdrawTagger, accountPaymentService, accountManager);

VaultEconomyProvider vaultEconomyProvider =
new VaultEconomyProvider(this, decimalFormatter, accountPaymentService, accountManager);
server.getServicesManager().register(Economy.class, vaultEconomyProvider, this, ServicePriority.Highest);
Expand All @@ -119,7 +125,7 @@ public void onEnable() {
.invalidUsage(new InvalidUsageHandlerImpl(noticeService))

.message(LiteMessages.COMMAND_COOLDOWN, new CommandCooldownMessage(noticeService, commandsConfig))
.message(LiteMessages.INVALID_NUMBER, (invocation, amount) -> noticeService.create()
.message(LiteMessages.INVALID_NUMBER, (invocation, amount) -> noticeService.create()
.notice(messageConfig.positiveNumberRequired)
.placeholder("{AMOUNT}", amount)
.viewer(invocation.sender()))
Expand All @@ -131,6 +137,8 @@ public void onEnable() {
new AdminSetCommand(accountPaymentService, decimalFormatter, noticeService),
new AdminResetCommand(accountPaymentService, noticeService),
new AdminBalanceCommand(noticeService, decimalFormatter),
new AdminItemCommand(withdrawManager),
new WithdrawCommand(withdrawManager, noticeService, decimalFormatter),
new MoneyBalanceCommand(noticeService, decimalFormatter),
new MoneyTransferCommand(accountPaymentService, decimalFormatter, noticeService, pluginConfig),
new EconomyReloadCommand(configService, noticeService),
Expand All @@ -140,13 +148,17 @@ public void onEnable() {
.context(Account.class, new AccountContext(accountManager, messageConfig))
.argument(Account.class, new AccountArgument(accountManager, noticeService, server))

.argument(BigDecimal.class, ArgumentKey.of(PriceArgumentResolver.KEY), new PriceArgumentResolver(pluginConfig, messageConfig))

.result(Notice.class, new NoticeHandler(noticeService))
.result(NoticeBroadcast.class, new NoticeBroadcastHandler())

.build();

server.getPluginManager().registerEvents(new AccountController(accountManager), this);

server.getPluginManager().registerEvents(new WithdrawListener(withdrawManager, withdrawTagger), this);

BridgeManager bridgeManager = new BridgeManager(
this.getDescription(),
accountManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class EconomyPermissionConstant {
public static final String ADMIN_REMOVE_PERMISSION = "eternaleconomy.admin.remove";
public static final String ADMIN_SET_PERMISSION = "eternaleconomy.admin.set";
public static final String ADMIN_RELOAD_PERMISSION = "eternaleconomy.admin.reload";
public static final String ADMIN_ITEM_PERMISSION = "eternaleconomy.admin.item";

public static final String PLAYER_BALANCE_PERMISSION = "eternaleconomy.player.balance";
public static final String PLAYER_BALANCE_OTHER_PERMISSION = "eternaleconomy.player.balance.other";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.eternalcode.economy.command.argument;

import com.eternalcode.economy.config.implementation.PluginConfig;
import com.eternalcode.economy.config.implementation.messages.MessageConfig;
import dev.rollczi.litecommands.argument.Argument;
import dev.rollczi.litecommands.argument.parser.ParseResult;
import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
import dev.rollczi.litecommands.invocation.Invocation;
import org.bukkit.command.CommandSender;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PriceArgumentResolver extends ArgumentResolver<CommandSender, BigDecimal> {
public static final String KEY = "price";
private static final Pattern PRICE_PATTERN =
Pattern.compile("^(\\d+(?:[.,]\\d+)?)([kmb])?$", Pattern.CASE_INSENSITIVE);

private final PluginConfig config;
private final MessageConfig messages;

private final Map<Character, BigDecimal> multipliers;

public PriceArgumentResolver(PluginConfig config, MessageConfig messages) {
this.config = config;
this.messages = messages;
this.multipliers = new HashMap<>();

config.units.format.forEach(unit -> {
this.multipliers.put(unit.getSuffix(), BigDecimal.valueOf(unit.getFactor()));
});
}

@Override
protected ParseResult<BigDecimal> parse(
Invocation<CommandSender> invocation, Argument<BigDecimal> argument, String raw) {
Matcher matcher = PRICE_PATTERN.matcher(raw.toLowerCase());

if (!matcher.matches()) {
return ParseResult.failure(this.messages.invalidPrice);
}

String numberPart = matcher.group(1).replace(',', '.');
String suffix = matcher.group(2);

try {
BigDecimal value = new BigDecimal(numberPart);

if (suffix != null) {
BigDecimal multiplier = multipliers.get(Character.toLowerCase(suffix.charAt(0)));

if (multiplier == null) {
return ParseResult.failure(this.messages.invalidPrice);
}

value = value.multiply(multiplier);
}

if (value.compareTo(BigDecimal.ZERO) <= 0) {
return ParseResult.failure(this.messages.priceNeedToBeGreaterThanZero);
}

return ParseResult.success(value.setScale(2, RoundingMode.DOWN));

} catch (NumberFormatException e) {
return ParseResult.failure(this.messages.invalidPrice);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.eternalcode.economy.command.impl.admin;

import com.eternalcode.economy.EconomyPermissionConstant;
import com.eternalcode.economy.withdraw.WithdrawManager;
import dev.rollczi.litecommands.annotations.command.Command;
import dev.rollczi.litecommands.annotations.context.Context;
import dev.rollczi.litecommands.annotations.execute.Execute;
import dev.rollczi.litecommands.annotations.permission.Permission;
import org.bukkit.entity.Player;

@Command(name = "economy item")
@Permission(EconomyPermissionConstant.ADMIN_ITEM_PERMISSION)
public class AdminItemCommand {
private final WithdrawManager withdrawManager;

public AdminItemCommand(WithdrawManager withdrawManager) {
this.withdrawManager = withdrawManager;
}

@Execute
void execute(@Context Player player) {
withdrawManager.setItem(player);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import eu.okaeri.configs.ConfigManager;
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.serdes.commons.SerdesCommons;
import eu.okaeri.configs.yaml.bukkit.serdes.SerdesBukkit;
import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer;
import java.io.File;
import java.util.HashSet;
Expand All @@ -30,7 +31,7 @@ public <T extends OkaeriConfig> T create(Class<T> config, File file) {
NoticeResolverRegistry noticeRegistry = NoticeResolverDefaults.createRegistry()
.registerResolver(new SoundBukkitResolver());
configFile
.withConfigurer(yamlConfigurer, new SerdesCommons())
.withConfigurer(yamlConfigurer, new SerdesCommons(), new SerdesBukkit())
.withConfigurer(yamlConfigurer, new MultificationSerdesPack(noticeRegistry))
.withBindFile(file)
.withRemoveOrphans(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import com.eternalcode.economy.format.DecimalUnit;
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
Expand All @@ -29,6 +32,9 @@ public class PluginConfig extends OkaeriConfig {
@Comment("Should leaderboard command show player's position in the leaderboard")
public boolean showLeaderboardPosition = true;

@Comment("Currency item settings")
public CurrencyItem currencyItem = new CurrencyItem();

public static class Units extends OkaeriConfig {

public List<DecimalUnit> format = Arrays.asList(
Expand All @@ -40,4 +46,13 @@ public static class Units extends OkaeriConfig {
new DecimalUnit(1_000_000_000_000_000_000L, 'e')
);
}

public static class CurrencyItem extends OkaeriConfig {
@Comment({"Name of the item",
"{VALUE} - value of the check",})
public String name = "<white>Check worth <green>{VALUE}$";

@Comment("Item")
public ItemStack item = new ItemStack(Material.PAPER);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public class MessageConfig extends OkaeriConfig {
public Notice missingPermission = Notice.chat(
"<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <white>Missing permission: <gradient:#00FFA2:#34AE00>{PERMISSION}</gradient>.</white>");

public Notice invalidPrice =
Notice.chat("<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <red>Nieprawidłowy format ceny! Użyj: 1000, 1k, 1.5k, 1m, etc.");
public Notice priceNeedToBeGreaterThanZero = Notice.chat("<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <red>Cena musi być większa od 0!");

public MessageAdminSubSection admin = new MessageAdminSubSection();
public MessagesPlayerSubSection player = new MessagesPlayerSubSection();
public MessagePaycheckSubSection paycheck = new MessagePaycheckSubSection();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.eternalcode.economy.config.implementation.messages;

import com.eternalcode.multification.notice.Notice;
import eu.okaeri.configs.OkaeriConfig;

public class MessagePaycheckSubSection extends OkaeriConfig {
public Notice noItem = Notice.chat(
"<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <red>You must hold item to create paycheck!"
);

public Notice noCheck = Notice.chat(
"<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <red>You must hold an paycheck to redeem it!"
);

public Notice setItem = Notice.chat(
"<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <green>You have set paycheck item to <white>{ITEM}<green>!"
);

public Notice withdraw = Notice.chat(
"<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <green>You have withdrawn a paycheck of <white>{VALUE}<green>!"
);

public Notice redeem = Notice.chat(
"<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray>➤</dark_gray> <green>You have redeemed your paycheck of <white>{VALUE}<green>!"
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class MessagesPlayerSubSection extends OkaeriConfig {
+ " <white><gradient:#00FFA2:#34AE00>{PLAYER}</gradient>'s balance is <gradient:#00FFA2:#34AE00>{BALANCE}</gradient>.</white>");
public Notice insufficientBalance = Notice.chat("<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> "
+ "<dark_gray>➤</dark_gray> <white>Insufficient funds,"
+ " you are missing <gradient:#00FFA2:#34AE00> {MISSING_BALANCE}</gradient>.</white>");
+ " you are missing <gradient:#00FFA2:#34AE00>{MISSING_BALANCE}</gradient>.</white>");
public Notice transferSuccess = Notice.chat("<b><gradient:#00FFA2:#34AE00>ECONOMY</gradient></b> <dark_gray"
+ ">➤</dark_gray> <white>Successfully transferred <gradient:#00FFA2:#34AE00>{AMOUNT}</gradient> to "
+ "<gradient:#00FFA2:#34AE00>{PLAYER}</gradient>.</white>");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.eternalcode.economy.withdraw;

import com.eternalcode.economy.EconomyPermissionConstant;
import com.eternalcode.economy.account.Account;
import com.eternalcode.economy.command.argument.PriceArgumentResolver;
import com.eternalcode.economy.format.DecimalFormatter;
import com.eternalcode.economy.multification.NoticeService;
import dev.rollczi.litecommands.annotations.argument.Arg;
import dev.rollczi.litecommands.annotations.argument.Key;
import dev.rollczi.litecommands.annotations.command.Command;
import dev.rollczi.litecommands.annotations.context.Context;
import dev.rollczi.litecommands.annotations.execute.Execute;
import dev.rollczi.litecommands.annotations.permission.Permission;
import jakarta.validation.constraints.Positive;

import java.math.BigDecimal;

@Command(name = "withdraw", aliases = {"paycheck", "check"})
@Permission(EconomyPermissionConstant.ADMIN_ITEM_PERMISSION)
public class WithdrawCommand {
private final WithdrawManager withdrawManager;
private final NoticeService noticeService;
private final DecimalFormatter decimalFormatter;

public WithdrawCommand(
WithdrawManager withdrawManager,
NoticeService noticeService,
DecimalFormatter decimalFormatter
) {
this.withdrawManager = withdrawManager;
this.noticeService = noticeService;
this.decimalFormatter = decimalFormatter;
}

@Execute
void execute(@Context Account account, @Arg @Positive @Key(PriceArgumentResolver.KEY) BigDecimal value) {
BigDecimal balance = account.balance();
BigDecimal subtract = balance.subtract(value);

if (subtract.compareTo(BigDecimal.ZERO) < 0) {
noticeService.create()
.notice(messageConfig -> messageConfig.player.insufficientBalance)
.placeholder("{MISSING_BALANCE}", decimalFormatter.format(subtract.abs()))
.player(account.uuid())
.send();

return;
}

withdrawManager.givePaycheck(account.uuid(), value);
}
}
Loading