Compare commits

...

16 commits

Author SHA1 Message Date
81f6f24aff Bump to 1.3.1 2026-05-19 20:32:44 -03:00
97f16f98c7 Fix messages in reload command 2026-05-19 20:31:01 -03:00
074f40abdc Merge remote-tracking branch 'origin/main' 2026-05-19 19:49:26 -03:00
1259cd874e Add messages to reload command 2026-05-19 19:48:01 -03:00
f65c3ddc97 Fix bug where Main.addItems would try to add 0 items to Ender Chest. Bumped version to 1.2.1. 2026-05-19 19:41:07 -03:00
天クマ
7e3edff269
Update README.md to include commands
Closes #1
2026-05-19 19:26:12 -03:00
Tenkuma
90b2a117b4
Cleaned up README.md
Configuration section now links to config file from GH tree.
2026-01-04 00:21:24 -03:00
9b3872c8ac Merge remote-tracking branch 'origin/main' 2026-01-03 23:17:06 -03:00
dfbf218aba Added support for localization and localization for Portuguese.
Added support for item name localization.
2026-01-03 23:16:57 -03:00
Tenkuma
d64bc1a144
Added logo to README.md 2026-01-02 21:25:41 -03:00
398bfb6deb Merge remote-tracking branch 'origin/main'
# Conflicts:
#	README.md
2026-01-02 20:57:21 -03:00
717f1b9a1a Bumped version to 1.2.
Added `/balance` and `/pay` commands and a config option to enable them.

Added safeIs method to Config to match values without case sensitivity.

Added getCurrencyText method to Config to generate a formatted string from a currency amount.

Value 'format' from config file now supports amount-name replacement.

Main now stores the instance of VaultLayer for further use.
2026-01-02 20:55:50 -03:00
Tenkuma
6d06921b21
Better formatting of README.md. 2026-01-01 17:57:52 -03:00
f04001176a Bumped version to 1.1.
Rewrite of config loading to support automatic missing field writing, reloading.

Economy item Material is now provided by Config.

Ender Chest support can now be disabled, `getInventory` (renamed to `getInventoryList`, the old method now returns an instance of Inventory) now returns an empty Inventory instance if Ender Chest is disabled.
2026-01-01 15:35:46 -03:00
3d5acde9f8 Merge remote-tracking branch 'origin/main' 2026-01-01 00:13:28 -03:00
9d58d8f377 Added support for Ender Chest item lookup. 2026-01-01 00:12:14 -03:00
16 changed files with 589 additions and 87 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ build/
out/ out/
.idea/ .idea/
libs/ libs/
run/

View file

