Adds commands for adding book title pages and for deleting book pages
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good

This commit is contained in:
2025-08-10 19:10:08 +02:00
parent f6d5108c7b
commit af094f9931
5 changed files with 284 additions and 1 deletions

View File

@@ -1,10 +1,12 @@
package net.knarcraft.bookswithoutborders;
import net.knarcraft.bookswithoutborders.command.CommandAddTitlePage;
import net.knarcraft.bookswithoutborders.command.CommandBooksWithoutBorders;
import net.knarcraft.bookswithoutborders.command.CommandClear;
import net.knarcraft.bookswithoutborders.command.CommandCopy;
import net.knarcraft.bookswithoutborders.command.CommandDecrypt;
import net.knarcraft.bookswithoutborders.command.CommandDelete;
import net.knarcraft.bookswithoutborders.command.CommandDeletePage;
import net.knarcraft.bookswithoutborders.command.CommandDeletePublic;
import net.knarcraft.bookswithoutborders.command.CommandEncrypt;
import net.knarcraft.bookswithoutborders.command.CommandFormat;
@@ -230,6 +232,8 @@ public class BooksWithoutBorders extends JavaPlugin {
registerCommand("setBookGeneration", new CommandSetGeneration());
registerCommand("clearBook", new CommandClear());
registerCommand("setBookshelfData", new CommandSetBookshelfData());
registerCommand("addBookTitlePage", new CommandAddTitlePage());
registerCommand("deleteBookPage", new CommandDeletePage());
}
/**

View File

@@ -0,0 +1,155 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
import net.knarcraft.bookswithoutborders.utility.BookFormatter;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import net.md_5.bungee.api.ChatColor;
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.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* A command for adding a title page to a book
*/
public class CommandAddTitlePage implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s,
@NotNull String[] arguments) {
if (!(sender instanceof Player player)) {
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
return false;
}
ItemStack heldBook = InventoryHelper.getHeldBook(player);
if (heldBook == null) {
BooksWithoutBorders.sendErrorMessage(sender, "You must be holding a book to perform this command");
return false;
}
int index;
if (arguments.length < 1) {
if (InventoryHelper.notHoldingOneWrittenBookCheck(player, "You must be holding a written book to " +
"add an author title page!", "You cannot add an author title page to two books at once!")) {
return false;
}
index = 0;
} else {
try {
index = Integer.parseInt(arguments[0]) - 1;
} catch (NumberFormatException exception) {
BooksWithoutBorders.sendErrorMessage(sender, "Invalid page index given!");
return false;
}
}
String title = null;
if (arguments.length > 1) {
// Get all arguments as a space-separated string
StringBuilder builder = new StringBuilder(arguments[1]);
for (int i = 2; i < arguments.length; i++) {
builder.append(" ").append(arguments[i]);
}
title = builder.toString();
}
BookMeta bookMeta = (BookMeta) heldBook.getItemMeta();
if (bookMeta == null) {
BooksWithoutBorders.sendErrorMessage(sender, "Unable to get metadata for the held book!");
return false;
}
List<String> pages = new ArrayList<>(bookMeta.getPages());
if (index < 0) {
BooksWithoutBorders.sendErrorMessage(sender, "The given page index is out of bounds!");
return false;
}
if (title == null && heldBook.getType() == Material.WRITTEN_BOOK) {
String loreSeparator = BooksWithoutBordersConfig.getLoreSeparator();
if (index > pages.size()) {
pages.add(formatTitle(bookMeta.getTitle() + loreSeparator + "By: " + bookMeta.getAuthor()));
} else {
pages.add(index, formatTitle(bookMeta.getTitle() + loreSeparator + "By: " + bookMeta.getAuthor()));
}
} else if (title == null) {
if (index > pages.size()) {
pages.add("");
} else {
pages.add(index, "");
}
} else {
if (index > pages.size()) {
pages.add(formatTitle(title));
} else {
pages.add(index, formatTitle(title));
}
}
bookMeta.setPages(pages);
heldBook.setItemMeta(bookMeta);
BooksWithoutBorders.sendSuccessMessage(sender, "Title page added!");
return true;
}
/**
* Formats a book title
*
* @param input <p>The input to format</p>
* @return <p>The formatted input</p>
*/
private String formatTitle(@NotNull String input) {
String loreSeparator = BooksWithoutBordersConfig.getLoreSeparator();
if (input.contains(loreSeparator)) {
String[] parts = input.split(loreSeparator);
StringBuilder output = new StringBuilder("\n");
output.append(ChatColor.UNDERLINE).append(ChatColor.BOLD).append(BookFormatter.stripColor(parts[0])).append(ChatColor.RESET);
for (int i = 1; i < parts.length; i++) {
output.append("\n").append("\n").append(ChatColor.ITALIC).append(BookFormatter.stripColor(parts[i])).append(ChatColor.RESET);
}
return output.toString();
} else {
return ChatColor.UNDERLINE + ChatColor.BOLD.toString() + input;
}
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] arguments) {
if (arguments.length == 1) {
if (!(commandSender instanceof Player player)) {
return List.of("1", "2", "3", "4");
}
ItemStack heldBook = InventoryHelper.getHeldBook(player);
if (heldBook != null) {
BookMeta bookMeta = (BookMeta) heldBook.getItemMeta();
if (bookMeta != null) {
List<String> pages = new ArrayList<>();
pages.add("1");
for (int i = 1; i <= bookMeta.getPages().size(); i++) {
pages.add(String.valueOf(i + 1));
}
return pages;
}
}
} else if (arguments.length == 2) {
return List.of("Title", "Chapter~Description");
}
return List.of();
}
}

