Adds possibility for message customization and translation #5

This commit is contained in:
2022-10-03 18:15:38 +02:00
parent 3d333c6406
commit 30bddfa9c8
20 changed files with 406 additions and 188 deletions

View File

@ -6,6 +6,7 @@ import net.knarcraft.blacksmith.command.BlackSmithConfigTabCompleter;
import net.knarcraft.blacksmith.command.BlackSmithEditCommand;
import net.knarcraft.blacksmith.command.BlackSmithEditTabCompleter;
import net.knarcraft.blacksmith.config.GlobalSettings;
import net.knarcraft.blacksmith.formatting.Translator;
import net.knarcraft.blacksmith.listener.NPCClickListener;
import net.knarcraft.blacksmith.listener.PlayerListener;
import net.knarcraft.blacksmith.manager.EconomyManager;
@ -70,6 +71,8 @@ public class BlacksmithPlugin extends JavaPlugin {
config = new GlobalSettings(this);
config.load();
Translator.loadLanguages("en");
//Set up Vault integration
if (!setUpVault()) {
return;

View File

@ -5,8 +5,9 @@ import net.knarcraft.blacksmith.config.GlobalSetting;
import net.knarcraft.blacksmith.config.GlobalSettings;
import net.knarcraft.blacksmith.config.NPCSetting;
import net.knarcraft.blacksmith.config.SettingValueType;
import net.knarcraft.blacksmith.manager.ItemType;
import net.knarcraft.blacksmith.manager.Message;
import net.knarcraft.blacksmith.formatting.ItemType;
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
import net.knarcraft.blacksmith.formatting.Translator;
import net.knarcraft.blacksmith.util.InputParsingHelper;
import net.knarcraft.blacksmith.util.TypeValidationHelper;
import net.md_5.bungee.api.ChatColor;
@ -18,8 +19,8 @@ import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import static net.knarcraft.blacksmith.util.MessageFormatter.displayErrorMessage;
import static net.knarcraft.blacksmith.util.MessageFormatter.displaySuccessMessage;
import static net.knarcraft.blacksmith.formatting.StringFormatter.displayErrorMessage;
import static net.knarcraft.blacksmith.formatting.StringFormatter.displaySuccessMessage;
/**
* The command used for changing global configuration options
@ -41,9 +42,8 @@ public class BlackSmithConfigCommand implements CommandExecutor {
//Changing reforge-able items' default isn't recommended
if (commandName.equalsIgnoreCase(NPCSetting.REFORGE_ABLE_ITEMS.getCommandName())) {
displayErrorMessage(sender, "Changing reforge-able items globally will make every new " +
"blacksmith unable to reforge anything not in the list, unless it's changed for the " +
"individual NPC. If you really want to change this, change it manually.");
displayErrorMessage(sender,
Translator.getTranslatedMessage(TranslatableMessage.DEFAULT_REFORGE_ABLE_ITEMS_UNCHANGEABLE));
return false;
}
@ -82,9 +82,10 @@ public class BlackSmithConfigCommand implements CommandExecutor {
} else {
return false;
}
displaySuccessMessage(sender, Message.getCurrentValueMessage(correctCommandName, rawValue));
displaySuccessMessage(sender, TranslatableMessage.getCurrentValueMessage(correctCommandName, rawValue));
if (printRawValue) {
sender.sendMessage("Raw value: " + rawValue.replace(ChatColor.COLOR_CHAR, '&'));
sender.sendMessage(TranslatableMessage.getRawValueMessage(
rawValue.replace(ChatColor.COLOR_CHAR, '&')));
}
return true;
} else if (args.length == 2 && isSpecialCase(commandName)) {
@ -100,11 +101,11 @@ public class BlackSmithConfigCommand implements CommandExecutor {
String newValue = args[1];
if (detectedGlobalSetting != null) {
settings.changeValue(detectedGlobalSetting, newValue);
displaySuccessMessage(sender, Message.getValueChangedMessage(detectedGlobalSetting.getCommandName(), newValue));
displaySuccessMessage(sender, TranslatableMessage.getValueChangedMessage(detectedGlobalSetting.getCommandName(), newValue));
return true;
} else if (detectedNPCSetting != null) {
settings.changeValue(detectedNPCSetting, newValue);
displaySuccessMessage(sender, Message.getValueChangedMessage(detectedNPCSetting.getNodeName(), newValue));
displaySuccessMessage(sender, TranslatableMessage.getValueChangedMessage(detectedNPCSetting.getNodeName(), newValue));
return true;
}
return false;
@ -132,7 +133,7 @@ public class BlackSmithConfigCommand implements CommandExecutor {
} else {
currentValue = String.valueOf(settings.getPricePerDurabilityPoint(material));
}
displaySuccessMessage(sender, Message.getItemCurrentValueMessage(setting.getCommandName(), ItemType.MATERIAL,
displaySuccessMessage(sender, TranslatableMessage.getItemCurrentValueMessage(setting.getCommandName(), ItemType.MATERIAL,
material.name(), currentValue));
return true;
} else if (setting == GlobalSetting.ENCHANTMENT_COST) {
@ -140,7 +141,7 @@ public class BlackSmithConfigCommand implements CommandExecutor {
if (enchantment == null) {
return false;
}
displaySuccessMessage(sender, Message.getItemCurrentValueMessage(setting.getCommandName(), ItemType.ENCHANTMENT,
displaySuccessMessage(sender, TranslatableMessage.getItemCurrentValueMessage(setting.getCommandName(), ItemType.ENCHANTMENT,
enchantment.toString(), String.valueOf(settings.getEnchantmentCost(enchantment))));
return true;
} else {
@ -204,7 +205,7 @@ public class BlackSmithConfigCommand implements CommandExecutor {
return false;
}
displaySuccessMessage(sender, Message.getItemValueChangedMessage(detectedGlobalSetting.getCommandName(),
displaySuccessMessage(sender, TranslatableMessage.getItemValueChangedMessage(detectedGlobalSetting.getCommandName(),
itemType, itemChanged, newValue));
return true;
}

View File

@ -24,11 +24,11 @@ public class BlackSmithConfigTabCompleter implements TabCompleter {
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args) {
if (args.length == 1) {
if (!sender.hasPermission("blacksmith.admin")) {
return new ArrayList<>();
}
if (!sender.hasPermission("blacksmith.admin")) {
return new ArrayList<>();
}
if (args.length == 1) {
List<String> availableCommands = new ArrayList<>();
availableCommands.add("reload");
for (NPCSetting setting : NPCSetting.values()) {

View File

@ -3,9 +3,10 @@ package net.knarcraft.blacksmith.command;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.knarcraft.blacksmith.config.NPCSetting;
import net.knarcraft.blacksmith.manager.Message;
import net.knarcraft.blacksmith.formatting.StringFormatter;
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
import net.knarcraft.blacksmith.formatting.Translator;
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
import net.knarcraft.blacksmith.util.MessageFormatter;
import net.knarcraft.blacksmith.util.TypeValidationHelper;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.command.Command;
@ -13,7 +14,7 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import static net.knarcraft.blacksmith.util.MessageFormatter.displaySuccessMessage;
import static net.knarcraft.blacksmith.formatting.StringFormatter.displaySuccessMessage;
/**
* The main command used for blacksmith editing
@ -25,7 +26,8 @@ public class BlackSmithEditCommand implements CommandExecutor {
@NotNull String[] args) {
NPC npc = CitizensAPI.getDefaultNPCSelector().getSelected(sender);
if (npc == null || !npc.hasTrait(BlacksmithTrait.class)) {
MessageFormatter.displayErrorMessage(sender, "You must select an NPC before running this command");
StringFormatter.displayErrorMessage(sender,
Translator.getTranslatedMessage(TranslatableMessage.NO_NPC_SELECTED));
return true;
}
@ -59,18 +61,20 @@ public class BlackSmithEditCommand implements CommandExecutor {
if (newValue == null) {
//Display the current value of the setting
String rawValue = String.valueOf(blacksmithTrait.getSettings().getRawValue(npcSetting));
displaySuccessMessage(sender, Message.getCurrentValueMessage(npcSetting.getCommandName(), rawValue));
displaySuccessMessage(sender, TranslatableMessage.getCurrentValueMessage(npcSetting.getCommandName(), rawValue));
if (npcSetting.getPath().startsWith("defaults.messages")) {
sender.sendMessage("Raw value: " + rawValue.replace(ChatColor.COLOR_CHAR, '&'));
sender.sendMessage(TranslatableMessage.getRawValueMessage(
rawValue.replace(ChatColor.COLOR_CHAR, '&')));
}
return true;
} else {
boolean isValidType = TypeValidationHelper.isValid(npcSetting.getValueType(), newValue, sender);
if (isValidType) {
//Change the setting
blacksmithTrait.getSettings().changeSetting(npcSetting,
ChatColor.translateAlternateColorCodes('&', newValue));
displaySuccessMessage(sender, Message.getValueChangedMessage(npcSetting.getNodeName(), newValue));
Object nullCheckedValue = newValue.equalsIgnoreCase("null") ? null :
ChatColor.translateAlternateColorCodes('&', newValue);
blacksmithTrait.getSettings().changeSetting(npcSetting, nullCheckedValue);
displaySuccessMessage(sender, TranslatableMessage.getValueChangedMessage(npcSetting.getNodeName(), newValue));
return true;
} else {
return false;

View File

@ -21,15 +21,16 @@ public class BlackSmithEditTabCompleter implements TabCompleter {
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args) {
if (!sender.hasPermission("blacksmith.edit")) {
return new ArrayList<>();
}
List<String> npcSettings = new ArrayList<>();
for (NPCSetting setting : NPCSetting.values()) {
npcSettings.add(setting.getCommandName());
}
if (args.length == 1) {
if (!sender.hasPermission("blacksmith.edit")) {
return new ArrayList<>();
}
return TabCompletionHelper.filterMatchingContains(npcSettings, args[0]);
} else {
if (npcSettings.contains(args[0]) && args.length <= 2) {

View File

@ -1,6 +1,8 @@
package net.knarcraft.blacksmith.command;
import net.knarcraft.blacksmith.BlacksmithPlugin;
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
import net.knarcraft.blacksmith.formatting.Translator;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
@ -10,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static net.knarcraft.blacksmith.util.MessageFormatter.displaySuccessMessage;
import static net.knarcraft.blacksmith.formatting.StringFormatter.displaySuccessMessage;
/**
* The command for re-loading the plugin
@ -21,7 +23,7 @@ public class ReloadCommand implements TabExecutor {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args) {
BlacksmithPlugin.getInstance().reload();
displaySuccessMessage(sender, "Blacksmith config reloaded!");
displaySuccessMessage(sender, Translator.getTranslatedMessage(TranslatableMessage.PLUGIN_RELOADED));
return true;
}

View File

@ -62,11 +62,9 @@ public class NPCSettings {
* @param newValue <p>The new value of the setting</p>
*/
public void changeSetting(NPCSetting setting, Object newValue) {
currentValues.put(setting, newValue);
if (setting == NPCSetting.REFORGE_ABLE_ITEMS) {
currentValues.put(setting, newValue);
updateReforgeAbleItems();
} else {
currentValues.put(setting, newValue);
}
}
@ -338,13 +336,13 @@ public class NPCSettings {
String[] list = string.split(",");
List<String> replaced = new ArrayList<>(list.length);
for (String item : list) {
replaced.add(SmithPreset.replacePlaceholder(item));
replaced.add(SmithPreset.replacePreset(item));
}
return String.join(",", replaced);
} else if (value instanceof String[] stringList) {
List<String> replaced = new ArrayList<>(stringList.length);
for (String item : stringList) {
replaced.add(SmithPreset.replacePlaceholder(item));
replaced.add(SmithPreset.replacePreset(item));
}
return replaced.toArray();
} else {

View File

@ -36,19 +36,19 @@ public enum SmithPreset {
RANGED_SMITH;
/**
* Replaces the given string if it's a smith type placeholder
* Replaces the given string if it's a smith type preset
*
* @param possiblePlaceholder <p>The string that might be a placeholder</p>
* @return <p>The string, possibly with the placeholder replaced</p>
* @param possiblePreset <p>The string that might be a preset</p>
* @return <p>The string, possibly with the preset replaced</p>
*/
public static String replacePlaceholder(String possiblePlaceholder) {
public static String replacePreset(String possiblePreset) {
for (SmithPreset smithPreset : SmithPreset.values()) {
if (possiblePlaceholder.replace('-', '_').equalsIgnoreCase("preset:" +
if (possiblePreset.replace('-', '_').equalsIgnoreCase("preset:" +
smithPreset.name())) {
return String.join(",", smithPreset.getMaterialNames());
}
}
return possiblePlaceholder;
return possiblePreset;
}
/**

View File

@ -0,0 +1,23 @@
package net.knarcraft.blacksmith.formatting;
/**
* An enum representing all item types used in messages
*/
public enum ItemType {
ENCHANTMENT,
MATERIAL;
/**
* Gets the name of this item type
*
* @return <p>The name of this item type</p>
*/
public String getItemTypeName() {
return switch (this) {
case MATERIAL -> Translator.getTranslatedMessage(TranslatableMessage.ITEM_TYPE_MATERIAL);
case ENCHANTMENT -> Translator.getTranslatedMessage(TranslatableMessage.ITEM_TYPE_ENCHANTMENT);
};
}
}

View File

@ -1,4 +1,4 @@
package net.knarcraft.blacksmith.util;
package net.knarcraft.blacksmith.formatting;
import net.citizensnpcs.api.npc.NPC;
import net.knarcraft.blacksmith.BlacksmithPlugin;
@ -6,14 +6,17 @@ import net.md_5.bungee.api.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A message formatter to ensure uniform colors and format of chat messages
* A formatter for formatting displayed messages
*/
public final class MessageFormatter {
public final class StringFormatter {
private final static String pluginName = BlacksmithPlugin.getInstance().getDescription().getName();
private MessageFormatter() {
private StringFormatter() {
}
@ -69,4 +72,47 @@ public final class MessageFormatter {
return ChatColor.translateAlternateColorCodes('&', input);
}
/**
* Replaces a placeholder in a string
*
* @param input <p>The input string to replace in</p>
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement value</p>
* @return <p>The input string with the placeholder replaced</p>
*/
public static String replacePlaceholder(String input, String placeholder, String replacement) {
return input.replace(placeholder, replacement);
}
/**
* Replaces placeholders in a string
*
* @param input <p>The input string to replace in</p>
* @param placeholders <p>The placeholders to replace</p>
* @param replacements <p>The replacement values</p>
* @return <p>The input string with placeholders replaced</p>
*/
public static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
input = replacePlaceholder(input, placeholders[i], replacements[i]);
}
return input;
}
/**
* Translates all found color codes to formatting in a string
*
* @param message <p>The string to search for color codes</p>
* @return <p>The message with color codes translated</p>
*/
public static String translateAllColorCodes(String message) {
message = ChatColor.translateAlternateColorCodes('&', message);
Pattern pattern = Pattern.compile("(#[a-fA-F0-9]{6})");
Matcher matcher = pattern.matcher(message);
while (matcher.find()) {
message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group()));
}
return message;
}
}

View File

@ -0,0 +1,95 @@
package net.knarcraft.blacksmith.formatting;
import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceholders;
/**
* An enum containing all translatable global messages
*
* <p>This does not include NPC messages as they are configurable per-npc, and can be translated by changing the
* default message values in the main config file.</p>
*/
public enum TranslatableMessage {
VALUE_CHANGED,
VALUE_FOR_ITEM_CHANGED,
CURRENT_VALUE,
CURRENT_VALUE_FOR_ITEM,
ITEM_TYPE_ENCHANTMENT,
ITEM_TYPE_MATERIAL,
RAW_VALUE,
NO_NPC_SELECTED,
DEFAULT_REFORGE_ABLE_ITEMS_UNCHANGEABLE,
INPUT_STRING_LIST_REQUIRED,
INPUT_PERCENTAGE_REQUIRED,
INPUT_STRING_REQUIRED,
INPUT_POSITIVE_DOUBLE_REQUIRED,
INPUT_POSITIVE_INTEGER_REQUIRED,
PERMISSION_DENIED,
PLUGIN_RELOADED;
/**
* Gets the message to display when displaying the raw value of messages
*
* @param rawValue <p>The raw value to display</p>
* @return <p>The message to display</p>
*/
public static String getRawValueMessage(String rawValue) {
return StringFormatter.replacePlaceholder(Translator.getTranslatedMessage(TranslatableMessage.RAW_VALUE),
"{rawValue}", rawValue);
}
/**
* Gets the message to display when a value has been changed
*
* @param setting <p>The setting whose value has been changed</p>
* @param newValue <p>The new value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getValueChangedMessage(String setting, String newValue) {
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.VALUE_CHANGED),
new String[]{"{setting}", "{newValue}"}, new String[]{setting, newValue});
}
/**
* Gets the message to display when a value has been changed for an item
*
* @param setting <p>The setting whose value has been changed</p>
* @param itemType <p>The type of item changed ("material" or "enchantment")</p>
* @param item <p>The item the setting was changed for (a material or an enchantment name)</p>
* @param newValue <p>The new value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getItemValueChangedMessage(String setting, ItemType itemType, String item, String newValue) {
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.VALUE_FOR_ITEM_CHANGED),
new String[]{"{setting}", "{itemType}", "{item}", "{newValue}"},
new String[]{setting, itemType.getItemTypeName(), item, newValue});
}
/**
* Gets the message to display when displaying a setting's current value
*
* @param setting <p>The setting whose value is shown</p>
* @param currentValue <p>The current value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getCurrentValueMessage(String setting, String currentValue) {
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.CURRENT_VALUE),
new String[]{"{setting}", "{currentValue}"}, new String[]{setting, currentValue});
}
/**
* Gets the message to display when displaying a setting's current value for an item
*
* @param setting <p>The setting whose value is shown</p>
* @param itemType <p>The type of item shown ("material" or "enchantment")</p>
* @param item <p>The item the setting is shown for (a material or an enchantment name)</p>
* @param currentValue <p>The current value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getItemCurrentValueMessage(String setting, ItemType itemType, String item, String currentValue) {
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.CURRENT_VALUE_FOR_ITEM),
new String[]{"{setting}", "{itemType}", "{item}", "{currentValue}"},
new String[]{setting, itemType.getItemTypeName(), item, currentValue});
}
}

View File

@ -0,0 +1,120 @@
package net.knarcraft.blacksmith.formatting;
import net.knarcraft.blacksmith.BlacksmithPlugin;
import net.knarcraft.blacksmith.util.FileHelper;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
/**
* A tool to get strings translated to the correct language
*/
public final class Translator {
private static Map<TranslatableMessage, String> translatedMessages;
private static Map<TranslatableMessage, String> backupTranslatedMessages;
private Translator() {
}
/**
* Loads the languages used by this translator
*/
public static void loadLanguages(String selectedLanguage) {
backupTranslatedMessages = loadTranslatedMessages("en");
translatedMessages = loadCustomTranslatedMessages(selectedLanguage);
if (translatedMessages == null) {
translatedMessages = loadTranslatedMessages(selectedLanguage);
}
}
/**
* Gets a translated version of the given translatable message
*
* @param translatableMessage <p>The message to translate</p>
* @return <p>The translated message</p>
*/
public static String getTranslatedMessage(TranslatableMessage translatableMessage) {
if (translatedMessages == null) {
return "Translated strings not loaded";
}
String translatedMessage;
if (translatedMessages.containsKey(translatableMessage)) {
translatedMessage = translatedMessages.get(translatableMessage);
} else if (backupTranslatedMessages.containsKey(translatableMessage)) {
translatedMessage = backupTranslatedMessages.get(translatableMessage);
} else {
translatedMessage = translatableMessage.toString();
}
return StringFormatter.translateAllColorCodes(translatedMessage);
}
/**
* Loads all translated messages for the given language
*
* @param language <p>The language chosen by the user</p>
* @return <p>A mapping of all strings for the given language</p>
*/
public static Map<TranslatableMessage, String> loadTranslatedMessages(String language) {
try {
BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
return loadTranslatableMessages(language, reader);
} catch (FileNotFoundException e) {
BlacksmithPlugin.getInstance().getLogger().log(Level.SEVERE, "Unable to load translated messages");
return null;
}
}
/**
* Tries to load translated messages from a custom strings.yml file
*
* @param language <p>The selected language</p>
* @return <p>The loaded translated strings, or null if no custom language file exists</p>
*/
public static Map<TranslatableMessage, String> loadCustomTranslatedMessages(String language) {
BlacksmithPlugin instance = BlacksmithPlugin.getInstance();
File strings = new File(instance.getDataFolder(), "strings.yml");
if (!strings.exists()) {
instance.getLogger().log(Level.FINEST, "Strings file not found");
return null;
}
try {
instance.getLogger().log(Level.INFO, "Loading custom strings...");
return loadTranslatableMessages(language, new BufferedReader(new InputStreamReader(new FileInputStream(strings))));
} catch (FileNotFoundException e) {
instance.getLogger().log(Level.WARNING, "Unable to load custom messages");
return null;
}
}
/**
* Loads translatable messages from the given reader
*
* @param language <p>The selected language</p>
* @param reader <p>The buffered reader to read from</p>
* @return <p>The loaded translated strings</p>
*/
private static Map<TranslatableMessage, String> loadTranslatableMessages(String language, BufferedReader reader) {
Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
for (TranslatableMessage message : TranslatableMessage.values()) {
String translated = configuration.getString(language + "." + message.toString());
if (translated != null) {
translatedMessages.put(message, translated);
}
}
return translatedMessages;
}
}

View File

@ -1,7 +1,9 @@
package net.knarcraft.blacksmith.listener;
import net.knarcraft.blacksmith.formatting.StringFormatter;
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
import net.knarcraft.blacksmith.formatting.Translator;
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
import net.knarcraft.blacksmith.util.MessageFormatter;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -24,7 +26,8 @@ public class NPCClickListener implements Listener {
//Permission check
if (!player.hasPermission("blacksmith.use")) {
MessageFormatter.displayErrorMessage(player, "You lack the necessary permission");
StringFormatter.displayErrorMessage(player,
Translator.getTranslatedMessage(TranslatableMessage.PERMISSION_DENIED));
return;
}

View File

@ -1,31 +0,0 @@
package net.knarcraft.blacksmith.manager;
/**
* An enum representing all item types used in messages
*/
public enum ItemType {
ENCHANTMENT("enchantment"),
MATERIAL("material");
private final String itemTypeName;
/**
* Instantiates an item type
*
* @param itemTypeName <p>The name shown in messages</p>
*/
ItemType(String itemTypeName) {
this.itemTypeName = itemTypeName;
}
/**
* Gets the name of this item type
*
* @return <p>The name of this item type</p>
*/
public String getItemTypeName() {
return this.itemTypeName;
}
}

View File

@ -1,100 +0,0 @@
package net.knarcraft.blacksmith.manager;
public enum Message {
VALUE_CHANGED("&7{setting} set to &6{newValue}"),
VALUE_FOR_ITEM_CHANGED("&7{setting} for {itemType} {item} set to &6{newValue}"),
CURRENT_VALUE("&7Current value of {setting}:&r {currentValue}"),
CURRENT_VALUE_FOR_ITEM("&7Current value of {setting} for {itemType} {item}:&r {currentValue}");
private final String messageString;
/**
* Instantiates a new message
*
* @param messageString <p>The string value of this message</p>
*/
Message(String messageString) {
this.messageString = messageString;
}
/**
* Gets the message to display when a value has been changed
*
* @param setting <p>The setting whose value has been changed</p>
* @param newValue <p>The new value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getValueChangedMessage(String setting, String newValue) {
return replacePlaceholders(VALUE_CHANGED.messageString, new String[]{"{setting}", "{newValue}"},
new String[]{setting, newValue});
}
/**
* Gets the message to display when a value has been changed for an item
*
* @param setting <p>The setting whose value has been changed</p>
* @param itemType <p>The type of item changed ("material" or "enchantment")</p>
* @param item <p>The item the setting was changed for (a material or an enchantment name)</p>
* @param newValue <p>The new value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getItemValueChangedMessage(String setting, ItemType itemType, String item, String newValue) {
return replacePlaceholders(VALUE_FOR_ITEM_CHANGED.messageString, new String[]{"{setting}", "{itemType}",
"{item}", "{newValue}"}, new String[]{setting, itemType.getItemTypeName(), item, newValue});
}
/**
* Gets the message to display when displaying a setting's current value
*
* @param setting <p>The setting whose value is shown</p>
* @param currentValue <p>The current value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getCurrentValueMessage(String setting, String currentValue) {
return replacePlaceholders(CURRENT_VALUE.messageString, new String[]{"{setting}", "{currentValue}"},
new String[]{setting, currentValue});
}
/**
* Gets the message to display when displaying a setting's current value for an item
*
* @param setting <p>The setting whose value is shown</p>
* @param itemType <p>The type of item shown ("material" or "enchantment")</p>
* @param item <p>The item the setting is shown for (a material or an enchantment name)</p>
* @param currentValue <p>The current value of the setting</p>
* @return <p>The string to display to a user</p>
*/
public static String getItemCurrentValueMessage(String setting, ItemType itemType, String item, String currentValue) {
return replacePlaceholders(CURRENT_VALUE_FOR_ITEM.messageString, new String[]{"{setting}", "{itemType}",
"{item}", "{currentValue}"}, new String[]{setting, itemType.getItemTypeName(), item, currentValue});
}
/**
* Replaces a placeholder in a string
*
* @param input <p>The input string to replace in</p>
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement value</p>
* @return <p>The input string with the placeholder replaced</p>
*/
private static String replacePlaceholder(String input, String placeholder, String replacement) {
return input.replace(placeholder, replacement);
}
/**
* Replaces placeholders in a string
*
* @param input <p>The input string to replace in</p>
* @param placeholders <p>The placeholders to replace</p>
* @param replacements <p>The replacement values</p>
* @return <p>The input string with placeholders replaced</p>
*/
private static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
input = replacePlaceholder(input, placeholders[i], replacements[i]);
}
return input;
}
}

View File

@ -22,7 +22,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import static net.knarcraft.blacksmith.util.MessageFormatter.sendNPCMessage;
import static net.knarcraft.blacksmith.formatting.StringFormatter.sendNPCMessage;
/**
* The class representing the Blacksmith NPC trait

View File

@ -20,7 +20,7 @@ import java.util.Objects;
import java.util.Random;
import java.util.logging.Level;
import static net.knarcraft.blacksmith.util.MessageFormatter.sendNPCMessage;
import static net.knarcraft.blacksmith.formatting.StringFormatter.sendNPCMessage;
/**
* A representation of the session between a player and a blacksmith

View File

@ -0,0 +1,32 @@
package net.knarcraft.blacksmith.util;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* A helper class for dealing with files
*/
public final class FileHelper {
private FileHelper() {
}
/**
* Gets a buffered reader for
*
* @return <p>A buffered read for reading the file</p>
* @throws FileNotFoundException <p>If unable to get an input stream for the given file</p>
*/
public static BufferedReader getBufferedReaderForInternalFile(String file) throws FileNotFoundException {
InputStream inputStream = FileHelper.class.getResourceAsStream(file);
if (inputStream == null) {
throw new FileNotFoundException("Unable to read the given file");
}
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
}
}

View File

@ -1,9 +1,11 @@
package net.knarcraft.blacksmith.util;
import net.knarcraft.blacksmith.config.SettingValueType;
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
import net.knarcraft.blacksmith.formatting.Translator;
import org.bukkit.command.CommandSender;
import static net.knarcraft.blacksmith.util.MessageFormatter.displayErrorMessage;
import static net.knarcraft.blacksmith.formatting.StringFormatter.displayErrorMessage;
/**
* A helper class for validating a value's type
@ -49,7 +51,7 @@ public final class TypeValidationHelper {
private static boolean isStringList(Object value, CommandSender sender) {
boolean isStringList = value instanceof String[] || value instanceof String;
if (!isStringList && sender != null) {
displayErrorMessage(sender, "A string list is required!");
displayErrorMessage(sender, Translator.getTranslatedMessage(TranslatableMessage.INPUT_STRING_LIST_REQUIRED));
}
return isStringList;
}
@ -67,7 +69,7 @@ public final class TypeValidationHelper {
return intValue > 0 && intValue <= 100;
} catch (NumberFormatException | NullPointerException exception) {
if (sender != null) {
displayErrorMessage(sender, "You specified a value which isn't between 0 and 100!");
displayErrorMessage(sender, Translator.getTranslatedMessage(TranslatableMessage.INPUT_PERCENTAGE_REQUIRED));
}
return false;
}
@ -83,7 +85,7 @@ public final class TypeValidationHelper {
private static boolean isNonEmptyString(Object value, CommandSender sender) {
boolean isString = value instanceof String string && !string.strip().isEmpty();
if (!isString && sender != null) {
displayErrorMessage(sender, "A non-empty string is required!");
displayErrorMessage(sender, Translator.getTranslatedMessage(TranslatableMessage.INPUT_STRING_REQUIRED));
}
return isString;
}
@ -100,7 +102,8 @@ public final class TypeValidationHelper {
return ConfigHelper.asDouble(value) > 0.0;
} catch (NumberFormatException | NullPointerException exception) {
if (sender != null) {
displayErrorMessage(sender, "You specified a value which isn't a positive double!");
displayErrorMessage(sender,
Translator.getTranslatedMessage(TranslatableMessage.INPUT_POSITIVE_DOUBLE_REQUIRED));
}
return false;
}
@ -118,7 +121,8 @@ public final class TypeValidationHelper {
return ConfigHelper.asInt(value) > 0;
} catch (NumberFormatException | NullPointerException exception) {
if (sender != null) {
displayErrorMessage(sender, "You specified a value which isn't a positive integer!");
displayErrorMessage(sender,
Translator.getTranslatedMessage(TranslatableMessage.INPUT_POSITIVE_INTEGER_REQUIRED));
}
return false;
}