@ -1,24 +1,37 @@
# ItemEconomy II # ItemEconomy II
ItemEconomy II is a fork of [ItemEconomy](https://modrinth.com/plugin/itemeconomy), keeping it updated to later versions of Minecraft. <p align="center">
<img alt="image" align="center" src="https://github.com/user-attachments/assets/06b7c885-e11d-415c-b45c-bea51f7e2cb7" />
</p>
This PaperMC plugin integrates with Vault to provide a unique, item-based economy system for your Minecraft server. Instead of relying solely on virtual balances, players use in-game items as physical currency, adding a layer of immersion and realism to your economy. **ItemEconomy II** is a fork of [ItemEconomy](https://modrinth.com/plugin/itemeconomy), keeping it updated to later versions of Minecraft and adding new features.
Features:
- Item-Based Currency: Set any Minecraft item as your server's currency (default: diamonds). This PaperMC plugin integrates with VaultUnlocked to provide a unique, item-based economy system for your Minecraft server. Instead of relying solely on virtual balances, players use in-game items as physical currency, adding a layer of immersion and realism to your economy.
- Vault Integration: Fully compatible with Vault, enabling seamless interaction with other economy-based plugins.
- Customizable Formatting: Define how your currency is displayed, including singular and plural forms.
## Configuration Example: ItemEconomy is as powerful as you need and as simple as you want, with every feature being optional.
```yaml
item: "diamond" # Define the item to be used as currency.
singular: "diamond" # Singular form of the currency.
plural: "diamonds" # Plural form of the currency.
format: "{}$" # Customize how the currency is displayed in messages.
```
This configuration will use diamonds as the currency, displayed as {amount}$, e.g., "5 diamonds" or "1 diamond".
## Usage: ## Features
- **Item-Based Currency:** Set any Minecraft item as your server's currency (diamonds by default).
- **VaultUnlocked Integration:** Fully compatible with VaultUnlocked, enabling seamless interaction with other economy-based plugins.
- **Simple logic:** Just checks if the user has the item/how many when queried.
- **Customizable Formatting:** Define how your currency is displayed, including singular and plural forms.
- **Ender Chest support:** Items on Ender Chests are counted in the user balance.
- **Built-int optional balance and pay commands** with support for permissions.
- **Translation support** with per-user language and per-language currency name.
## Configuration
An updated example configuration file is available [here](https://github.com/adrianvic/ItemEconomy/blob/main/src/main/resources/config.yml).
## Usage
- Players can earn, trade, and store the configured item as physical currency. - Players can earn, trade, and store the configured item as physical currency.
- Integrates seamlessly with Vault-compatible plugins for shops, auctions, and more. - Once they spend the currency, that amount of the item will be subtracted from their inventory.
- Administrators can customize the item and formatting to match their server's theme. - Administrators can customize the item and formatting to match their server's theme.
## Commands
<dl>
<dt>/balance <player></dt>
<dd>Prints player balance, permission is `iteco.balance` but is allowed by default. Requires permission `iteco.balance.others` to specify other user.</dd>
<dt>/pay <player> <amount></dt>
<dd>Transfers money from your account to another player's, permission is `iteco.pay` but is allowed by default.</dd>
<dt>/itecoreload</dt>
<dd>Reloads the plugin configuration, requires permission `iteco.reload`.</dd>
</dl>

View file

@ -1,17 +1,120 @@
package io.github.adrianvic.itemeconomy; package io.github.adrianvic.itemeconomy;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.*;
public class Config { public class Config {
public static Material ITEM; private static Map<String, String> entries = new HashMap<>();
public static String FORMAT; private static UnrealConfig uConf;
public static String PLURAL;
public static String SINGULAR;
public static void loadConfig(UnrealConfig conf) { public static void loadConfig(UnrealConfig conf) {
ITEM = Material.valueOf(((String)conf.get("item")).toUpperCase()); uConf = conf;
FORMAT = (String)conf.get("format"); entries.put("item", "diamond");
PLURAL = (String)conf.get("plural"); entries.put("format", "{} $");
SINGULAR = (String)conf.get("singular"); entries.put("plural", "diamonds");
entries.put("singular", "diamond");
entries.put("ender_chest", "balance");
entries.put("commands", "true");
entries.put("player", "&a{}");
entries.put("localization", "default");
getAvailableLocales().forEach(l -> entries.put("plural_%s".formatted(l.getLanguage()), entries.get("plural")));
getAvailableLocales().forEach(l -> entries.put("singular_%s".formatted(l.getLanguage()), entries.get("singular")));
Map<String, String> missingValues = new HashMap<>();
for (Map.Entry<String, String> e : entries.entrySet()) {
String val = (String) conf.get(e.getKey());
if (val != null) {
entries.put(e.getKey(), val);
} else {
missingValues.put(e.getKey(), e.getValue());
}
}
missingValues.forEach((key, value) -> {
conf.put(key, value);
Main.getInstance().getLogger().info("Generating new config entry that was missing: %s: %s".formatted(key, value));
});
conf.save();
}
public static String get(String entry) {
return entries.get(entry);
}
public static boolean is(String entry, String value) {
return entries.get(entry).equals(value);
}
public static boolean safeIs(String entry, String value) {
return is(entry.toLowerCase(Locale.ROOT), value.toLowerCase(Locale.ROOT));
}
public static String getCurrencyText(int amount, String lang) {
String plural = entries.get("plural_%s".formatted(lang));
String singular = entries.get("singular_%s".formatted(lang));
if (plural == null || singular == null) {
plural = entries.get("plural");
singular = entries.get("singular");
}
return ChatColor.translateAlternateColorCodes('&', entries.get("format")
.replace("{}", String.valueOf(amount))
.replace("$", (amount != 1) ? plural : singular)
+ ChatColor.RESET
);
}
public static String getCurrencyText(int amount, Locale locale) {
return getCurrencyText(amount, locale.getLanguage());
}
public static String getCurrencyText(int amount) {
return getCurrencyText(amount, getServerLocale().getLanguage());
}
public static Locale getServerLocale() {
Locale locale = Locale.forLanguageTag(entries.get("localization"));
if (locale.getCountry().isEmpty()) {
locale = Locale.getDefault();
}
return locale;
}
public static UnrealConfig getuConf() {
return uConf;
}
public static Material ecoItem() {
try {
return Material.valueOf(Config.get("item").toUpperCase());
} catch (IllegalArgumentException e) {
Main.getInstance().getLogger().warning("Invalid item was set as economy item, disabling.");
Main.getInstance().getServer().getPluginManager().disablePlugin(Main.getInstance());
}
return Material.DIAMOND;
}
public static String playerPrefix(String playerName) {
return ChatColor.translateAlternateColorCodes('&', entries.get("player").replace("{}", playerName)) + ChatColor.RESET;
}
public static String playerPrefix(Player player) {
return playerPrefix(player.getName());
}
public static Set<Locale> getAvailableLocales() {
return Set.of(
Locale.forLanguageTag("en"),
Locale.forLanguageTag("pt")
);
} }
} }

View file

@ -1,50 +1,148 @@
package io.github.adrianvic.itemeconomy; package io.github.adrianvic.itemeconomy;
import java.util.Arrays; import java.util.*;
import java.util.HashMap;
import java.util.Iterator; import io.github.adrianvic.itemeconomy.commands.Balance;
import java.util.List; import io.github.adrianvic.itemeconomy.commands.Pay;
import io.github.adrianvic.itemeconomy.commands.Reload;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin { public class Main extends JavaPlugin {
private static Main instance;
private static Economy economy;
public void onEnable() { public void onEnable() {
instance = this;
Config.loadConfig(new UnrealConfig(this, this.getDataFolder(), "config.yml")); Config.loadConfig(new UnrealConfig(this, this.getDataFolder(), "config.yml"));
Bukkit.getServicesManager().register(Economy.class, new VaultLayer(), this, ServicePriority.High); getLogger().info(Messages.ENABLING.get(
"ItemEconomy",
getDescription().getVersion(),
Config.getServerLocale()
));
economy = new VaultLayer();
Bukkit.getServicesManager().register(Economy.class, economy, this, ServicePriority.High);
getCommand("itecoreload").setExecutor(new Reload());
if (Config.safeIs("commands", "true")) {
getCommand("balance").setExecutor(new Balance());
getCommand("pay").setExecutor(new Pay());
}
} }
public void onDisable() { public void onDisable() {
super.onDisable(); super.onDisable();
} }
public static List<ItemStack> getInventory(Player player) { public static JavaPlugin getInstance() {
return Arrays.stream(player.getInventory().getContents()).map((o) -> { return instance;
return o == null ? new ItemStack(Material.AIR) : o; }
}).toList();
public static Economy getEconomy() {
return economy;
}
public enum InventoryID {
INVENTORY,
ENDER_CHEST
}
public static Inventory getInventory(Player player, InventoryID inventory) {
Inventory inv = player.getInventory();
switch (inventory) {
case INVENTORY -> inv = player.getInventory();
case ENDER_CHEST -> {
if (Config.is("ender_chest", "balance")) {
inv = player.getEnderChest();
} else {
inv = getInstance().getServer().createInventory(null, 9);
}
}
}
return inv;
}
public static List<ItemStack> getInventoryList(Player player, InventoryID inventory) {
Inventory inv = getInventory(player, inventory);
return Arrays.stream(inv.getContents()).map((o) -> o == null ? new ItemStack(Material.AIR) : o).toList();
}
public static List<ItemStack> getInventoryList(Player player) {
return getInventoryList(player, InventoryID.INVENTORY);
}
public static double getBalance(Player player, InventoryID inventory) {
return getInventoryList(player, inventory).stream().filter(Objects::nonNull).filter((i) -> i.getType().equals(Config.ecoItem())).mapToInt(ItemStack::getAmount).sum();
}
public static double getBalance(Player player) {
double total = 0.0D;
for (InventoryID id : InventoryID.values()) {
total += getBalance(player, id);
}
return total;
}
public static double getBalance(String player) {
return getBalance(Bukkit.getPlayer(player));
} }
public static boolean removeItems(Player player, Material type, int amount) { public static boolean removeItems(Player player, Material type, int amount) {
if (player.getInventory().all(type).values().stream().mapToInt(ItemStack::getAmount).sum() < amount) { int remaining = amount;
return false;
} else { remaining = removeFrom(player.getInventory(), type, remaining);
player.getInventory().removeItem(new ItemStack[]{new ItemStack(type, amount)}); if (remaining > 0) {
return true; remaining = removeFrom(player.getEnderChest(), type, remaining);
} }
return remaining == 0;
}
private static int removeFrom(Inventory inv, Material type, int amount) {
if (amount <= 0) return 0;
for (ItemStack stack : inv.all(type).values()) {
int take = Math.min(stack.getAmount(), amount);
stack.setAmount(stack.getAmount() - take);
amount -= take;
if (amount == 0) break;
}
return amount;
} }
public static void addItems(Player player, Material type, int amount) { public static void addItems(Player player, Material type, int amount) {
HashMap<Integer, ItemStack> nope = player.getInventory().addItem(new ItemStack[]{new ItemStack(type, amount)}); if (amount <= 0) return;
Iterator var4 = nope.values().iterator();
while(var4.hasNext()) { HashMap<Integer, ItemStack> invOverflow =
ItemStack v = (ItemStack)var4.next(); getInventory(player, InventoryID.INVENTORY)
player.getWorld().dropItemNaturally(player.getLocation(), v); .addItem(new ItemStack(type, amount));
int overflowAmount = invOverflow.values()
.stream()
.mapToInt(ItemStack::getAmount)
.sum();
if (overflowAmount <= 0) {
return;
} }
HashMap<Integer, ItemStack> echestOverflow =
getInventory(player, InventoryID.ENDER_CHEST)
.addItem(new ItemStack(type, overflowAmount));
for (ItemStack overflow : echestOverflow.values()) {
player.getWorld().dropItemNaturally(player.getLocation(), overflow);
}
} }
} }

View file

@ -0,0 +1,51 @@
package io.github.adrianvic.itemeconomy;
import io.github.adrianvic.itemeconomy.commands.Utils;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import java.util.Locale;
import java.util.ResourceBundle;
public enum Messages {
ENABLING("enabling"),
BALANCE_SUCCESSFUL("balance-successful"),
BALANCE_OTHER_SUCCESSFUL("balance-other-successful"),
MUST_BE_PLAYER_TO_ISSUE_COMMAND("must-be-player-to-issue-command"),
PAY_SUCCESSFUL("pay-successful"),
PAY_RECEIVED("pay-received"),
PAY_COULD_NOT_REALIZE_TRANSACTION("pay-could-not-realize-transaction"),
PAY_COULD_NOT_FIND_TARGET("pay-could-not-find-target"),
PAY_NOT_ENOUGH_MONEY("pay-not-enough-money"),
PAY_INVALID_AMOUNT("pay-invalid-amount"),
RELOADING("reloading"),
RELOAD_ERROR("reload-error"),
RELOAD_FINISHED("reload-finished");
private final String path;
Messages(String path) { this.path = path; }
private String raw(Locale locale) {
ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
return bundle.getString(path);
}
public String get(Locale locale, Object... args) {
String pattern = raw(locale);
try {
return ChatColor.translateAlternateColorCodes('&', args.length == 0 ? pattern : String.format(pattern, args));
} catch (Exception e) {
return pattern;
}
}
public String get(Player player, Object... args) {
Locale locale = Utils.localeOrDefault(player);
return get(locale, args);
}
public String get(Object... args) {
return get(Config.getServerLocale(), args);
}
}

View file

@ -1,14 +1,12 @@
package io.github.adrianvic.itemeconomy; package io.github.adrianvic.itemeconomy;
import java.util.List; import java.util.List;
import java.util.Objects;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse; import net.milkbowl.vault.economy.EconomyResponse;
import net.milkbowl.vault.economy.EconomyResponse.ResponseType; import net.milkbowl.vault.economy.EconomyResponse.ResponseType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class VaultLayer implements Economy { public class VaultLayer implements Economy {
public boolean isEnabled() { public boolean isEnabled() {
@ -16,7 +14,7 @@ public class VaultLayer implements Economy {
} }
public String getName() { public String getName() {
return "ItemEconomy"; return "ItemEconomy II";
} }
public boolean hasBankSupport() { public boolean hasBankSupport() {
@ -28,15 +26,15 @@ public class VaultLayer implements Economy {
} }
public String format(double amount) { public String format(double amount) {
return Config.FORMAT.replace("{}", String.valueOf(amount)); return Config.getCurrencyText((int) amount);
} }
public String currencyNamePlural() { public String currencyNamePlural() {
return Config.PLURAL; return Config.get("plural");
} }
public String currencyNameSingular() { public String currencyNameSingular() {
return Config.SINGULAR; return Config.get("singular");
} }
public boolean hasAccount(String playerName) { public boolean hasAccount(String playerName) {
@ -44,14 +42,11 @@ public class VaultLayer implements Economy {
} }
public double getBalance(String playerName) { public double getBalance(String playerName) {
Player player = Bukkit.getPlayer(playerName); return Main.getBalance(playerName);
return player != null ? (double)Main.getInventory(player).stream().filter(Objects::nonNull).filter((i) -> {
return i.getType().equals(Config.ITEM);
}).mapToInt(ItemStack::getAmount).sum() : 0.0D;
} }
public boolean has(String playerName, double amount) { public boolean has(String playerName, double amount) {
return this.getBalance(playerName) >= amount; return Main.getBalance(playerName) >= amount;
} }
public EconomyResponse withdrawPlayer(String playerName, double amount) { public EconomyResponse withdrawPlayer(String playerName, double amount) {
@ -60,13 +55,13 @@ public class VaultLayer implements Economy {
} else if (amount < 0.0D) { } else if (amount < 0.0D) {
return this.depositPlayer(playerName, -amount); return this.depositPlayer(playerName, -amount);
} else if (!this.has(playerName, amount)) { } else if (!this.has(playerName, amount)) {
return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "Недостаточно средств"); return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "Insufficient founds.");
} else { } else {
Player player; Player player;
if ((player = Bukkit.getPlayer(playerName)) == null) { if ((player = Bukkit.getPlayer(playerName)) == null) {
return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "Игрок офлайн"); return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "This player is offline.");
} else { } else {
return !Main.removeItems(player, Config.ITEM, (int)amount) ? new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "Недостаточно средств") : new EconomyResponse(amount, this.getBalance(playerName), ResponseType.SUCCESS, (String)null); return !Main.removeItems(player, Config.ecoItem(), (int)amount) ? new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "Insufficient founds.") : new EconomyResponse(amount, this.getBalance(playerName), ResponseType.SUCCESS, (String)null);
} }
} }
} }
@ -79,9 +74,9 @@ public class VaultLayer implements Economy {
} else { } else {
Player player; Player player;
if ((player = Bukkit.getPlayer(playerName)) == null) { if ((player = Bukkit.getPlayer(playerName)) == null) {
return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "Игрок офлайн"); return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.FAILURE, "This player is offline.");
} else { } else {
Main.addItems(player, Config.ITEM, (int)amount); Main.addItems(player, Config.ecoItem(), (int)amount);
return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.SUCCESS, (String)null); return new EconomyResponse(amount, this.getBalance(playerName), ResponseType.SUCCESS, (String)null);
} }
} }

