From 1c390893e9b66cb4715c9ad4c0a6f73c3104dbf7 Mon Sep 17 00:00:00 2001 From: Mrec <66518248+RecoTG@users.noreply.github.com> Date: Sun, 17 Aug 2025 00:32:58 +0100 Subject: [PATCH] Add per-player language aliases --- .../yourorg/servershop/ServerShopPlugin.java | 4 + .../servershop/commands/SellCommand.java | 2 +- .../servershop/commands/ShopCommand.java | 12 +- .../com/yourorg/servershop/commands/Util.java | 8 +- .../servershop/lang/LanguageManager.java | 104 ++++++++++++++++++ src/main/resources/aliases-de.yml | 2 + src/main/resources/aliases-en.yml | 2 + 7 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/yourorg/servershop/lang/LanguageManager.java create mode 100644 src/main/resources/aliases-de.yml create mode 100644 src/main/resources/aliases-en.yml diff --git a/src/main/java/com/yourorg/servershop/ServerShopPlugin.java b/src/main/java/com/yourorg/servershop/ServerShopPlugin.java index 5f18fb9..0b7d558 100644 --- a/src/main/java/com/yourorg/servershop/ServerShopPlugin.java +++ b/src/main/java/com/yourorg/servershop/ServerShopPlugin.java @@ -7,6 +7,7 @@ import com.yourorg.servershop.weekly.*; import com.yourorg.servershop.dynamic.*; import com.yourorg.servershop.config.*; +import com.yourorg.servershop.lang.LanguageManager; import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -22,6 +23,7 @@ public final class ServerShopPlugin extends JavaPlugin { private ShopService shopService; private DynamicPricingManager dynamic; private CategorySettings categorySettings; + private LanguageManager languageManager; @Override public void onEnable() { saveDefaultConfig(); @@ -39,6 +41,7 @@ public final class ServerShopPlugin extends JavaPlugin { this.dynamic = new DynamicPricingManager(this); this.shopService = new ShopService(this); this.menus = new MenuManager(this); + this.languageManager = new LanguageManager(this); Bukkit.getPluginManager().registerEvents(menus, this); int saveEvery = Math.max(1, getConfig().getInt("dynamicPricing.decay.saveEveryMinutes", 5)); @@ -79,4 +82,5 @@ public String prefixed(String msg) { public ShopService shop() { return shopService; } public DynamicPricingManager dynamic() { return dynamic; } public CategorySettings categorySettings() { return categorySettings; } + public LanguageManager lang() { return languageManager; } } diff --git a/src/main/java/com/yourorg/servershop/commands/SellCommand.java b/src/main/java/com/yourorg/servershop/commands/SellCommand.java index a2d9f50..f889773 100644 --- a/src/main/java/com/yourorg/servershop/commands/SellCommand.java +++ b/src/main/java/com/yourorg/servershop/commands/SellCommand.java @@ -12,7 +12,7 @@ public final class SellCommand implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { if (!(sender instanceof Player p)) { sender.sendMessage(plugin.prefixed(plugin.getConfig().getString("messages.not-a-player"))); return true; } if (args.length < 2) { p.sendMessage(plugin.prefixed("/sell ")); return true; } - Material mat = Util.parseMaterial(args[1]); + Material mat = Util.parseMaterial(plugin, p, args[1]); int qty; try { qty = Math.max(1, Integer.parseInt(args.length > 2 ? args[2] : "1")); } catch (Exception e) { qty = 1; } if (mat == null) { p.sendMessage(plugin.prefixed(plugin.getConfig().getString("messages.unknown-material").replace("%material%", args[1]))); return true; } plugin.shop().sell(p, mat, qty).ifPresent(err -> p.sendMessage(plugin.prefixed(err))); diff --git a/src/main/java/com/yourorg/servershop/commands/ShopCommand.java b/src/main/java/com/yourorg/servershop/commands/ShopCommand.java index b3cd85c..7709382 100644 --- a/src/main/java/com/yourorg/servershop/commands/ShopCommand.java +++ b/src/main/java/com/yourorg/servershop/commands/ShopCommand.java @@ -25,6 +25,12 @@ public final class ShopCommand implements TabExecutor { if (args[0].equalsIgnoreCase("search")) return search(sender, args); if (args[0].equalsIgnoreCase("price")) return price(sender, args); if (args[0].equalsIgnoreCase("buy")) return buy(sender, args); + if (args[0].equalsIgnoreCase("lang")) { + if (!(sender instanceof Player p)) { sender.sendMessage(plugin.prefixed(plugin.getConfig().getString("messages.not-a-player"))); return true; } + String lang = plugin.lang().toggle(p); + p.sendMessage(plugin.prefixed("Language set to " + lang)); + return true; + } sender.sendMessage(plugin.prefixed("Unknown subcommand.")); return true; } @@ -60,7 +66,7 @@ private boolean search(CommandSender sender, String[] args) { private boolean price(CommandSender sender, String[] args) { if (args.length < 2) { sender.sendMessage(plugin.prefixed("/shop price ")); return true; } - Material mat = Util.parseMaterial(args[1]); + Material mat = Util.parseMaterial(plugin, sender, args[1]); if (mat == null) { sender.sendMessage(plugin.prefixed(msg("unknown-material").replace("%material%", args[1]))); return true; } Optional opt = plugin.catalog().get(mat); if (opt.isEmpty() || !opt.get().canBuy()) { sender.sendMessage(plugin.prefixed(msg("not-for-sale").replace("%material%", mat.name()))); return true; } @@ -73,7 +79,7 @@ private boolean buy(CommandSender sender, String[] args) { if (!(sender instanceof Player p)) { sender.sendMessage(plugin.prefixed(msg("not-a-player"))); return true; } if (plugin.economy() == null) { sender.sendMessage(plugin.prefixed(msg("no-economy"))); return true; } if (args.length < 3) { p.sendMessage(plugin.prefixed("/shop buy ")); return true; } - Material mat = Util.parseMaterial(args[1]); + Material mat = Util.parseMaterial(plugin, sender, args[1]); int qty; try { qty = Math.max(1, Integer.parseInt(args[2])); } catch (Exception ex) { qty = 1; } if (mat == null) { p.sendMessage(plugin.prefixed(msg("unknown-material").replace("%material%", args[1]))); return true; } plugin.shop().buy(p, mat, qty).ifPresent(err -> p.sendMessage(plugin.prefixed(err))); @@ -84,7 +90,7 @@ private boolean buy(CommandSender sender, String[] args) { @Override public java.util.List onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) { java.util.List out = new java.util.ArrayList<>(); - if (args.length == 1) { suggest(out, args[0], "price","buy","search","admin"); return out; } + if (args.length == 1) { suggest(out, args[0], "price","buy","search","admin","lang"); return out; } if (args[0].equalsIgnoreCase("admin")) { if (args.length == 2) { suggest(out, args[1], "category","import","reload"); return out; } if (args[1].equalsIgnoreCase("category")) { diff --git a/src/main/java/com/yourorg/servershop/commands/Util.java b/src/main/java/com/yourorg/servershop/commands/Util.java index ba10dba..411e718 100644 --- a/src/main/java/com/yourorg/servershop/commands/Util.java +++ b/src/main/java/com/yourorg/servershop/commands/Util.java @@ -1,10 +1,12 @@ package com.yourorg.servershop.commands; +import com.yourorg.servershop.ServerShopPlugin; import org.bukkit.Material; +import org.bukkit.command.CommandSender; public final class Util { - public static Material parseMaterial(String raw) { - if (raw == null) return null; - return Material.matchMaterial(raw.toUpperCase().replace('-', '_').replace(' ', '_')); + public static Material parseMaterial(ServerShopPlugin plugin, CommandSender sender, String raw) { + if (plugin == null) return null; + return plugin.lang().parseMaterial(sender, raw); } } diff --git a/src/main/java/com/yourorg/servershop/lang/LanguageManager.java b/src/main/java/com/yourorg/servershop/lang/LanguageManager.java new file mode 100644 index 0000000..a4b5d6f --- /dev/null +++ b/src/main/java/com/yourorg/servershop/lang/LanguageManager.java @@ -0,0 +1,104 @@ +package com.yourorg.servershop.lang; + +import com.yourorg.servershop.ServerShopPlugin; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +public final class LanguageManager { + private final ServerShopPlugin plugin; + private final Map> aliases = new HashMap<>(); + private final Map playerLang = new HashMap<>(); + private final java.util.List languages = new ArrayList<>(); + + public LanguageManager(ServerShopPlugin plugin) { + this.plugin = plugin; + // ensure default resources exist + plugin.saveResource("aliases-en.yml", false); + plugin.saveResource("aliases-de.yml", false); + loadAliases(); + loadPlayers(); + } + + private void loadAliases() { + aliases.clear(); + languages.clear(); + File folder = plugin.getDataFolder(); + File[] files = folder.listFiles(f -> f.getName().startsWith("aliases-") && f.getName().endsWith(".yml")); + if (files == null) return; + for (File f : files) { + String name = f.getName(); + String lang = name.substring("aliases-".length(), name.length() - 4).toLowerCase(Locale.ROOT); + YamlConfiguration y = YamlConfiguration.loadConfiguration(f); + Map map = new HashMap<>(); + for (String key : y.getKeys(false)) { + String matName = y.getString(key); + if (matName == null) continue; + Material m = Material.matchMaterial(matName.toUpperCase(Locale.ROOT).replace(' ', '_').replace('-', '_')); + if (m != null) map.put(key.toLowerCase(Locale.ROOT).replace('-', ' ').replace('_', ' '), m); + } + aliases.put(lang, map); + languages.add(lang); + } + } + + private void loadPlayers() { + playerLang.clear(); + File f = new File(plugin.getDataFolder(), "lang.yml"); + YamlConfiguration y = YamlConfiguration.loadConfiguration(f); + for (String key : y.getKeys(false)) { + try { + UUID id = UUID.fromString(key); + String lang = y.getString(key, "en"); + playerLang.put(id, lang); + } catch (IllegalArgumentException ignored) {} + } + } + + private void savePlayers() { + File f = new File(plugin.getDataFolder(), "lang.yml"); + YamlConfiguration y = new YamlConfiguration(); + for (Map.Entry e : playerLang.entrySet()) { + y.set(e.getKey().toString(), e.getValue()); + } + try { y.save(f); } catch (IOException ignored) {} + } + + public Material parseMaterial(CommandSender sender, String raw) { + if (raw == null) return null; + String norm = raw.toLowerCase(Locale.ROOT).replace('-', ' ').replace('_', ' '); + if (sender instanceof Player p) { + String lang = playerLang.get(p.getUniqueId()); + if (lang != null) { + Material m = match(lang, norm); + if (m != null) return m; + } + } + for (String lang : languages) { + Material m = match(lang, norm); + if (m != null) return m; + } + return Material.matchMaterial(raw.toUpperCase(Locale.ROOT).replace('-', '_').replace(' ', '_')); + } + + private Material match(String lang, String norm) { + Map map = aliases.get(lang); + if (map == null) return null; + return map.get(norm); + } + + public String toggle(Player p) { + if (languages.isEmpty()) return "en"; + String cur = playerLang.getOrDefault(p.getUniqueId(), languages.get(0)); + int idx = languages.indexOf(cur); + String next = languages.get((idx + 1) % languages.size()); + playerLang.put(p.getUniqueId(), next); + savePlayers(); + return next; + } +} diff --git a/src/main/resources/aliases-de.yml b/src/main/resources/aliases-de.yml new file mode 100644 index 0000000..5e07277 --- /dev/null +++ b/src/main/resources/aliases-de.yml @@ -0,0 +1,2 @@ +# German item aliases +eisenbarren: IRON_INGOT diff --git a/src/main/resources/aliases-en.yml b/src/main/resources/aliases-en.yml new file mode 100644 index 0000000..39abf7b --- /dev/null +++ b/src/main/resources/aliases-en.yml @@ -0,0 +1,2 @@ +# English item aliases +iron ingot: IRON_INGOT