diff --git a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java index 93b9992..ff659df 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java @@ -386,24 +386,4 @@ public class BooksWithoutBorders extends JavaPlugin { return true; } - /** - * Sends a success message to a command sender (player or a console) - * - * @param sender
The sender to send the message to
- * @param messageThe message to send
- */ - public static void sendSuccessMessage(@NotNull CommandSender sender, @NotNull String message) { - sender.sendMessage(getConfiguration().getSuccessColor() + message); - } - - /** - * Sends an error message to a command sender (player or a console) - * - * @param senderThe sender to send the message to
- * @param messageThe message to send
- */ - public static void sendErrorMessage(@NotNull CommandSender sender, @NotNull String message) { - sender.sendMessage(getConfiguration().getErrorColor() + message); - } - } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java index 0aacab3..8c772ca 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java @@ -101,7 +101,7 @@ public class CommandDelete implements TabExecutor { } else { stringFormatter.displayErrorMessage(sender, Translatable.ERROR_DELETE_FAILED_SILENT); } - } catch (Exception e) { + } catch (Exception exception) { stringFormatter.displayErrorMessage(sender, Translatable.ERROR_DELETE_FAILED_EXCEPTION); } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java index 4abbd9c..c3fc635 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java @@ -105,7 +105,7 @@ public class CommandSave implements TabExecutor { try { fileName = BookHelper.getBookFile(book, player, saveToPublicFolder); } catch (IllegalArgumentException exception) { - BooksWithoutBorders.sendErrorMessage(player, exception.getMessage()); + stringFormatter.displayErrorMessage(player, exception.getMessage()); return; } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java index 5ded6c2..49be74c 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java @@ -53,7 +53,7 @@ public class CommandSetBookPrice implements TabExecutor { stringFormatter.displayErrorMessage(sender, CostMessage.ERROR_COST_INVALID_QUANTITY); return false; } - } catch (NumberFormatException e) { + } catch (NumberFormatException exception) { stringFormatter.displayErrorMessage(sender, CostMessage.ERROR_COST_INVALID_QUANTITY); return false; } @@ -142,7 +142,8 @@ public class CommandSetBookPrice implements TabExecutor { CostMessage.SUCCESS_COST_ECONOMY_SET, "{cost}", economyManager.getEconomy().format(newPriceQuantity))); return true; } else { - BooksWithoutBorders.sendErrorMessage(sender, StaticMessage.EXCEPTION_VAULT_PRICE_NOT_CHANGED.toString()); + BooksWithoutBorders.getStringFormatter().displayErrorMessage(sender, + StaticMessage.EXCEPTION_VAULT_PRICE_NOT_CHANGED.toString()); return false; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java index cb23807..4c4dc52 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java @@ -30,6 +30,7 @@ public enum StaticMessage { EXCEPTION_BOOK_LOAD_FAILED("Unable to read text file"), EXCEPTION_BOOK_UNKNOWN_EXTENSION("Trying to load a book file with an unrecognized extension"), EXCEPTION_UNEXPECTED_ENCRYPTED_BOOK("Attempted to load a normal book, but found an encrypted book instead"), + EXCEPTION_NOT_HOLDING_ONE_BOOK("The player is not holding exactly one book."), ; private final @NotNull String messageString; diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/CostMessage.java b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/CostMessage.java index fe8644f..21d96dd 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/CostMessage.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/CostMessage.java @@ -47,6 +47,26 @@ public enum CostMessage implements TranslatableMessage { * The error displayed when attempting to set an item cost without providing an item */ ERROR_COST_ITEM_MISSING, + + /** + * The error displayed when a player is unable to pay the item cost of printing a book + */ + ERROR_COST_INSUFFICIENT_AMOUNT, + + /** + * The error displayed when a player is unable to pay the book and quill cost of printing a book + */ + ERROR_COST_INSUFFICIENT_WRITABLE_BOOK, + + /** + * The success message displayed when economy cost is successfully paid + */ + SUCCESS_COST_PAID, + + /** + * The error displayed when a player is unable to pay the economy cost of printing a book + */ + ERROR_COST_INSUFFICIENT_ECONOMY, ; @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 index fed8fad..893265c 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java @@ -52,6 +52,11 @@ public enum SignText implements TranslatableMessage { * The error displayed when attempting to use an invalid BwB sign */ ERROR_SIGN_COMMAND_INVALID, + + /** + * The success message displayed when successfully getting a book from a give sign + */ + SUCCESS_SIGN_GIVE, ; @Override 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 396a098..9e42eaa 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java @@ -83,11 +83,26 @@ public enum Translatable implements TranslatableMessage { */ SUCCESS_TITLE_SET, + /** + * The success message displayed when books have been successfully migrated + */ + SUCCESS_MIGRATED, + /** * The error to display when the console attempts to run a player-only command */ ERROR_PLAYER_ONLY, + /** + * The success message displayed when a book is successfully encrypted + */ + SUCCESS_ENCRYPTED, + + /** + * The neutral message displayed when attempting legacy decryption after the updated decryption has failed + */ + NEUTRAL_ATTEMPTING_LEGACY_DECRYPTION, + /** * The error displayed when running a relevant command without holding a written book */ @@ -312,6 +327,87 @@ public enum Translatable implements TranslatableMessage { * The error displayed when attempting to encrypt a book that has an existing encrypted file */ ERROR_ENCRYPT_ALREADY_SAVED, + + /** + * The error displayed if attempting to replace a player's held book with another book, but the player is no longer + * holding exactly one book + */ + ERROR_BOOK_NOT_FOUND, + + /** + * The error displayed if attempting to list books while no books have been saved + */ + ERROR_NO_BOOKS_TO_LIST, + + /** + * The error displayed if attempting to decrypt a group encrypted book without the necessary permissions + */ + ERROR_GROUP_DECRYPT_NO_PERMISSION, + + /** + * The error displayed if a group encrypted book's file cannot be found on the server + */ + ERROR_GROUP_DECRYPT_NOT_FOUND, + + /** + * The error displayed if a group encrypted book cannot be loaded during decryption + */ + ERROR_GROUP_DECRYPT_LOAD_FAILED, + + /** + * The error displayed when one or more books fails to be migrated + */ + ERROR_MIGRATION_FAILED, + + /** + * The error displayed when a book fails to be migrated + */ + ERROR_MIGRATION_BOOK_FAILED, + + /** + * The error displayed when an unrecognized book directory is encountered + */ + ERROR_BOOK_DIRECTORY_UNKNOWN, + + /** + * The error displayed when unable to get blank book metadata from the item factory + */ + ERROR_METADATA_CREATION_FAILED, + + /** + * The error displayed when a loaded book is empty + */ + ERROR_LOAD_BOOK_EMPTY, + + /** + * The error displayed when a command can only be used by the author of a book + */ + ERROR_AUTHOR_ONLY, + + /** + * The error displayed when attempting to encrypt an empty book + */ + ERROR_ENCRYPT_BOOK_EMPTY, + + /** + * The error displayed when the book to be decrypted cannot be found + */ + ERROR_DECRYPT_NOT_FOUND, + + /** + * The error displayed when an invalid key is given during legacy encryption + */ + ERROR_DECRYPT_LEGACY_INVALID_KEY, + + /** + * The error displayed when group encryption fails + */ + ERROR_GROUP_ENCRYPT_FAILED, + + /** + * The error displayed when encryption fails + */ + ERROR_ENCRYPT_FAILED, ; @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/encryption/SubstitutionCipher.java b/src/main/java/net/knarcraft/bookswithoutborders/encryption/SubstitutionCipher.java index 053d5cb..327a0d7 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/encryption/SubstitutionCipher.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/encryption/SubstitutionCipher.java @@ -89,7 +89,7 @@ public class SubstitutionCipher implements Encryptor { try { offsetArray[i] = Integer.parseInt(nextToken); - } catch (NumberFormatException e) { + } catch (NumberFormatException exception) { BigInteger big = new BigInteger(nextToken); offsetArray[i] = Math.abs(big.intValue()); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/GroupDecryptListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/GroupDecryptListener.java new file mode 100644 index 0000000..8c2bfca --- /dev/null +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/GroupDecryptListener.java @@ -0,0 +1,114 @@ +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.Translatable; +import net.knarcraft.bookswithoutborders.state.BookDirectory; +import net.knarcraft.bookswithoutborders.utility.BookFileHelper; +import net.knarcraft.bookswithoutborders.utility.BookLoader; +import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper; +import net.knarcraft.knarlib.formatting.StringFormatter; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.BookMeta; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +/** + * A listener for players trying to decrypt a group encrypted book + */ +public class GroupDecryptListener implements Listener { + + @EventHandler + public void onEncryptedBookClick(@NotNull PlayerInteractEvent event) { + Player player = event.getPlayer(); + PlayerInventory playerInventory = player.getInventory(); + EquipmentSlot hand = event.getHand(); + if (hand == null) { + return; + } + ItemStack heldItem = playerInventory.getItem(hand); + if (heldItem == null) { + return; + } + Material heldItemType = heldItem.getType(); + if (heldItemType == Material.WRITTEN_BOOK && (event.getAction() == Action.LEFT_CLICK_AIR + || event.getAction() == Action.LEFT_CLICK_BLOCK)) { + + BookMeta oldBook = (BookMeta) heldItem.getItemMeta(); + if (oldBook == null) { + return; + } + + decryptBook(oldBook, player, heldItem, hand); + } + } + + /** + * Decrypts a book decryptable for a given group + * + * @param oldBookMetadata for the encrypted book
+ * @param playerThe player decrypting the book
+ * @param heldItemThe type of the held book
+ * @param handThe hand the player is using to hold the book
+ */ + private void decryptBook(@NotNull BookMeta oldBook, @NotNull Player player, @NotNull ItemStack heldItem, + @NotNull EquipmentSlot hand) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + BwBConfig config = BooksWithoutBorders.getConfiguration(); + + ItemStack newBook; + + //Check if the book is encrypted by Books Without Borders + if (!oldBook.hasLore() || oldBook.getLore() == null || !oldBook.getLore().get(0).contains(" encrypted]")) { + return; + } + + String groupName = oldBook.getLore().get(0).substring(3).split(" encrypted")[0]; + + //Permission check + if (!player.hasPermission(Permission.DECRYPT + "." + groupName) && + !(config.getAdminDecrypt() && player.hasPermission(Permission.ADMIN.toString()))) { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_GROUP_DECRYPT_NO_PERMISSION); + return; + } + + String encryptedFolder = BooksWithoutBorders.getConfiguration().getEncryptedBookPath(); + String fileName = oldBook.getTitle() + config.getTitleAuthorSeparator() + oldBook.getAuthor(); + + File file = BookFileHelper.findBookFile(encryptedFolder + InputCleaningHelper.cleanString(groupName) + + config.getSlash(), oldBook); + if (file == null) { + file = BookFileHelper.findBookFile(encryptedFolder, oldBook); + if (file == null) { + file = BookFileHelper.findBookFile(config.getBookFolder(), oldBook); + if (file == null) { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_GROUP_DECRYPT_NOT_FOUND); + return; + } + } + } + + newBook = BookLoader.loadBook(player, fileName, true, BookDirectory.ENCRYPTED, groupName, + heldItem.getAmount()); + + if (newBook == null) { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_GROUP_DECRYPT_LOAD_FAILED); + return; + } + + player.getInventory().setItem(hand, newBook); + player.closeInventory(); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_AUTO_DECRYPTED); + } + +} diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java index d301036..5151da7 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java @@ -1,17 +1,15 @@ 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.GiveMessage; 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; @@ -29,11 +27,9 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; -import org.bukkit.inventory.meta.BookMeta; 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; @@ -126,15 +122,6 @@ public class SignEventListener implements Listener { 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 - || event.getAction() == Action.LEFT_CLICK_BLOCK)) { - - BookMeta oldBook = (BookMeta) heldItem.getItemMeta(); - if (oldBook == null) { - return; - } - - decryptBook(oldBook, player, heldItem, hand); } } @@ -193,13 +180,6 @@ public class SignEventListener implements Listener { */ private void generateGiveSign(@NotNull SignChangeEvent event, @NotNull String[] lines, @NotNull Player player) { - if (lines[2].length() > 13 || lines[3].length() > 13) { - BooksWithoutBorders.sendErrorMessage(player, - "[Give] signs' 3rd and 4th lines must be 13 characters or less!"); - markGiveSignValidity(event, false); - return; - } - //Tests if a full file name has been supplied and points to an actual file String signFile = BooksWithoutBorders.getConfiguration().getBookFolder() + lines[2] + lines[3]; if (BookFileHelper.bookFileExists(signFile)) { @@ -232,62 +212,6 @@ public class SignEventListener implements Listener { } } - /** - * Decrypts a book decryptable for a given group - * - * @param oldBookMetadata for the encrypted book
- * @param playerThe player decrypting the book
- * @param heldItemThe type of the held book
- * @param handThe hand the player is using to hold the book
- */ - private void decryptBook(@NotNull BookMeta oldBook, @NotNull Player player, @NotNull ItemStack heldItem, - @NotNull EquipmentSlot hand) { - BwBConfig config = BooksWithoutBorders.getConfiguration(); - - ItemStack newBook; - - //Check if the book is encrypted by Books Without Borders - if (!oldBook.hasLore() || oldBook.getLore() == null || !oldBook.getLore().get(0).contains(" encrypted]")) { - return; - } - - String groupName = oldBook.getLore().get(0).substring(3).split(" encrypted")[0]; - - //Permission check - if (!player.hasPermission(Permission.DECRYPT + "." + groupName) && - !(config.getAdminDecrypt() && player.hasPermission(Permission.ADMIN.toString()))) { - BooksWithoutBorders.sendErrorMessage(player, "You are not allowed to decrypt that book"); - return; - } - - String encryptedFolder = BooksWithoutBorders.getConfiguration().getEncryptedBookPath(); - String fileName = oldBook.getTitle() + config.getTitleAuthorSeparator() + oldBook.getAuthor(); - - File file = BookFileHelper.findBookFile(encryptedFolder + InputCleaningHelper.cleanString(groupName) + - config.getSlash(), oldBook); - if (file == null) { - file = BookFileHelper.findBookFile(encryptedFolder, oldBook); - if (file == null) { - file = BookFileHelper.findBookFile(config.getBookFolder(), oldBook); - if (file == null) { - BooksWithoutBorders.sendErrorMessage(player, "Unable to find encrypted book"); - return; - } - } - } - - newBook = BookLoader.loadBook(player, fileName, true, BookDirectory.ENCRYPTED, groupName, heldItem.getAmount()); - - if (newBook == null) { - BooksWithoutBorders.sendErrorMessage(player, "Unable to load the unencrypted book!"); - return; - } - - player.getInventory().setItem(hand, newBook); - player.closeInventory(); - BooksWithoutBorders.sendSuccessMessage(player, "Book auto-decrypted!"); - } - /** * Encrypts and replaces the player's used book * @@ -335,11 +259,12 @@ public class SignEventListener implements Listener { ItemStack newBook = BookLoader.loadBook(player, fileName, true, "public"); + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); if (newBook != null) { player.getInventory().addItem(newBook); - BooksWithoutBorders.sendSuccessMessage(player, "Received book!"); + stringFormatter.displaySuccessMessage(player, SignText.SUCCESS_SIGN_GIVE); } else { - BooksWithoutBorders.sendErrorMessage(player, "Book failed to load!"); + stringFormatter.displayErrorMessage(player, GiveMessage.ERROR_GIVE_LOAD_FAILED); } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/manager/EconomyManager.java b/src/main/java/net/knarcraft/bookswithoutborders/manager/EconomyManager.java index 15fc96c..f9cac2a 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/manager/EconomyManager.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/manager/EconomyManager.java @@ -3,6 +3,7 @@ package net.knarcraft.bookswithoutborders.manager; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.BwBConfig; import net.knarcraft.bookswithoutborders.config.translation.CostMessage; +import net.knarcraft.knarlib.formatting.StringFormatter; import net.milkbowl.vault.economy.Economy; import org.bukkit.Material; import org.bukkit.Server; @@ -64,6 +65,7 @@ public class EconomyManager { */ public boolean cannotPayForBookPrinting(@NotNull Player player, int numCopies) { BwBConfig config = BooksWithoutBorders.getConfiguration(); + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); //BookPriceQuantity: How many items are required to pay for each book //BookPriceType: Which item is used to pay for the books. AIR = use economy Material bookCurrency = config.getBookPriceType(); @@ -72,20 +74,20 @@ public class EconomyManager { if (bookCurrency == Material.AIR) { return !payForBookPrintingEconomy(player, cost, numCopies); + } + if (bookCurrency == Material.WRITABLE_BOOK) { + //Writable books are treated as a special case to prevent WIP books from being used + return !takeWritableBookPayment(player, itemCost); + } + + if (player.getInventory().contains(bookCurrency, itemCost)) { + payForBookPrintingItem(player, itemCost); + return false; } else { - if (bookCurrency == Material.WRITABLE_BOOK) { - //Writable books are treated as a special case to prevent WIP books from being used - return !takeWritableBookPayment(player, itemCost); - } else { - if (player.getInventory().contains(bookCurrency, itemCost)) { - payForBookPrintingItem(player, itemCost); - return false; - } else { - BooksWithoutBorders.sendErrorMessage(player, itemCost + " " + bookCurrency + - "(s) are required for this command!"); - return true; - } - } + stringFormatter.displayErrorMessage(player, stringFormatter.replacePlaceholders( + CostMessage.ERROR_COST_INSUFFICIENT_AMOUNT, List.of("{cost}", "{currency}"), + List.of(String.valueOf(itemCost), bookCurrency.toString()))); + return true; } } @@ -97,10 +99,11 @@ public class EconomyManager { * @returnTrue if the payment was successful
*/ private boolean takeWritableBookPayment(@NotNull Player player, int itemCost) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); ListTrue if the player had the money and it has been withdrawn
*/ private boolean payForBookPrintingEconomy(@NotNull Player player, double cost, int numCopies) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); if (economy == null) { - BooksWithoutBorders.getStringFormatter().displayErrorMessage(player, CostMessage.ERROR_VAULT_COST_BUT_UNAVAILABLE); + stringFormatter.displayErrorMessage(player, CostMessage.ERROR_VAULT_COST_BUT_UNAVAILABLE); return false; } if ((economy.getBalance(player) - cost) >= 0) { economy.withdrawPlayer(player, cost); - BooksWithoutBorders.sendSuccessMessage(player, economy.format(cost) + " withdrawn to create " + - numCopies + " book(s)"); - BooksWithoutBorders.sendSuccessMessage(player, "New balance: " + - economy.format(economy.getBalance(player))); + stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholders( + CostMessage.SUCCESS_COST_PAID, List.of("{cost}", "{copies}", "{balance}"), + List.of(economy.format(cost), String.valueOf(numCopies), economy.format(economy.getBalance(player))))); return true; } else { - BooksWithoutBorders.sendErrorMessage(player, economy.format(cost) + " is required for this command!"); + stringFormatter.replacePlaceholder(CostMessage.ERROR_COST_INSUFFICIENT_ECONOMY, "{cost}", economy.format(cost)); return false; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java b/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java index f3a83b0..a1c1f50 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java @@ -1,12 +1,14 @@ package net.knarcraft.bookswithoutborders.thread; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; +import net.knarcraft.bookswithoutborders.config.translation.Translatable; import net.knarcraft.bookswithoutborders.container.EncryptedBook; import net.knarcraft.bookswithoutborders.container.MigrationRequest; import net.knarcraft.bookswithoutborders.utility.BookFileHelper; import net.knarcraft.bookswithoutborders.utility.BookHelper; import net.knarcraft.bookswithoutborders.utility.BookToFromTextHelper; import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; +import net.knarcraft.knarlib.formatting.StringFormatter; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; @@ -16,6 +18,7 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.UUID; import java.util.logging.Level; @@ -65,11 +68,12 @@ public class MigrationQueueThread implements Runnable { success = success & migrateFile(migrationRequest.file(), migrationRequest.player()); if (BooksWithoutBorders.getMigrationQueue().peek() == null) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); Player player = migrationRequest.player(); if (success) { - BooksWithoutBorders.sendSuccessMessage(player, "Successfully migrated all books"); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_MIGRATED); } else { - BooksWithoutBorders.sendErrorMessage(player, "Failed to migrate all books"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_MIGRATION_FAILED); } BooksWithoutBorders.getInstance().getServer().getScheduler().cancelTask(this.taskId); success = null; @@ -145,8 +149,10 @@ public class MigrationQueueThread implements Runnable { } return deleteBook(file.getParentFile(), newName, file); } catch (IllegalArgumentException | IOException exception) { - BooksWithoutBorders.sendErrorMessage(player, "Failed to migrate book: " + file.getName() + " Cause:"); - BooksWithoutBorders.sendErrorMessage(player, exception.getMessage()); + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + stringFormatter.displayErrorMessage(player, stringFormatter.replacePlaceholders( + Translatable.ERROR_MIGRATION_BOOK_FAILED, List.of("{file}", "{exception}"), + List.of(file.getName(), exception.getMessage()))); return false; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java index c429588..f6c76cf 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java @@ -2,6 +2,7 @@ package net.knarcraft.bookswithoutborders.utility; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.translation.Formatting; +import net.knarcraft.bookswithoutborders.config.translation.Translatable; import net.knarcraft.bookswithoutborders.state.BookDirectory; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -141,7 +142,7 @@ public final class BookFileHelper { File[] existingFiles = searchDirectory.listFiles(); if (!searchDirectory.exists() || existingFiles == null || existingFiles.length == 0) { - BooksWithoutBorders.sendErrorMessage(sender, "No books have been saved!"); + BooksWithoutBorders.getStringFormatter().displayErrorMessage(sender, Translatable.ERROR_NO_BOOKS_TO_LIST); return null; } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java index 49303f1..92ed643 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java @@ -3,6 +3,7 @@ package net.knarcraft.bookswithoutborders.utility; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.BwBConfig; import net.knarcraft.bookswithoutborders.config.translation.Formatting; +import net.knarcraft.bookswithoutborders.config.translation.Translatable; import net.knarcraft.bookswithoutborders.state.BookDirectory; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -227,8 +228,7 @@ public final class BookHelper { if (isAuthor(player.getName(), book.getAuthor())) { return false; } else { - BooksWithoutBorders.sendErrorMessage(player, - "You must be the author of this book to use this command!"); + BooksWithoutBorders.getStringFormatter().displayErrorMessage(player, Translatable.ERROR_AUTHOR_ONLY); return true; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java index f36d510..84eca47 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java @@ -3,7 +3,9 @@ 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.config.translation.Translatable; import net.knarcraft.bookswithoutborders.state.BookDirectory; +import net.knarcraft.knarlib.formatting.StringFormatter; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -55,7 +57,8 @@ public final class BookLoader { @NotNull String directory, int numCopies) { BookDirectory bookDirectory = BookDirectory.getFromString(directory); if (bookDirectory == null) { - BooksWithoutBorders.sendErrorMessage(sender, "Unrecognized book directory!"); + BooksWithoutBorders.getStringFormatter().displayErrorMessage(sender, + Translatable.ERROR_BOOK_DIRECTORY_UNKNOWN); return null; } return loadBook(sender, fileName, isSigned, bookDirectory, directory, numCopies); @@ -75,6 +78,7 @@ public final class BookLoader { @Nullable public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, boolean isSigned, @NotNull BookDirectory bookDirectory, @NotNull String directory, int numCopies) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); //Find the filename if a book index is given try { int bookIndex = Integer.parseInt(fileName); @@ -95,7 +99,8 @@ public final class BookLoader { String replaced = BookFileHelper.replaceAuthorWithUUID(fileName); file = getFullPath(sender, replaced, bookDirectory, directory); if (file == null) { - BooksWithoutBorders.sendErrorMessage(sender, "Incorrect file name!"); + stringFormatter.displayErrorMessage(sender, + Translatable.ERROR_INCORRECT_FILE_NAME); return null; } } @@ -113,14 +118,15 @@ public final class BookLoader { BookMeta bookMetadata = (BookMeta) BooksWithoutBorders.getItemFactory().getItemMeta(Material.WRITTEN_BOOK); if (bookMetadata == null) { - BooksWithoutBorders.sendErrorMessage(sender, "Unable to create blank book metadata!"); + stringFormatter.displayErrorMessage(sender, + Translatable.ERROR_METADATA_CREATION_FAILED); return null; } //Load the book from the given file bookMetadata = BookToFromTextHelper.bookFromFile(file, bookMetadata); if (bookMetadata == null) { - BooksWithoutBorders.sendErrorMessage(sender, "File was blank!!"); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_LOAD_BOOK_EMPTY); return null; } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java index 42ea4d5..33b0877 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java @@ -155,14 +155,15 @@ public final class EncryptionHelper { public static ItemStack encryptBook(Player player, boolean mainHand, @NotNull String key, @NotNull EncryptionStyle style, @NotNull String groupName, boolean preventAdminDecrypt) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); BookMeta book = InventoryHelper.getHeldBookMetadata(player, mainHand); if (book == null) { - BooksWithoutBorders.sendErrorMessage(player, "Unable to get metadata from the held book!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_METADATA_MISSING); return null; } if (!book.hasPages()) { - BooksWithoutBorders.sendErrorMessage(player, "Book is empty!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_ENCRYPT_BOOK_EMPTY); return null; } @@ -190,7 +191,7 @@ public final class EncryptionHelper { ItemStack encryptedBook = createEncryptedBook(book, newPages, player, newMetadata); - BooksWithoutBorders.sendSuccessMessage(player, "Book encrypted!"); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_ENCRYPTED); return encryptedBook; } @@ -257,6 +258,7 @@ public final class EncryptionHelper { @Nullable public static ItemStack loadEncryptedBook(@NotNull Player player, @NotNull String key, boolean deleteEncryptedFile, boolean forceDecrypt) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); ItemStack heldBook = InventoryHelper.getHeldBook(player, true); BookMeta bookMetadata = (BookMeta) heldBook.getItemMeta(); String path = BooksWithoutBorders.getConfiguration().getEncryptedBookPath(); @@ -271,7 +273,7 @@ public final class EncryptionHelper { File file = new File(path + fileName + ".yml"); if (!file.isFile()) { - BooksWithoutBorders.sendErrorMessage(player, "Book not found!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_DECRYPT_NOT_FOUND); return null; } else { try { @@ -281,8 +283,8 @@ public final class EncryptionHelper { } else { bookMetadata = book.bookMeta(); } - } catch (Exception e) { - BooksWithoutBorders.sendErrorMessage(player, "Decryption failed!"); + } catch (Exception exception) { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_DECRYPT_FAILED); return null; } } @@ -307,7 +309,8 @@ public final class EncryptionHelper { */ @Nullable public static ItemStack loadEncryptedBookLegacy(@NotNull Player player, @NotNull String key, boolean deleteEncryptedFile) { - BooksWithoutBorders.sendErrorMessage(player, "Attempting legacy decryption"); + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + stringFormatter.displayNeutralMessage(player, Translatable.NEUTRAL_ATTEMPTING_LEGACY_DECRYPTION); ItemStack heldBook = InventoryHelper.getHeldBook(player, true); BookMeta bookMetadata = (BookMeta) heldBook.getItemMeta(); String path = BooksWithoutBorders.getConfiguration().getEncryptedBookPath(); @@ -328,7 +331,7 @@ public final class EncryptionHelper { if (!file.isFile()) { file = new File(path + fileName + ".txt"); if (!file.isFile()) { - BooksWithoutBorders.sendErrorMessage(player, "Incorrect decryption key!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_DECRYPT_LEGACY_INVALID_KEY); return null; } } @@ -336,11 +339,11 @@ public final class EncryptionHelper { try { bookMetadata = BookToFromTextHelper.bookFromFile(file, bookMetadata); if (bookMetadata == null) { - BooksWithoutBorders.sendErrorMessage(player, "Decryption failed!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_DECRYPT_FAILED); return null; } - } catch (Exception e) { - BooksWithoutBorders.sendErrorMessage(player, "Decryption failed!"); + } catch (Exception exception) { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_DECRYPT_FAILED); return null; } @@ -464,7 +467,7 @@ public final class EncryptionHelper { try { BookToFromTextHelper.bookToYml(path, fileName, bookMetadata); } catch (IOException exception) { - BooksWithoutBorders.sendErrorMessage(player, "Group encrypted failed!"); + BooksWithoutBorders.getStringFormatter().displayErrorMessage(player, Translatable.ERROR_GROUP_ENCRYPT_FAILED); return null; } } @@ -481,6 +484,7 @@ public final class EncryptionHelper { */ @NotNull private static Boolean saveEncryptedBook(@NotNull Player player, @NotNull EncryptedBook encryptedBook) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); String path = BooksWithoutBorders.getConfiguration().getEncryptedBookPath(); String fileName = BookHelper.getBookFile(encryptedBook.bookMeta(), player, true); @@ -489,14 +493,14 @@ public final class EncryptionHelper { //cancels saving if file is already encrypted File file = new File(path, fileName + ".yml"); if (file.isFile()) { - BooksWithoutBorders.getStringFormatter().displayErrorMessage(player, Translatable.ERROR_ENCRYPT_ALREADY_SAVED); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_ENCRYPT_ALREADY_SAVED); return false; } try { BookToFromTextHelper.encryptedBookToYml(path, fileName, encryptedBook); } catch (IOException exception) { - BooksWithoutBorders.sendErrorMessage(player, "Encryption failed!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_ENCRYPT_FAILED); return false; } return true; diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/InventoryHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/InventoryHelper.java index bfc65bc..e4388e5 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/InventoryHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/InventoryHelper.java @@ -1,6 +1,8 @@ package net.knarcraft.bookswithoutborders.utility; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; +import net.knarcraft.bookswithoutborders.config.StaticMessage; +import net.knarcraft.bookswithoutborders.config.translation.Translatable; import net.knarcraft.bookswithoutborders.state.BookHoldingState; import net.knarcraft.bookswithoutborders.state.ItemSlot; import net.knarcraft.knarlib.formatting.StringFormatter; @@ -49,7 +51,7 @@ public final class InventoryHelper { } else if (heldSlot == ItemSlot.OFF_HAND) { return getHeldItem(player, false); } else { - throw new IllegalArgumentException("The player is not holding exactly one book."); + throw new IllegalArgumentException(StaticMessage.EXCEPTION_NOT_HOLDING_ONE_BOOK.toString()); } } @@ -66,7 +68,7 @@ public final class InventoryHelper { } else if (itemSlot == ItemSlot.OFF_HAND) { replaceHeldItem(player, newBook, false); } else { - BooksWithoutBorders.sendErrorMessage(player, "Could not find a book to replace!"); + BooksWithoutBorders.getStringFormatter().displayErrorMessage(player, Translatable.ERROR_BOOK_NOT_FOUND); } } @@ -107,16 +109,17 @@ public final class InventoryHelper { */ public static boolean notHoldingOneWrittenBookCheck(@NotNull Player player, @NotNull String noBookMessage, @NotNull String twoBooksMessage) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); BookHoldingState holdingState = getBookHoldingState(player); if (holdingState == BookHoldingState.NONE || holdingState == BookHoldingState.UNSIGNED_BOTH_HANDS || holdingState == BookHoldingState.UNSIGNED_MAIN_HAND || holdingState == BookHoldingState.UNSIGNED_OFF_HAND) { - BooksWithoutBorders.sendErrorMessage(player, noBookMessage); + stringFormatter.displayErrorMessage(player, noBookMessage); return true; } if (holdingState == BookHoldingState.SIGNED_BOTH_HANDS) { - BooksWithoutBorders.sendErrorMessage(player, twoBooksMessage); + stringFormatter.displayErrorMessage(player, twoBooksMessage); return true; } diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index 5c8baa5..2249a93 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -18,12 +18,17 @@ en: SUCCESS_COST_REMOVED: "Price to create books removed!" SUCCESS_COST_ITEM_SET: "Book creation price set to {quantity} {price}(s)!" SUCCESS_COST_ECONOMY_SET: "Book creation price set to {cost}!" + SUCCESS_COST_PAID: | + {cost} withdrawn to create {copies} book(s) + New balance: {balance} SUCCESS_BOOKSHELF_DATA_DELETED: "Bookshelf successfully deleted!" SUCCESS_BOOKSHELF_TITLE_SET: "Title successfully saved!" SUCCESS_BOOKSHELF_LORE_SET: "Lore successfully saved!" SUCCESS_GENERATION_CHANGED: "Book generation successfully changed!" SUCCESS_LORE_SET: "Added lore to item!" SUCCESS_TITLE_SET: "Title set to {title}!" + SUCCESS_MIGRATED: "Successfully migrated all books" + SUCCESS_ENCRYPTED: "Book encrypted!" ACTION_COPY: "copy" ACTION_CLEAR: "clear" ACTION_DECRYPT: "decrypt" @@ -81,6 +86,9 @@ en: ERROR_COST_INVALID_QUANTITY: "[quantity] must be a number greater than 0!" ERROR_COST_INVALID_TYPE: "Price type must be \"item\" or \"economy\"!" ERROR_COST_ITEM_MISSING: "Must be holding an item to set an [Item] price!" + ERROR_COST_INSUFFICIENT_ECONOMY: "{cost} is required for this command!" + ERROR_COST_INSUFFICIENT_AMOUNT: "{cost} {currency}(s) are required for this command!" + ERROR_COST_INSUFFICIENT_WRITABLE_BOOK: "{cost} empty book and quill(s) are required for this command!" ERROR_BOOKSHELF_NOT_FOUND: "You are not looking at a bookshelf!" ERROR_BOOKSHELF_NOT_REGISTERED: "The block you are looking at is not a registered bookshelf" ERROR_BOOKSHELF_NAME_REQUIRED: "You must name the bookshelf before assigning lore!" @@ -93,6 +101,23 @@ en: ERROR_ENCRYPT_ALREADY_SAVED: | An encrypted version of this book is already saved. Please decrypt your previously encrypted copy first. + ERROR_BOOK_NOT_FOUND: "Could not find a book to replace!" + ERROR_NO_BOOKS_TO_LIST: "No books have been saved!" + ERROR_GROUP_DECRYPT_NO_PERMISSION: "You are not allowed to decrypt that book" + ERROR_GROUP_DECRYPT_NOT_FOUND: "Unable to find encrypted book" + ERROR_GROUP_DECRYPT_LOAD_FAILED: "Unable to load the unencrypted book!" + ERROR_MIGRATION_FAILED: "Failed to migrate all books" + ERROR_MIGRATION_BOOK_FAILED: "Failed to migrate book: {file} Cause: {exception}" + ERROR_BOOK_DIRECTORY_UNKNOWN: "Unrecognized book directory!" + ERROR_METADATA_CREATION_FAILED: "Unable to create blank book metadata!" + ERROR_LOAD_BOOK_EMPTY: "File was blank!!" + ERROR_AUTHOR_ONLY: "You must be the author of this book to use this command!" + ERROR_ENCRYPT_BOOK_EMPTY: "Book is empty!" + ERROR_DECRYPT_NOT_FOUND: "Book not found!" + ERROR_DECRYPT_LEGACY_INVALID_KEY: "Incorrect decryption key!" + ERROR_GROUP_ENCRYPT_FAILED: "Group encrypted failed!" + ERROR_ENCRYPT_FAILED: "Encryption failed!" + NEUTRAL_ATTEMPTING_LEGACY_DECRYPTION: "Attempting legacy decryption" # ---------------------------------- # # Custom formatting for some output # # ---------------------------------- # @@ -155,4 +180,5 @@ en: 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 + ERROR_SIGN_COMMAND_INVALID: "Sign command {action} {data} is invalid" + SUCCESS_SIGN_GIVE: "Received book!" \ No newline at end of file