diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java index ddf4695..05473b9 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandAddTitlePage.java @@ -34,7 +34,7 @@ public class CommandAddTitlePage implements TabExecutor { return true; } - // Note: There are two different book checks as an book is accepted normally, but a written book is required for + // Note: There are two different book checks as a book is accepted normally, but a written book is required for // adding an author title page at the beginning. ItemStack heldBook = InventoryUtil.getHeldBook(player); if (heldBook == null) { diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java index f703233..b69844c 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDelete.java @@ -32,7 +32,8 @@ public class CommandDelete implements TabExecutor { return true; } - return deleteBook(sender, arguments, false, label); + deleteBook(sender, arguments, false, label); + return true; } /** @@ -42,25 +43,23 @@ public class CommandDelete implements TabExecutor { * @param arguments

The arguments given

* @param deletePublic

Whether to delete a public book

* @param commandName

The name of the command calling this method

- * @return

True if the book was deleted successfully

*/ - protected boolean deleteBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean deletePublic, - @NotNull String commandName) { + protected void deleteBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean deletePublic, + @NotNull String commandName) { if (PagedBookIndex.displayPage(arguments, sender, deletePublic, commandName)) { - return true; + return; } //Delete the file List availableBooks = BooksWithoutBorders.getAvailableBooks(sender, deletePublic); if (availableBooks.isEmpty()) { new FormatBuilder(Translatable.ERROR_DELETE_EMPTY).error(sender); - return true; + return; } performBookDeletion(sender, InputParsingUtil.mergeArguments(arguments, 0), deletePublic); //Update the book list BooksWithoutBorders.updateBooks(sender, deletePublic); - return true; } /** diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDeletePublic.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDeletePublic.java index 2346699..93834cd 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDeletePublic.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDeletePublic.java @@ -15,7 +15,8 @@ public class CommandDeletePublic extends CommandDelete implements TabExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] arguments) { - return deleteBook(sender, arguments, true, label); + deleteBook(sender, arguments, true, label); + return true; } @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java index 89e7b74..af9a5ca 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Command executor for the encrypt command @@ -36,7 +37,8 @@ public class CommandEncrypt implements TabExecutor { return false; } - EncryptionStyle encryptionStyle = arguments.length == 2 ? EncryptionStyle.getFromString(arguments[1]) : EncryptionStyle.AES; + EncryptionStyle encryptionStyle = arguments.length == 2 ? Objects.requireNonNullElse( + EncryptionStyle.getFromString(arguments[1]), EncryptionStyle.AES) : EncryptionStyle.AES; // AES is the only reliable method for retaining the plaintext BwBConfig config = BooksWithoutBorders.getConfiguration(); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java index 8f9d567..c8fc04b 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.meta.BookMeta; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Objects; /** * Command executor for the group encrypt command @@ -39,7 +40,8 @@ public class CommandGroupEncrypt extends CommandEncrypt implements TabExecutor { return true; } - EncryptionStyle encryptionStyle = arguments.length == 3 ? EncryptionStyle.getFromString(arguments[2]) : EncryptionStyle.AES; + EncryptionStyle encryptionStyle = arguments.length == 3 ? Objects.requireNonNullElse( + EncryptionStyle.getFromString(arguments[2]), EncryptionStyle.AES) : EncryptionStyle.AES; return encryptBook(encryptionStyle, player, arguments[1], arguments[0], false); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java index 43e73ab..6893e71 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java @@ -36,7 +36,8 @@ public class CommandSave implements TabExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] arguments) { - return saveHeldBook(sender, arguments, false, label); + saveHeldBook(sender, arguments, false, label); + return true; } /** @@ -46,13 +47,12 @@ public class CommandSave implements TabExecutor { * @param arguments

The arguments given

* @param savePublic

Whether to save the book in the public directory or the player directory

* @param command

The command executed to trigger this method

- * @return

True if a book was saved successfully

*/ - protected boolean saveHeldBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean savePublic, - @NotNull String command) { + protected void saveHeldBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean savePublic, + @NotNull String command) { if (!(sender instanceof Player player)) { new FormatBuilder(Translatable.ERROR_PLAYER_ONLY).error(sender); - return true; + return; } ItemStack heldBook = InventoryUtil.getHeldBook(player); @@ -62,7 +62,6 @@ public class CommandSave implements TabExecutor { } else { new FormatBuilder(Translatable.ERROR_NOT_HOLDING_ANY_BOOK).error(sender); } - return true; } /** diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSavePublic.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSavePublic.java index 262de2d..b5de9e1 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSavePublic.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSavePublic.java @@ -13,7 +13,8 @@ public class CommandSavePublic extends CommandSave implements TabExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] arguments) { - return saveHeldBook(sender, arguments, true, label); + saveHeldBook(sender, arguments, true, label); + return true; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java index 9b9d362..6aedbde 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSetBookPrice.java @@ -62,7 +62,8 @@ public class CommandSetBookPrice implements TabExecutor { if (arguments[0].equalsIgnoreCase("item")) { return setItemPrice(sender, price); } else if (arguments[0].equalsIgnoreCase(StaticMessage.COST_ECONOMY.toString())) { - return setEconomyPrice(sender, price); + setEconomyPrice(sender, price); + return true; } else { new FormatBuilder(CostMessage.ERROR_COST_INVALID_TYPE).error(sender); return false; @@ -123,9 +124,8 @@ public class CommandSetBookPrice implements TabExecutor { * * @param sender

The sender of the command

* @param price

The new price

- * @return

True if the price was changed successfully

*/ - private boolean setEconomyPrice(@NotNull CommandSender sender, double price) { + private void setEconomyPrice(@NotNull CommandSender sender, double price) { EconomyManager economyManager = BooksWithoutBorders.getConfiguration().getEconomyManager(); if (economyManager.getEconomy() != null) { BwBConfig config = BooksWithoutBorders.getConfiguration(); @@ -141,7 +141,6 @@ public class CommandSetBookPrice implements TabExecutor { } else { new FormatBuilder(StaticMessage.EXCEPTION_VAULT_PRICE_NOT_CHANGED.toString()).error(sender); } - return true; } @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java index 7a4bb2b..189e596 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java @@ -50,6 +50,7 @@ public enum StaticMessage { EXCEPTION_GET_HELD_BOOK_INVALID_MATERIAL("Invalid required material specified for method"), EXCEPTION_ITEM_SLOT_INVALID("Attempting to get item from an invalid item slot"), + /** * The cost type used to specify economy */ diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Placeholder.java b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Placeholder.java index 7c25e19..9aae426 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Placeholder.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Placeholder.java @@ -17,8 +17,6 @@ public enum Placeholder implements TranslatableMessage { COST, TITLE, DISPLAY_NAME, - LINE, - PASSWORD, COMMAND, EXCEPTION, PATH, 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 893265c..b9a6ab3 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/SignText.java @@ -28,21 +28,6 @@ public enum SignText implements TranslatableMessage { */ 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 */ 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 0b5365d..f3ec09a 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java @@ -344,11 +344,6 @@ public enum Translatable implements TranslatableMessage { */ 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 */ @@ -374,11 +369,6 @@ public enum Translatable implements TranslatableMessage { */ 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 */ diff --git a/src/main/java/net/knarcraft/bookswithoutborders/encryption/EncryptionStyle.java b/src/main/java/net/knarcraft/bookswithoutborders/encryption/EncryptionStyle.java index a72b468..c39017e 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/encryption/EncryptionStyle.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/encryption/EncryptionStyle.java @@ -1,6 +1,7 @@ package net.knarcraft.bookswithoutborders.encryption; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * This enum represents the different available encryption styles @@ -65,14 +66,14 @@ public enum EncryptionStyle { * @param name

The name of the encryption style

* @return

An encryption style or null if no match is found

*/ - @NotNull + @Nullable public static EncryptionStyle getFromString(@NotNull String name) { for (EncryptionStyle style : EncryptionStyle.values()) { if (style.name.equalsIgnoreCase(name)) { return style; } } - return AES; + return null; } @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java index 27753d6..22a240d 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/SignEventListener.java @@ -1,6 +1,5 @@ package net.knarcraft.bookswithoutborders.listener; -import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.Permission; import net.knarcraft.bookswithoutborders.config.translation.GiveMessage; import net.knarcraft.bookswithoutborders.config.translation.Placeholder; @@ -13,7 +12,6 @@ import net.knarcraft.bookswithoutborders.state.SignType; import net.knarcraft.bookswithoutborders.utility.BookFileUtil; import net.knarcraft.bookswithoutborders.utility.BookLoaderUtil; import net.knarcraft.bookswithoutborders.utility.EncryptedBookUtil; -import net.knarcraft.bookswithoutborders.utility.InputCleaningUtil; import net.knarcraft.knarlib.formatting.FormatBuilder; import net.md_5.bungee.api.ChatColor; import org.bukkit.Material; @@ -34,13 +32,18 @@ import org.bukkit.inventory.PlayerInventory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static net.knarcraft.bookswithoutborders.utility.BookFileUtil.isBookListIndex; +import java.util.Objects; /** * A listener for relevant sign events such as clicking a decryption sign */ public class SignEventListener implements Listener { + private final static ChatColor ERROR_COLOR = ChatColor.DARK_RED; + private final static ChatColor SUCCESS_COLOR = ChatColor.DARK_GREEN; + private final static ChatColor META_COLOR = ChatColor.DARK_BLUE; + private final static ChatColor PASSWORD_COLOR = ChatColor.MAGIC; + @EventHandler public void onSignChange(@NotNull SignChangeEvent event) { if (event.isCancelled()) { @@ -51,34 +54,19 @@ public class SignEventListener implements Listener { Player player = event.getPlayer(); //Check if creating a Books Without Borders Sign and if the player has permission - if (SignType.fromString(lines[0]) != SignType.BOOKS_WITHOUT_BORDERS || + if (getSignType(lines[0]) != SignType.BOOKS_WITHOUT_BORDERS || !player.hasPermission(Permission.SIGNS.toString())) { return; } - //Mark the sign as active - event.setLine(0, new FormatBuilder(SignText.SIGN_HEADER).color().toString()); - - //Check if the sign is of a valid type - SignType type = SignType.fromString(lines[1]); - if (type == null || lines[2].trim().isEmpty()) { - //Mark the second line as invalid - event.setLine(1, new FormatBuilder(SignText.SIGN_INVALID).replace(Placeholder.LINE, lines[1]).color().toString()); + // Check and mark the sign + if (isSignInvalid(lines, true)) { new FormatBuilder(SignText.ERROR_SIGN_INVALID).error(player); - return; } - //Mark the second line as valid - event.setLine(1, new FormatBuilder(SignText.SIGN_VALID).replace(Placeholder.LINE, lines[1]).color().toString()); - lines = event.getLines(); - - //Mark valid encryption/decryption sign - if (type == SignType.GIVE) { - //Generate book giving sign - generateGiveSign(event, lines, player); - } else { - event.setLine(2, new FormatBuilder(SignText.SIGN_PASSWORD).replace(Placeholder.PASSWORD, lines[2]).color().toString()); - event.setLine(3, new FormatBuilder(SignText.SIGN_VALID).replace(Placeholder.LINE, lines[3]).color().toString()); + // Update any changed lines + for (int i = 0; i < lines.length; i++) { + event.setLine(i, lines[i]); } } @@ -102,6 +90,11 @@ public class SignEventListener implements Listener { return; } + // Return if not a valid sign + if (isSignInvalid(((Sign) event.getClickedBlock().getState()).getSide(Side.FRONT).getLines(), false)) { + return; + } + //The player right-clicked a sign checkSign(event, (Sign) event.getClickedBlock().getState(), heldItemType, hand); } @@ -117,22 +110,18 @@ public class SignEventListener implements Listener { private void checkSign(@NotNull PlayerInteractEvent event, @NotNull Sign sign, @NotNull Material heldItemType, @NotNull EquipmentSlot hand) { Player player = event.getPlayer(); - if (SignType.fromString(sign.getSide(Side.FRONT).getLine(0)) != SignType.BOOKS_WITHOUT_BORDERS) { - return; - } - event.setUseItemInHand(Event.Result.DENY); event.setCancelled(true); - SignType signType = SignType.fromString(sign.getSide(Side.FRONT).getLine(1)); + SignSide front = sign.getSide(Side.FRONT); + SignType signType = getSignType(front.getLine(1)); if (signType == SignType.ENCRYPT) { encryptHeldBookUsingSign(sign, heldItemType, player, hand); } else if (signType == SignType.DECRYPT) { decryptHeldBookUsingSign(sign, heldItemType, player, hand); - } else if (signType == SignType.GIVE && getSignLine2Color(sign) == ChatColor.DARK_GREEN) { + } else if (signType == SignType.GIVE) { giveBook(sign, player); } else { - SignSide front = sign.getSide(Side.FRONT); new FormatBuilder(SignText.ERROR_SIGN_COMMAND_INVALID).replace(Placeholder.ACTION, front.getLine(1)). replace(Placeholder.DATA, front.getLine(2)).error(player); } @@ -156,12 +145,11 @@ public class SignEventListener implements Listener { player.closeInventory(); //Converts user supplied key into integer form - String lineText = InputCleaningUtil.stripColor(sign.getSide(Side.FRONT).getLine(2)); + String password = getPassword(sign.getSide(Side.FRONT).getLines()); - - ItemStack book = EncryptedBookUtil.loadEncryptedBook(player, lineText, false, false); + ItemStack book = EncryptedBookUtil.loadEncryptedBook(player, password, false, false); if (book == null) { - book = EncryptedBookUtil.loadEncryptedBookLegacy(player, lineText, false); + book = EncryptedBookUtil.loadEncryptedBookLegacy(player, password, false); } if (book != null) { @@ -170,63 +158,6 @@ public class SignEventListener implements Listener { } } - /** - * Gets the color of a line on a sign - * - * @param sign

The sign to check

- * @return

The color of the sign

- */ - @Nullable - private ChatColor getSignLine2Color(@NotNull Sign sign) { - String line = sign.getSide(Side.FRONT).getLine(2); - if (!InputCleaningUtil.stripColor(line).equals(line)) { - return ChatColor.getByChar(sign.getSide(Side.FRONT).getLine(2).substring(1, 2).charAt(0)); - } else { - return null; - } - } - - /** - * Changes an edited sign into a sign to give books - * - * @param event

The event caused by changing the sign

- * @param lines

The lines on the sign

- * @param player

The player which edited the sign

- */ - private void generateGiveSign(@NotNull SignChangeEvent event, @NotNull String[] lines, - @NotNull Player player) { - //Tests if a full file name has been supplied and points to an actual file - String signFile = lines[2] + lines[3]; - if (BookFileUtil.getFile(BookDirectory.PUBLIC, null, signFile) != null) { - markGiveSignValidity(event, true); - return; - } else { - if (isBookListIndex(lines[2])) { - BooksWithoutBorders.updateBooks(player, true); - markGiveSignValidity(event, true); - return; - } - } - markGiveSignValidity(event, false); - } - - /** - * Marks a give sign as valid or invalid - * - * @param event

The event causing the creation of the give sign

- * @param isValid

Whether the created sign is valid

- */ - private void markGiveSignValidity(@NotNull SignChangeEvent event, boolean isValid) { - String[] lines = event.getLines(); - if (isValid) { - event.setLine(2, ChatColor.DARK_GREEN + lines[2]); - event.setLine(3, ChatColor.DARK_GREEN + lines[3]); - } else { - event.setLine(2, ChatColor.DARK_RED + lines[2]); - event.setLine(3, ChatColor.DARK_RED + lines[3]); - } - } - /** * Encrypts and replaces the player's used book * @@ -237,15 +168,15 @@ public class SignEventListener implements Listener { */ private void encryptHeldBookUsingSign(@NotNull Sign sign, @NotNull Material heldItemType, @NotNull Player player, @NotNull EquipmentSlot hand) { - ItemStack eBook; String[] lines = sign.getSide(Side.FRONT).getLines(); - if (heldItemType == Material.WRITTEN_BOOK) { - player.closeInventory(); - eBook = EncryptedBookUtil.encryptBook(player, ItemSlot.fromEquipmentSlot(hand), InputCleaningUtil.stripColor(lines[2]), - EncryptionStyle.getFromString(InputCleaningUtil.stripColor(lines[3])), false); - if (eBook != null) { - player.getInventory().setItem(hand, eBook); - } + if (heldItemType != Material.WRITTEN_BOOK) { + return; + } + player.closeInventory(); + ItemStack eBook = EncryptedBookUtil.encryptBook(player, ItemSlot.fromEquipmentSlot(hand), getPassword(lines), + getEncryptionStyle(lines), false); + if (eBook != null) { + player.getInventory().setItem(hand, eBook); } } @@ -256,23 +187,12 @@ public class SignEventListener implements Listener { * @param player

The player which clicked the sign

*/ private void giveBook(@NotNull Sign sign, @NotNull Player player) { - String fileName = InputCleaningUtil.stripColor(sign.getSide(Side.FRONT).getLine(2)); - boolean isLoadListNumber = false; - - try { - Integer.parseInt(fileName); - isLoadListNumber = true; - } catch (NumberFormatException ignored) { + String fileName = getBookName(sign.getSide(Side.FRONT).getLines()); + if (fileName.isBlank()) { + new FormatBuilder(GiveMessage.ERROR_GIVE_LOAD_FAILED).error(player); + return; } - - //Add the third line to the second line for the full filename - String thirdLine = sign.getSide(Side.FRONT).getLine(3); - if (!isLoadListNumber && thirdLine.length() >= 2) { - fileName += InputCleaningUtil.stripColor(thirdLine); - } - ItemStack newBook = BookLoaderUtil.loadBook(player, fileName, true, BookDirectory.PUBLIC, 1); - if (newBook != null) { player.getInventory().addItem(newBook); new FormatBuilder(SignText.SUCCESS_SIGN_GIVE).success(player); @@ -281,4 +201,185 @@ public class SignEventListener implements Listener { } } + /** + * Checks whether the given sign lines belong to a valid sign + * + * @param lines

The lines to verify

+ * @param markSign

Whether to mark the sign's validity after verifying

+ * @return

True if the lines belong to a valid sign

+ */ + private boolean isSignInvalid(@NotNull String[] lines, boolean markSign) { + // Check and optionally mark the [BwB] header + if (getSignType(lines[0]) != SignType.BOOKS_WITHOUT_BORDERS) { + if (markSign) { + lines[0] = ERROR_COLOR + lines[0]; + } + return true; + } else if (markSign) { + lines[0] = SUCCESS_COLOR + lines[0]; + } + + // Check and optionally mark the sign type + if (lines[1].startsWith(ERROR_COLOR.toString())) { + return true; + } + SignType type = getSignType(lines[1]); + if (type == null || type == SignType.BOOKS_WITHOUT_BORDERS) { + if (markSign) { + lines[1] = ERROR_COLOR + lines[1]; + } + return true; + } else if (markSign) { + lines[1] = META_COLOR + lines[1]; + } + + // Check and optionally mark + if (type == SignType.GIVE) { + return !isValidBook(lines, markSign); + } else if (type == SignType.DECRYPT || type == SignType.ENCRYPT) { + return !isValidPassword(lines, markSign); + } + throw new IllegalStateException(); + } + + /** + * Gets the sign type from the given sign line + * + * @param line

The line to get sign type from

+ * @return

The sign type

+ */ + @Nullable + private SignType getSignType(@NotNull String line) { + return SignType.fromString(getCleanLine(line)); + } + + /** + * Gets a cleaned valid sign line + * + * @param line

The line to clean initial color code from

+ * @return

The cleaned line

+ */ + @NotNull + private String getCleanLine(@NotNull String line) { + if (line.startsWith(META_COLOR.toString())) { + return line.replaceFirst(META_COLOR.toString(), ""); + } else if (line.startsWith(SUCCESS_COLOR.toString())) { + return line.replaceFirst(SUCCESS_COLOR.toString(), ""); + } else if (line.startsWith(PASSWORD_COLOR.toString())) { + return line.replaceFirst(PASSWORD_COLOR.toString(), ""); + } else { + return line; + } + } + + /** + * Checks whether the given sign lines specify a valid book + * + * @param lines

The lines to check

+ * @param markSign

Whether to mark the sign's validity after verifying

+ * @return

True if the lines point to a valid book

+ */ + private boolean isValidBook(@NotNull String[] lines, boolean markSign) { + if (isInvalid(lines)) { + return false; + } + String bookName = getBookName(lines); + boolean isValid = BookFileUtil.getFile(BookDirectory.PUBLIC, null, bookName) != null || + BookFileUtil.isBookListIndex(bookName); + if (markSign) { + if (isValid) { + markLine(lines, 2, SUCCESS_COLOR); + markLine(lines, 3, SUCCESS_COLOR); + } else { + markLine(lines, 2, ERROR_COLOR); + markLine(lines, 3, ERROR_COLOR); + } + } + return true; + } + + /** + * Checks whether the given sign lines specify a valid password + * + * @param lines

The lines to check

+ * @param markSign

Whether to mark the sign's validity after verifying

+ * @return

True if the lines specify a valid password

+ */ + private boolean isValidPassword(@NotNull String[] lines, boolean markSign) { + if (isInvalid(lines)) { + return false; + } + boolean isValid = !getPassword(lines).isBlank() && (lines[3].isBlank() || + EncryptionStyle.getFromString(getCleanLine(lines[3])) != null); + if (markSign) { + if (isValid) { + markLine(lines, 2, PASSWORD_COLOR); + markLine(lines, 3, META_COLOR); + } else { + markLine(lines, 2, ERROR_COLOR); + markLine(lines, 3, ERROR_COLOR); + } + } + return isValid; + } + + /** + * Gets the encryption style specified on the given sign + * + * @param lines

The lines to parse

+ * @return

The encryption style

+ */ + @NotNull + private EncryptionStyle getEncryptionStyle(@NotNull String[] lines) { + return Objects.requireNonNullElse(EncryptionStyle.getFromString(getCleanLine(lines[3])), EncryptionStyle.AES); + } + + /** + * Gets the password specified on the given sign + * + * @param lines

The lines to parse

+ * @return

The password

+ */ + private String getPassword(@NotNull String[] lines) { + return getCleanLine(lines[2]); + } + + /** + * Gets the book name specified in the given lines + * + * @param lines

The lines to parse

+ * @return

The name of the book

+ */ + @NotNull + private String getBookName(@NotNull String[] lines) { + String bookSpecifier = getCleanLine(lines[2]) + getCleanLine(lines[3]); + if (bookSpecifier.contains(":")) { + return bookSpecifier.split(":")[1]; + } else { + return bookSpecifier; + } + } + + /** + * Checks whether the specified sign lines are marked as invalid + * + * @param lines

The lines to check

+ * @return

True if the lines belong to an invalid sign

+ */ + private boolean isInvalid(@NotNull String[] lines) { + return lines[2].startsWith(ERROR_COLOR.toString()) || lines[3].startsWith(ERROR_COLOR.toString()) || + lines[2].isBlank(); + } + + /** + * Marks the specified line by prepending the specified chat color + * + * @param lines

The lines to mark an index of

+ * @param index

The index to mark

+ * @param chatColor

The color to mark with

+ */ + private void markLine(@NotNull String[] lines, int index, @NotNull ChatColor chatColor) { + lines[index] = chatColor + lines[index]; + } + } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileReaderWriterUtil.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileReaderWriterUtil.java index b28d3b9..6ff7e25 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileReaderWriterUtil.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileReaderWriterUtil.java @@ -20,6 +20,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.logging.Level; /** @@ -152,7 +153,8 @@ public final class BookFileReaderWriterUtil { if (encryptionStyleName == null) { return null; } - EncryptionStyle encryptionStyle = EncryptionStyle.getFromString(encryptionStyleName); + EncryptionStyle encryptionStyle = Objects.requireNonNullElse(EncryptionStyle.getFromString(encryptionStyleName), + EncryptionStyle.AES); AESConfiguration aesConfiguration = null; if (encryptionStyle == EncryptionStyle.AES) { diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileUtil.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileUtil.java index bc56a60..753dcaf 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileUtil.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileUtil.java @@ -38,6 +38,9 @@ public final class BookFileUtil { * @return

True if the number is a book index

*/ public static boolean isBookListIndex(@NotNull String possibleIndex) { + if (possibleIndex.isBlank()) { + return false; + } File bookDirectory = new File(BooksWithoutBorders.getConfiguration().getBookFolder().replaceAll("[\\\\/]$", "")); try { diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index 53c274a..7de305c 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -104,13 +104,11 @@ en: 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!" @@ -173,16 +171,16 @@ en: # -----------------------------------------# NEUTRAL_UNKNOWN_AUTHOR: "Unknown" NEUTRAL_UNKNOWN_TITLE: "Untitled" - # ---------------------- # - # Sign text and messages # - # ---------------------- # - SIGN_HEADER: "&2[BwB]" + # --------------------------- # + # Sign headers and specifiers # + # --------------------------- # + SIGN_HEADER: "[BwB]" SIGN_ENCRYPT: "[Encrypt]" SIGN_DECRYPT: "[Decrypt]" SIGN_GIVE: "[Give]" - SIGN_PASSWORD: "&k{password}" - SIGN_INVALID: "&4{line}" - SIGN_VALID: "&1{line}" + # -------------- # + # Sign responses # + # -------------- # ERROR_SIGN_INVALID: "Invalid sign!" ERROR_SIGN_COMMAND_INVALID: "Sign command {action} {data} is invalid" SUCCESS_SIGN_GIVE: "Received book!" @@ -202,8 +200,6 @@ en: COST: "{cost}" TITLE: "{title}" DISPLAY_NAME: "{displayName}" - LINE: "{line}" - PASSWORD: "{password}" COMMAND: "{command}" EXCEPTION: "{exception}" PATH: "{path}"