View file

@ -0,0 +1,49 @@
package io.github.adrianvic.itemeconomy.commands;
import io.github.adrianvic.itemeconomy.Config;
import io.github.adrianvic.itemeconomy.Main;
import io.github.adrianvic.itemeconomy.Messages;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.stream.Collectors;
public class Balance implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String @NotNull [] strings) {
if ((commandSender.isOp() || commandSender.hasPermission("iteco.balance.others")) && strings.length > 0) {
double amount = Main.getEconomy().getBalance(strings[0]);
commandSender.sendMessage(Messages.BALANCE_OTHER_SUCCESSFUL.get(
Utils.localeOrDefault(commandSender),
Config.playerPrefix(strings[0]),
Config.getCurrencyText((int) amount, Utils.localeOrDefault(commandSender))
));
} else {
if (commandSender instanceof Player player) {
double amount = Main.getEconomy().getBalance(player);
commandSender.sendMessage(Messages.BALANCE_SUCCESSFUL.get(player, Config.getCurrencyText((int) amount, Utils.localeOrDefault(commandSender))));
} else {
commandSender.sendMessage(Messages.MUST_BE_PLAYER_TO_ISSUE_COMMAND.get());
}
}
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
if ((sender.isOp() || sender.hasPermission("iteco.balance.others")) && args.length == 1) {
return Bukkit.getOnlinePlayers()
.stream()
.map(Player::getName)
.collect(Collectors.toList());
}
return List.of();
}
}

