From 6cd8895cce3d0b682913b3fb372008405554b0ef Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Fri, 8 Aug 2025 02:06:08 +0200 Subject: [PATCH] Adds full support for spaces in book names, and fixes unsigned book loading --- .../command/CommandLoad.java | 56 ++++++++++++++++--- .../command/CommandUnSign.java | 28 ++-------- .../bookswithoutborders/gui/BookIndex.java | 2 +- .../utility/BookFileHelper.java | 24 +++++--- .../utility/BookHelper.java | 41 +++++++++++++- .../utility/BookLoader.java | 11 ++-- .../utility/BookToFromTextHelper.java | 6 +- .../utility/EncryptionHelper.java | 5 +- .../utility/InputCleaningHelper.java | 17 ------ 9 files changed, 116 insertions(+), 74 deletions(-) diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java index 2230f01..18a8742 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java @@ -59,14 +59,20 @@ public class CommandLoad implements TabExecutor { String bookIdentifier = arguments[0]; String copies = "1"; String isSigned = "true"; - if (argumentCount == 3) { - copies = arguments[1]; - isSigned = arguments[2]; - } else if (argumentCount == 2) { - if (arguments[1].equalsIgnoreCase("true") || arguments[1].equalsIgnoreCase("false")) { - isSigned = arguments[1]; + + if (argumentCount > 1) { + if (argumentCount > 2 && isInt(arguments[argumentCount - 2]) && isBoolean(arguments[argumentCount - 1])) { + isSigned = arguments[argumentCount - 1]; + copies = arguments[argumentCount - 2]; + bookIdentifier = mergeArguments(arguments, 2); + } else if (isBoolean(arguments[argumentCount - 1])) { + isSigned = arguments[argumentCount - 1]; + bookIdentifier = mergeArguments(arguments, 1); + } else if (isInt(arguments[argumentCount - 1])) { + copies = arguments[argumentCount - 1]; + bookIdentifier = mergeArguments(arguments, 1); } else { - copies = arguments[1]; + bookIdentifier = mergeArguments(arguments, 0); } } @@ -95,6 +101,26 @@ public class CommandLoad implements TabExecutor { } } + /** + * Checks whether the given input is a boolean + * + * @param input

The input to validate

+ * @return

True if the given input is a boolean

+ */ + private boolean isBoolean(@NotNull String input) { + return input.matches("(true|false)"); + } + + /** + * Checks whether the given input is an integer + * + * @param input

The input to validate

+ * @return

True if the given input is an integer

+ */ + private boolean isInt(@NotNull String input) { + return input.matches("[0-9]+"); + } + @Override public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] arguments) { @@ -131,4 +157,20 @@ public class CommandLoad implements TabExecutor { return new ArrayList<>(); } + /** + * Merges all arguments to a string with spaces + * + * @param arguments

The arguments to merge

+ * @param stripLastN

How many of the last arguments to ignore

+ * @return

The merged arguments

+ */ + @NotNull + private String mergeArguments(String[] arguments, int stripLastN) { + StringBuilder builder = new StringBuilder(arguments[0]); + for (int i = 1; i < arguments.length - stripLastN; i++) { + builder.append(" ").append(arguments[i]); + } + return builder.toString(); + } + } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandUnSign.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandUnSign.java index 4d7b4ac..6c97c67 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandUnSign.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandUnSign.java @@ -4,20 +4,17 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.state.ItemSlot; import net.knarcraft.bookswithoutborders.utility.BookHelper; import net.knarcraft.bookswithoutborders.utility.InventoryHelper; -import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; -import org.bukkit.inventory.meta.WritableBookMeta; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.logging.Level; /** * Command executor for the unsign command @@ -49,7 +46,7 @@ public class CommandUnSign implements TabExecutor { * @param player

The player holding the book

* @param mainHand

Whether the player is holding the book in its main hand or its off hand

*/ - public void unSignHeldBook(@NotNull Player player, boolean mainHand) { + protected void unSignHeldBook(@NotNull Player player, boolean mainHand) { //Get the old book BookMeta oldMetadata = InventoryHelper.getHeldBookMetadata(player, mainHand); if (oldMetadata == null) { @@ -66,27 +63,12 @@ public class CommandUnSign implements TabExecutor { } } - WritableBookMeta newMetadata = (BookMeta) BooksWithoutBorders.getItemFactory().getItemMeta(Material.WRITABLE_BOOK); - if (newMetadata == null) { - BooksWithoutBorders.log(Level.SEVERE, "Unable to create writable book metadata"); + // Give the player the new book + ItemStack book = BookHelper.unsignBook(oldMetadata, heldBook.getAmount()); + if (book == null) { return; } - - //Create a new unsigned book with the same data - ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK, heldBook.getAmount()); - if (oldMetadata.hasLore()) { - List oldLore = oldMetadata.getLore(); - if (oldLore != null) { - List newLore = new ArrayList<>(oldLore); - newLore.remove(0); - newMetadata.setLore(newLore); - } - } - newMetadata.setPages(oldMetadata.getPages()); - newBook.setItemMeta(newMetadata); - - // Give the player the new book - InventoryHelper.replaceHeldItem(player, newBook, mainHand); + InventoryHelper.replaceHeldItem(player, book, mainHand); } @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/gui/BookIndex.java b/src/main/java/net/knarcraft/bookswithoutborders/gui/BookIndex.java index f7a3456..1bd1808 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/gui/BookIndex.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/gui/BookIndex.java @@ -143,7 +143,7 @@ public abstract class BookIndex { String title = BookFileHelper.getBookTitleFromPath(bookPath); String author = BookFileHelper.getBookAuthorFromPath(bookPath); return ChatColor.translateAlternateColorCodes('&', - title.replace("_", " ") + ChatColor.RESET + " by " + author + ChatColor.RESET); + title + ChatColor.RESET + " by " + author + ChatColor.RESET); } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java index deba501..7320141 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java @@ -144,7 +144,7 @@ public final class BookFileHelper { for (File foundFile : existingFiles) { // Filter out invalid files - if (!foundFile.isFile() || foundFile.getName().contains(" ") || foundFile.getName().contains("§")) { + if (!foundFile.isFile() || foundFile.getName().contains("§")) { continue; } String fileName = foundFile.getName(); @@ -225,11 +225,14 @@ public final class BookFileHelper { */ @NotNull public static String stripExtensionFromPath(@NotNull String path) { - if (path.contains(".")) { - return path.substring(0, path.lastIndexOf(".")); - } else { - return path; + int dotIndex = path.lastIndexOf("."); + if (dotIndex > 0) { + String separator = BooksWithoutBorders.getConfiguration().getTitleAuthorSeparator(); + if (path.lastIndexOf(separator) < dotIndex && (path.length() - dotIndex == 4)) { + return path.substring(0, dotIndex); + } } + return path; } /** @@ -240,11 +243,14 @@ public final class BookFileHelper { */ @NotNull public static String getExtensionFromPath(@NotNull String path) { - if (path.contains(".")) { - return path.substring((path.length() - path.lastIndexOf(".")) + 1); - } else { - return ""; + int dotIndex = path.lastIndexOf("."); + if (dotIndex > 0) { + String separator = BooksWithoutBorders.getConfiguration().getTitleAuthorSeparator(); + if (path.lastIndexOf(separator) < dotIndex && (path.length() - dotIndex == 4)) { + return path.substring((path.length() - dotIndex) + 1); + } } + return ""; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java index 425ecb8..3c5da3a 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookHelper.java @@ -5,17 +5,20 @@ import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig; import net.knarcraft.bookswithoutborders.config.Translatable; import net.knarcraft.bookswithoutborders.state.BookDirectory; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; +import org.bukkit.inventory.meta.WritableBookMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; - -import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName; +import java.util.logging.Level; /** * Helper class for getting abstract book information @@ -26,6 +29,38 @@ public final class BookHelper { } + /** + * Un-signs a book + * + * @param oldMetadata

The signed book's metadata

+ * @param amount

The amount of unsigned books to produce

+ * @return

The unsigned books, or null if unable to generate metadata

+ */ + @Nullable + public static ItemStack unsignBook(@NotNull BookMeta oldMetadata, int amount) { + WritableBookMeta newMetadata = (BookMeta) BooksWithoutBorders.getItemFactory().getItemMeta(Material.WRITABLE_BOOK); + if (newMetadata == null) { + BooksWithoutBorders.log(Level.SEVERE, "Unable to create writable book metadata"); + return null; + } + + //Create a new unsigned book with the same data + ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK, amount); + if (oldMetadata.hasLore()) { + List oldLore = oldMetadata.getLore(); + if (oldLore != null) { + List newLore = new ArrayList<>(oldLore); + newLore.remove(0); + newMetadata.setLore(newLore); + } + } + newMetadata.setPages(oldMetadata.getPages()); + newBook.setItemMeta(newMetadata); + + // Give the player the new book + return newBook; + } + /** * Converts the author of a book from UUID if necessary * @@ -154,7 +189,7 @@ public final class BookHelper { "book would lead to unexpected problems."); } - return fixName(InputCleaningHelper.cleanString(bookName + titleAuthorSeparator + authorName), false); + return InputCleaningHelper.cleanString(bookName + titleAuthorSeparator + authorName); } /** diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java index ffcf563..f53b55f 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java @@ -101,13 +101,8 @@ public final class BookLoader { } //Generate a new empty book - ItemStack book; + ItemStack book = new ItemStack(Material.WRITTEN_BOOK); BookMeta bookMetadata = (BookMeta) BooksWithoutBorders.getItemFactory().getItemMeta(Material.WRITTEN_BOOK); - if (isSigned.equalsIgnoreCase("true")) { - book = new ItemStack(Material.WRITTEN_BOOK); - } else { - book = new ItemStack(Material.WRITABLE_BOOK); - } if (bookMetadata == null) { BooksWithoutBorders.sendErrorMessage(sender, "Unable to create blank book metadata!"); @@ -137,6 +132,10 @@ public final class BookLoader { BookHelper.increaseGeneration(book); book.setAmount(numCopies); + + if (!isSigned.equalsIgnoreCase("true") && book.getItemMeta() != null) { + return BookHelper.unsignBook((BookMeta) book.getItemMeta(), book.getAmount()); + } return book; } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java index d63dbd7..46b440b 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.logging.Level; import static net.knarcraft.bookswithoutborders.utility.BookHelper.authorFromUUID; -import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName; /** * Helper class for converting books to and from text/yml files @@ -146,9 +145,6 @@ public final class BookToFromTextHelper { String title = BookFileHelper.getBookTitleFromPath(fileName); String author = BookFileHelper.getBookAuthorFromPath(fileName); - //Replace underscores with spaces - title = fixName(title, true); - //Read the .txt file List rawPages; try { @@ -173,7 +169,7 @@ public final class BookToFromTextHelper { //Update the metadata of the book with its new values bookMetadata.setAuthor(authorFromUUID(author)); - bookMetadata.setTitle(title); + bookMetadata.setTitle(title.substring(0, 32)); bookMetadata.setPages(pages); return bookMetadata; diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java index 13a75e5..ca9b6e1 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java @@ -22,7 +22,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.cleanString; -import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName; /** * Helper class for book encryption @@ -223,7 +222,7 @@ public final class EncryptionHelper { } String fileName = "[" + key + "]" + BookHelper.getBookFile(bookMetadata, player, true); - fileName = fixName(cleanString(fileName), false); + fileName = cleanString(fileName); File file = new File(path + fileName + ".yml"); if (!file.isFile()) { @@ -327,7 +326,7 @@ public final class EncryptionHelper { String path = BooksWithoutBorders.getConfiguration().getEncryptedBookPath(); String fileName = "[" + key + "]" + BookHelper.getBookFile(bookMetaData, player, true); - fileName = fixName(cleanString(fileName), false); + fileName = cleanString(fileName); //cancels saving if file is already encrypted File file = (BooksWithoutBorders.getConfiguration().getUseYml()) ? new File(path + fileName + ".yml") : diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/InputCleaningHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/InputCleaningHelper.java index 01146c4..320fa4b 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/InputCleaningHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/InputCleaningHelper.java @@ -50,23 +50,6 @@ public final class InputCleaningHelper { return fileName; } - /** - * Changes spaces to underscores or underscores to spaces, depending on context - * - * @param fileName

The file name to fix

- * @param isLoading

Whether loading from a file as opposed to saving to a file

- * @return

The fixed name

- */ - @NotNull - public static String fixName(@NotNull String fileName, @NotNull Boolean isLoading) { - if (isLoading) { - fileName = fileName.replace("_", " "); - } else { - fileName = fileName.replace(" ", "_"); - } - return fileName; - } - /** * Parses a page number for a string like "page1" *