Adds a ChatComponent-enhanced book list
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good

This commit is contained in:
2025-08-01 20:59:16 +02:00
parent 35e98e0f18
commit 4be023bd63
5 changed files with 116 additions and 21 deletions

View File

@@ -4,6 +4,7 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.state.BookDirectory; import net.knarcraft.bookswithoutborders.state.BookDirectory;
import net.knarcraft.bookswithoutborders.utility.BookFileHelper; import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
import net.knarcraft.bookswithoutborders.utility.BookHelper; import net.knarcraft.bookswithoutborders.utility.BookHelper;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.knarcraft.knarlib.util.TabCompletionHelper; import net.knarcraft.knarlib.util.TabCompletionHelper;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -39,13 +40,20 @@ public class CommandDelete implements TabExecutor {
* @return <p>True if the book was deleted successfully</p> * @return <p>True if the book was deleted successfully</p>
*/ */
boolean deleteBook(CommandSender sender, String[] args, boolean deletePublic) { boolean deleteBook(CommandSender sender, String[] args, boolean deletePublic) {
String command = deletePublic ? "deletepublicbook" : "deletebook";
//List deletable files //List deletable files
if (args.length == 0) { if (args.length == 0) {
BookFileHelper.printBooks(sender, deletePublic); BookFileHelper.printBooks(sender, deletePublic, command, 1);
return true; return true;
} }
//Delete the file //Delete the file
if (args.length == 1) { if (args.length == 1) {
int page = InputCleaningHelper.parsePageNumber(args[0]);
if (page > 0) {
BookFileHelper.printBooks(sender, deletePublic, command, page);
return true;
}
List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, deletePublic); List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, deletePublic);
if (!availableBooks.isEmpty()) { if (!availableBooks.isEmpty()) {
performBookDeletion(sender, args[0], deletePublic); performBookDeletion(sender, args[0], deletePublic);

View File

@@ -44,16 +44,23 @@ public class CommandGive implements TabExecutor {
* @return <p>True if the book was given successfully</p> * @return <p>True if the book was given successfully</p>
*/ */
boolean giveBook(CommandSender sender, String[] args, boolean givePublic, String folder) { boolean giveBook(CommandSender sender, String[] args, boolean givePublic, String folder) {
String command = givePublic ? "givepublicbook" : "givebook";
if (args.length == 0) {
BookFileHelper.printBooks(sender, givePublic, command, 1);
return true;
} else if (args.length == 1) {
int page = InputCleaningHelper.parsePageNumber(args[0]);
if (page > 0) {
BookFileHelper.printBooks(sender, givePublic, command, page);
return true;
}
}
if (args.length == 1 || args.length > 4) { if (args.length == 1 || args.length > 4) {
BooksWithoutBorders.sendErrorMessage(sender, "Incorrect number of arguments for this command!"); BooksWithoutBorders.sendErrorMessage(sender, "Incorrect number of arguments for this command!");
return false; return false;
} }
if (args.length == 0) {
BookFileHelper.printBooks(sender, givePublic);
return true;
}
//Organize and parse input //Organize and parse input
String bookIdentifier = args[0]; String bookIdentifier = args[0];
String receivingPlayerName = args[1]; String receivingPlayerName = args[1];

View File

@@ -49,19 +49,26 @@ public class CommandLoad implements TabExecutor {
int argumentCount = args.length; int argumentCount = args.length;
//Show books available to the player //Show books available to the player
String command = loadPublic ? "loadpublicbook" : "loadbook";
if (argumentCount == 0) { if (argumentCount == 0) {
BookFileHelper.printBooks(sender, loadPublic); BookFileHelper.printBooks(sender, loadPublic, command, 1);
return true; return true;
} else if (argumentCount == 1) {
int page = InputCleaningHelper.parsePageNumber(args[0]);
if (page > 0) {
BookFileHelper.printBooks(sender, loadPublic, command, page);
return true;
}
} }
//Organize and parse input //Organize and parse input
String bookIdentifier = args[0]; String bookIdentifier = args[0];
String copies = "1"; String copies = "1";
String isSigned = "true"; String isSigned = "true";
if (args.length == 3) { if (argumentCount == 3) {
copies = args[1]; copies = args[1];
isSigned = args[2]; isSigned = args[2];
} else if (args.length == 2) { } else if (argumentCount == 2) {
if (args[1].equalsIgnoreCase("true") || args[1].equalsIgnoreCase("false")) { if (args[1].equalsIgnoreCase("true") || args[1].equalsIgnoreCase("false")) {
isSigned = args[1]; isSigned = args[1];
} else { } else {

View File

@@ -4,7 +4,13 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig; import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
import net.knarcraft.bookswithoutborders.state.BookDirectory; import net.knarcraft.bookswithoutborders.state.BookDirectory;
import net.md_5.bungee.api.ChatColor; 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.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@@ -19,6 +25,8 @@ import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig
*/ */
public final class BookFileHelper { public final class BookFileHelper {
private final static int booksPerPage = 10;
private BookFileHelper() { private BookFileHelper() {
} }
@@ -106,27 +114,68 @@ public final class BookFileHelper {
* *
* @param sender <p>The sender to display the books to</p> * @param sender <p>The sender to display the books to</p>
* @param listPublic <p>Whether to display public books</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(CommandSender sender, boolean listPublic) { public static void printBooks(@NotNull CommandSender sender, boolean listPublic, @NotNull String command, int page) {
List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, listPublic); List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, listPublic);
BookFileHelper.printFiles(sender, availableBooks); int totalPages = (int) Math.ceil((double) availableBooks.size() / booksPerPage);
if (page > totalPages) {
sender.sendMessage(ChatColor.GRAY + "No such page");
} else {
showBookMenu(sender, command, page, totalPages, availableBooks);
}
} }
/** /**
* Prints a list of files * Shows a menu listing available books
* *
* @param sender <p>The command sender to show the list to</p> * @param sender <p>The sender wanting to see the book menu</p>
* @param fileList <p>The files to list</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>
*/ */
public static void printFiles(CommandSender sender, List<String> fileList) { private static void showBookMenu(@NotNull CommandSender sender, @NotNull String command, int page,
BooksWithoutBorders.sendSuccessMessage(sender, "Available Books:"); int totalPages, @NotNull List<String> availableBooks) {
if (fileList == null) { // Print the previous page button
return; ComponentBuilder previousComponent = new ComponentBuilder();
if (page > 1) {
HoverEvent prevPagePreview = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("To page " + (page - 1)));
ClickEvent prevPageClick = new ClickEvent(ClickEvent.Action.RUN_COMMAND, command + " page" + (page - 1));
previousComponent.append("Previous [<]").event(prevPagePreview).event(prevPageClick);
} else {
previousComponent.append("Previous [<]").color(ChatColor.GRAY);
} }
int listSize = fileList.size(); sender.spigot().sendMessage(previousComponent.create());
for (int fileIndex = 0; fileIndex < listSize; fileIndex++) {
sender.sendMessage(ChatColor.GRAY + "[" + (fileIndex + 1) + "] " + fileList.get(fileIndex)); // Print the main list of all book indexes and titles
HoverEvent interactSuggestion = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click me"));
int startIndex = (page - 1) * booksPerPage;
for (int bookIndex = startIndex; bookIndex < Math.min(startIndex + booksPerPage, availableBooks.size()); bookIndex++) {
ComponentBuilder bookComponent = new ComponentBuilder();
TextComponent indexComponent = new TextComponent("[" + (bookIndex + 1) + "] ");
indexComponent.setColor(ChatColor.GOLD);
bookComponent.append(indexComponent).event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND,
"/" + command + " " + (bookIndex + 1))).event(interactSuggestion);
TextComponent bookNameComponent = new TextComponent(availableBooks.get(bookIndex));
bookNameComponent.setColor(ChatColor.WHITE);
bookComponent.append(bookNameComponent).event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND,
"/" + command + " " + availableBooks.get(bookIndex))).event(interactSuggestion);
sender.spigot().sendMessage(bookComponent.create());
} }
// Print the next page button
ComponentBuilder nextComponent = new ComponentBuilder();
if (page < totalPages) {
HoverEvent nextPagePreview = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("To page " + (page + 1)));
ClickEvent nextPageClick = new ClickEvent(ClickEvent.Action.RUN_COMMAND, command + " page" + (page + 1));
nextComponent.append("Next [>]").event(nextPagePreview).event(nextPageClick);
} else {
nextComponent.append("Next [>]").color(ChatColor.GRAY).reset();
}
sender.spigot().sendMessage(nextComponent.create());
} }
/** /**

View File

@@ -1,7 +1,11 @@
package net.knarcraft.bookswithoutborders.utility; package net.knarcraft.bookswithoutborders.utility;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* Helper class for cleaning input and names * Helper class for cleaning input and names
@@ -58,4 +62,24 @@ public final class InputCleaningHelper {
return fileName; return fileName;
} }
/**
* Parses a page number for a string like "page1"
*
* @param input <p>The input to parse</p>
* @return <p>The page number, or 0 if not valid</p>
*/
public static int parsePageNumber(@NotNull String input) {
try {
Pattern pattern = Pattern.compile("page([0-9])+");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
return Integer.parseInt(matcher.group(1));
} else {
return 0;
}
} catch (NumberFormatException exception) {
return 0;
}
}
} }