Adds some code required for custom formatting and translation
This commit is contained in:
parent
cfff5485b2
commit
5b02a094e8
@ -1,5 +1,6 @@
|
||||
package net.knarcraft.dynmapcitizens;
|
||||
|
||||
import net.knarcraft.dynmapcitizens.formatting.Translator;
|
||||
import net.knarcraft.dynmapcitizens.handler.VaultHandler;
|
||||
import net.knarcraft.dynmapcitizens.handler.trait.BlacksmithHandler;
|
||||
import net.knarcraft.dynmapcitizens.handler.trait.CitizensTraitHandler;
|
||||
@ -49,6 +50,9 @@ public final class DynmapCitizens extends JavaPlugin {
|
||||
configuration = this.getConfig();
|
||||
this.globalSettings.load(configuration);
|
||||
|
||||
//Load all messages
|
||||
Translator.loadLanguages("en");
|
||||
|
||||
//Initialize all enabled traits
|
||||
initializeTraitHandlers(configuration);
|
||||
|
||||
|
@ -0,0 +1,114 @@
|
||||
package net.knarcraft.dynmapcitizens.formatting;
|
||||
|
||||
import net.knarcraft.dynmapcitizens.DynmapCitizens;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A formatter for formatting displayed messages
|
||||
*/
|
||||
public final class StringFormatter {
|
||||
|
||||
private final static String pluginName = DynmapCitizens.getInstance().getDescription().getName();
|
||||
|
||||
private StringFormatter() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying a successful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The translatable message to display</p>
|
||||
*/
|
||||
public static void displaySuccessMessage(CommandSender sender, TranslatableMessage message) {
|
||||
sender.sendMessage(ChatColor.GREEN + getFormattedMessage(Translator.getTranslatedMessage(message)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying a successful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The raw message to display</p>
|
||||
*/
|
||||
public static void displaySuccessMessage(CommandSender sender, String message) {
|
||||
sender.sendMessage(ChatColor.GREEN + getFormattedMessage(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying an unsuccessful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The translatable message to display</p>
|
||||
*/
|
||||
public static void displayErrorMessage(CommandSender sender, TranslatableMessage message) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + getFormattedMessage(Translator.getTranslatedMessage(message)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted version of any chat message
|
||||
*
|
||||
* @param message <p>The message to format</p>
|
||||
* @return <p>The formatted message</p>
|
||||
*/
|
||||
private static String getFormattedMessage(String message) {
|
||||
return "[" + pluginName + "] " + ChatColor.RESET + translateColors(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates & color codes to proper colors
|
||||
*
|
||||
* @param input <p>The input string to translate colors for</p>
|
||||
* @return <p>The input with color codes translated</p>
|
||||
*/
|
||||
private static String translateColors(String input) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package net.knarcraft.dynmapcitizens.formatting;
|
||||
|
||||
public enum TranslatableMessage {
|
||||
|
||||
SENTINEL_DETAILS
|
||||
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
package net.knarcraft.dynmapcitizens.formatting;
|
||||
|
||||
import net.knarcraft.dynmapcitizens.DynmapCitizens;
|
||||
import net.knarcraft.dynmapcitizens.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) {
|
||||
DynmapCitizens.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) {
|
||||
DynmapCitizens instance = DynmapCitizens.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;
|
||||
}
|
||||
|
||||
}
|
@ -47,12 +47,14 @@ public class SentinelHandler extends AbstractTraitHandler {
|
||||
description += "<br><b>Squad:</b> " + trait.squad;
|
||||
}
|
||||
if (settings.displaySentinelStats()) {
|
||||
description += "<br><b>Invincible:</b> " + trait.invincible + "<br><b>Armor:</b> " +
|
||||
trait.armor + "<br><b>Health:</b> " + trait.health + "<br><b>Accuracy:</b> " + trait.accuracy +
|
||||
"<br><b>Damage:</b> " + trait.damage + "<br><b>Allow knockback:</b> " + trait.allowKnockback;
|
||||
description += "<br><b>Invincible:</b> " + trait.invincible + "<br><b>Armor:</b> " + trait.armor;
|
||||
description += "<br><b>Health:</b> " + trait.health + "<br><b>Accuracy:</b> " + trait.accuracy;
|
||||
description += "<br><b>Damage:</b> " + trait.damage + "<br><b>Speed:</b> " + trait.speed;
|
||||
description += "<br><b>Allow knockback:</b> " + trait.allowKnockback;
|
||||
description += "<br><b>Range:</b> " + trait.range + "<br><b>Reach:</b> " + trait.reach;
|
||||
description += "<br><b>Targets:</b> " + trait.allTargets.toAllInOneString() + "<br><b>Avoids:</b> " +
|
||||
trait.allAvoids.toAllInOneString() + "<br><b>Ignores:</b> " + trait.allIgnores.toAllInOneString();
|
||||
description += "<br><b>Targets:</b> " + trait.allTargets.toAllInOneString();
|
||||
description += "<br><b>Avoids:</b> " + trait.allAvoids.toAllInOneString();
|
||||
description += "<br><b>Ignores:</b> " + trait.allIgnores.toAllInOneString();
|
||||
}
|
||||
addNPCMarker(npc.getUniqueId(), "Sentinel NPC: ", description,
|
||||
DynmapCitizens.getInstance().getGlobalSettings().getMarkerIcons().get(Icon.SENTINEL), super.markerSet);
|
||||
|
@ -0,0 +1,32 @@
|
||||
package net.knarcraft.dynmapcitizens.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));
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceholder;
|
||||
import static net.knarcraft.dynmapcitizens.formatting.StringFormatter.replacePlaceholder;
|
||||
|
||||
/**
|
||||
* A helper class for time formatting
|
||||
|
55
src/main/resources/strings.yml
Normal file
55
src/main/resources/strings.yml
Normal file
@ -0,0 +1,55 @@
|
||||
en:
|
||||
SENTINEL_DESCRIPTION: |
|
||||
<h2>name</h2>
|
||||
<br><b>Squad:</b> {squad}
|
||||
{sentinelDetails}
|
||||
SENTINEL_DETAILS: |
|
||||
<ul>
|
||||
<li><b>Invincible:</b> {invincible}</li>
|
||||
<li><b>Armor:</b> {armor}</li>
|
||||
<li><b>Health:</b> {health}</li>
|
||||
<li><b>Accuracy:</b> {accuracy}</li>
|
||||
<li><b>Damage:</b> {damage}</li>
|
||||
<li><b>Speed:</b> {speed}</li>
|
||||
<li><b>Allow knockback:</b> {allowKnockback}</li>
|
||||
<li><b>Range:</b> {range}</li>
|
||||
<li><b>Reach:</b> {reach}</li>
|
||||
<li><b>Targets:</b> {targets}</li>
|
||||
<li><b>Avoids:</b> {avoids}</li>
|
||||
<li><b>Ignores:</b> {ignores}</li>
|
||||
</ul>
|
||||
QUESTS_PLANNER_DESCRIPTION: |
|
||||
<b>Planner:</b><ul>
|
||||
{questCoolDown}
|
||||
{questFrom}
|
||||
{questUntil}
|
||||
{questRepeat}
|
||||
</ul>
|
||||
QUESTS_PLANNER_COOL_DOWN: "<li>Quest repeatable after: {coolDown}</li>"
|
||||
QUESTS_PLANNER_UNREPEATABLE: "<li>Quest cannot be repeated!</li>"
|
||||
QUESTS_PLANNER_FROM: "<li>Quest available from {startDate}</li>"
|
||||
QUESTS_PLANNER_UNTIL: "<li>Quest available until {endDate}</li>"
|
||||
QUEST_PLANNER_REPEAT: "<li>Quest will become available again after {repeatDelay}</li>"
|
||||
QUESTS_REQUIREMENTS_FORMAT: |
|
||||
<b>Requirements: </b><ul>
|
||||
{requirementQuestPoints}
|
||||
{requirementExp}
|
||||
{requirementBlockedByQuests}
|
||||
{requirementRequiredQuests}
|
||||
{requirementRequiredItems}
|
||||
{requirementMCMMOSkills}
|
||||
{requirementPermissions}
|
||||
{requirementCustom}
|
||||
</ul>
|
||||
QUESTS_REQUIREMENTS_QUEST_POINTS: "<li>{questPoints} quest points</li>"
|
||||
QUESTS_REQUIREMENTS_EXP: "<li>{exp} exp</li>"
|
||||
QUESTS_REQUIREMENTS_BLOCKED_BY_QUEST_FORMAT: "<li>Blocked by quests:<ul>{blockingQuests}</ul></li>"
|
||||
QUESTS_REQUIREMENTS_BLOCKED_BY_QUEST_ITEM: "<li>{questName}</li>"
|
||||
QUESTS_REQUIREMENTS_REQUIRED_QUEST_FORMAT: "<li>Required quests:<ul>{requiredQuests}</ul></li>"
|
||||
QUESTS_REQUIREMENTS_REQUIRED_QUEST_ITEM: "<li>{questName}</li>"
|
||||
QUESTS_REQUIREMENTS_REQUIRED_ITEM_FORMAT: "<li>Required items:<ul>{requiredItems}</ul></li>"
|
||||
QUESTS_REQUIREMENTS_REQUIRED_ITEM_ITEM: "<li>{itemName}</li>"
|
||||
QUESTS_REQUIREMENTS_MCMMO_SKILL: "<li>Requires mcMMO skill {skill} at level {level}</li>"
|
||||
QUESTS_REQUIREMENTS_REQUIRED_PERMISSION_FORMAT: "<li>Required permissions:<ul>{permissions}</ul></li>"
|
||||
QUESTS_REQUIREMENTS_REQUIRED_PERMISSION_ITEM: "<li>{permission}</li>"
|
||||
|
Loading…
Reference in New Issue
Block a user