View file

@ -0,0 +1,79 @@
package io.github.adrianvic.itemeconomy.commands;
import io.github.adrianvic.itemeconomy.Config;
import io.github.adrianvic.itemeconomy.Main;
import io.github.adrianvic.itemeconomy.Messages;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
public class Pay implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String @NotNull [] strings) {
if (strings.length < 2) {
commandSender.sendMessage(command.getUsage());
return false;
}
int amount;
try {
amount = Integer.parseInt(strings[1]);
String amountString = Config.getCurrencyText(amount, Utils.localeOrDefault(commandSender));
if (commandSender instanceof Player player && Main.getEconomy().has(player, amount)) {
if (Bukkit.getPlayer(strings[0]) instanceof Player target) {
EconomyResponse withdrawResponse = Main.getEconomy().withdrawPlayer(player.getName(), amount);
if (withdrawResponse.transactionSuccess()) {
EconomyResponse depositResponse = Main.getEconomy().depositPlayer(target.getName(), amount);
if (depositResponse.transactionSuccess()) {
commandSender.sendMessage(Messages.PAY_SUCCESSFUL.get(
Utils.localeOrDefault(commandSender),
amountString,
Config.playerPrefix(target)));
target.sendMessage(Messages.PAY_RECEIVED.get(target, amountString, Config.playerPrefix(player)));
} else {
commandSender.sendMessage(Messages.PAY_COULD_NOT_REALIZE_TRANSACTION.get(Utils.localeOrDefault(commandSender), depositResponse.errorMessage));
Main.getEconomy().depositPlayer(player.getName(), amount);
}
} else {
commandSender.sendMessage(Messages.PAY_COULD_NOT_REALIZE_TRANSACTION.get(Utils.localeOrDefault(commandSender), withdrawResponse.errorMessage));;
}
} else {
commandSender.sendMessage(Messages.PAY_COULD_NOT_FIND_TARGET.get(Utils.localeOrDefault(commandSender)));
}
} else {
commandSender.sendMessage(Messages.PAY_NOT_ENOUGH_MONEY.get(Utils.localeOrDefault(commandSender)));
}
} catch (NumberFormatException nfe) {
commandSender.sendMessage(Messages.PAY_INVALID_AMOUNT.get(Utils.localeOrDefault(commandSender)));
return true;
}
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
if (sender instanceof Player player) {
if (args.length == 1) {
return Bukkit.getOnlinePlayers()
.stream()
.map(Player::getName)
.collect(Collectors.toList());
}
}
return List.of();
}
}

