From 9641852f822046a6990a148c103eac0e625ade2d Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Thu, 21 Aug 2025 01:09:41 +0200 Subject: [PATCH] Replaces lots more static strings --- .../BooksWithoutBorders.java | 2 + .../command/CommandGive.java | 114 +++++++++-------- .../command/CommandLoad.java | 116 +++++++++++------- .../config/Permission.java | 11 +- .../config/StaticMessage.java | 1 + .../config/translation/Formatting.java | 55 +++++++++ .../config/translation/SignText.java | 62 ++++++++++ .../config/translation/Translatable.java | 5 - .../handler/BookshelfHandler.java | 26 ++-- .../listener/BookshelfListener.java | 97 +++++++++------ .../listener/PlayerEventListener.java | 8 +- .../listener/SignEventListener.java | 64 +++++----- .../bookswithoutborders/state/SignType.java | 75 +++++++++++ .../utility/BookLoader.java | 11 +- src/main/resources/strings.yml | 26 +++- 15 files changed, 472 insertions(+), 201 deletions(-) create mode 100644 src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java create mode 100644 src/main/java/net/knarcraft/bookswithoutborders/state/SignType.java diff --git a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java index fd5a707..93b9992 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java @@ -34,6 +34,7 @@ import net.knarcraft.bookswithoutborders.config.translation.CostMessage; import net.knarcraft.bookswithoutborders.config.translation.Formatting; import net.knarcraft.bookswithoutborders.config.translation.GiveMessage; import net.knarcraft.bookswithoutborders.config.translation.SaveMessage; +import net.knarcraft.bookswithoutborders.config.translation.SignText; import net.knarcraft.bookswithoutborders.config.translation.Translatable; import net.knarcraft.bookswithoutborders.container.MigrationRequest; import net.knarcraft.bookswithoutborders.handler.BookshelfHandler; @@ -217,6 +218,7 @@ public class BooksWithoutBorders extends JavaPlugin { translator.registerMessageCategory(Formatting.NEUTRAL_COMMANDS_HEADER); translator.registerMessageCategory(CostMessage.SUCCESS_COST_ITEM_SET); translator.registerMessageCategory(SaveMessage.SUCCESS_SAVED); + translator.registerMessageCategory(SignText.SIGN_HEADER); stringFormatter = new StringFormatter(this.getDescription().getName(), translator); stringFormatter.setColorConversion(ColorConversion.RGB); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java index 96cda6b..6ebf9cd 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java @@ -56,65 +56,13 @@ public class CommandGive implements TabExecutor { return true; } - int argumentCount = arguments.length; - StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); if (arguments.length == 1) { stringFormatter.displayErrorMessage(sender, GiveMessage.ERROR_GIVE_NO_RECIPIENT); return false; } - //Organize and parse input - String bookIdentifier; - String receivingPlayerName; - String copies = "1"; - String isSigned = "true"; - - if (argumentCount > 3 && InputCleaningHelper.isInt(arguments[argumentCount - 2]) && - InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { - receivingPlayerName = arguments[argumentCount - 3]; - isSigned = arguments[argumentCount - 1]; - copies = arguments[argumentCount - 2]; - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 3); - } else if (argumentCount > 2 && InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { - isSigned = arguments[argumentCount - 1]; - receivingPlayerName = arguments[argumentCount - 2]; - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 2); - } else if (argumentCount > 2 && InputCleaningHelper.isInt(arguments[argumentCount - 1])) { - copies = arguments[argumentCount - 1]; - receivingPlayerName = arguments[argumentCount - 2]; - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 2); - } else { - receivingPlayerName = arguments[argumentCount - 1]; - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 1); - } - - //Try and find the target player - Player receivingPlayer = booksWithoutBorders.getServer().getPlayerExact(receivingPlayerName); - if (receivingPlayer == null) { - stringFormatter.displayErrorMessage(sender, GiveMessage.ERROR_GIVE_RECIPIENT_UNKNOWN); - return false; - } - - //Make sure the receiver is able to fit the book - if (receivingPlayer.getInventory().firstEmpty() == -1) { - stringFormatter.displayErrorMessage(sender, GiveMessage.ERROR_GIVE_RECIPIENT_FULL); - return false; - } - - //Load books available to the player - try { - Integer.parseInt(bookIdentifier); - BooksWithoutBorders.updateBooks(sender, givePublic); - } catch (NumberFormatException ignored) { - } - - try { - return loadAndGiveBook(bookIdentifier, sender, receivingPlayer, isSigned, folder, copies); - } catch (NumberFormatException e) { - stringFormatter.displayErrorMessage(sender, Translatable.ERROR_INVALID_COPIES_AMOUNT); - return false; - } + return parseArgumentsAndContinue(arguments, sender, folder, givePublic); } @Override @@ -172,6 +120,64 @@ public class CommandGive implements TabExecutor { return output; } + /** + * Parses the user input, before continuing to load the book + * + * @param arguments

The arguments given by the player

+ * @param sender

The player attempting to load a book

+ * @param directory

The directory to load from

+ * @param givePublic

Whether to give from the public or player directory

+ * @return

True if successful, false otherwise

+ * @throws NumberFormatException

If the number of copies given is not a number

