Adds ability to filter books by author
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good

This commit is contained in:
2025-08-02 20:00:48 +02:00
parent 175b66465a
commit 2627407e6b
11 changed files with 312 additions and 174 deletions

View File

@@ -95,7 +95,7 @@ public class BooksWithoutBorders extends JavaPlugin {
playerBooksList.put(playerUUID, newFiles);
playerLetterIndex.put(playerUUID, BookFileHelper.populateLetterIndices(newFiles));
}
return playerBooksList.get(playerUUID);
return new ArrayList<>(playerBooksList.get(playerUUID));
} else {
return new ArrayList<>();
}

View File

@@ -5,7 +5,6 @@ import net.knarcraft.bookswithoutborders.gui.PagedBookIndex;
import net.knarcraft.bookswithoutborders.state.BookDirectory;
import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
import net.knarcraft.bookswithoutborders.utility.BookHelper;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.knarcraft.knarlib.util.TabCompletionHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -23,41 +22,34 @@ import java.util.List;
public class CommandDelete implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] arguments) {
if (!(sender instanceof Player)) {
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
return false;
}
return deleteBook(sender, args, false);
return deleteBook(sender, arguments, false);
}
/**
* Deletes a book
*
* @param sender <p>The sender trying to delete the book</p>
* @param args <p>The arguments given</p>
* @param arguments <p>The arguments given</p>
* @param deletePublic <p>Whether to delete a public book</p>
* @return <p>True if the book was deleted successfully</p>
*/
boolean deleteBook(CommandSender sender, String[] args, boolean deletePublic) {
boolean deleteBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean deletePublic) {
String command = deletePublic ? "deletepublicbook" : "deletebook";
//List deletable files
if (args.length == 0) {
PagedBookIndex.printBooks(sender, deletePublic, command, 1);
if (PagedBookIndex.displayPage(arguments, sender, deletePublic, command)) {
return true;
}
//Delete the file
if (args.length == 1) {
int page = InputCleaningHelper.parsePageNumber(args[0]);
if (page > 0) {
PagedBookIndex.printBooks(sender, deletePublic, command, page);
return true;
}
if (arguments.length == 1) {
List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, deletePublic);
if (!availableBooks.isEmpty()) {
performBookDeletion(sender, args[0], deletePublic);
performBookDeletion(sender, arguments[0], deletePublic);
//Update the book list
BooksWithoutBorders.updateBooks(sender, deletePublic);
return true;

View File

@@ -13,8 +13,8 @@ import java.util.List;
public class CommandDeletePublic extends CommandDelete implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
return deleteBook(sender, args, true);
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] arguments) {
return deleteBook(sender, arguments, true);
}
@Override

View File

@@ -25,55 +25,48 @@ public class CommandGive implements TabExecutor {
private final BooksWithoutBorders booksWithoutBorders = BooksWithoutBorders.getInstance();
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] arguments) {
if (!(sender instanceof Player)) {
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
return false;
}
return giveBook(sender, args, false, "player");
return giveBook(sender, arguments, false, "player");
}
/**
* Gives a book to another player
*
* @param sender <p>The sender trying to give a book</p>
* @param args <p>The arguments given</p>
* @param arguments <p>The arguments given</p>
* @param givePublic <p>Whether to give a public book</p>
* @param folder <p>The folder containing the book to load</p>
* @return <p>True if the book was given successfully</p>
*/
boolean giveBook(CommandSender sender, String[] args, boolean givePublic, String folder) {
boolean giveBook(@NotNull CommandSender sender, String[] arguments, boolean givePublic, String folder) {
String command = givePublic ? "givepublicbook" : "givebook";
if (args.length == 0) {
PagedBookIndex.printBooks(sender, givePublic, command, 1);
if (PagedBookIndex.displayPage(arguments, sender, givePublic, command)) {
return true;
} else if (args.length == 1) {
int page = InputCleaningHelper.parsePageNumber(args[0]);
if (page > 0) {
PagedBookIndex.printBooks(sender, givePublic, command, page);
return true;
}
}
if (args.length == 1 || args.length > 4) {
if (arguments.length == 1 || arguments.length > 4) {
BooksWithoutBorders.sendErrorMessage(sender, "Incorrect number of arguments for this command!");
return false;
}
//Organize and parse input
String bookIdentifier = args[0];
String receivingPlayerName = args[1];
String bookIdentifier = arguments[0];
String receivingPlayerName = arguments[1];
String copies = "1";
String isSigned = "true";
if (args.length == 4) {
copies = args[2];
isSigned = args[3];
} else if (args.length == 3) {
if (args[2].equalsIgnoreCase("true") || args[2].equalsIgnoreCase("false")) {
isSigned = args[2];
if (arguments.length == 4) {
copies = arguments[2];
isSigned = arguments[3];
} else if (arguments.length == 3) {
if (arguments[2].equalsIgnoreCase("true") || arguments[2].equalsIgnoreCase("false")) {
isSigned = arguments[2];
} else {
copies = args[2];
copies = arguments[2];
}
}

View File

@@ -13,8 +13,8 @@ import java.util.List;
public class CommandGivePublic extends CommandGive implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
return giveBook(sender, args, true, "public");
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] arguments) {
return giveBook(sender, arguments, true, "public");
}
@Override

View File

@@ -22,20 +22,21 @@ import java.util.List;
public class CommandLoad implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return loadBook(sender, args, "player", false);
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] arguments) {
return loadBook(sender, arguments, "player", false);
}
/**
* Loads a stored book
*
* @param sender <p>The sender asking to load the book</p>
* @param args <p>The arguments given</p>
* @param arguments <p>The arguments given</p>
* @param directory <p>The directory to load from (public/player)</p>
* @param loadPublic <p>Whether to list public files as loadable</p>
* @return <p>True if the book was loaded successfully</p>
*/
public boolean loadBook(CommandSender sender, String[] args, String directory, boolean loadPublic) {
public boolean loadBook(@NotNull CommandSender sender, @NotNull String[] arguments, @NotNull String directory,
boolean loadPublic) {
if (!(sender instanceof Player player)) {
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
return false;
@@ -46,33 +47,25 @@ public class CommandLoad implements TabExecutor {
return false;
}
int argumentCount = args.length;
int argumentCount = arguments.length;
//Show books available to the player
String command = loadPublic ? "loadpublicbook" : "loadbook";
if (argumentCount == 0) {
PagedBookIndex.printBooks(sender, loadPublic, command, 1);
if (PagedBookIndex.displayPage(arguments, sender, loadPublic, command)) {
return true;
} else if (argumentCount == 1) {
int page = InputCleaningHelper.parsePageNumber(args[0]);
if (page > 0) {
PagedBookIndex.printBooks(sender, loadPublic, command, page);
return true;
}
}
//Organize and parse input
String bookIdentifier = args[0];
String bookIdentifier = arguments[0];
String copies = "1";
String isSigned = "true";
if (argumentCount == 3) {
copies = args[1];
isSigned = args[2];
copies = arguments[1];
isSigned = arguments[2];
} else if (argumentCount == 2) {
if (args[1].equalsIgnoreCase("true") || args[1].equalsIgnoreCase("false")) {
isSigned = args[1];
if (arguments[1].equalsIgnoreCase("true") || arguments[1].equalsIgnoreCase("false")) {
isSigned = arguments[1];
} else {
copies = args[1];
copies = arguments[1];
}
}

View File

@@ -13,8 +13,8 @@ import java.util.List;
public class CommandLoadPublic extends CommandLoad implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
return loadBook(sender, args, "public", true);
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] arguments) {
return loadBook(sender, arguments, "public", true);
}
@Override

View File

@@ -0,0 +1,86 @@
package net.knarcraft.bookswithoutborders.gui;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.BookFormatter;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.hover.content.Text;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class AuthorBookIndex extends BookIndex {
private final static int booksPerPage = 10;
/**
* Prints the available books
*
* @param sender <p>The sender to display the books to</p>
* @param listPublic <p>Whether to display public books</p>
* @param command <p>The base command causing this to be called</p>
* @param page <p>The page of the book list to display</p>
*/
public static void printBooks(@NotNull CommandSender sender, boolean listPublic, @NotNull String command, int page,
@NotNull String authorName) {
List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, listPublic);
availableBooks.removeIf((bookPath) -> !BookFormatter.stripColor(bookPath.substring(0, bookPath.length() - 4).split(",")[1]).equalsIgnoreCase(authorName));
int totalPages = (int) Math.ceil((double) availableBooks.size() / booksPerPage);
if (page > totalPages) {
sender.sendMessage(ChatColor.GRAY + "No such page");
} else {
showAuthorBooks(sender, command, page, totalPages, availableBooks, authorName);
}
}
/**
* Shows a menu listing available books from an author
*
* @param sender <p>The sender wanting to see the book menu</p>
* @param command <p>The main command used to trigger display of the book menu</p>
* @param page <p>The currently selected page</p>
* @param totalPages <p>The total amount of pages</p>
* @param availableBooks <p>All books available to the sender</p>
* @param authorName <p>The name of the author currently shown</p>
*/
private static void showAuthorBooks(@NotNull CommandSender sender, @NotNull String command, int page,
int totalPages, @NotNull List<String> availableBooks, @NotNull String authorName) {
ComponentBuilder componentBuilder = new ComponentBuilder();
// Display the list of books, with the next and previous buttons
displayPreviousButton(componentBuilder, command + " author" + authorName, page);
displayBookList(componentBuilder, command, page, availableBooks);
displayNextButton(componentBuilder, command + " author" + authorName, page, totalPages);
// Display total pages and the manual change page command suggestion
componentBuilder.append(" ", ComponentBuilder.FormatRetention.NONE);
displayTotalPages(componentBuilder, page, totalPages);
componentBuilder.append(" ", ComponentBuilder.FormatRetention.NONE);
sender.spigot().sendMessage(componentBuilder.create());
}
/**
* Displays the list of books on the current page
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param page <p>The current page</p>
* @param availableBooks <p>All available books</p>
*/
protected static void displayBookList(@NotNull ComponentBuilder componentBuilder, @NotNull String command, int page,
@NotNull List<String> availableBooks) {
int startIndex = (page - 1) * booksPerPage;
for (int bookIndex = startIndex; bookIndex < Math.min(startIndex + booksPerPage, availableBooks.size()); bookIndex++) {
componentBuilder.append(getNiceName(availableBooks.get(bookIndex))).color(ChatColor.WHITE).event(
new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " +
availableBooks.get(bookIndex))).event(
new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Select book by path")));
componentBuilder.append("\n");
}
}
}

View File

@@ -0,0 +1,153 @@
package net.knarcraft.bookswithoutborders.gui;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.hover.content.Text;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public abstract class BookIndex {
protected final static int booksPerPage = 10;
/**
* Displays the correct GUI, if specified in the given arguments
*
* @param arguments <p>The arguments given by a command sender</p>
* @param sender <p>The sender executing the command</p>
* @param selectPublic <p>Whether to display public books, or only those available to the command sender</p>
* @param command <p>The command used for changing pages and making the final selection</p>
* @return <p>True if the GUI was displayed</p>
*/
public static boolean displayPage(@NotNull String[] arguments, @NotNull CommandSender sender, boolean selectPublic,
@NotNull String command) {
if (arguments.length == 0) {
PagedBookIndex.printBooks(sender, selectPublic, command, 1);
return true;
} else if (arguments.length == 1) {
int page = InputCleaningHelper.parsePageNumber(arguments[0]);
if (page > 0) {
PagedBookIndex.printBooks(sender, selectPublic, command, page);
return true;
}
} else if (arguments.length == 2) {
String author = InputCleaningHelper.parseAuthorSpecifier(arguments[0]);
if (author != null) {
int page = InputCleaningHelper.parsePageNumber(arguments[1]);
if (page > 0) {
AuthorBookIndex.printBooks(sender, selectPublic, command, page, author);
}
return true;
}
}
return false;
}
/**
* Displays the suggestion for manually going to any page
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param page <p>The current page</p>
*/
protected static void displayPageCommand(@NotNull ComponentBuilder componentBuilder, @NotNull String command, int page) {
componentBuilder.append("[Page Command]", ComponentBuilder.FormatRetention.NONE).event(new HoverEvent(
HoverEvent.Action.SHOW_TEXT, new Text("/" + command + " page" + page))).event(
new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " page" + page));
}
/**
* Displays the current page and total amount of pages
*
* @param componentBuilder <p>The component builder to append to</p>
* @param page <p>The current page</p>
* @param totalPages <p>The total amount of pages</p>
*/
protected static void displayTotalPages(@NotNull ComponentBuilder componentBuilder, int page, int totalPages) {
componentBuilder.append("Page " + page + " of " + totalPages,
ComponentBuilder.FormatRetention.NONE).color(ChatColor.GREEN);
}
/**
* Displays the alphabet-based page index
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param firstInstances <p>The map of where the first index of a letter is found</p>
*/
protected static void displayAlphabetIndex(@NotNull ComponentBuilder componentBuilder,
@NotNull String command, @NotNull Map<Character, Integer> firstInstances) {
for (int characterIndex = 0; characterIndex <= 25; characterIndex++) {
char character = (char) ('a' + characterIndex);
if (firstInstances.containsKey(character)) {
int pageIndex = (firstInstances.get(character) / booksPerPage) + 1;
componentBuilder.append(character + "").color(
ChatColor.AQUA).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
"/" + command + " page" + pageIndex)).event(new HoverEvent(
HoverEvent.Action.SHOW_TEXT, new Text("To page " + pageIndex)));
} else {
componentBuilder.append(character + "", ComponentBuilder.FormatRetention.NONE).color(ChatColor.GRAY);
}
}
componentBuilder.append("\n");
}
/**
* Displays the previous page button
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param page <p>The current page</p>
*/
protected static void displayPreviousButton(@NotNull ComponentBuilder componentBuilder,
@NotNull String command, int page) {
if (page > 1) {
String fullCommand = "/" + command + " page" + (page - 1);
HoverEvent prevPagePreview = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("To page " + (page - 1)));
ClickEvent prevPageClick = new ClickEvent(ClickEvent.Action.RUN_COMMAND, fullCommand);
componentBuilder.append("Previous [<]", ComponentBuilder.FormatRetention.NONE).event(prevPagePreview).event(prevPageClick);
} else {
componentBuilder.append("Previous [<]", ComponentBuilder.FormatRetention.NONE).color(ChatColor.GRAY);
}
componentBuilder.append("\n");
}
/**
* Displays the next page button
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param page <p>The current page</p>
* @param totalPages <p>The total amount of pages</p>
*/
protected static void displayNextButton(@NotNull ComponentBuilder componentBuilder,
@NotNull String command, int page, int totalPages) {
if (page < totalPages) {
String fullCommand = "/" + command + " page" + (page + 1);
HoverEvent nextPagePreview = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("To page " + (page + 1)));
ClickEvent nextPageClick = new ClickEvent(ClickEvent.Action.RUN_COMMAND, fullCommand);
componentBuilder.append("Next [>]", ComponentBuilder.FormatRetention.NONE).event(nextPagePreview).event(nextPageClick);
} else {
componentBuilder.append("Next [>]", ComponentBuilder.FormatRetention.NONE).color(ChatColor.GRAY);
}
}
/**
* Gets a nice name from a book's path
*
* @param bookPath <p>The path of a book</p>
* @return <p>The prettified book name</p>
*/
@NotNull
protected static String getNiceName(@NotNull String bookPath) {
bookPath = ChatColor.translateAlternateColorCodes('&', bookPath.substring(0, bookPath.length() - 4));
String[] parts = bookPath.split(",");
return parts[0].replace("_", " ") + ChatColor.RESET + " by " + parts[1] + ChatColor.RESET;
}
}

