diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java index 421bdd8..00a870a 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java @@ -3,9 +3,9 @@ package net.knarcraft.bookswithoutborders.command; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.Translatable; import net.knarcraft.bookswithoutborders.utility.BookFormatter; +import net.knarcraft.bookswithoutborders.utility.BookHelper; import net.knarcraft.bookswithoutborders.utility.InventoryHelper; import net.knarcraft.knarlib.formatting.StringFormatter; -import net.md_5.bungee.api.ChatColor; import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -42,8 +42,11 @@ public class CommandAddTitlePage implements TabExecutor { int index; if (arguments.length < 1) { - if (InventoryHelper.notHoldingOneWrittenBookCheck(player, "You must be holding a written book to " + - "add an author title page!", "You cannot add an author title page to two books at once!")) { + if (InventoryHelper.notHoldingOneWrittenBookCheck(player, + stringFormatter.replacePlaceholder(Translatable.ERROR_NOT_HOLDING_WRITTEN_BOOK, "{action}", + stringFormatter.getUnFormattedColoredMessage(Translatable.ACTION_ADD_TITLE_AUTHOR_PAGE)), + stringFormatter.replacePlaceholder(Translatable.ERROR_ONLY_ONE_BOOK, "{action}", + stringFormatter.getUnFormattedColoredMessage(Translatable.ACTION_ADD_TITLE_AUTHOR_PAGE)))) { return false; } @@ -52,7 +55,7 @@ public class CommandAddTitlePage implements TabExecutor { try { index = Integer.parseInt(arguments[0]) - 1; } catch (NumberFormatException exception) { - BooksWithoutBorders.sendErrorMessage(sender, "Invalid page index given!"); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_INVALID_BOOK_PAGE); return false; } } @@ -70,30 +73,37 @@ public class CommandAddTitlePage implements TabExecutor { BookMeta bookMeta = (BookMeta) heldBook.getItemMeta(); if (bookMeta == null) { - BooksWithoutBorders.sendErrorMessage(sender, "Unable to get metadata for the held book!"); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_METADATA_MISSING); return false; } List pages = new ArrayList<>(bookMeta.getPages()); if (index < 0) { - BooksWithoutBorders.sendErrorMessage(sender, "The given page index is out of bounds!"); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_INVALID_BOOK_PAGE); return false; } if (title == null && heldBook.getType() == Material.WRITTEN_BOOK) { + // Add a page with the book title and book author String loreSeparator = BooksWithoutBorders.getConfiguration().getLoreSeparator(); + String pageText = formatTitle(stringFormatter.replacePlaceholders(Translatable.NEUTRAL_TITLE_PAGE_TITLE_AUTHOR_FORMAT, + List.of("{title}", "{separator}", "{author}"), List.of(BookHelper.getBookTitle(bookMeta), + loreSeparator, BookHelper.getBookAuthor(bookMeta, null)))); + if (index > pages.size()) { - pages.add(formatTitle(bookMeta.getTitle() + loreSeparator + "By: " + bookMeta.getAuthor())); + pages.add(pageText); } else { - pages.add(index, formatTitle(bookMeta.getTitle() + loreSeparator + "By: " + bookMeta.getAuthor())); + pages.add(index, pageText); } } else if (title == null) { + // Add a blank page if (index > pages.size()) { pages.add(""); } else { pages.add(index, ""); } } else { + // Add a custom chapter page if (index > pages.size()) { pages.add(formatTitle(title)); } else { @@ -102,7 +112,7 @@ public class CommandAddTitlePage implements TabExecutor { } bookMeta.setPages(pages); heldBook.setItemMeta(bookMeta); - BooksWithoutBorders.sendSuccessMessage(sender, "Title page added!"); + stringFormatter.displaySuccessMessage(sender, Translatable.SUCCESS_TITLE_PAGE_ADDED); return true; } @@ -113,18 +123,21 @@ public class CommandAddTitlePage implements TabExecutor { * @return

The formatted input

*/ private String formatTitle(@NotNull String input) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); String loreSeparator = BooksWithoutBorders.getConfiguration().getLoreSeparator(); if (input.contains(loreSeparator)) { String[] parts = input.split(loreSeparator); - StringBuilder output = new StringBuilder("\n"); - output.append(ChatColor.UNDERLINE).append(ChatColor.BOLD).append(BookFormatter.stripColor(parts[0])).append(ChatColor.RESET); + StringBuilder output = new StringBuilder(); + output.append(stringFormatter.replacePlaceholder(Translatable.NEUTRAL_TITLE_PAGE_HEADER_FORMAT, + "{header}", BookFormatter.stripColor(parts[0]))); for (int i = 1; i < parts.length; i++) { - output.append("\n").append("\n").append(ChatColor.ITALIC).append(BookFormatter.stripColor(parts[i])).append(ChatColor.RESET); + output.append(stringFormatter.replacePlaceholder(Translatable.NEUTRAL_TITLE_PAGE_TEXT_FORMAT, + "{text}", BookFormatter.stripColor(parts[i]))); } return output.toString(); } else { - return ChatColor.UNDERLINE + ChatColor.BOLD.toString() + input; + return input; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandFormat.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandFormat.java index b44cf6b..d5fb0b1 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandFormat.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandFormat.java @@ -35,7 +35,7 @@ public class CommandFormat implements TabExecutor { stringFormatter.displayErrorMessage(sender, Translatable.ERROR_NOT_HOLDING_ANY_BOOK); return false; } - + BookMeta meta = (BookMeta) heldBook.getItemMeta(); if (meta == null) { diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java b/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java index c5f645a..8f3ff4e 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java @@ -48,6 +48,11 @@ public enum Translatable implements TranslatableMessage { */ SUCCESS_GIVE_RECEIVED, + /** + * The success message displayed when a title page is successfully added + */ + SUCCESS_TITLE_PAGE_ADDED, + /** * The error to display when the console attempts to run a player-only command */ @@ -188,6 +193,11 @@ public enum Translatable implements TranslatableMessage { */ ERROR_NOT_HOLDING_ANY_BOOK, + /** + * The error displayed when a book page is specified outside the allowed range. + */ + ERROR_INVALID_BOOK_PAGE, + /** * The header displayed before printing all commands */ @@ -223,6 +233,26 @@ public enum Translatable implements TranslatableMessage { */ NEUTRAL_UNKNOWN_AUTHOR, + /** + * The translation of unknown title for a book + */ + NEUTRAL_UNKNOWN_TITLE, + + /** + * The format used when generating a title + author title page + */ + NEUTRAL_TITLE_PAGE_TITLE_AUTHOR_FORMAT, + + /** + * The formatting used when formatting the header on a title page + */ + NEUTRAL_TITLE_PAGE_HEADER_FORMAT, + + /** + * The format used when formatting text on a title page + */ + NEUTRAL_TITLE_PAGE_TEXT_FORMAT, + /** * The translation of the copy action */ @@ -247,6 +277,11 @@ public enum Translatable implements TranslatableMessage { * The translation of the format action */ ACTION_FORMAT, + + /** + * The translation of the add title page action + */ + ACTION_ADD_TITLE_AUTHOR_PAGE, ; @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java index 74181d4..07b337a 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/BookshelfListener.java @@ -1,9 +1,9 @@ package net.knarcraft.bookswithoutborders.listener; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; -import net.knarcraft.bookswithoutborders.config.Translatable; 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.md_5.bungee.api.ChatColor; import org.bukkit.Location; @@ -147,18 +147,8 @@ public class BookshelfListener implements Listener { */ @NotNull private String getBookDescription(@NotNull BookMeta bookMeta) { - String title; - String author; - if (!bookMeta.hasTitle() || bookMeta.getTitle() == null) { - title = "Untitled"; - } else { - title = bookMeta.getTitle(); - } - if (!bookMeta.hasAuthor() || bookMeta.getAuthor() == null) { - author = BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage(Translatable.NEUTRAL_UNKNOWN_AUTHOR); - } else { - author = bookMeta.getAuthor(); - } + String title = BookHelper.getBookTitle(bookMeta); + String author = BookHelper.getBookAuthor(bookMeta, null); return ChatColor.of("#686868") + "[Q]" + ChatColor.RESET + title + ChatColor.RESET + " by " + author; } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java index 47e4e4e..0f76ca9 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java @@ -162,29 +162,8 @@ public final class BookHelper { @NotNull public static String getBookFile(@NotNull BookMeta book, @NotNull OfflinePlayer player, boolean isPublic) throws IllegalArgumentException { String separator = BooksWithoutBorders.getConfiguration().getTitleAuthorSeparator(); - String bookName; - if (book.hasTitle()) { - bookName = book.getTitle(); - if (bookName == null) { - bookName = "Untitled"; - } - } else { - bookName = "Untitled"; - } - - String playerName = player.getName() == null ? player.getUniqueId().toString() : player.getName(); - String authorName; - if ((!book.hasAuthor() || isAuthor(playerName, book.getAuthor())) && !isPublic) { - //Store as unique id to account for name changes - authorName = player.getUniqueId().toString(); - } else if (!book.hasAuthor()) { - authorName = player.getName(); - } else { - authorName = book.getAuthor(); - if (authorName == null) { - authorName = BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage(Translatable.NEUTRAL_UNKNOWN_AUTHOR); - } - } + String bookName = getBookTitle(book); + String authorName = getBookAuthor(book, isPublic ? null : player); if (InputCleaningHelper.cleanString(bookName).contains(separator) || InputCleaningHelper.cleanString(authorName).contains(separator)) { @@ -196,6 +175,47 @@ public final class BookHelper { return InputCleaningHelper.cleanString(bookName + separator + authorName); } + /** + * Gets the author of a book, with fallback for unknown author + * + * @param book

The book to get the author of

+ * @param player

A player that might be the author (only used for private book folders), or null if dealing with public books

+ * @return

The book author, or an appropriate fallback

+ */ + public static String getBookAuthor(@NotNull BookMeta book, @Nullable OfflinePlayer player) { + String playerName = player == null ? "?" : (player.getName() == null ? player.getUniqueId().toString() : player.getName()); + String authorName; + if ((!book.hasAuthor() || isAuthor(playerName, book.getAuthor())) && player != null) { + //Store as unique id to account for name changes + authorName = player.getUniqueId().toString(); + } else if (!book.hasAuthor() && player != null) { + authorName = player.getName(); + } else { + authorName = book.getAuthor(); + if (authorName == null) { + authorName = BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage(Translatable.NEUTRAL_UNKNOWN_AUTHOR); + } + } + return authorName; + } + + /** + * Gets a book's name, defaulting to "Untitled" if not named + * + * @param book

The book to get the name of

+ * @return

The book's name or "Untitled"

+ */ + public static String getBookTitle(@NotNull BookMeta book) { + String bookName = null; + if (book.hasTitle()) { + bookName = book.getTitle(); + } + if (bookName == null) { + bookName = BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage(Translatable.NEUTRAL_UNKNOWN_TITLE); + } + return bookName; + } + /** * Checks whether the given player is the author of a given book * diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java index 7924d41..f422855 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java @@ -4,6 +4,7 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.Translatable; import net.knarcraft.bookswithoutborders.encryption.AESConfiguration; import net.knarcraft.bookswithoutborders.encryption.EncryptionStyle; +import net.knarcraft.knarlib.formatting.StringFormatter; import net.knarcraft.knarlib.util.FileHelper; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -200,13 +201,15 @@ public final class BookToFromTextHelper { */ @Nullable private static BookMeta bookFromYml(@NotNull File file, @NotNull BookMeta bookMetadata) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); try { FileConfiguration bookYml = YamlConfiguration.loadConfiguration(file); bookMetadata.setGeneration(BookMeta.Generation.valueOf(bookYml.getString("Generation", "ORIGINAL"))); - bookMetadata.setTitle(bookYml.getString("Title", "Untitled")); + bookMetadata.setTitle(bookYml.getString("Title", + stringFormatter.getUnFormattedColoredMessage(Translatable.NEUTRAL_UNKNOWN_TITLE))); bookMetadata.setAuthor(authorFromUUID(bookYml.getString("Author", - BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage(Translatable.NEUTRAL_UNKNOWN_AUTHOR)))); + stringFormatter.getUnFormattedColoredMessage(Translatable.NEUTRAL_UNKNOWN_AUTHOR)))); bookMetadata.setPages(bookYml.getStringList("Pages")); bookMetadata.setLore(bookYml.getStringList("Lore")); } catch (IllegalArgumentException e) { diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index 3bec32d..551d83f 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -8,6 +8,7 @@ en: SUCCESS_FORMATTED: "Book formatted!" SUCCESS_GIVE_SENT: "Book sent!" SUCCESS_GIVE_RECEIVED: "Book received!" + SUCCESS_TITLE_PAGE_ADDED: "Title page added!" ERROR_PLAYER_ONLY: "This command can only be used by a player!" ERROR_NOT_HOLDING_WRITTEN_BOOK: "You must be holding a written book to {action} it!" ERROR_NOT_HOLDING_WRITABLE_BOOK: "You must be holding a writable book to {action} it!" @@ -18,6 +19,7 @@ en: ACTION_DECRYPT: "decrypt" ACTION_ENCRYPT: "encrypt" ACTION_FORMAT: "format" + ACTION_ADD_TITLE_AUTHOR_PAGE: "add an author title page to" ERROR_COPY_COUNT_NOT_SPECIFIED: "You must specify the number of copies to be made!" ERROR_COPY_NEGATIVE_AMOUNT: "Number of copies must be larger than 0!" ERROR_COPY_INVALID_AMOUNT: | @@ -43,6 +45,7 @@ en: ERROR_GIVE_RECIPIENT_FULL: "Receiving player must have space in their inventory to receive books!" ERROR_GIVE_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!" NEUTRAL_COMMANDS_HEADER: | &e[] denote optional parameters <> denote required parameters @@ -55,4 +58,8 @@ en: NEUTRAL_COMMANDS_COMMAND: "\n \n&e{usage}: &a{description}" NEUTRAL_COMMANDS_COMMAND_NO_PERMISSION_REQUIRED: "None" NEUTRAL_COMMANDS_COMMAND_PERMISSION: " &7{{permission}}" - NEUTRAL_UNKNOWN_AUTHOR: "Unknown" \ No newline at end of file + NEUTRAL_UNKNOWN_AUTHOR: "Unknown" + NEUTRAL_UNKNOWN_TITLE: "Untitled" + NEUTRAL_TITLE_PAGE_TITLE_AUTHOR_FORMAT: "{title}{separator}By: {author}" + NEUTRAL_TITLE_PAGE_HEADER_FORMAT: "\n&n&l{header}&r" + NEUTRAL_TITLE_PAGE_TEXT_FORMAT: "\n\n&o{text}&r" \ No newline at end of file