+ */ + private boolean parseArgumentsAndContinue(@NotNull String[] arguments, @NotNull CommandSender sender, + @NotNull String directory, boolean givePublic) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + int argumentCount = arguments.length; + //Organize and parse input + String bookIdentifier; + String receivingPlayerName; + String copies = "1"; + boolean isSigned = true; + + // Parse arguments at the end of the command, and treat the rest as the book name + if (argumentCount > 3 && InputCleaningHelper.isInt(arguments[argumentCount - 2]) && + InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { + receivingPlayerName = arguments[argumentCount - 3]; + isSigned = Boolean.parseBoolean(arguments[argumentCount - 1]); + copies = arguments[argumentCount - 2]; + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 3); + } else if (argumentCount > 2 && InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { + isSigned = Boolean.parseBoolean(arguments[argumentCount - 1]); + receivingPlayerName = arguments[argumentCount - 2]; + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 2); + } else if (argumentCount > 2 && InputCleaningHelper.isInt(arguments[argumentCount - 1])) { + copies = arguments[argumentCount - 1]; + receivingPlayerName = arguments[argumentCount - 2]; + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 2); + } else { + receivingPlayerName = arguments[argumentCount - 1]; + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 1); + } + + //Try and find the target player + Player receivingPlayer = booksWithoutBorders.getServer().getPlayerExact(receivingPlayerName); + if (receivingPlayer == null) { + stringFormatter.displayErrorMessage(sender, GiveMessage.ERROR_GIVE_RECIPIENT_UNKNOWN); + return false; + } + + //Make sure the receiver is able to fit the book + if (receivingPlayer.getInventory().firstEmpty() == -1) { + stringFormatter.displayErrorMessage(sender, GiveMessage.ERROR_GIVE_RECIPIENT_FULL); + return false; + } + + //Load books available to the player + BooksWithoutBorders.updateBooks(sender, givePublic); + return loadAndGiveBook(bookIdentifier, sender, receivingPlayer, isSigned, directory, copies); + } + /** * Loads a book and gives it to the correct player * @@ -184,7 +190,7 @@ public class CommandGive implements TabExecutor { * @return

True if the book was successfully given

*/ private boolean loadAndGiveBook(@NotNull String bookIdentifier, @NotNull CommandSender sender, - @NotNull Player receivingPlayer, @NotNull String isSigned, @NotNull String folder, + @NotNull Player receivingPlayer, boolean isSigned, @NotNull String folder, @NotNull String copies) throws NumberFormatException { StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); String bookToLoad = InputCleaningHelper.cleanString(bookIdentifier); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java index 4a77a17..5a45548 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java @@ -52,58 +52,12 @@ public class CommandLoad implements TabExecutor { return false; } - int argumentCount = arguments.length; - if (PagedBookIndex.displayPage(arguments, sender, loadPublic, commandName)) { return true; } - //Organize and parse input - String bookIdentifier = arguments[0]; - String copies = "1"; - String isSigned = "true"; - - // Parse arguments at the end of the command, and treat the rest as the book name - if (argumentCount > 1) { - if (argumentCount > 2 && InputCleaningHelper.isInt(arguments[argumentCount - 2]) && - InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { - isSigned = arguments[argumentCount - 1]; - copies = arguments[argumentCount - 2]; - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 2); - } else if (InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { - isSigned = arguments[argumentCount - 1]; - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 1); - } else if (InputCleaningHelper.isInt(arguments[argumentCount - 1])) { - copies = arguments[argumentCount - 1]; - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 1); - } else { - bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 0); - } - } - //Load books available to the player - try { - Integer.parseInt(bookIdentifier); - BooksWithoutBorders.updateBooks(sender, loadPublic); - } catch (NumberFormatException ignored) { - } - - String bookToLoad = InputCleaningHelper.cleanString(bookIdentifier); - try { - //Give the new book if it can be loaded - ItemStack newBook = BookLoader.loadBook(player, bookToLoad, isSigned, directory, Integer.parseInt(copies)); - if (newBook != null) { - player.getInventory().addItem(newBook); - stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_BOOK_LOADED); - return true; - } else { - stringFormatter.displayErrorMessage(player, Translatable.ERROR_LOAD_FAILED); - return false; - } - } catch (NumberFormatException e) { - stringFormatter.displayErrorMessage(player, Translatable.ERROR_INVALID_COPIES_AMOUNT); - return false; - } + return parseArgumentsAndContinue(arguments, player, directory, loadPublic); } @Override @@ -151,4 +105,72 @@ public class CommandLoad implements TabExecutor { return output; } + /** + * Parses the user input, before continuing to load the book + * + * @param arguments

The arguments given by the player

+ * @param player

The player attempting to load a book

+ * @param directory

The directory to load from

+ * @param loadPublic

Whether to load from the public or player directory

+ * @return

True if successful, false otherwise

+ * @throws NumberFormatException

If the number of copies given is not a number

