Paper1.21.11Resmi#ekonomi#para#komut

Mini Ekonomi

/bakiye, /pay, /baltop ve yönetici /eco (give/take/set): başlangıç parası, otomatik kayıt, sekme tamamlama. Bağımlılık gerektirmez.

MinborAIminborai 2 0 0 0
Kaynak kod (ZIP)
Tüm hakları saklıdırSunucuda kullanDeğiştirTicari· Atıf gerekli
src/main/java/com/minborai/miniekonomi/MiniEkonomi.java
1package com.minborai.miniekonomi;
2
3import net.kyori.adventure.text.Component;
4import net.kyori.adventure.text.minimessage.MiniMessage;
5import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
6import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
7import org.bukkit.Bukkit;
8import org.bukkit.OfflinePlayer;
9import org.bukkit.command.Command;
10import org.bukkit.command.CommandSender;
11import org.bukkit.configuration.file.YamlConfiguration;
12import org.bukkit.entity.Player;
13import org.bukkit.event.EventHandler;
14import org.bukkit.event.Listener;
15import org.bukkit.event.player.PlayerJoinEvent;
16import org.bukkit.plugin.java.JavaPlugin;
17
18import java.io.File;
19import java.io.IOException;
20import java.math.BigDecimal;
21import java.math.RoundingMode;
22import java.text.DecimalFormat;
23import java.text.DecimalFormatSymbols;
24import java.util.ArrayList;
25import java.util.Collections;
26import java.util.List;
27import java.util.Locale;
28import java.util.Map;
29import java.util.UUID;
30import java.util.concurrent.ConcurrentHashMap;
31
32public final class MiniEkonomi extends JavaPlugin implements Listener {
33
34 private static final MiniMessage MM = MiniMessage.miniMessage();
35 private static final BigDecimal MAX = new BigDecimal("1000000000000");
36
37 private final Map<UUID, BigDecimal> balances = new ConcurrentHashMap<>();
38 private File file;
39 private boolean dirty = false;
40 private DecimalFormat format;
41
42 @Override
43 public void onEnable() {
44 saveDefaultConfig();
45 format = new DecimalFormat("#,##0.##", DecimalFormatSymbols.getInstance(new Locale("tr", "TR")));
46 file = new File(getDataFolder(), "balances.yml");
47 YamlConfiguration yml = YamlConfiguration.loadConfiguration(file);
48 for (String key : yml.getKeys(false)) {
49 try {
50 balances.put(UUID.fromString(key), new BigDecimal(yml.getString(key, "0")));
51 } catch (IllegalArgumentException ignored) {
52 // bozuk satır atlanır
53 }
54 }
55 getServer().getPluginManager().registerEvents(this, this);
56 // Değişiklik varsa 5 dakikada bir kaydet
57 getServer().getScheduler().runTaskTimer(this, () -> {
58 if (dirty) save();
59 }, 6000L, 6000L);
60 }
61
62 @Override
63 public void onDisable() {
64 save();
65 }
66
67 private void save() {
68 YamlConfiguration yml = new YamlConfiguration();
69 balances.forEach((id, value) -> yml.set(id.toString(), value.toPlainString()));
70 try {
71 yml.save(file);
72 dirty = false;
73 } catch (IOException e) {
74 getLogger().warning("balances.yml kaydedilemedi: " + e.getMessage());
75 }
76 }
77
78 public BigDecimal balance(UUID id) {
79 return balances.getOrDefault(id, BigDecimal.ZERO);
80 }
81
82 private void set(UUID id, BigDecimal value) {
83 balances.put(id, value.setScale(2, RoundingMode.HALF_UP));
84 dirty = true;
85 }
86
87 private String money(BigDecimal v) {
88 return format.format(v) + getConfig().getString("currency-symbol", "₺");
89 }
90
91 private Component text(String key, String... pairs) {
92 List<TagResolver> tags = new ArrayList<>();
93 for (int i = 0; i + 1 < pairs.length; i += 2) tags.add(Placeholder.unparsed(pairs[i], pairs[i + 1]));
94 return MM.deserialize(getConfig().getString("messages.prefix", "") + getConfig().getString("messages." + key, key), TagResolver.resolver(tags));
95 }
96
97 /** "12,5" ya da "12.5" → pozitif tutar (2 hane); geçersizse null */
98 private BigDecimal parse(String raw) {
99 try {
100 BigDecimal v = new BigDecimal(raw.replace(',', '.')).setScale(2, RoundingMode.DOWN);
101 return v.signum() > 0 && v.compareTo(MAX) <= 0 ? v : null;
102 } catch (NumberFormatException e) {
103 return null;
104 }
105 }
106
107 private OfflinePlayer find(String name) {
108 Player online = Bukkit.getPlayerExact(name);
109 return online != null ? online : Bukkit.getOfflinePlayerIfCached(name);
110 }
111
112 @EventHandler
113 public void onJoin(PlayerJoinEvent event) {
114 UUID id = event.getPlayer().getUniqueId();
115 if (!balances.containsKey(id)) set(id, BigDecimal.valueOf(getConfig().getDouble("starting-balance", 100)));
116 }
117
118 @Override
119 public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
120 switch (command.getName()) {
121 case "bakiye" -> {
122 if (args.length > 0 && sender.hasPermission("economy.balance.others")) {
123 OfflinePlayer target = find(args[0]);
124 if (target == null) {
125 sender.sendMessage(text("unknown-player", "player", args[0]));
126 return true;
127 }
128 sender.sendMessage(text("balance-other", "player", String.valueOf(target.getName()), "amount", money(balance(target.getUniqueId()))));
129 } else if (sender instanceof Player player) {
130 sender.sendMessage(text("balance", "amount", money(balance(player.getUniqueId()))));
131 } else {
132 sender.sendMessage(text("players-only"));
133 }
134 }
135 case "pay" -> {
136 if (!(sender instanceof Player player)) {
137 sender.sendMessage(text("players-only"));
138 return true;
139 }
140 if (args.length < 2) return false;
141 OfflinePlayer target = find(args[0]);
142 BigDecimal amount = parse(args[1]);
143 if (target == null) {
144 sender.sendMessage(text("unknown-player", "player", args[0]));
145 return true;
146 }
147 if (target.getUniqueId().equals(player.getUniqueId())) {
148 sender.sendMessage(text("pay-self"));
149 return true;
150 }
151 if (amount == null) {
152 sender.sendMessage(text("invalid-amount"));
153 return true;
154 }
155 if (balance(player.getUniqueId()).compareTo(amount) < 0) {
156 sender.sendMessage(text("not-enough", "amount", money(balance(player.getUniqueId()))));
157 return true;
158 }
159 set(player.getUniqueId(), balance(player.getUniqueId()).subtract(amount));
160 set(target.getUniqueId(), balance(target.getUniqueId()).add(amount));
161 sender.sendMessage(text("paid", "player", String.valueOf(target.getName()), "amount", money(amount)));
162 if (target instanceof Player online) online.sendMessage(text("received", "player", player.getName(), "amount", money(amount)));
163 }
164 case "baltop" -> {
165 List<Map.Entry<UUID, BigDecimal>> top = new ArrayList<>(balances.entrySet());
166 top.sort(Map.Entry.<UUID, BigDecimal>comparingByValue().reversed());
167 sender.sendMessage(text("top-header"));
168 for (int i = 0; i < Math.min(10, top.size()); i++) {
169 String name = Bukkit.getOfflinePlayer(top.get(i).getKey()).getName();
170 sender.sendMessage(MM.deserialize(getConfig().getString("messages.top-line", "<gray><rank>. <white><player></white> <dark_gray>-</dark_gray> <green><amount>"),
171 Placeholder.unparsed("rank", String.valueOf(i + 1)),
172 Placeholder.unparsed("player", name == null ? "?" : name),
173 Placeholder.unparsed("amount", money(top.get(i).getValue()))));
174 }
175 }
176 case "eco" -> {
177 if (args.length < 3) return false;
178 OfflinePlayer target = find(args[1]);
179 BigDecimal amount = args[0].equalsIgnoreCase("set") ? parseNonNegative(args[2]) : parse(args[2]);
180 if (target == null) {
181 sender.sendMessage(text("unknown-player", "player", args[1]));
182 return true;
183 }
184 if (amount == null) {
185 sender.sendMessage(text("invalid-amount"));
186 return true;
187 }
188 UUID id = target.getUniqueId();
189 switch (args[0].toLowerCase(Locale.ROOT)) {
190 case "give" -> set(id, balance(id).add(amount).min(MAX));
191 case "take" -> set(id, balance(id).subtract(amount).max(BigDecimal.ZERO));
192 case "set" -> set(id, amount);
193 default -> {
194 return false;
195 }
196 }
197 sender.sendMessage(text("admin-done", "player", String.valueOf(target.getName()), "amount", money(balance(id))));
198 }
199 default -> {
200 return false;
201 }
202 }
203 return true;
204 }
205
206 private BigDecimal parseNonNegative(String raw) {
207 if (raw.equals("0")) return BigDecimal.ZERO;
208 return parse(raw);
209 }
210
211 @Override
212 public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
213 List<String> out = new ArrayList<>();
214 String last = args.length == 0 ? "" : args[args.length - 1].toLowerCase(Locale.ROOT);
215 boolean playerArg = (command.getName().equals("pay") || command.getName().equals("bakiye")) && args.length == 1
216 || command.getName().equals("eco") && args.length == 2;
217 if (command.getName().equals("eco") && args.length == 1) {
218 for (String s : List.of("give", "take", "set")) if (s.startsWith(last)) out.add(s);
219 } else if (playerArg) {
220 for (Player p : Bukkit.getOnlinePlayers()) if (p.getName().toLowerCase(Locale.ROOT).startsWith(last)) out.add(p.getName());
221 }
222 return out;
223 }
224}
225