Adds full support for spaces in book names, and fixes unsigned book loading

This commit is contained in:
2025-08-08 02:06:08 +02:00
parent fb225a2351
commit 6cd8895cce
9 changed files with 116 additions and 74 deletions

View File

@@ -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 <p>The input to validate</p>
* @return <p>True if the given input is a boolean</p>
*/
private boolean isBoolean(@NotNull String input) {
return input.matches("(true|false)");
}
/**
* Checks whether the given input is an integer
*
* @param input <p>The input to validate</p>
* @return <p>True if the given input is an integer</p>
*/
private boolean isInt(@NotNull String input) {
return input.matches("[0-9]+");
}
@Override
public List<String> 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 <p>The arguments to merge</p>
* @param stripLastN <p>How many of the last arguments to ignore</p>
* @return <p>The merged arguments</p>
*/
@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();
}
}

View File

@@ -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 <p>The player holding the book</p>
* @param mainHand <p>Whether the player is holding the book in its main hand or its off hand</p>
*/
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<String> oldLore = oldMetadata.getLore();
if (oldLore != null) {
List<String> 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

View File

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

View File

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

View File

@@ -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 <p>The signed book's metadata</p>
* @param amount <p>The amount of unsigned books to produce</p>
* @return <p>The unsigned books, or null if unable to generate metadata</p>
*/
@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<String> oldLore = oldMetadata.getLore();
if (oldLore != null) {
List<String> 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);
}
/**

View File

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

View File

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

View File

@@ -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") :

View File

@@ -50,23 +50,6 @@ public final class InputCleaningHelper {
return fileName;
}
/**
* Changes spaces to underscores or underscores to spaces, depending on context
*
* @param fileName <p>The file name to fix</p>
* @param isLoading <p>Whether loading from a file as opposed to saving to a file</p>
* @return <p>The fixed name</p>
*/
@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"
*