Cleans up sign code quite a lot #14
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good

This commit is contained in:
2025-09-03 16:49:01 +02:00
parent 12a2cd5a73
commit 6c1094ff98
17 changed files with 258 additions and 178 deletions

View File

@@ -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) {

View File

@@ -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 <p>The arguments given</p>
* @param deletePublic <p>Whether to delete a public book</p>
* @param commandName <p>The name of the command calling this method</p>
* @return <p>True if the book was deleted successfully</p>
*/
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<String> 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;
}
/**

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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 <p>The arguments given</p>
* @param savePublic <p>Whether to save the book in the public directory or the player directory</p>
* @param command <p>The command executed to trigger this method</p>
* @return <p>True if a book was saved successfully</p>
*/
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;
}
/**

View File

@@ -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;
}
}

View File

@@ -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 <p>The sender of the command</p>
* @param price <p>The new price</p>
* @return <p>True if the price was changed successfully</p>
*/
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

View File

@@ -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
*/

View File

@@ -17,8 +17,6 @@ public enum Placeholder implements TranslatableMessage {
COST,
TITLE,
DISPLAY_NAME,
LINE,
PASSWORD,
COMMAND,
EXCEPTION,
PATH,

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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 <p>The name of the encryption style</p>
* @return <p>An encryption style or null if no match is found</p>
*/
@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

View File

@@ -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 <p>The sign to check</p>
* @return <p>The color of the sign</p>
*/
@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 <p>The event caused by changing the sign</p>
* @param lines <p>The lines on the sign</p>
* @param player <p>The player which edited the sign</p>
*/
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 <p>The event causing the creation of the give sign</p>
* @param isValid <p>Whether the created sign is valid</p>
*/
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 <p>The player which clicked the sign</p>
*/
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 <p>The lines to verify</p>
* @param markSign <p>Whether to mark the sign's validity after verifying</p>
* @return <p>True if the lines belong to a valid sign</p>
*/
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 <p>The line to get sign type from</p>
* @return <p>The sign type</p>
*/
@Nullable
private SignType getSignType(@NotNull String line) {
return SignType.fromString(getCleanLine(line));
}
/**
* Gets a cleaned valid sign line
*
* @param line <p>The line to clean initial color code from</p>
* @return <p>The cleaned line</p>
*/
@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 <p>The lines to check</p>
* @param markSign <p>Whether to mark the sign's validity after verifying</p>
* @return <p>True if the lines point to a valid book</p>
*/
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 <p>The lines to check</p>
* @param markSign <p>Whether to mark the sign's validity after verifying</p>
* @return <p>True if the lines specify a valid password</p>
*/
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 <p>The lines to parse</p>
* @return <p>The encryption style</p>
*/
@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 <p>The lines to parse</p>
* @return <p>The password</p>
*/
private String getPassword(@NotNull String[] lines) {
return getCleanLine(lines[2]);
}
/**
* Gets the book name specified in the given lines
*
* @param lines <p>The lines to parse</p>
* @return <p>The name of the book</p>
*/
@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 <p>The lines to check</p>
* @return <p>True if the lines belong to an invalid sign</p>
*/
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 <p>The lines to mark an index of</p>
* @param index <p>The index to mark</p>
* @param chatColor <p>The color to mark with</p>
*/
private void markLine(@NotNull String[] lines, int index, @NotNull ChatColor chatColor) {
lines[index] = chatColor + lines[index];
}
}

View File

@@ -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) {

View File

@@ -38,6 +38,9 @@ public final class BookFileUtil {
* @return <p>True if the number is a book index</p>
*/
public static boolean isBookListIndex(@NotNull String possibleIndex) {
if (possibleIndex.isBlank()) {
return false;
}
File bookDirectory = new File(BooksWithoutBorders.getConfiguration().getBookFolder().replaceAll("[\\\\/]$", ""));
try {

View File

@@ -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}"