View file

@ -0,0 +1,30 @@
package io.github.adrianvic.itemeconomy.commands;
import io.github.adrianvic.itemeconomy.Config;
import io.github.adrianvic.itemeconomy.Main;
import io.github.adrianvic.itemeconomy.Messages;
import io.github.adrianvic.itemeconomy.UnrealConfig;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Locale;
public class Reload implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String @NotNull [] strings) {
Locale locale = Utils.localeOrDefault(commandSender);
try {
commandSender.sendMessage("[ECONOMY] %s".formatted(Messages.RELOADING.get(locale)));
Config.loadConfig(new UnrealConfig(Main.getInstance(), Main.getInstance().getDataFolder(), "config.yml"));
commandSender.sendMessage("[ECONOMY] %s".formatted(Messages.RELOAD_FINISHED.get(locale)));
return true;
} catch (Exception e) {
commandSender.sendMessage("[ECONOMY] %s".formatted(Messages.RELOAD_ERROR.get(locale)));
e.printStackTrace();
return false;
}
}
}

View file

@ -0,0 +1,15 @@
package io.github.adrianvic.itemeconomy.commands;
import io.github.adrianvic.itemeconomy.Config;
import io.github.adrianvic.itemeconomy.Main;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Locale;
public class Utils {
public static Locale localeOrDefault(CommandSender sender) {
return (sender instanceof Player p) ? Locale.forLanguageTag(p.getLocale().replace('_', '-')) : Config.getServerLocale();
}
}