+ */ + private boolean parseArgumentsAndContinue(@NotNull String[] arguments, @NotNull Player player, + @NotNull String directory, boolean loadPublic) { + int argumentCount = arguments.length; + String bookIdentifier = arguments[0]; + int copies = 1; + boolean isSigned = true; + + // Parse arguments at the end of the command, and treat the rest as the book name + if (argumentCount > 1) { + if (argumentCount > 2 && InputCleaningHelper.isInt(arguments[argumentCount - 2]) && + InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { + isSigned = Boolean.parseBoolean(arguments[argumentCount - 1]); + copies = Integer.parseInt(arguments[argumentCount - 2]); + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 2); + } else if (InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { + isSigned = Boolean.parseBoolean(arguments[argumentCount - 1]); + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 1); + } else if (InputCleaningHelper.isInt(arguments[argumentCount - 1])) { + copies = Integer.parseInt(arguments[argumentCount - 1]); + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 1); + } else { + bookIdentifier = InputCleaningHelper.mergeArguments(arguments, 0); + } + } + + return loadBook(player, loadPublic, bookIdentifier, isSigned, directory, copies); + } + + /** + * Loads the specified book + * + * @param player

The player attempting to load the book

+ * @param loadPublic

Whether to load a book from the public directory

+ * @param bookIdentifier

The identifier of the book to load

+ * @param isSigned

Whether the loaded book should be signed

+ * @param directory

The directory to load the book from

+ * @param copies

The number of copies to load

+ * @return

The loaded book(s)

+ */ + private boolean loadBook(@NotNull Player player, boolean loadPublic, @NotNull String bookIdentifier, + boolean isSigned, @NotNull String directory, int copies) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + BooksWithoutBorders.updateBooks(player, loadPublic); + + String bookToLoad = InputCleaningHelper.cleanString(bookIdentifier); + + //Give the new book if it can be loaded + ItemStack newBook = BookLoader.loadBook(player, bookToLoad, isSigned, directory, copies); + if (newBook != null) { + player.getInventory().addItem(newBook); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_BOOK_LOADED); + return true; + } else { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_LOAD_FAILED); + return false; + } + } + } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/Permission.java b/src/main/java/net/knarcraft/bookswithoutborders/config/Permission.java index b56860d..dadb981 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/Permission.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/Permission.java @@ -41,7 +41,16 @@ public enum Permission { * The permission for bypassing author only un-signing */ AUTHOR_ONLY_UNSIGN("bypassAuthorOnlyUnsign"), - ; + + /** + * The permission for peeking at a bookshelf's contents + */ + PEEK_BOOKSHELF("peekBookshelf"), + + /** + * The permission for using special signs + */ + SIGNS("signs"); private final @NotNull String node; diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java index 7e06c4b..a7a42f3 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java @@ -25,6 +25,7 @@ public enum StaticMessage { DEBUG_AES_INVALID_ALGORITHM("Invalid AES algorithm"), DEBUG_AES_INVALID_PADDING_CIPHER("Invalid AES padding during Cipher generation"), DEBUG_AES_INVALID_KEY_SPECIFICATION("Invalid AES key specification"), + WARNING_USER_BOOK_MIGRATION_IMPOSSIBLE("Unable to migrate player book directory for player {player}"), ; private final @NotNull String messageString; diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Formatting.java b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Formatting.java index 877c13c..98a1ac3 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Formatting.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Formatting.java @@ -147,6 +147,61 @@ public enum Formatting implements TranslatableMessage { * The format used when showing book int index in the book list */ NEUTRAL_BOOK_LIST_BOOK_INDEX_NUMBER, + + /** + * The format of the bookshelf header title + */ + NEUTRAL_BOOKSHELF_HEADER_TITLE, + + /** + * The format of a bookshelf title which is not set + */ + NEUTRAL_BOOKSHELF_HEADER_TITLE_EMPTY, + + /** + * The format of a bookshelf's lore line + */ + NEUTRAL_BOOKSHELF_HEADER_LORE, + + /** + * The format of the sub-header for a bookshelf's top row + */ + NEUTRAL_BOOKSHELF_HEADER_TOP, + + /** + * The format of the sub-header for a bookshelf's bottom row + */ + NEUTRAL_BOOKSHELF_HEADER_BOTTOM, + + /** + * The format of the prefix used when displaying an enchanted book in a bookcase + */ + NEUTRAL_BOOKSHELF_ENCHANTED_PREFIX, + + /** + * The format used when displaying a player written book in a bookshelf + */ + NEUTRAL_BOOKSHELF_WRITTEN_FORMAT, + + /** + * The format of the prefix used when displaying a plain book in a bookcase + */ + NEUTRAL_BOOKSHELF_PLAIN_BOOK_PREFIX, + + /** + * The format used when displaying an unnamed plain book in a bookshelf + */ + NEUTRAL_BOOKSHELF_UNNAMED_PLAIN_BOOK_FORMAT, + + /** + * The format used when displaying the index of a book in a bookshelf + */ + NEUTRAL_BOOKSHELF_ENTRY_INDEX, + + /** + * The format used when displaying that a bookshelf position is empty + */ + NEUTRAL_BOOKSHELF_EMPTY, ; @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java new file mode 100644 index 0000000..fed8fad --- /dev/null +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java @@ -0,0 +1,62 @@ +package net.knarcraft.bookswithoutborders.config.translation; + +import net.knarcraft.knarlib.formatting.TranslatableMessage; +import org.jetbrains.annotations.NotNull; + +/** + * Translations for the text on BwB signs + */ +public enum SignText implements TranslatableMessage { + + /** + * The header for all BwB signs + */ + SIGN_HEADER, + + /** + * The encryption sign specifier + */ + SIGN_ENCRYPT, + + /** + * The decryption sign specifier + */ + SIGN_DECRYPT, + + /** + * The give sign specifier + */ + SIGN_GIVE, + + /** + * The format for displaying the password on the sign + */ + SIGN_PASSWORD, + + /** + * The format for marking a sign line as invalid + */ + SIGN_INVALID, + + /** + * The format for marking a sign line as valid + */ + SIGN_VALID, + + /** + * The error displayed when a player creates an invalid BwB sign + */ + ERROR_SIGN_INVALID, + + /** + * The error displayed when attempting to use an invalid BwB sign + */ + ERROR_SIGN_COMMAND_INVALID, + ; + + @Override + public @NotNull TranslatableMessage[] getAllMessages() { + return SignText.values(); + } + +} diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java index 91d5178..ff33580 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java @@ -228,11 +228,6 @@ public enum Translatable implements TranslatableMessage { */ ERROR_ENCRYPT_EMPTY, - /** - * The error displayed when using the give command with an invalid number of copies (unlikely to ever happen) - */ - ERROR_INVALID_COPIES_AMOUNT, - /** * The error displayed when running a command without holding any book in the main hand */ diff --git a/src/main/java/net/knarcraft/bookswithoutborders/handler/BookshelfHandler.java b/src/main/java/net/knarcraft/bookswithoutborders/handler/BookshelfHandler.java index c1c525a..66deb4c 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/handler/BookshelfHandler.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/handler/BookshelfHandler.java @@ -26,8 +26,12 @@ import java.util.logging.Level; */ public class BookshelfHandler { - private static final File bookshelfFile = new File(BooksWithoutBorders.getInstance().getDataFolder(), + private static final File BOOKSHELF_FILE = new File(BooksWithoutBorders.getInstance().getDataFolder(), "bookshelves.yml"); + private static final String BOOKSHELVES_SECTION = "bookshelves"; + private static final String TITLE_KEY = ".title"; + private static final String LORE_KEY = ".lore"; + private Set bookshelves; private Map locationLookup; @@ -69,8 +73,8 @@ public class BookshelfHandler { this.bookshelves = new HashSet<>(); this.locationLookup = new HashMap<>(); - YamlConfiguration configuration = YamlConfiguration.loadConfiguration(bookshelfFile); - ConfigurationSection bookshelfSection = configuration.getConfigurationSection("bookshelves"); + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(BOOKSHELF_FILE); + ConfigurationSection bookshelfSection = configuration.getConfigurationSection(BOOKSHELVES_SECTION); if (bookshelfSection == null) { BooksWithoutBorders.log(Level.INFO, StaticMessage.NOTICE_NO_BOOKSHELVES.toString()); return; @@ -84,8 +88,8 @@ public class BookshelfHandler { double z = Integer.parseInt(locationInfo[3]); Location bookshelfLocation = new Location(world, x, y, z); - String titleKey = key + ".title"; - String loreKey = key + ".lore"; + String titleKey = key + TITLE_KEY; + String loreKey = key + LORE_KEY; String title = bookshelfSection.getString(titleKey, null); List lore = bookshelfSection.getStringList(loreKey); @@ -102,11 +106,11 @@ public class BookshelfHandler { public void save() { try { YamlConfiguration configuration = new YamlConfiguration(); - ConfigurationSection bookshelfSection = configuration.createSection("bookshelves"); + ConfigurationSection bookshelfSection = configuration.createSection(BOOKSHELVES_SECTION); for (Bookshelf bookshelf : bookshelves) { saveBookshelf(bookshelfSection, bookshelf); } - configuration.save(bookshelfFile); + configuration.save(BOOKSHELF_FILE); } catch (IOException exception) { BooksWithoutBorders.log(Level.SEVERE, StaticMessage.EXCEPTION_BOOKSHELF_SAVING_FAILED.toString()); } @@ -124,10 +128,10 @@ public class BookshelfHandler { return; } - String key = location.getWorld().getUID() + "," + location.getBlockX() + "," + location.getBlockY() + - "," + location.getBlockZ(); - String titleKey = key + ".title"; - String loreKey = key + ".lore"; + String key = location.getWorld().getUID() + "," + location.getBlockX() + "," + location.getBlockY() + "," + + location.getBlockZ(); + String titleKey = key + TITLE_KEY; + String loreKey = key + LORE_KEY; section.set(titleKey, bookshelf.getTitle()); section.set(loreKey, bookshelf.getLore()); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java index 2e66272..089a429 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java @@ -1,13 +1,13 @@ package net.knarcraft.bookswithoutborders.listener; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; +import net.knarcraft.bookswithoutborders.config.Permission; +import net.knarcraft.bookswithoutborders.config.translation.Formatting; import net.knarcraft.bookswithoutborders.container.Bookshelf; import net.knarcraft.bookswithoutborders.handler.BookshelfHandler; import net.knarcraft.bookswithoutborders.utility.BookHelper; import net.knarcraft.bookswithoutborders.utility.IntegerToRomanConverter; -import net.knarcraft.knarlib.property.ColorConversion; -import net.knarcraft.knarlib.util.ColorHelper; -import net.md_5.bungee.api.ChatColor; +import net.knarcraft.knarlib.formatting.StringFormatter; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -66,7 +66,7 @@ public class BookshelfListener implements Listener { // Check if bookshelf peeking is enabled, and the player can peek if (!BooksWithoutBorders.getConfiguration().getEnableBookshelfPeeking() || - !event.getPlayer().hasPermission("bookswithoutborders.peekbookshelf")) { + !event.getPlayer().hasPermission(Permission.PEEK_BOOKSHELF.toString())) { return; } @@ -74,7 +74,8 @@ public class BookshelfListener implements Listener { event.setUseItemInHand(Event.Result.DENY); ChiseledBookshelfInventory bookshelfInventory = chiseledBookshelf.getInventory(); - player.sendMessage(getBookshelfDescription(bookshelfInventory, event.getClickedBlock().getLocation())); + BooksWithoutBorders.getStringFormatter().displaySuccessMessage(player, + getBookshelfDescription(bookshelfInventory, event.getClickedBlock().getLocation())); } /** @@ -86,48 +87,67 @@ public class BookshelfListener implements Listener { */ @NotNull private String getBookshelfDescription(@NotNull ChiseledBookshelfInventory bookshelfInventory, @NotNull Location location) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); StringBuilder builder = new StringBuilder(); Bookshelf bookshelf = BooksWithoutBorders.getBookshelfHandler().getFromLocation(location); + String title; + StringBuilder lore = new StringBuilder(); if (bookshelf != null) { - builder.append(ChatColor.of("#FF5700")).append("Books in ").append( - ColorHelper.translateColorCodes(bookshelf.getTitle(), ColorConversion.RGB)).append( - ChatColor.RESET).append(ChatColor.of("#FF5700")).append(":"); - for (String lore : bookshelf.getLore()) { - builder.append("\n ").append(ChatColor.LIGHT_PURPLE).append( - ColorHelper.translateColorCodes(lore, ColorConversion.RGB)).append(ChatColor.RESET); + title = bookshelf.getTitle(); + for (String loreLine : bookshelf.getLore()) { + lore.append(stringFormatter.replacePlaceholder(Formatting.NEUTRAL_BOOKSHELF_HEADER_LORE, "{lore}", loreLine)); } } else { - builder.append(ChatColor.of("#FF5700")).append("Books in shelf:").append(ChatColor.RESET); + title = stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_BOOKSHELF_HEADER_TITLE_EMPTY); } + builder.append(stringFormatter.replacePlaceholders(Formatting.NEUTRAL_BOOKSHELF_HEADER_TITLE, + List.of("{name}", "{lore}"), List.of(title, lore.toString()))); for (int i = 0; i < bookshelfInventory.getSize(); i++) { - int index = (i % 3) + 1; - if (i % 3 == 0) { - builder.append("\n ").append(ChatColor.of("#FF5700")).append( - i < 3 ? "Top Row:" : "Bottom Row:").append(ChatColor.RESET); - } - - builder.append("\n ").append(ChatColor.of("#ffd700")).append(index).append(". ").append(ChatColor.RESET); - - ItemStack itemStack = bookshelfInventory.getItem(i); - if (itemStack == null) { - builder.append(ChatColor.GRAY).append(""); - continue; - } - ItemMeta meta = itemStack.getItemMeta(); - - if (meta instanceof BookMeta bookMeta) { - builder.append(getBookDescription(bookMeta)); - } else if (meta instanceof EnchantmentStorageMeta enchantmentStorageMeta) { - builder.append(getEnchantedBookDescription(enchantmentStorageMeta)); - } else if (meta != null) { - builder.append(ChatColor.of("#A5682A")).append("[P]").append(ChatColor.RESET).append(getPlainBookDescription(meta)); - } + appendBookshelfItem(i, builder, bookshelfInventory); } return builder.toString(); } + /** + * Displays info about one item in a bookshelf + * + * @param counter

The book index to display

+ * @param builder

The string builder to append to

+ * @param bookshelfInventory

The inventory of the bookshelf to display a book from

+ */ + private void appendBookshelfItem(int counter, @NotNull StringBuilder builder, + @NotNull ChiseledBookshelfInventory bookshelfInventory) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + + // Show the row header before the first item, and before the fourth item + int index = (counter % 3) + 1; + if (counter == 0) { + builder.append(stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_BOOKSHELF_HEADER_TOP)); + } else if (counter == 3) { + builder.append(stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_BOOKSHELF_HEADER_BOTTOM)); + } + + builder.append(stringFormatter.replacePlaceholder(Formatting.NEUTRAL_BOOKSHELF_ENTRY_INDEX, "{index}", String.valueOf(index))); + + ItemStack itemStack = bookshelfInventory.getItem(counter); + if (itemStack == null) { + builder.append(stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_BOOKSHELF_EMPTY)); + return; + } + ItemMeta meta = itemStack.getItemMeta(); + + if (meta instanceof BookMeta bookMeta) { + builder.append(getBookDescription(bookMeta)); + } else if (meta instanceof EnchantmentStorageMeta enchantmentStorageMeta) { + builder.append(getEnchantedBookDescription(enchantmentStorageMeta)); + } else if (meta != null) { + builder.append(stringFormatter.getUnFormattedColoredMessage( + Formatting.NEUTRAL_BOOKSHELF_PLAIN_BOOK_PREFIX)).append(getPlainBookDescription(meta)); + } + } + /** * Gets the description of a plain (enchant-able) book * @@ -138,7 +158,8 @@ public class BookshelfListener implements Listener { private String getPlainBookDescription(@NotNull ItemMeta itemMeta) { String name = itemMeta.getDisplayName(); if (name.isEmpty()) { - name = "Plain book"; + name = BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage( + Formatting.NEUTRAL_BOOKSHELF_UNNAMED_PLAIN_BOOK_FORMAT); } return name; } @@ -153,7 +174,8 @@ public class BookshelfListener implements Listener { private String getBookDescription(@NotNull BookMeta bookMeta) { String title = BookHelper.getBookTitle(bookMeta); String author = BookHelper.getBookAuthor(bookMeta, null); - return ChatColor.of("#686868") + "[Q]" + ChatColor.RESET + title + ChatColor.RESET + " by " + author; + return BooksWithoutBorders.getStringFormatter().replacePlaceholders(Formatting.NEUTRAL_BOOKSHELF_WRITTEN_FORMAT, + List.of("{title}", "{author}"), List.of(title, author)); } /** @@ -165,7 +187,8 @@ public class BookshelfListener implements Listener { @NotNull private String getEnchantedBookDescription(@NotNull EnchantmentStorageMeta enchantmentStorageMeta) { StringBuilder builder = new StringBuilder(); - builder.append(ChatColor.of("#A64CFF")).append("[E]").append(ChatColor.RESET); + builder.append(BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage( + Formatting.NEUTRAL_BOOKSHELF_ENCHANTED_PREFIX)); Map enchantmentMap = enchantmentStorageMeta.getStoredEnchants(); List enchantments = new ArrayList<>(enchantmentMap.size()); for (Map.Entry enchantmentEntry : enchantmentMap.entrySet()) { diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java index 36b19ee..cdc0bad 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java @@ -2,8 +2,10 @@ package net.knarcraft.bookswithoutborders.listener; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.BwBConfig; +import net.knarcraft.bookswithoutborders.config.StaticMessage; import net.knarcraft.bookswithoutborders.utility.BookLoader; import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper; +import net.knarcraft.knarlib.formatting.StringFormatter; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -31,8 +33,8 @@ public class PlayerEventListener implements Listener { File file = new File(bookFolder, InputCleaningHelper.cleanString(player.getName())); if (file.exists()) { if (!file.renameTo(new File(bookFolder, player.getUniqueId().toString()))) { - BooksWithoutBorders.log(Level.WARNING, "Unable to migrate player book " + - "directory for player " + player.getName()); + BooksWithoutBorders.log(Level.WARNING, StringFormatter.replacePlaceholder( + StaticMessage.WARNING_USER_BOOK_MIGRATION_IMPOSSIBLE.toString(), "{player}", player.getName())); } } @@ -59,7 +61,7 @@ public class PlayerEventListener implements Listener { if (!bookName.trim().isEmpty()) { //Give the book to the player if it exists - ItemStack newBook = BookLoader.loadBook(player, bookName, "true", "public"); + ItemStack newBook = BookLoader.loadBook(player, bookName, true, "public"); if (newBook != null) { player.getInventory().addItem(newBook); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java index 43c66cb..3409969 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java @@ -3,13 +3,16 @@ package net.knarcraft.bookswithoutborders.listener; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.BwBConfig; import net.knarcraft.bookswithoutborders.config.Permission; +import net.knarcraft.bookswithoutborders.config.translation.SignText; import net.knarcraft.bookswithoutborders.encryption.EncryptionStyle; import net.knarcraft.bookswithoutborders.state.BookDirectory; +import net.knarcraft.bookswithoutborders.state.SignType; import net.knarcraft.bookswithoutborders.utility.BookFileHelper; import net.knarcraft.bookswithoutborders.utility.BookFormatter; import net.knarcraft.bookswithoutborders.utility.BookLoader; import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper; +import net.knarcraft.knarlib.formatting.StringFormatter; import net.md_5.bungee.api.ChatColor; import org.bukkit.Material; import org.bukkit.Tag; @@ -31,6 +34,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.util.List; import static net.knarcraft.bookswithoutborders.utility.BookFileHelper.isBookListIndex; @@ -48,40 +52,43 @@ public class SignEventListener implements Listener { String[] lines = event.getLines(); Player player = event.getPlayer(); + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + //Check if creating a Books Without Borders Sign and if the player has permission - if (!lines[0].equalsIgnoreCase("[BwB]") || !player.hasPermission("bookswithoutborders.signs")) { + if (SignType.fromString(lines[0]) != SignType.BOOKS_WITHOUT_BORDERS || + !player.hasPermission(Permission.SIGNS.toString())) { return; } //Mark the sign as active - event.setLine(0, ChatColor.DARK_GREEN + "[BwB]"); + event.setLine(0, stringFormatter.getUnFormattedColoredMessage(SignText.SIGN_HEADER)); //Check if the sign is of a valid type - if ((!lines[1].equalsIgnoreCase("[Encrypt]") && !lines[1].equalsIgnoreCase("[Decrypt]") && - !lines[1].equalsIgnoreCase("[Give]")) || lines[2].trim().isEmpty()) { + SignType type = SignType.fromString(lines[1]); + if (type == null || lines[2].trim().isEmpty()) { //Mark the second line as invalid - event.setLine(1, ChatColor.DARK_RED + lines[1]); - player.sendMessage("Invalid sign!"); + event.setLine(1, stringFormatter.replacePlaceholder(SignText.SIGN_INVALID, "{line}", lines[1])); + stringFormatter.displayErrorMessage(player, SignText.ERROR_SIGN_INVALID); return; } //Mark the second line as valid - event.setLine(1, ChatColor.DARK_BLUE + lines[1]); + event.setLine(1, stringFormatter.replacePlaceholder(SignText.SIGN_VALID, "{line}", lines[1])); lines = event.getLines(); //Mark valid encryption/decryption sign - if (lines[1].equalsIgnoreCase(ChatColor.DARK_BLUE + "[Encrypt]") || - lines[1].equalsIgnoreCase(ChatColor.DARK_BLUE + "[Decrypt]")) { - event.setLine(2, ChatColor.MAGIC + lines[2]); - event.setLine(3, ChatColor.DARK_BLUE + lines[3]); - } else if (lines[1].equalsIgnoreCase(ChatColor.DARK_BLUE + "[Give]")) { + if (type == SignType.GIVE) { //Generate book giving sign generateGiveSign(event, lines, player); + } else { + event.setLine(2, stringFormatter.replacePlaceholder(SignText.SIGN_PASSWORD, "{password}", lines[2])); + event.setLine(3, stringFormatter.replacePlaceholder(SignText.SIGN_VALID, "{line}", lines[3])); } } @EventHandler public void onClick(@NotNull PlayerInteractEvent event) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); Player player = event.getPlayer(); PlayerInventory playerInventory = player.getInventory(); EquipmentSlot hand = event.getHand(); @@ -99,24 +106,24 @@ public class SignEventListener implements Listener { Tag.WALL_SIGNS.isTagged(event.getClickedBlock().getType())))) { //The player right-clicked a sign Sign sign = (Sign) event.getClickedBlock().getState(); - if (!signLineEquals(sign, 0, "[BwB]", ChatColor.DARK_GREEN)) { + if (SignType.fromString(sign.getSide(Side.FRONT).getLine(0)) != SignType.BOOKS_WITHOUT_BORDERS) { return; } event.setUseItemInHand(Event.Result.DENY); event.setCancelled(true); - if (signLineEquals(sign, 1, "[Encrypt]", ChatColor.DARK_BLUE)) { + SignType signType = SignType.fromString(sign.getSide(Side.FRONT).getLine(1)); + if (signType == SignType.ENCRYPT) { encryptHeldBookUsingSign(sign, heldItemType, player, hand); - } else if (signLineEquals(sign, 1, "[Decrypt]", ChatColor.DARK_BLUE)) { + } else if (signType == SignType.DECRYPT) { decryptHeldBookUsingSign(sign, heldItemType, player, hand); - } else if (signLineEquals(sign, 1, "[Give]", ChatColor.DARK_BLUE) && - getSignLine2Color(sign) == ChatColor.DARK_GREEN) { + } else if (signType == SignType.GIVE && getSignLine2Color(sign) == ChatColor.DARK_GREEN) { giveBook(sign, player); } else { SignSide front = sign.getSide(Side.FRONT); - player.sendMessage(String.format("Sign command %s %s is invalid", front.getLine(1), - front.getLine(2))); + stringFormatter.displayErrorMessage(player, stringFormatter.replacePlaceholders(SignText.ERROR_SIGN_COMMAND_INVALID, + List.of("{action}", "{data}"), List.of(front.getLine(1), front.getLine(2)))); player.sendMessage(String.valueOf(getSignLine2Color(sign))); } } else if (heldItemType == Material.WRITTEN_BOOK && (event.getAction() == Action.LEFT_CLICK_AIR @@ -177,21 +184,6 @@ public class SignEventListener implements Listener { } } - /** - * Checks if a line on a sign equals some string, and that the sign is the correct color - * - * @param sign

The sign to read

- * @param lineNumber

The sign line to read

- * @param compareTo

The string to look for

- * @param color

The color to match

- * @return

True if the given string is what's on the sign

- */ - private boolean signLineEquals(@NotNull Sign sign, int lineNumber, @NotNull String compareTo, - @NotNull ChatColor color) { - String line = sign.getSide(Side.FRONT).getLine(lineNumber); - return line.equalsIgnoreCase(color + compareTo); - } - /** * Changes an edited sign into a sign to give books * @@ -284,7 +276,7 @@ public class SignEventListener implements Listener { } } - newBook = BookLoader.loadBook(player, fileName, "true", BookDirectory.ENCRYPTED, groupName, heldItem.getAmount()); + newBook = BookLoader.loadBook(player, fileName, true, BookDirectory.ENCRYPTED, groupName, heldItem.getAmount()); if (newBook == null) { BooksWithoutBorders.sendErrorMessage(player, "Unable to load the unencrypted book!"); @@ -341,7 +333,7 @@ public class SignEventListener implements Listener { fileName += BookFormatter.stripColor(thirdLine); } - ItemStack newBook = BookLoader.loadBook(player, fileName, "true", "public"); + ItemStack newBook = BookLoader.loadBook(player, fileName, true, "public"); if (newBook != null) { player.getInventory().addItem(newBook); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/state/SignType.java b/src/main/java/net/knarcraft/bookswithoutborders/state/SignType.java new file mode 100644 index 0000000..85f61bc --- /dev/null +++ b/src/main/java/net/knarcraft/bookswithoutborders/state/SignType.java @@ -0,0 +1,75 @@ +package net.knarcraft.bookswithoutborders.state; + +import net.knarcraft.bookswithoutborders.BooksWithoutBorders; +import net.knarcraft.bookswithoutborders.config.translation.SignText; +import net.knarcraft.bookswithoutborders.utility.BookFormatter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * The type of a BwB sign + */ +public enum SignType { + + /** + * The header of a BwB sign + */ + BOOKS_WITHOUT_BORDERS(SignText.SIGN_HEADER), + + /** + * A sign for giving a book + */ + GIVE(SignText.SIGN_GIVE), + + /** + * A sign for encrypting a book + */ + ENCRYPT(SignText.SIGN_ENCRYPT), + + /** + * A sign for decrypting a book + */ + DECRYPT(SignText.SIGN_DECRYPT), + ; + + private final @NotNull SignText text; + + /** + * Instantiates a new sign type + * + * @param text

The text designating this sign type

+ */ + SignType(@NotNull SignText text) { + this.text = text; + } + + /** + * Gets the sign type from the given sting + * + * @param input

The input to parse

+ * @return

The sign type, or null if not valid

+ */ + @Nullable + public static SignType fromString(@NotNull String input) { + input = BookFormatter.stripColor(input); + for (SignType signType : SignType.values()) { + if (input.equalsIgnoreCase(getText(signType.text))) { + return signType; + } + } + return null; + } + + /** + * Gets the text of the specified sign text + * + * @param signText

The sign text to get

+ * @return

The text

+ */ + @NotNull + private static String getText(@NotNull SignText signText) { + return BookFormatter.stripColor( + BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage(signText)); + } + +} diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java index cf89dab..54ea3d6 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java @@ -2,6 +2,7 @@ package net.knarcraft.bookswithoutborders.utility; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.BwBConfig; +import net.knarcraft.bookswithoutborders.config.Permission; import net.knarcraft.bookswithoutborders.state.BookDirectory; import org.bukkit.Material; import org.bukkit.command.CommandSender; @@ -34,7 +35,7 @@ public final class BookLoader { * @return

The loaded book

*/ @Nullable - public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, @NotNull String isSigned, + public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, boolean isSigned, @NotNull String directory) { return loadBook(sender, fileName, isSigned, directory, 1); } @@ -50,7 +51,7 @@ public final class BookLoader { * @return

The loaded book

*/ @Nullable - public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, @NotNull String isSigned, + public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, boolean isSigned, @NotNull String directory, int numCopies) { BookDirectory bookDirectory = BookDirectory.getFromString(directory); if (bookDirectory == null) { @@ -72,7 +73,7 @@ public final class BookLoader { * @return

The loaded book

*/ @Nullable - public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, @NotNull String isSigned, + public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, boolean isSigned, @NotNull BookDirectory bookDirectory, @NotNull String directory, int numCopies) { //Find the filename if a book index is given try { @@ -101,7 +102,7 @@ public final class BookLoader { //Make sure the player can pay for the book if (config.booksHavePrice() && - !sender.hasPermission("bookswithoutborders.bypassBookPrice") && + !sender.hasPermission(Permission.BYPASS_BOOK_PRICE.toString()) && (bookDirectory == BookDirectory.PUBLIC || bookDirectory == BookDirectory.PLAYER) && config.getEconomyManager().cannotPayForBookPrinting((Player) sender, numCopies)) { return null; @@ -140,7 +141,7 @@ public final class BookLoader { book.setAmount(numCopies); - if (!isSigned.equalsIgnoreCase("true") && book.getItemMeta() != null) { + if (!isSigned && book.getItemMeta() != null) { return BookHelper.unsignBook((BookMeta) book.getItemMeta(), book.getAmount()); } return book; diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index e2c316c..5cb2569 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -60,7 +60,6 @@ en: ERROR_GIVE_NO_RECIPIENT: "You have not specified the recipient of the book!" ERROR_GIVE_RECIPIENT_UNKNOWN: "Player not found!" ERROR_GIVE_RECIPIENT_FULL: "Receiving player must have space in their inventory to receive books!" - ERROR_INVALID_COPIES_AMOUNT: "Invalid number of book copies specified!" ERROR_GIVE_LOAD_FAILED: "Book failed to load!" ERROR_INVALID_BOOK_PAGE: "Invalid page index given!" ERROR_OUT_OF_RANGE_BOOK_PAGE: "The given page index is out of bounds!" @@ -125,9 +124,32 @@ en: NEUTRAL_BOOK_LIST_PATH_HOVER: "Select book by path" NEUTRAL_BOOK_LIST_BOOK_INDEX_HOVER: "Select book by index" NEUTRAL_BOOK_LIST_BOOK_INDEX_NUMBER: "[{index}]" + NEUTRAL_BOOKSHELF_HEADER_TITLE: "&nBookshelf summary\n&#FF5700Books in {name}&r&#FF5700:{lore}" + NEUTRAL_BOOKSHELF_HEADER_LORE: "\n &d{lore}&r" + NEUTRAL_BOOKSHELF_HEADER_TITLE_EMPTY: "shelf" + NEUTRAL_BOOKSHELF_HEADER_TOP: "\n &#FF5700Top Row:&r" + NEUTRAL_BOOKSHELF_HEADER_BOTTOM: "\n &#FF5700Bottom Row:&r" + NEUTRAL_BOOKSHELF_ENCHANTED_PREFIX: "&#A64CFF[E]&r" + NEUTRAL_BOOKSHELF_WRITTEN_FORMAT: "򧬔[Q]&r{title}&r by {author}" + NEUTRAL_BOOKSHELF_PLAIN_BOOK_PREFIX: "&#A5682A[P]&r" + NEUTRAL_BOOKSHELF_UNNAMED_PLAIN_BOOK_FORMAT: "Plain book" + NEUTRAL_BOOKSHELF_ENTRY_INDEX: "\n &#ffd700{index}. &r" + NEUTRAL_BOOKSHELF_EMPTY: "&7" # -----------------------------------------# # Translations of unknown/untitled author. # # Altering this might cause problems. # # -----------------------------------------# NEUTRAL_UNKNOWN_AUTHOR: "Unknown" - NEUTRAL_UNKNOWN_TITLE: "Untitled" \ No newline at end of file + NEUTRAL_UNKNOWN_TITLE: "Untitled" + # ---------------------- # + # Sign text and messages # + # ---------------------- # + SIGN_HEADER: "&2[BwB]" + SIGN_ENCRYPT: "[Encrypt]" + SIGN_DECRYPT: "[Decrypt]" + SIGN_GIVE: "[Give]" + SIGN_PASSWORD: "&k{password}" + SIGN_INVALID: "&4{line}" + SIGN_VALID: "&1{line}" + ERROR_SIGN_INVALID: "Invalid sign!" + ERROR_SIGN_COMMAND_INVALID: "Sign command {action} {data} is invalid" \ No newline at end of file