View File

@@ -0,0 +1,91 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
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.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* A command for deleting a single page from a book
*/
public class CommandDeletePage implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] arguments) {
if (!(sender instanceof Player player)) {
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
return false;
}
if (arguments.length == 0) {
BooksWithoutBorders.sendErrorMessage(sender, "You must supply a page index");
return false;
}
ItemStack heldBook = InventoryHelper.getHeldBook(player);
if (heldBook == null) {
BooksWithoutBorders.sendErrorMessage(sender, "You must be holding a book to perform this command");
return false;
}
int index;
try {
index = Integer.parseInt(arguments[0]) - 1;
} catch (NumberFormatException exception) {
BooksWithoutBorders.sendErrorMessage(sender, "Invalid page index given!");
return false;
}
BookMeta bookMeta = (BookMeta) heldBook.getItemMeta();
if (bookMeta == null) {
BooksWithoutBorders.sendErrorMessage(sender, "Unable to get metadata for the held book!");
return false;
}
List<String> pages = new ArrayList<>(bookMeta.getPages());
if (index < 0 || index >= pages.size()) {
BooksWithoutBorders.sendErrorMessage(sender, "The given page index is out of bounds!");
return false;
}
pages.remove(index);
bookMeta.setPages(pages);
heldBook.setItemMeta(bookMeta);
BooksWithoutBorders.sendSuccessMessage(sender, "Page deleted!");
return true;
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] arguments) {
if (arguments.length == 1) {
if (!(commandSender instanceof Player player)) {
return List.of("1", "2", "3", "4");
}
ItemStack heldBook = InventoryHelper.getHeldBook(player);
if (heldBook != null) {
BookMeta bookMeta = (BookMeta) heldBook.getItemMeta();
if (bookMeta != null) {
List<String> pages = new ArrayList<>();
for (int i = 0; i < bookMeta.getPages().size(); i++) {
pages.add(String.valueOf(i + 1));
}
return pages;
}
}
}
return List.of();
}
}

View File

@@ -18,6 +18,25 @@ public final class InventoryHelper {
private InventoryHelper() {
}
/**
* Gets the book from a player's main hand
*
* @param player <p>The player holding the book</p>
* @return <p>The held book, or null if not holding one book in the main hand</p>
*/
public static ItemStack getHeldBook(@NotNull Player player) {
@NotNull ItemSlot heldSigned = InventoryHelper.getHeldSlotBook(player, true, true,
true, true);
@NotNull ItemSlot heldUnSigned = InventoryHelper.getHeldSlotBook(player, true, true,
true, false);
if (heldSigned == ItemSlot.MAIN_HAND || heldUnSigned == ItemSlot.MAIN_HAND) {
boolean holdingSigned = heldSigned == ItemSlot.MAIN_HAND;
return InventoryHelper.getHeldBook(player, holdingSigned);
} else {
return null;
}
}
/**
* Gets the book the holder is playing
*

View File

@@ -101,6 +101,14 @@ commands:
description: Sets custom data for a chiseled bookshelf used when peeking at the bookshelf
usage: /<command> <delete/name/lore> <text> [more text]
permission: bookswithoutborders.editbookshelf
addBookTitlePage:
description: Adds a blank page, title page or chapter page depending on input and whether the book is signed
usage: /<command> [page index] [title~description]
permission: bookswithoutborders.addtitlepage
deleteBookPage:
description: Deletes one page from a book
usage: /<command> <page>
permission: bookswithoutborders.deletepage
permissions:
bookswithoutborders.*:
description: Grants all permissions
@@ -147,6 +155,8 @@ permissions:
bookswithoutborders.setlore: true
bookswithoutborders.format: true
bookswithoutborders.setgeneration: true
bookswithoutborders.addtitlepage: true
bookswithoutborders.deletepage: true
bookswithoutborders.format:
description: Allows a player to format a book
bookswithoutborders.save:
@@ -200,4 +210,8 @@ permissions:
bookswithoutborders.peekbookshelf:
description: Allows player to left-click a bookshelf to see the contents of the shelf
bookswithoutborders.editbookshelf:
description: Allows player to set name/lore for bookshelves, used for peeking
description: Allows player to set name/lore for bookshelves, used for peeking
bookswithoutborders.addtitlepage:
description: Allows player to add a blank title page to a book
bookswithoutborders.deletepage:
description: Allows player to delete a page from a book