View file

@ -1,4 +1,7 @@
item: "diamond" item: "diamond" # MUST be a valid item.
singular: "diamond" singular: "diamond"
plural: "diamonds" plural: "diamonds"
format: "{}$" format: "&b{} $" # {} unfolds to amount and $ to singular or plural.
commands: "true" # Enables or disables plugin commands.
player: "&b{}" # {} unfolds to player name.
localization: "default" # can be "en" and "pt" too, if set to anything else uses system locale.

View file

@ -0,0 +1,13 @@
enabling=enabling
balance-successful=balance-successful
balance-other-successful=balance-other-successful
must-be-player-to-issue-command=must-be-player-to-issue-command
pay-successful=pay-successful
pay-received=pay-received
pay-could-not-realize-transaction=pay-could-not-realize-transaction
pay-could-not-find-target=pay-could-not-find-target
pay-not-enough-money=pay-not-enough-money
pay-invalid-amount=pay-invalid-amount
reloading=reloading
reload-error=reload-error
reload-finished=reload-finished

View file

@ -0,0 +1,13 @@
enabling=Starting %s version %s with locale '%s'.
balance-successful=You have %s.
balance-other-successful=%s has %s.
must-be-player-to-issue-command=You must be a player to issue this command.
pay-successful=Transaction of %s to %s was successfully realized.
pay-received=You received %s from %s.
pay-could-not-realize-transaction=Could not realize transaction: %s
pay-could-not-find-target=Could not find target player.
pay-not-enough-money=You don't have enough money.
pay-invalid-amount=The amount you tried to pay is not valid.
reloading=Reloading...
reload-error=An error occurred while reloading the config, please check your logs.
reload-finished=Reload complete.

