diff --git a/src/main/java/com/songoda/epichoppers/EpicHoppers.java b/src/main/java/com/songoda/epichoppers/EpicHoppers.java index 8f19536..816bca9 100644 --- a/src/main/java/com/songoda/epichoppers/EpicHoppers.java +++ b/src/main/java/com/songoda/epichoppers/EpicHoppers.java @@ -23,6 +23,7 @@ import com.songoda.epichoppers.storage.types.StorageMysql; import com.songoda.epichoppers.storage.types.StorageYaml; import com.songoda.epichoppers.tasks.HopTask; import com.songoda.epichoppers.utils.*; +import com.songoda.epichoppers.utils.locale.Locale; import com.songoda.epichoppers.utils.settings.Setting; import com.songoda.epichoppers.utils.settings.SettingsManager; import com.songoda.epichoppers.utils.updateModules.LocaleModule; @@ -38,15 +39,8 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; import java.io.File; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -60,7 +54,6 @@ public class EpicHoppers extends JavaPlugin { private ServerVersion serverVersion = ServerVersion.fromPackageName(Bukkit.getServer().getClass().getPackage().getName()); - public References references = null; public Enchantment enchantmentHandler; private SettingsManager settingsManager; private ConfigWrapper levelsFile = new ConfigWrapper(this, "", "levels.yml"); @@ -96,21 +89,19 @@ public class EpicHoppers extends JavaPlugin { this.settingsManager = new SettingsManager(this); this.settingsManager.setupConfig(); - this.setupLanguage(); + // Setup language + new Locale(this, "en_US"); + this.locale = Locale.getLocale(getConfig().getString("System.Language Mode")); // Running Songoda Updater Plugin plugin = new Plugin(this, 15); plugin.addModule(new LocaleModule()); SongodaUpdate.load(plugin); - if (getConfig().getBoolean("System.Download Needed Data Files")) - this.update(); - this.enchantmentHandler = new Enchantment(); this.hopperManager = new HopperManager(); this.playerDataManager = new PlayerDataManager(); this.boostManager = new BoostManager(); - this.references = new References(); this.commandManager = new CommandManager(this); PluginManager pluginManager = Bukkit.getPluginManager(); @@ -166,46 +157,6 @@ public class EpicHoppers extends JavaPlugin { console.sendMessage(Methods.formatText("&a=============================")); } - private void update() { - try { - URL url = new URL("http://update.songoda.com/index.php?plugin=" + getDescription().getName() + "&version=" + getDescription().getVersion()); - URLConnection urlConnection = url.openConnection(); - InputStream is = urlConnection.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - - int numCharsRead; - char[] charArray = new char[1024]; - StringBuffer sb = new StringBuffer(); - while ((numCharsRead = isr.read(charArray)) > 0) { - sb.append(charArray, 0, numCharsRead); - } - String jsonString = sb.toString(); - JSONObject json = (JSONObject) new JSONParser().parse(jsonString); - - JSONArray files = (JSONArray) json.get("neededFiles"); - for (Object o : files) { - JSONObject file = (JSONObject) o; - - switch ((String) file.get("type")) { - case "locale": - InputStream in = new URL((String) file.get("link")).openStream(); - Locale.saveDefaultLocale(in, (String) file.get("name")); - break; - } - } - } catch (Exception e) { - System.out.println("Failed to update."); - //e.printStackTrace(); - } - } - - private void setupLanguage() { - String langMode = getConfig().getString("System.Language Mode"); - Locale.init(this); - Locale.saveDefaultLocale("en_US"); - this.locale = Locale.getLocale(getConfig().getString("System.Language Mode", langMode)); - } - public ServerVersion getServerVersion() { return serverVersion; } @@ -359,10 +310,8 @@ public class EpicHoppers extends JavaPlugin { } public void reload() { - String langMode = getConfig().getString("System.Language Mode"); - this.locale = Locale.getLocale(getConfig().getString("System.Language Mode", langMode)); + this.locale = Locale.getLocale(getConfig().getString("System.Language Mode")); this.locale.reloadMessages(); - references = new References(); this.settingsManager.reloadConfig(); loadLevelManager(); } @@ -371,7 +320,7 @@ public class EpicHoppers extends JavaPlugin { ItemStack item = new ItemStack(Material.HOPPER, 1); ItemMeta itemmeta = item.getItemMeta(); itemmeta.setDisplayName(Methods.formatText(Methods.formatName(level.getLevel(), true))); - String line = getLocale().getMessage("general.nametag.lore"); + String line = getLocale().getMessage("general.nametag.lore").getMessage(); if (!line.equals("")) { itemmeta.setLore(Arrays.asList(line.split("\n"))); } diff --git a/src/main/java/com/songoda/epichoppers/Locale.java b/src/main/java/com/songoda/epichoppers/Locale.java deleted file mode 100644 index d68fe44..0000000 --- a/src/main/java/com/songoda/epichoppers/Locale.java +++ /dev/null @@ -1,375 +0,0 @@ -package com.songoda.epichoppers; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import org.bukkit.ChatColor; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * Assists in the creation of multiple localizations and languages, - * as well as the generation of default .lang files - * - * @author Parker Hawke - 2008Choco - */ -public class Locale { - - private static final List LOCALES = Lists.newArrayList(); - private static final Pattern NODE_PATTERN = Pattern.compile("(\\w+(?:\\.{1}\\w+)*)\\s*=\\s*\"(.*)\""); - private static final String FILE_EXTENSION = ".lang"; - private static JavaPlugin plugin; - private static File localeFolder; - - private static String defaultLocale; - - private final Map nodes = new HashMap<>(); - - private final File file; - private final String name, region; - - private Locale(String name, String region) { - if (plugin == null) - throw new IllegalStateException("Cannot generate locales without first initializing the class (Locale#init(JavaPlugin))"); - - this.name = name.toLowerCase(); - this.region = region.toUpperCase(); - - String fileName = name + "_" + region + FILE_EXTENSION; - this.file = new File(localeFolder, fileName); - - if (this.reloadMessages()) return; - - plugin.getLogger().info("Loaded locale " + fileName); - } - - /** - * Initialize the locale class to generate information and search for localizations. - * This must be called before any other methods in the Locale class can be invoked. - * Note that this will also call {@link #searchForLocales()}, so there is blacklist need to - * invoke it for yourself after the initialization - * - * @param plugin the plugin instance - */ - public static void init(JavaPlugin plugin) { - Locale.plugin = plugin; - - if (localeFolder == null) { - localeFolder = new File(plugin.getDataFolder(), "locales/"); - } - - localeFolder.mkdirs(); - Locale.searchForLocales(); - } - - /** - * Find all .lang file locales under the "locales" folder - */ - public static void searchForLocales() { - if (!localeFolder.exists()) localeFolder.mkdirs(); - - for (File file : localeFolder.listFiles()) { - String name = file.getName(); - if (!name.endsWith(".lang")) continue; - - String fileName = name.substring(0, name.lastIndexOf('.')); - String[] localeValues = fileName.split("_"); - - if (localeValues.length != 2) continue; - if (localeExists(localeValues[0] + "_" + localeValues[1])) continue; - - LOCALES.add(new Locale(localeValues[0], localeValues[1])); - plugin.getLogger().info("Found and loaded locale \"" + fileName + "\""); - } - } - - /** - * Get a locale by its entire proper name (i.e. "en_US") - * - * @param name the full name of the locale - * @return locale of the specified name - */ - public static Locale getLocale(String name) { - for (Locale locale : LOCALES) - if (locale.getLanguageTag().equalsIgnoreCase(name)) return locale; - return null; - } - - /** - * Get a locale from the cache by its name (i.e. "en" from "en_US") - * - * @param name the name of the language - * @return locale of the specified language. Null if not cached - */ - public static Locale getLocaleByName(String name) { - for (Locale locale : LOCALES) - if (locale.getName().equalsIgnoreCase(name)) return locale; - return null; - } - - /** - * Get a locale from the cache by its region (i.e. "US" from "en_US") - * - * @param region the name of the region - * @return locale of the specified region. Null if not cached - */ - public static Locale getLocaleByRegion(String region) { - for (Locale locale : LOCALES) - if (locale.getRegion().equalsIgnoreCase(region)) return locale; - return null; - } - - /** - * Check whether a locale exists and is registered or not - * - * @param name the whole language tag (i.e. "en_US") - * @return true if it exists - */ - public static boolean localeExists(String name) { - for (Locale locale : LOCALES) - if (locale.getLanguageTag().equals(name)) return true; - return false; - } - - /** - * Get an immutable list of all currently loaded locales - * - * @return list of all locales - */ - public static List getLocales() { - return ImmutableList.copyOf(LOCALES); - } - - /** - * Save a default locale file from the project source directory, to the locale folder - * - * @param in file to save - * @param fileName the name of the file to save - * @return true if the operation was successful, false otherwise - */ - public static boolean saveDefaultLocale(InputStream in, String fileName) { - if (!localeFolder.exists()) localeFolder.mkdirs(); - - if (!fileName.endsWith(FILE_EXTENSION)) - fileName = (fileName.lastIndexOf(".") == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + FILE_EXTENSION; - - File destinationFile = new File(localeFolder, fileName); - if (destinationFile.exists()) { - return compareFiles(plugin.getResource(fileName), destinationFile); - } - - try (OutputStream outputStream = new FileOutputStream(destinationFile)) { - copy(in == null ? plugin.getResource(fileName) : in, outputStream); - - fileName = fileName.substring(0, fileName.lastIndexOf('.')); - String[] localeValues = fileName.split("_"); - - if (localeValues.length != 2) return false; - - LOCALES.add(new Locale(localeValues[0], localeValues[1])); - if (defaultLocale == null) defaultLocale = fileName; - - return true; - } catch (IOException e) { - return false; - } - } - - /** - * Save a default locale file from the project source directory, to the locale folder - * - * @param fileName the name of the file to save - * @return true if the operation was successful, false otherwise - */ - public static boolean saveDefaultLocale(String fileName) { - return saveDefaultLocale(null, fileName); - } - - /** - * Clear all current locale data - */ - public static void clearLocaleData() { - for (Locale locale : LOCALES) - locale.nodes.clear(); - LOCALES.clear(); - } - - // Write new changes to existing files, if any at all - private static boolean compareFiles(InputStream defaultFile, File existingFile) { - // Look for default - if (defaultFile == null) { - defaultFile = plugin.getResource(defaultLocale != null ? defaultLocale : "en_US"); - if (defaultFile == null) return false; // No default at all - } - - boolean changed = false; - - List defaultLines, existingLines; - try (BufferedReader defaultReader = new BufferedReader(new InputStreamReader(defaultFile)); - BufferedReader existingReader = new BufferedReader(new FileReader(existingFile)); - BufferedWriter writer = new BufferedWriter(new FileWriter(existingFile, true))) { - defaultLines = defaultReader.lines().collect(Collectors.toList()); - existingLines = existingReader.lines().map(s -> s.split("\\s*=")[0]).collect(Collectors.toList()); - - for (String defaultValue : defaultLines) { - if (defaultValue.isEmpty() || defaultValue.startsWith("#")) continue; - - String key = defaultValue.split("\\s*=")[0]; - - if (!existingLines.contains(key)) { - if (!changed) { - writer.newLine(); - writer.newLine(); - writer.write("# New messages for " + plugin.getName() + " v" + plugin.getDescription().getVersion()); - } - - writer.newLine(); - writer.write(defaultValue); - - changed = true; - } - } - } catch (IOException e) { - return false; - } - - return changed; - } - - private static void copy(InputStream input, OutputStream output) { - int n; - byte[] buffer = new byte[1024 * 4]; - - try { - while ((n = input.read(buffer)) != -1) { - output.write(buffer, 0, n); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Get the name of the language that this locale is based on. - * (i.e. "en" for English, or "fr" for French) - * - * @return the name of the language - */ - public String getName() { - return name; - } - - /** - * Get the name of the region that this locale is from. - * (i.e. "US" for United States or "CA" for Canada) - * - * @return the name of the region - */ - public String getRegion() { - return region; - } - - /** - * Return the entire locale tag (i.e. "en_US") - * - * @return the language tag - */ - public String getLanguageTag() { - return name + "_" + region; - } - - /** - * Get the file that represents this locale - * - * @return the locale file (.lang) - */ - public File getFile() { - return file; - } - - /** - * Get a message set for a specific node - * - * @param node the node to get - * @return the message for the specified node - */ - public String getMessage(String node) { - return ChatColor.translateAlternateColorCodes('&', this.getMessageOrDefault(node, node)); - } - - /** - * Get a message set for a specific node and replace its params with a supplied arguments. - * - * @param node the node to get - * @param args the replacement arguments - * @return the message for the specified node - */ - public String getMessage(String node, Object... args) { - String message = getMessage(node); - for (Object arg : args) { - message = message.replaceFirst("\\%.*?\\%", arg.toString()); - } - return message; - } - - /** - * Get a message set for a specific node - * - * @param node the node to get - * @param defaultValue the default value given that a value for the node was not found - * @return the message for the specified node. Default if none found - */ - public String getMessageOrDefault(String node, String defaultValue) { - return this.nodes.getOrDefault(node, defaultValue); - } - - /** - * Get the key-value map of nodes to messages - * - * @return node-message map - */ - public Map getMessageNodeMap() { - return ImmutableMap.copyOf(nodes); - } - - /** - * Clear the previous message cache and load new messages directly from file - * - * @return reload messages from file - */ - public boolean reloadMessages() { - if (!this.file.exists()) { - plugin.getLogger().warning("Could not find file for locale " + this.name); - return false; - } - - this.nodes.clear(); // Clear previous data (if any) - - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - for (int lineNumber = 0; (line = reader.readLine()) != null; lineNumber++) { - if (line.trim().isEmpty() || line.startsWith("#") /* Comment */) continue; - - Matcher matcher = NODE_PATTERN.matcher(line); - if (!matcher.find()) { - System.err.println("Invalid locale syntax at (line=" + lineNumber + ")"); - continue; - } - - nodes.put(matcher.group(1), matcher.group(2)); - } - } catch (IOException e) { - e.printStackTrace(); - return false; - } - return true; - } - -} \ No newline at end of file diff --git a/src/main/java/com/songoda/epichoppers/References.java b/src/main/java/com/songoda/epichoppers/References.java deleted file mode 100644 index ccefa9a..0000000 --- a/src/main/java/com/songoda/epichoppers/References.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.songoda.epichoppers; - -public class References { - - private String prefix; - - public References() { - prefix = EpicHoppers.getInstance().getLocale().getMessage("general.nametag.prefix") + " "; - } - - public String getPrefix() { - return this.prefix; - } -} diff --git a/src/main/java/com/songoda/epichoppers/command/CommandManager.java b/src/main/java/com/songoda/epichoppers/command/CommandManager.java index 648b89c..ad6b2a6 100644 --- a/src/main/java/com/songoda/epichoppers/command/CommandManager.java +++ b/src/main/java/com/songoda/epichoppers/command/CommandManager.java @@ -63,24 +63,24 @@ public class CommandManager implements CommandExecutor { } } } - commandSender.sendMessage(instance.references.getPrefix() + Methods.formatText("&7The command you entered does not exist or is spelt incorrectly.")); + instance.getLocale().newMessage("&7The command you entered does not exist or is spelt incorrectly.").sendPrefixedMessage(commandSender); return true; } private void processRequirements(AbstractCommand command, CommandSender sender, String[] strings) { if (!(sender instanceof Player) && command.isNoConsole()) { - sender.sendMessage("You must be a player to use this command."); + sender.sendMessage("You must be a player to use this commands."); return; } if (command.getPermissionNode() == null || sender.hasPermission(command.getPermissionNode())) { AbstractCommand.ReturnType returnType = command.runCommand(instance, sender, strings); if (returnType == AbstractCommand.ReturnType.SYNTAX_ERROR) { - sender.sendMessage(instance.references.getPrefix() + Methods.formatText("&cInvalid Syntax!")); - sender.sendMessage(instance.references.getPrefix() + Methods.formatText("&7The valid syntax is: &6" + command.getSyntax() + "&7.")); + instance.getLocale().newMessage("&cInvalid Syntax!").sendPrefixedMessage(sender); + instance.getLocale().newMessage("&7The valid syntax is: &6" + command.getSyntax() + "&7.").sendPrefixedMessage(sender); } return; } - sender.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.general.nopermission")); + instance.getLocale().newMessage("event.general.nopermission").sendPrefixedMessage(sender); } public List getCommands() { diff --git a/src/main/java/com/songoda/epichoppers/command/commands/CommandBook.java b/src/main/java/com/songoda/epichoppers/command/commands/CommandBook.java index 47716b7..4ecd4cb 100644 --- a/src/main/java/com/songoda/epichoppers/command/commands/CommandBook.java +++ b/src/main/java/com/songoda/epichoppers/command/commands/CommandBook.java @@ -23,7 +23,8 @@ public class CommandBook extends AbstractCommand { return ReturnType.SUCCESS; } } else if (Bukkit.getPlayerExact(args[1]) == null) { - sender.sendMessage(instance.references.getPrefix() + Methods.formatText("&cThat username does not exist, or the user is not online!")); + instance.getLocale().newMessage("&cThat username does not exist, or the user is not online!") + .sendPrefixedMessage(sender); return ReturnType.FAILURE; } else { Bukkit.getPlayerExact(args[1]).getInventory().addItem(instance.enchantmentHandler.getbook()); diff --git a/src/main/java/com/songoda/epichoppers/command/commands/CommandBoost.java b/src/main/java/com/songoda/epichoppers/command/commands/CommandBoost.java index 196562f..fa2771e 100644 --- a/src/main/java/com/songoda/epichoppers/command/commands/CommandBoost.java +++ b/src/main/java/com/songoda/epichoppers/command/commands/CommandBoost.java @@ -22,10 +22,10 @@ public class CommandBoost extends AbstractCommand { return ReturnType.SYNTAX_ERROR; } if (Bukkit.getPlayer(args[1]) == null) { - sender.sendMessage(Methods.formatText(instance.references.getPrefix() + "&cThat player does not exist...")); + instance.getLocale().newMessage("&cThat player does not exist...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } else if (!Methods.isInt(args[2])) { - sender.sendMessage(Methods.formatText(instance.references.getPrefix() + "&6" + args[2] + " &7is not a number...")); + instance.getLocale().newMessage("&6" + args[2] + " &7is not a number...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } else { Calendar c = Calendar.getInstance(); @@ -52,7 +52,7 @@ public class CommandBoost extends AbstractCommand { c.add(Calendar.YEAR, Integer.parseInt(arr2[1])); time = " &7for &6" + arr2[1] + " years&7."; } else { - sender.sendMessage(Methods.formatText(instance.references.getPrefix() + "&7" + args[3] + " &7is invalid.")); + instance.getLocale().newMessage("&7" + args[3] + " &7is invalid.").sendPrefixedMessage(sender); return ReturnType.SUCCESS; } } else { @@ -61,7 +61,7 @@ public class CommandBoost extends AbstractCommand { BoostData boostData = new BoostData(Integer.parseInt(args[2]), c.getTime().getTime(), Bukkit.getPlayer(args[1]).getUniqueId()); instance.getBoostManager().addBoostToPlayer(boostData); - sender.sendMessage(Methods.formatText(instance.references.getPrefix() + "&7Successfully boosted &6" + Bukkit.getPlayer(args[1]).getName() + "'s &7hoppers transfer rates by &6" + args[2] + "x" + time)); + instance.getLocale().newMessage("&7Successfully boosted &6" + Bukkit.getPlayer(args[1]).getName() + "'s &7hoppers transfer rates by &6" + args[2] + "x" + time).sendPrefixedMessage(sender); } return ReturnType.FAILURE; } diff --git a/src/main/java/com/songoda/epichoppers/command/commands/CommandEpicHoppers.java b/src/main/java/com/songoda/epichoppers/command/commands/CommandEpicHoppers.java index ed00ce6..c0be484 100644 --- a/src/main/java/com/songoda/epichoppers/command/commands/CommandEpicHoppers.java +++ b/src/main/java/com/songoda/epichoppers/command/commands/CommandEpicHoppers.java @@ -16,7 +16,8 @@ public class CommandEpicHoppers extends AbstractCommand { @Override protected ReturnType runCommand(EpicHoppers instance, CommandSender sender, String... args) { sender.sendMessage(""); - sender.sendMessage(Methods.formatText(instance.references.getPrefix() + "&7Version " + instance.getDescription().getVersion() + " Created with <3 by &5&l&oSongoda")); + instance.getLocale().newMessage("&7Version " + instance.getDescription().getVersion() + + " Created with <3 by &5&l&oSongoda").sendPrefixedMessage(sender); for (AbstractCommand command : instance.getCommandManager().getCommands()) { if (command.getPermissionNode() == null || sender.hasPermission(command.getPermissionNode())) { diff --git a/src/main/java/com/songoda/epichoppers/command/commands/CommandGive.java b/src/main/java/com/songoda/epichoppers/command/commands/CommandGive.java index 3bf84ef..99743dd 100644 --- a/src/main/java/com/songoda/epichoppers/command/commands/CommandGive.java +++ b/src/main/java/com/songoda/epichoppers/command/commands/CommandGive.java @@ -3,7 +3,6 @@ package com.songoda.epichoppers.command.commands; import com.songoda.epichoppers.EpicHoppers; import com.songoda.epichoppers.command.AbstractCommand; import com.songoda.epichoppers.hopper.levels.Level; -import com.songoda.epichoppers.utils.Methods; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -15,7 +14,7 @@ import java.util.List; public class CommandGive extends AbstractCommand { public CommandGive(AbstractCommand parent) { - super(parent, false,"give"); + super(parent, false, "give"); } @Override @@ -24,14 +23,14 @@ public class CommandGive extends AbstractCommand { return ReturnType.SYNTAX_ERROR; } if (Bukkit.getPlayerExact(args[1]) == null) { - sender.sendMessage(instance.references.getPrefix() + Methods.formatText("&cThat username does not exist, or the user is not online!")); + instance.getLocale().newMessage("&cThat username does not exist, or the user is not online!").sendPrefixedMessage(sender); return ReturnType.FAILURE; } Level level = instance.getLevelManager().getLowestLevel(); Player player; if (Bukkit.getPlayer(args[1]) == null) { - sender.sendMessage(instance.references.getPrefix() + Methods.formatText("&cThat player does not exist or is currently offline.")); + instance.getLocale().newMessage("&cThat player does not exist or is currently offline.").sendPrefixedMessage(sender); return ReturnType.FAILURE; } else { player = Bukkit.getPlayer(args[1]); @@ -39,13 +38,14 @@ public class CommandGive extends AbstractCommand { if (!instance.getLevelManager().isLevel(Integer.parseInt(args[2]))) { - sender.sendMessage(instance.references.getPrefix() + Methods.formatText("&cNot a valid level... The current valid levels are: &4" + instance.getLevelManager().getLowestLevel().getLevel() + "-" + instance.getLevelManager().getHighestLevel().getLevel() + "&c.")); + instance.getLocale().newMessage("&cNot a valid level... The current valid levels are: &4" + level.getLevel() + "-" + instance.getLevelManager().getHighestLevel().getLevel() + "&c.") + .sendPrefixedMessage(sender); return ReturnType.FAILURE; } else { level = instance.getLevelManager().getLevel(Integer.parseInt(args[2])); } player.getInventory().addItem(instance.newHopperItem(level)); - player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("command.give.success", level.getLevel())); + instance.getLocale().getMessage("command.give.success").processPlaceholder("level", level.getLevel()).sendPrefixedMessage(player); return ReturnType.SUCCESS; } diff --git a/src/main/java/com/songoda/epichoppers/command/commands/CommandReload.java b/src/main/java/com/songoda/epichoppers/command/commands/CommandReload.java index 56a17a2..7816010 100644 --- a/src/main/java/com/songoda/epichoppers/command/commands/CommandReload.java +++ b/src/main/java/com/songoda/epichoppers/command/commands/CommandReload.java @@ -16,7 +16,7 @@ public class CommandReload extends AbstractCommand { @Override protected ReturnType runCommand(EpicHoppers instance, CommandSender sender, String... args) { instance.reload(); - sender.sendMessage(Methods.formatText(instance.references.getPrefix() + "&7Configuration and Language files reloaded.")); + instance.getLocale().getMessage("&7Configuration and Language files reloaded.").sendPrefixedMessage(sender); return ReturnType.SUCCESS; } diff --git a/src/main/java/com/songoda/epichoppers/gui/GUIFilter.java b/src/main/java/com/songoda/epichoppers/gui/GUIFilter.java index ecbded6..edb0517 100644 --- a/src/main/java/com/songoda/epichoppers/gui/GUIFilter.java +++ b/src/main/java/com/songoda/epichoppers/gui/GUIFilter.java @@ -55,7 +55,7 @@ public class GUIFilter extends AbstractGUI { ItemStack it = new ItemStack(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.WHITE_STAINED_GLASS_PANE : Material.valueOf("STAINED_GLASS_PANE"), 1); ItemMeta itm = it.getItemMeta(); - itm.setDisplayName(plugin.getLocale().getMessage("interface.filter.whitelist")); + itm.setDisplayName(plugin.getLocale().getMessage("interface.filter.whitelist").getMessage()); it.setItemMeta(itm); int[] whiteSlots = {0, 1, 45, 46}; @@ -73,7 +73,7 @@ public class GUIFilter extends AbstractGUI { it = new ItemStack(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.BLACK_STAINED_GLASS_PANE : Material.valueOf("STAINED_GLASS_PANE"), 1, (short) 15); itm = it.getItemMeta(); - itm.setDisplayName(plugin.getLocale().getMessage("interface.filter.blacklist")); + itm.setDisplayName(plugin.getLocale().getMessage("interface.filter.blacklist").getMessage()); it.setItemMeta(itm); int[] blackSlots = {2, 3, 47, 48}; @@ -91,7 +91,7 @@ public class GUIFilter extends AbstractGUI { it = new ItemStack(Material.BARRIER); itm = it.getItemMeta(); - itm.setDisplayName(plugin.getLocale().getMessage("interface.filter.void")); + itm.setDisplayName(plugin.getLocale().getMessage("interface.filter.void").getMessage()); it.setItemMeta(itm); int[] avoid = {4, 5, 49, 50}; @@ -109,9 +109,9 @@ public class GUIFilter extends AbstractGUI { ItemStack itemInfo = new ItemStack(Material.PAPER, 1); ItemMeta itemmetaInfo = itemInfo.getItemMeta(); - itemmetaInfo.setDisplayName(plugin.getLocale().getMessage("interface.filter.infotitle")); + itemmetaInfo.setDisplayName(plugin.getLocale().getMessage("interface.filter.infotitle").getMessage()); ArrayList loreInfo = new ArrayList<>(); - String[] parts = plugin.getLocale().getMessage("interface.filter.infolore").split("\\|"); + String[] parts = plugin.getLocale().getMessage("interface.filter.infolore").getMessage().split("\\|"); for (String line : parts) { loreInfo.add(Methods.formatText(line)); } @@ -123,9 +123,11 @@ public class GUIFilter extends AbstractGUI { ItemStack hook = new ItemStack(Material.TRIPWIRE_HOOK, 1); ItemMeta hookmeta = hook.getItemMeta(); - hookmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.rejectsync")); + hookmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.rejectsync").getMessage()); ArrayList lorehook = new ArrayList<>(); - parts = plugin.getLocale().getMessage("interface.hopper.synclore", filter.getEndPoint() != null ? 1 : 0).split("\\|"); + parts = plugin.getLocale().getMessage("interface.hopper.synclore") + .processPlaceholder("amount", filter.getEndPoint() != null ? 1 : 0) + .getMessage().split("\\|"); for (String line : parts) { lorehook.add(Methods.formatText(line)); } @@ -143,11 +145,11 @@ public class GUIFilter extends AbstractGUI { protected void registerClickables() { registerClickable(43, ((player, inventory, cursor, slot, type) -> { if (type == ClickType.RIGHT) { - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.hopper.desync")); + plugin.getLocale().getMessage("event.hopper.desync").sendPrefixedMessage(player); hopper.getFilter().setEndPoint(null); } else { plugin.getPlayerDataManager().getPlayerData(player).setSyncType(SyncType.FILTERED); - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.hopper.syncnext")); + plugin.getLocale().getMessage("event.hopper.syncnext").sendPrefixedMessage(player); hopper.timeout(player); } player.closeInventory(); diff --git a/src/main/java/com/songoda/epichoppers/gui/GUIOverview.java b/src/main/java/com/songoda/epichoppers/gui/GUIOverview.java index 0134d58..0c23e9a 100644 --- a/src/main/java/com/songoda/epichoppers/gui/GUIOverview.java +++ b/src/main/java/com/songoda/epichoppers/gui/GUIOverview.java @@ -55,9 +55,12 @@ public class GUIOverview extends AbstractGUI { ItemStack perl = new ItemStack(Material.ENDER_PEARL, 1); ItemMeta perlmeta = perl.getItemMeta(); - perlmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.perltitle")); + perlmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.perltitle").getMessage()); ArrayList loreperl = new ArrayList<>(); - String[] parts = plugin.getLocale().getMessage("interface.hopper.perllore2", hopper.getTeleportTrigger() == TeleportTrigger.DISABLED ? plugin.getLocale().getMessage("general.word.disabled") : hopper.getTeleportTrigger().name()).split("\\|"); + String[] parts = plugin.getLocale().getMessage("interface.hopper.perllore2") + .processPlaceholder("type", hopper.getTeleportTrigger() == TeleportTrigger.DISABLED + ? plugin.getLocale().getMessage("general.word.disabled").getMessage() + : hopper.getTeleportTrigger().name()).getMessage().split("\\|"); for (String line : parts) { loreperl.add(Methods.formatText(line)); } @@ -66,9 +69,9 @@ public class GUIOverview extends AbstractGUI { ItemStack filter = new ItemStack(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.COMPARATOR : Material.valueOf("REDSTONE_COMPARATOR"), 1); ItemMeta filtermeta = filter.getItemMeta(); - filtermeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.filtertitle")); + filtermeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.filtertitle").getMessage()); ArrayList lorefilter = new ArrayList<>(); - parts = plugin.getLocale().getMessage("interface.hopper.filterlore").split("\\|"); + parts = plugin.getLocale().getMessage("interface.hopper.filterlore").getMessage().split("\\|"); for (String line : parts) { lorefilter.add(Methods.formatText(line)); } @@ -78,20 +81,23 @@ public class GUIOverview extends AbstractGUI { ItemStack item = new ItemStack(Material.HOPPER, 1); ItemMeta itemmeta = item.getItemMeta(); - itemmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.currentlevel", level.getLevel())); + itemmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.currentlevel").processPlaceholder("level", level.getLevel()).getMessage()); List lore = level.getDescription(); if (plugin.getConfig().getBoolean("Main.Allow hopper Upgrading")) { lore.add(""); - if (nextLevel == null) lore.add(plugin.getLocale().getMessage("interface.hopper.alreadymaxed")); + if (nextLevel == null) lore.add(plugin.getLocale().getMessage("interface.hopper.alreadymaxed").getMessage()); else { - lore.add(plugin.getLocale().getMessage("interface.hopper.nextlevel", nextLevel.getLevel())); + lore.add(plugin.getLocale().getMessage("interface.hopper.nextlevel").processPlaceholder("level", nextLevel.getLevel()).getMessage()); lore.addAll(nextLevel.getDescription()); } } BoostData boostData = plugin.getBoostManager().getBoost(hopper.getPlacedBy()); if (boostData != null) { - parts = plugin.getLocale().getMessage("interface.hopper.boostedstats", Integer.toString(boostData.getMultiplier()), Methods.makeReadable(boostData.getEndTime() - System.currentTimeMillis())).split("\\|"); + parts = plugin.getLocale().getMessage("interface.hopper.boostedstats") + .processPlaceholder("amount", Integer.toString(boostData.getMultiplier())) + .processPlaceholder("time", Methods.makeReadable(boostData.getEndTime() - System.currentTimeMillis())) + .getMessage().split("\\|"); lore.add(""); for (String line : parts) lore.add(Methods.formatText(line)); @@ -102,9 +108,11 @@ public class GUIOverview extends AbstractGUI { ItemStack hook = new ItemStack(Material.TRIPWIRE_HOOK, 1); ItemMeta hookmeta = hook.getItemMeta(); - hookmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.synchopper")); + hookmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.synchopper").getMessage()); ArrayList lorehook = new ArrayList<>(); - parts = plugin.getLocale().getMessage("interface.hopper.synclore", hopper.getLinkedBlocks().stream().distinct().count()).split("\\|"); + parts = plugin.getLocale().getMessage("interface.hopper.synclore") + .processPlaceholder("amount", hopper.getLinkedBlocks().stream().distinct().count()) + .getMessage().split("\\|"); for (String line : parts) { lorehook.add(Methods.formatText(line)); } @@ -163,23 +171,27 @@ public class GUIOverview extends AbstractGUI { if (plugin.getConfig().getBoolean("Main.Allow hopper Upgrading")) { ItemStack itemXP = new ItemStack(Material.valueOf(plugin.getConfig().getString("Interfaces.XP Icon")), 1); ItemMeta itemmetaXP = itemXP.getItemMeta(); - itemmetaXP.setDisplayName(plugin.getLocale().getMessage("interface.hopper.upgradewithxp")); + itemmetaXP.setDisplayName(plugin.getLocale().getMessage("interface.hopper.upgradewithxp").getMessage()); ArrayList loreXP = new ArrayList<>(); if (nextLevel != null) - loreXP.add(plugin.getLocale().getMessage("interface.hopper.upgradewithxplore", nextLevel.getCostExperience())); + loreXP.add(plugin.getLocale().getMessage("interface.hopper.upgradewithxplore") + .processPlaceholder("cost", nextLevel.getCostExperience()).getMessage()); else - loreXP.add(plugin.getLocale().getMessage("interface.hopper.alreadymaxed")); + loreXP.add(plugin.getLocale().getMessage("interface.hopper.alreadymaxed").getMessage()); itemmetaXP.setLore(loreXP); itemXP.setItemMeta(itemmetaXP); ItemStack itemECO = new ItemStack(Material.valueOf(plugin.getConfig().getString("Interfaces.Economy Icon")), 1); ItemMeta itemmetaECO = itemECO.getItemMeta(); - itemmetaECO.setDisplayName(plugin.getLocale().getMessage("interface.hopper.upgradewitheconomy")); + itemmetaECO.setDisplayName(plugin.getLocale().getMessage("interface.hopper.upgradewitheconomy") + .getMessage()); ArrayList loreECO = new ArrayList<>(); if (nextLevel != null) - loreECO.add(plugin.getLocale().getMessage("interface.hopper.upgradewitheconomylore", Methods.formatEconomy(nextLevel.getCostEconomy()))); + loreECO.add(plugin.getLocale().getMessage("interface.hopper.upgradewitheconomylore") + .processPlaceholder("cost", Methods.formatEconomy(nextLevel.getCostEconomy())) + .getMessage()); else - loreECO.add(plugin.getLocale().getMessage("interface.hopper.alreadymaxed")); + loreECO.add(plugin.getLocale().getMessage("interface.hopper.alreadymaxed").getMessage()); itemmetaECO.setLore(loreECO); itemECO.setItemMeta(itemmetaECO); @@ -266,16 +278,16 @@ public class GUIOverview extends AbstractGUI { } else if (inventory.getItem(slot).getItemMeta() .getDisplayName().equals(plugin.getLocale().getMessage("interface.hopper.synchopper"))) { if (type == ClickType.RIGHT) { - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.hopper.desync")); + plugin.getLocale().getMessage("event.hopper.desync").sendPrefixedMessage(player); hopper.clearLinkedBlocks(); } else { if (hopper.getLastPlayerOpened() != null && !hopper.getLastPlayerOpened().equals(player.getUniqueId())) { - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.hopper.syncdidnotplace")); + plugin.getLocale().getMessage("event.hopper.syncdidnotplace").sendPrefixedMessage(player); return; } plugin.getPlayerDataManager().getPlayerData(player).setSyncType(SyncType.REGULAR); hopper.clearLinkedBlocks(); - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.hopper.syncnext")); + plugin.getLocale().getMessage("event.hopper.syncnext").sendPrefixedMessage(player); hopper.timeout(player); } player.closeInventory(); diff --git a/src/main/java/com/songoda/epichoppers/hopper/Hopper.java b/src/main/java/com/songoda/epichoppers/hopper/Hopper.java index e87b887..b26f373 100644 --- a/src/main/java/com/songoda/epichoppers/hopper/Hopper.java +++ b/src/main/java/com/songoda/epichoppers/hopper/Hopper.java @@ -49,31 +49,30 @@ public class Hopper { public void upgrade(Player player, CostType type) { EpicHoppers plugin = EpicHoppers.getInstance(); - if (plugin.getLevelManager().getLevels().containsKey(this.level.getLevel() + 1)) { + if (!plugin.getLevelManager().getLevels().containsKey(this.level.getLevel() + 1)) return; - Level level = plugin.getLevelManager().getLevel(this.level.getLevel() + 1); - int cost = type == CostType.ECONOMY ? level.getCostEconomy() : level.getCostExperience(); + Level level = plugin.getLevelManager().getLevel(this.level.getLevel() + 1); + int cost = type == CostType.ECONOMY ? level.getCostEconomy() : level.getCostExperience(); - if (type == CostType.ECONOMY) { - if (plugin.getEconomy() == null) { - player.sendMessage("Economy not enabled."); - return; + if (type == CostType.ECONOMY) { + if (plugin.getEconomy() == null) { + player.sendMessage("Economy not enabled."); + return; + } + if (!plugin.getEconomy().hasBalance(player, cost)) { + plugin.getInstance().getLocale().getMessage("event.upgrade.cannotafford").sendPrefixedMessage(player); + return; + } + plugin.getEconomy().withdrawBalance(player, cost); + upgradeFinal(level, player); + } else if (type == CostType.EXPERIENCE) { + if (player.getLevel() >= cost || player.getGameMode() == GameMode.CREATIVE) { + if (player.getGameMode() != GameMode.CREATIVE) { + player.setLevel(player.getLevel() - cost); } - if (!plugin.getEconomy().hasBalance(player, cost)) { - player.sendMessage(plugin.references.getPrefix() + plugin.getInstance().getLocale().getMessage("event.upgrade.cannotafford")); - return; - } - plugin.getEconomy().withdrawBalance(player, cost); upgradeFinal(level, player); - } else if (type == CostType.EXPERIENCE) { - if (player.getLevel() >= cost || player.getGameMode() == GameMode.CREATIVE) { - if (player.getGameMode() != GameMode.CREATIVE) { - player.setLevel(player.getLevel() - cost); - } - upgradeFinal(level, player); - } else { - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.upgrade.cannotafford")); - } + } else { + plugin.getLocale().getMessage("event.upgrade.cannotafford").sendPrefixedMessage(player); } } } @@ -83,9 +82,11 @@ public class Hopper { this.level = level; syncName(); if (plugin.getLevelManager().getHighestLevel() != level) { - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.upgrade.success", level.getLevel())); + plugin.getLocale().getMessage("event.upgrade.success") + .processPlaceholder("level", level.getLevel()).sendPrefixedMessage(player); } else { - player.sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.upgrade.maxed", level.getLevel())); + plugin.getLocale().getMessage("event.upgrade.maxed") + .processPlaceholder("level", level.getLevel()).sendPrefixedMessage(player); } Location loc = location.clone().add(.5, .5, .5); @@ -118,7 +119,7 @@ public class Hopper { Bukkit.getScheduler().scheduleSyncDelayedTask(instance, () -> { PlayerData playerData = instance.getPlayerDataManager().getPlayerData(player); if (playerData.getSyncType() != null) { - player.sendMessage(instance.getLocale().getMessage("event.hopper.synctimeout")); + instance.getLocale().getMessage("event.hopper.synctimeout").sendPrefixedMessage(player); playerData.setSyncType(null); } }, instance.getConfig().getLong("Main.Timeout When Syncing Hoppers")); @@ -131,12 +132,12 @@ public class Hopper { && !player.hasPermission("EpicHoppers.Override") && !player.hasPermission("EpicHoppers.Admin") && location.distance(toLink.getLocation()) > level.getRange()) { - player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.hopper.syncoutofrange")); + instance.getLocale().getMessage("event.hopper.syncoutofrange").sendPrefixedMessage(player); return; } if (linkedBlocks.contains(toLink)) { - player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.hopper.already")); + instance.getLocale().getMessage("event.hopper.already").sendPrefixedMessage(player); return; } @@ -144,7 +145,7 @@ public class Hopper { this.linkedBlocks.add(toLink.getLocation()); else { this.filter.setEndPoint(toLink.getLocation()); - player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.hopper.syncsuccess")); + instance.getLocale().getMessage("event.hopper.syncsuccess").sendPrefixedMessage(player); instance.getPlayerDataManager().getPlayerData(player).setSyncType(null); return; } @@ -152,13 +153,15 @@ public class Hopper { if (level.getLinkAmount() > 1) { if (getLinkedBlocks().size() == level.getLinkAmount()) { - player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.hopper.syncdone")); + instance.getLocale().getMessage("event.hopper.syncdone").sendPrefixedMessage(player); return; } - player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.hopper.syncsuccessmore", level.getLinkAmount() - getLinkedBlocks().size())); + instance.getLocale().getMessage("event.hopper.syncsuccessmore") + .processPlaceholder("amount", level.getLinkAmount() - getLinkedBlocks().size()) + .sendPrefixedMessage(player); return; } - player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.hopper.syncsuccess")); + instance.getLocale().getMessage("event.hopper.syncsuccess").sendPrefixedMessage(player); instance.getPlayerDataManager().getPlayerData(player).setSyncType(null); } diff --git a/src/main/java/com/songoda/epichoppers/hopper/levels/Level.java b/src/main/java/com/songoda/epichoppers/hopper/levels/Level.java index 88a761e..7bd766f 100644 --- a/src/main/java/com/songoda/epichoppers/hopper/levels/Level.java +++ b/src/main/java/com/songoda/epichoppers/hopper/levels/Level.java @@ -13,7 +13,7 @@ public class Level { private int level, costExperience, costEconomy, range, amount, linkAmount; private boolean filter, teleport; - Level(int level, int costExperience, int costEconomy, int range, int amount, boolean filter, boolean teleport, int linkAmount, ArrayList registeredModules) { + Level(int level, int costExperience, int costEconomy, int range, int amount, boolean filter, boolean teleport, int linkAmount, ArrayList registeredModules) { this.level = level; this.costExperience = costExperience; this.costEconomy = costEconomy; @@ -33,14 +33,21 @@ public class Level { description.clear(); - description.add(instance.getLocale().getMessage("interface.hopper.range", range)); - description.add(instance.getLocale().getMessage("interface.hopper.amount", amount)); + description.add(instance.getLocale().getMessage("interface.hopper.range") + .processPlaceholder("range", range).getMessage()); + description.add(instance.getLocale().getMessage("interface.hopper.amount") + .processPlaceholder("amount", amount).getMessage()); if (linkAmount != 1) - description.add(instance.getLocale().getMessage("interface.hopper.linkamount", linkAmount)); + description.add(instance.getLocale().getMessage("interface.hopper.linkamount") + .processPlaceholder("amount", linkAmount).getMessage()); if (filter) - description.add(instance.getLocale().getMessage("interface.hopper.filter", EpicHoppers.getInstance().getLocale().getMessage("general.word.enabled"))); + description.add(instance.getLocale().getMessage("interface.hopper.filter") + .processPlaceholder("enabled", EpicHoppers.getInstance().getLocale() + .getMessage("general.word.enabled").getMessage()).getMessage()); if (teleport) - description.add(instance.getLocale().getMessage("interface.hopper.teleport", EpicHoppers.getInstance().getLocale().getMessage("general.word.enabled"))); + description.add(instance.getLocale().getMessage("interface.hopper.teleport") + .processPlaceholder("enabled", EpicHoppers.getInstance() + .getLocale().getMessage("general.word.enabled").getMessage()).getMessage()); for (Module module : registeredModules) { description.add(module.getDescription()); diff --git a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoCrafting.java b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoCrafting.java index 9701e90..03d23ad 100644 --- a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoCrafting.java +++ b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoCrafting.java @@ -101,9 +101,11 @@ public class ModuleAutoCrafting extends Module { public ItemStack getGUIButton(Hopper hopper) { ItemStack crafting = new ItemStack(EpicHoppers.getInstance().isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CRAFTING_TABLE : Material.valueOf("WORKBENCH"), 1); ItemMeta craftingmeta = crafting.getItemMeta(); - craftingmeta.setDisplayName(EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.craftingtitle")); + craftingmeta.setDisplayName(EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.craftingtitle") + .getMessage()); ArrayList lorecrafting = new ArrayList<>(); - String[] parts = EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.craftinglore").split("\\|"); + String[] parts = EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.craftinglore") + .getMessage().split("\\|"); for (String line : parts) { lorecrafting.add(Methods.formatText(line)); } @@ -159,8 +161,8 @@ public class ModuleAutoCrafting extends Module { @Override public String getDescription() { - return EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.crafting", - EpicHoppers.getInstance().getLocale().getMessage("general.word.enabled")); + return EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.crafting").processPlaceholder("enabled", + EpicHoppers.getInstance().getLocale().getMessage("general.word.enabled").getMessage()).getMessage(); } public ItemStack getAutoCrafting(Hopper hopper) { diff --git a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoSell.java b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoSell.java index 8c147fd..bda14bf 100644 --- a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoSell.java +++ b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleAutoSell.java @@ -89,7 +89,9 @@ public class ModuleAutoSell extends Module { HopTask.updateAdjacentComparators(hopper.getLocation()); if (totalValue != 0 && player.isOnline()) { - player.getPlayer().sendMessage(plugin.references.getPrefix() + plugin.getLocale().getMessage("event.hopper.autosell", amountSold, Methods.formatEconomy(totalValue))); + plugin.getLocale().getMessage("event.hopper.autosell") + .processPlaceholder("items", amountSold) + .processPlaceholder("amount", Methods.formatEconomy(totalValue)).sendPrefixedMessage(player.getPlayer()); } modifyDataCache(hopper, "time", timeOut); @@ -103,9 +105,11 @@ public class ModuleAutoSell extends Module { public ItemStack getGUIButton(Hopper hopper) { ItemStack sell = new ItemStack(EpicHoppers.getInstance().isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SUNFLOWER : Material.valueOf("DOUBLE_PLANT"), 1); ItemMeta sellmeta = sell.getItemMeta(); - sellmeta.setDisplayName(EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.selltitle")); + sellmeta.setDisplayName(EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.selltitle").getMessage()); ArrayList loreSell = new ArrayList<>(); - String[] parts = EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.selllore", getTime(hopper) == -9999 ? "\u221E" : (int) Math.floor(getTime(hopper) / 20), isNotifying(hopper)).split("\\|"); + String[] parts = EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.selllore") + .processPlaceholder("timeleft", getTime(hopper) == -9999 ? "\u221E" : (int) Math.floor(getTime(hopper) / 20)) + .processPlaceholder("state", isNotifying(hopper)).getMessage().split("\\|"); for (String line : parts) { loreSell.add(Methods.formatText(line)); } @@ -134,7 +138,8 @@ public class ModuleAutoSell extends Module { @Override public String getDescription() { - return EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.autosell", (int) Math.floor(timeOut / 20)); + return EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.autosell") + .processPlaceholder("seconds", (int) Math.floor(timeOut / 20)).getMessage(); } private boolean isNotifying(Hopper hopper) { diff --git a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleBlockBreak.java b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleBlockBreak.java index b11cf59..258788a 100644 --- a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleBlockBreak.java +++ b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleBlockBreak.java @@ -95,11 +95,13 @@ public class ModuleBlockBreak extends Module { public ItemStack getGUIButton(Hopper hopper) { ItemStack block = new ItemStack(Material.IRON_ORE, 1); ItemMeta blockmeta = block.getItemMeta(); - blockmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.blocktitle")); + blockmeta.setDisplayName(plugin.getLocale().getMessage("interface.hopper.blocktitle").getMessage()); ArrayList loreblock = new ArrayList<>(); - String[] parts = plugin.getLocale().getMessage("interface.hopper.blocklore", - isEnabled(hopper) ? plugin.getLocale().getMessage("general.word.enabled") - : plugin.getLocale().getMessage("general.word.disabled")).split("\\|"); + String[] parts = plugin.getLocale().getMessage("interface.hopper.blocklore") + .processPlaceholder("enabled", isEnabled(hopper) + ? plugin.getLocale().getMessage("general.word.enabled").getMessage() + : plugin.getLocale().getMessage("general.word.disabled").getMessage()) + .getMessage().split("\\|"); for (String line : parts) { loreblock.add(Methods.formatText(line)); } @@ -120,7 +122,8 @@ public class ModuleBlockBreak extends Module { @Override public String getDescription() { - return plugin.getLocale().getMessage("interface.hopper.blockbreak", amount); + return plugin.getLocale().getMessage("interface.hopper.blockbreak") + .processPlaceholder("ticks", amount).getMessage(); } public boolean isEnabled(Hopper hopper) { diff --git a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleSuction.java b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleSuction.java index e00039a..22abcb6 100644 --- a/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleSuction.java +++ b/src/main/java/com/songoda/epichoppers/hopper/levels/modules/ModuleSuction.java @@ -145,7 +145,8 @@ public class ModuleSuction extends Module { @Override public String getDescription() { - return EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.suction", amount); + return EpicHoppers.getInstance().getLocale().getMessage("interface.hopper.suction") + .processPlaceholder("suction", amount).getMessage(); } private boolean canMove(Inventory inventory, ItemStack item) { diff --git a/src/main/java/com/songoda/epichoppers/listeners/BlockListeners.java b/src/main/java/com/songoda/epichoppers/listeners/BlockListeners.java index 6a30311..8154a43 100644 --- a/src/main/java/com/songoda/epichoppers/listeners/BlockListeners.java +++ b/src/main/java/com/songoda/epichoppers/listeners/BlockListeners.java @@ -53,7 +53,7 @@ public class BlockListeners implements Listener { int max = maxHoppers(player); if (max != -1 && amt > max) { - player.sendMessage(instance.getLocale().getMessage("event.hopper.toomany", max)); + player.sendMessage(instance.getLocale().getMessage("event.hopper.toomany").processPlaceholder("amount", max).getMessage()); e.setCancelled(true); return; } diff --git a/src/main/java/com/songoda/epichoppers/listeners/InteractListeners.java b/src/main/java/com/songoda/epichoppers/listeners/InteractListeners.java index aaf1b56..70b94d2 100644 --- a/src/main/java/com/songoda/epichoppers/listeners/InteractListeners.java +++ b/src/main/java/com/songoda/epichoppers/listeners/InteractListeners.java @@ -62,10 +62,12 @@ public class InteractListeners implements Listener { if (e.getClickedBlock().getType() == Material.CHEST && Methods.isSync(player)) { ItemStack item = e.getPlayer().getInventory().getItemInHand(); if (item.getItemMeta().getLore().size() == 2) { - player.sendMessage(instance.getLocale().getMessage("event.hopper.desyncchest", item.getType().toString())); + instance.getLocale().getMessage("event.hopper.desyncchest") + .processPlaceholder("name", item.getType().toString()).sendPrefixedMessage(player); instance.enchantmentHandler.createSyncTouch(item, null); } else { - player.sendMessage(instance.getLocale().getMessage("event.hopper.syncchest", item.getType().toString())); + instance.getLocale().getMessage("event.hopper.syncchest") + .processPlaceholder("name", item.getType().toString()).sendPrefixedMessage(player); instance.enchantmentHandler.createSyncTouch(item, e.getClickedBlock()); } e.setCancelled(true); @@ -92,7 +94,7 @@ public class InteractListeners implements Listener { if (e.getClickedBlock().getState() instanceof InventoryHolder || (e.getClickedBlock().getType().equals(Material.ENDER_CHEST) && instance.getConfig().getBoolean("Main.Support Enderchests"))) { Hopper hopper = playerData.getLastHopper(); if (playerData.getSyncType() != null && e.getClickedBlock().getLocation().equals(playerData.getLastHopper().getLocation())) { - player.sendMessage(instance.getLocale().getMessage("event.hopper.syncself")); + instance.getLocale().getMessage("event.hopper.syncself").sendPrefixedMessage(player); } else if (playerData.getSyncType() != null) { hopper.link(e.getClickedBlock(), playerData.getSyncType() == SyncType.FILTERED, player); } diff --git a/src/main/java/com/songoda/epichoppers/utils/Methods.java b/src/main/java/com/songoda/epichoppers/utils/Methods.java index 8cb07c0..486af06 100644 --- a/src/main/java/com/songoda/epichoppers/utils/Methods.java +++ b/src/main/java/com/songoda/epichoppers/utils/Methods.java @@ -141,7 +141,8 @@ public class Methods { public static String formatName(int level, boolean full) { EpicHoppers instance = EpicHoppers.getInstance(); - String name = instance.getLocale().getMessage("general.nametag.nameformat", level); + String name = instance.getLocale().getMessage("general.nametag.nameformat") + .processPlaceholder("level", level).getMessage(); String info = ""; if (full) { diff --git a/src/main/java/com/songoda/epichoppers/utils/locale/Locale.java b/src/main/java/com/songoda/epichoppers/utils/locale/Locale.java new file mode 100644 index 0000000..3adc965 --- /dev/null +++ b/src/main/java/com/songoda/epichoppers/utils/locale/Locale.java @@ -0,0 +1,302 @@ +package com.songoda.epichoppers.utils.locale; + +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * Assists in the utilization of localization files. + * Created to be used by the Songoda Team. + * + * @author Brianna O'Keefe - Songoda + */ +public class Locale { + + private static final List LOCALES = new ArrayList<>(); + private static final Pattern NODE_PATTERN = Pattern.compile("(\\w+(?:\\.{1}\\w+)*)\\s*=\\s*\"(.*)\""); + private static final String FILE_EXTENSION = ".lang"; + private static JavaPlugin plugin; + private static File localeFolder; + + private final Map nodes = new HashMap<>(); + + private static String defaultLocale; + + private File file; + private String name; + + /** + * Instantiate the Locale class for future use + * + * @param name the name of the instantiated language + */ + private Locale(String name) { + if (plugin == null) + return; + + this.name = name; + + String fileName = name + FILE_EXTENSION; + this.file = new File(localeFolder, fileName); + + if (!this.reloadMessages()) return; + + plugin.getLogger().info("Loaded locale \"" + fileName + "\""); + } + + /** + * Initialize the class to load all existing language files and update them. + * This must be called before any other methods in this class as otherwise + * the methods will fail to invoke + * + * @param plugin the plugin instance + * @param defaultLocale the default language + */ + public Locale(JavaPlugin plugin, String defaultLocale) { + + Locale.plugin = plugin; + Locale.localeFolder = new File(plugin.getDataFolder(), "locales/"); + + if (!localeFolder.exists()) localeFolder.mkdirs(); + + //Save the default locale file. + Locale.defaultLocale = defaultLocale; + saveLocale(defaultLocale); + + for (File file : localeFolder.listFiles()) { + String fileName = file.getName(); + if (!fileName.endsWith(FILE_EXTENSION)) continue; + + String name = fileName.substring(0, fileName.lastIndexOf('.')); + + if (name.split("_").length != 2) continue; + if (localeLoaded(name)) continue; + + LOCALES.add(new Locale(name)); + } + } + + /** + * Save a locale file from the InputStream, to the locale folder + * + * @param fileName the name of the file to save + * @return true if the operation was successful, false otherwise + */ + public static boolean saveLocale(String fileName) { + return saveLocale(plugin.getResource(defaultLocale + FILE_EXTENSION), fileName); + } + + + /** + * Save a locale file from the InputStream, to the locale folder + * + * @param in file to save + * @param fileName the name of the file to save + * @return true if the operation was successful, false otherwise + */ + public static boolean saveLocale(InputStream in, String fileName) { + if (!localeFolder.exists()) localeFolder.mkdirs(); + + if (!fileName.endsWith(FILE_EXTENSION)) + fileName = (fileName.lastIndexOf(".") == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + FILE_EXTENSION; + + File destinationFile = new File(localeFolder, fileName); + if (destinationFile.exists()) + return compareFiles(in, destinationFile); + + try (OutputStream outputStream = new FileOutputStream(destinationFile)) { + copy(in, outputStream); + + fileName = fileName.substring(0, fileName.lastIndexOf('.')); + + if (fileName.split("_").length != 2) return false; + + LOCALES.add(new Locale(fileName)); + if (defaultLocale == null) defaultLocale = fileName; + return true; + } catch (IOException e) { + return false; + } + } + + // Write new changes to existing files, if any at all + private static boolean compareFiles(InputStream in, File existingFile) { + InputStream defaultFile = + in == null ? plugin.getResource((defaultLocale != null ? defaultLocale : "en_US") + FILE_EXTENSION) : in; + + boolean changed = false; + + List defaultLines, existingLines; + try (BufferedReader defaultReader = new BufferedReader(new InputStreamReader(defaultFile)); + BufferedReader existingReader = new BufferedReader(new FileReader(existingFile)); + BufferedWriter writer = new BufferedWriter(new FileWriter(existingFile, true))) { + defaultLines = defaultReader.lines().collect(Collectors.toList()); + existingLines = existingReader.lines().map(s -> s.split("\\s*=")[0]).collect(Collectors.toList()); + + for (String defaultValue : defaultLines) { + if (defaultValue.isEmpty() || defaultValue.startsWith("#")) continue; + + String key = defaultValue.split("\\s*=")[0]; + + if (!existingLines.contains(key)) { + if (!changed) { + writer.newLine(); + writer.newLine(); + // Leave a note alerting the user of the newly added messages. + writer.write("# New messages for " + plugin.getName() + " v" + plugin.getDescription().getVersion() + "."); + + // If changes were found outside of the default file leave a note explaining that. + if (in == null) { + writer.newLine(); + writer.write("# These translations were found untranslated, join"); + writer.newLine(); + writer.write("# our translation Discord https://discord.gg/f7fpZEf"); + writer.newLine(); + writer.write("# to request an official update!"); + } + } + + writer.newLine(); + writer.write(defaultValue); + + changed = true; + } + } + if (in != null && !changed) compareFiles(null, existingFile); + } catch (IOException e) { + return false; + } + + return changed; + } + + + /** + * Check whether a locale exists and is registered or not + * + * @param name the whole language tag (i.e. "en_US") + * @return true if it exists + */ + public static boolean localeLoaded(String name) { + for (Locale locale : LOCALES) + if (locale.getName().equals(name)) return true; + return false; + } + + + /** + * Get a locale by its entire proper name (i.e. "en_US") + * + * @param name the full name of the locale + * @return locale of the specified name + */ + public static Locale getLocale(String name) { + for (Locale locale : LOCALES) + if (locale.getName().equalsIgnoreCase(name)) return locale; + return null; + } + + /** + * Clear the previous message cache and load new messages directly from file + * + * @return reload messages from file + */ + public boolean reloadMessages() { + if (!this.file.exists()) { + plugin.getLogger().warning("Could not find file for locale \"" + this.name + "\""); + return false; + } + + this.nodes.clear(); // Clear previous data (if any) + + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + for (int lineNumber = 0; (line = reader.readLine()) != null; lineNumber++) { + if (line.trim().isEmpty() || line.startsWith("#") /* Comment */) continue; + + Matcher matcher = NODE_PATTERN.matcher(line); + if (!matcher.find()) { + System.err.println("Invalid locale syntax at (line=" + lineNumber + ")"); + continue; + } + + nodes.put(matcher.group(1), matcher.group(2)); + } + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * Supply the Message object with the plugins prefix. + * + * @param message message to be applied + * @return applied message + */ + private Message supplyPrefix(Message message) { + return message.setPrefix(this.nodes.getOrDefault("general.nametag.prefix", "[Plugin]")); + } + + /** + * Create a new unsaved Message + * + * @param message the message to create + * @return the created message + */ + public Message newMessage(String message) { + return supplyPrefix(new Message(message)); + } + + /** + * Get a message set for a specific node. + * + * @param node the node to get + * @return the message for the specified node + */ + public Message getMessage(String node) { + return this.getMessageOrDefault(node, node); + } + + /** + * Get a message set for a specific node + * + * @param node the node to get + * @param defaultValue the default value given that a value for the node was not found + * @return the message for the specified node. Default if none found + */ + public Message getMessageOrDefault(String node, String defaultValue) { + return supplyPrefix(new Message(this.nodes.getOrDefault(node, defaultValue))); + } + + /** + * Return the locale name (i.e. "en_US") + * + * @return the locale name + */ + public String getName() { + return name; + } + + private static void copy(InputStream input, OutputStream output) { + int n; + byte[] buffer = new byte[1024 * 4]; + + try { + while ((n = input.read(buffer)) != -1) { + output.write(buffer, 0, n); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/songoda/epichoppers/utils/locale/Message.java b/src/main/java/com/songoda/epichoppers/utils/locale/Message.java new file mode 100644 index 0000000..9e717d4 --- /dev/null +++ b/src/main/java/com/songoda/epichoppers/utils/locale/Message.java @@ -0,0 +1,115 @@ +package com.songoda.epichoppers.utils.locale; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * The Message object. This holds the message to be sent + * as well as the plugins prefix so that they can both be + * easily manipulated then deployed + */ +public class Message { + + private String prefix = null; + private String message; + + /** + * create a new message + * + * @param message the message text + */ + public Message(String message) { + this.message = message; + } + + /** + * Format and send the held message to a player + * + * @param player player to send the message to + */ + public void sendMessage(Player player) { + player.sendMessage(this.getMessage()); + } + + /** + * Format and send the held message with the + * appended plugin prefix to a player + * + * @param player player to send the message to + */ + public void sendPrefixedMessage(Player player) { + player.sendMessage(this.getPrefixedMessage()); + } + + /** + * Format and send the held message to a player + * + * @param sender command sender to send the message to + */ + public void sendMessage(CommandSender sender) { + sender.sendMessage(this.getMessage()); + } + + /** + * Format and send the held message with the + * appended plugin prefix to a command sender + * + * @param sender command sender to send the message to + */ + public void sendPrefixedMessage(CommandSender sender) { + sender.sendMessage(this.getPrefixedMessage()); + } + + /** + * Format the held message and append the plugins + * prefix + * + * @return the prefixed message + */ + public String getPrefixedMessage() { + return ChatColor.translateAlternateColorCodes('&',(prefix == null ? "" : this.prefix) + + " " + this.message); + } + + /** + * Get and format the held message + * + * @return the message + */ + public String getMessage() { + return ChatColor.translateAlternateColorCodes('&', this.message); + } + + /** + * Get the held message + * + * @return the message + */ + public String getUnformattedMessage() { + return this.message; + } + + /** + * Replace the provided placeholder with the + * provided object + * + * @param placeholder the placeholder to replace + * @param replacement the replacement object + * @return the modified Message + */ + public Message processPlaceholder(String placeholder, Object replacement) { + this.message = message.replace("%" + placeholder + "%", replacement.toString()); + return this; + } + + Message setPrefix(String prefix) { + this.prefix = prefix; + return this; + } + + @Override + public String toString() { + return this.message; + } +} \ No newline at end of file diff --git a/src/main/java/com/songoda/epichoppers/utils/updateModules/LocaleModule.java b/src/main/java/com/songoda/epichoppers/utils/updateModules/LocaleModule.java index 621f775..51856bb 100644 --- a/src/main/java/com/songoda/epichoppers/utils/updateModules/LocaleModule.java +++ b/src/main/java/com/songoda/epichoppers/utils/updateModules/LocaleModule.java @@ -1,6 +1,6 @@ package com.songoda.epichoppers.utils.updateModules; -import com.songoda.epichoppers.Locale; +import com.songoda.epichoppers.utils.locale.Locale; import com.songoda.update.Module; import com.songoda.update.Plugin; import org.json.simple.JSONArray; @@ -22,7 +22,7 @@ public class LocaleModule implements Module { if (file.get("type").equals("locale")) { InputStream in = new URL((String) file.get("link")).openStream(); - Locale.saveDefaultLocale(in, (String) file.get("name")); + Locale.saveLocale(in, (String) file.get("name")); } } } catch (IOException e) {