View File

@@ -1,6 +1,7 @@
package net.knarcraft.bookswithoutborders.gui;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.BookFormatter;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
@@ -17,9 +18,7 @@ import java.util.Map;
/**
* A class for displaying a paged index of all available books
*/
public class PagedBookIndex {
private final static int booksPerPage = 10;
public class PagedBookIndex extends BookIndex {
/**
* Prints the available books
@@ -45,7 +44,7 @@ public class PagedBookIndex {
if (page > totalPages) {
sender.sendMessage(ChatColor.GRAY + "No such page");
} else {
PagedBookIndex.showBookMenu(sender, command, page, totalPages, availableBooks, firstInstances);
showBookMenu(sender, command, page, totalPages, availableBooks, firstInstances);
}
}
@@ -80,31 +79,6 @@ public class PagedBookIndex {
sender.spigot().sendMessage(componentBuilder.create());
}
/**
* Displays the suggestion for manually going to any page
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param page <p>The current page</p>
*/
private static void displayPageCommand(@NotNull ComponentBuilder componentBuilder, @NotNull String command, int page) {
componentBuilder.append("[Page Command]", ComponentBuilder.FormatRetention.NONE).event(new HoverEvent(
HoverEvent.Action.SHOW_TEXT, new Text("/" + command + " page" + page))).event(
new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " page" + page));
}
/**
* Displays the current page and total amount of pages
*
* @param componentBuilder <p>The component builder to append to</p>
* @param page <p>The current page</p>
* @param totalPages <p>The total amount of pages</p>
*/
private static void displayTotalPages(@NotNull ComponentBuilder componentBuilder, int page, int totalPages) {
componentBuilder.append("Page " + page + " of " + totalPages,
ComponentBuilder.FormatRetention.NONE).color(ChatColor.GREEN);
}
/**
* Displays the list of books on the current page
*
@@ -113,8 +87,8 @@ public class PagedBookIndex {
* @param page <p>The current page</p>
* @param availableBooks <p>All available books</p>
*/
private static void displayBookList(@NotNull ComponentBuilder componentBuilder, @NotNull String command, int page,
@NotNull List<String> availableBooks) {
protected static void displayBookList(@NotNull ComponentBuilder componentBuilder, @NotNull String command, int page,
@NotNull List<String> availableBooks) {
int startIndex = (page - 1) * booksPerPage;
for (int bookIndex = startIndex; bookIndex < Math.min(startIndex + booksPerPage, availableBooks.size()); bookIndex++) {
componentBuilder.append("[" + (bookIndex + 1) + "]").color(ChatColor.GOLD).event(
@@ -124,89 +98,18 @@ public class PagedBookIndex {
componentBuilder.append(" ", ComponentBuilder.FormatRetention.NONE);
componentBuilder.append(getNiceName(availableBooks.get(bookIndex))).color(ChatColor.WHITE).event(
String[] parts = getNiceName(availableBooks.get(bookIndex)).split(" by ");
componentBuilder.append(parts[0]).color(ChatColor.WHITE).event(
new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " +
availableBooks.get(bookIndex))).event(
new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Select book by path")));
componentBuilder.append(" by ", ComponentBuilder.FormatRetention.NONE).color(ChatColor.WHITE);
componentBuilder.append(parts[1]).color(ChatColor.WHITE).event(
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + command + " author" +
BookFormatter.stripColor(parts[1]) + " page1")).event(
new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Filter by author")));
componentBuilder.append("\n");
}
}
/**
* Displays the alphabet-based page index
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param firstInstances <p>The map of where the first index of a letter is found</p>
*/
private static void displayAlphabetIndex(@NotNull ComponentBuilder componentBuilder,
@NotNull String command, @NotNull Map<Character, Integer> firstInstances) {
for (int characterIndex = 0; characterIndex <= 25; characterIndex++) {
char character = (char) ('a' + characterIndex);
if (firstInstances.containsKey(character)) {
int pageIndex = (firstInstances.get(character) / booksPerPage) + 1;
componentBuilder.append(character + "").color(
ChatColor.AQUA).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
"/" + command + " page" + pageIndex)).event(new HoverEvent(
HoverEvent.Action.SHOW_TEXT, new Text("To page " + pageIndex)));
} else {
componentBuilder.append(character + "", ComponentBuilder.FormatRetention.NONE).color(ChatColor.GRAY);
}
}
componentBuilder.append("\n");
}
/**
* Displays the previous page button
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param page <p>The current page</p>
*/
private static void displayPreviousButton(@NotNull ComponentBuilder componentBuilder,
@NotNull String command, int page) {
if (page > 1) {
String fullCommand = "/" + command + " page" + (page - 1);
HoverEvent prevPagePreview = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("To page " + (page - 1)));
ClickEvent prevPageClick = new ClickEvent(ClickEvent.Action.RUN_COMMAND, fullCommand);
componentBuilder.append("Previous [<]", ComponentBuilder.FormatRetention.NONE).event(prevPagePreview).event(prevPageClick);
} else {
componentBuilder.append("Previous [<]", ComponentBuilder.FormatRetention.NONE).color(ChatColor.GRAY);
}
componentBuilder.append("\n");
}
/**
* Displays the next page button
*
* @param componentBuilder <p>The component builder to append to</p>
* @param command <p>The command used for switching pages</p>
* @param page <p>The current page</p>
* @param totalPages <p>The total amount of pages</p>
*/
private static void displayNextButton(@NotNull ComponentBuilder componentBuilder,
@NotNull String command, int page, int totalPages) {
if (page < totalPages) {
String fullCommand = "/" + command + " page" + (page + 1);
HoverEvent nextPagePreview = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("To page " + (page + 1)));
ClickEvent nextPageClick = new ClickEvent(ClickEvent.Action.RUN_COMMAND, fullCommand);
componentBuilder.append("Next [>]", ComponentBuilder.FormatRetention.NONE).event(nextPagePreview).event(nextPageClick);
} else {
componentBuilder.append("Next [>]", ComponentBuilder.FormatRetention.NONE).color(ChatColor.GRAY);
}
}
/**
* Gets a nice name from a book's path
*
* @param bookPath <p>The path of a book</p>
* @return <p>The prettified book name</p>
*/
@NotNull
private static String getNiceName(@NotNull String bookPath) {
bookPath = ChatColor.translateAlternateColorCodes('&', bookPath.substring(0, bookPath.length() - 4));
String[] parts = bookPath.split(",");
return parts[0].replace("_", " ") + ChatColor.RESET + " by " + parts[1] + ChatColor.RESET;
}
}

View File

@@ -1,6 +1,7 @@
package net.knarcraft.bookswithoutborders.utility;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -82,4 +83,21 @@ public final class InputCleaningHelper {
}
}
/**
* Parses an author specifier given in a command
*
* @param input <p>The input to parse</p>
* @return <p>The author name, or null if not an author specifier</p>
*/
@Nullable
public static String parseAuthorSpecifier(@NotNull String input) {
Pattern pattern = Pattern.compile("author([0-9a-zA-Z_]+)");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
return matcher.group(1);
} else {
return null;
}
}
}