View file

@ -0,0 +1,13 @@
enabling=Iniciando %s versão %s com localização para %s.
balance-successful=Você tem %s.
balance-other-successful=%s possui %s.
must-be-player-to-issue-command=Você precisa ser um jogador para executar esse comando.
pay-successful=Transação de %s para %s realizada com sucesso.
pay-received=Você recebeu %s de %s.
pay-could-not-realize-transaction=Não foi possível realizar a transação: %s
pay-could-not-find-target=Não foi possível encontrar o jogador-alvo.
pay-not-enough-money=Você não tem dinheiro suficiente.
pay-invalid-amount=A quantidade que você tentou enviar é inválida.
reloading=Recarregando...
reload-error=Ocorreu um erro ao recarregar, por favor, verifique seu registro.
reload-finished=Carregamento completo.

View file

@ -1,6 +1,32 @@
name: ItemEconomy name: ItemEconomy
main: io.github.adrianvic.itemeconomy.Main main: io.github.adrianvic.itemeconomy.Main
version: 1.0 version: 1.3.1
depend: depend: [Vault]
- Vault
api-version: '1.21' api-version: '1.21'
commands:
itecoreload:
description: Reloads the config for ItemEconomy
usage: "/itecoreload"
permission: iteco.reload
default: op
balance:
description: Prints your balance
usage: "/balance"
aliases: [bal]
permission: iteco.balance
pay:
description: Transfers money from your balance to other player
usage: "/pay <player> <amount>"
permission: iteco.pay
permissions:
iteco.reload:
description: "Permission to use the command '/itecoreload'."
default: false
iteco.balance:
description: "Permission to use the command '/balance'."
default: true
children:
iteco.balance.others: false
iteco.pay:
description: "Permission to use the command '/pay'."
default: true