Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
2627407e6b | |||
175b66465a | |||
36b57b9191 | |||
0d5ad490ff | |||
9e300afbef | |||
a84a56391a | |||
b15ad18ae3 | |||
67ccdf3b1d | |||
b9bd686ae9 | |||
a5be6bb72c | |||
ed0a750eb4 | |||
6aa422d461 | |||
4be023bd63 | |||
35e98e0f18 |
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>net.knarcraft</groupId>
|
||||
<artifactId>BooksWithoutBorders</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.9-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<licenses>
|
||||
|
@@ -39,12 +39,15 @@ import org.bukkit.inventory.ItemFactory;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@@ -61,6 +64,8 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
private static ItemFactory itemFactory;
|
||||
private static Map<UUID, List<String>> playerBooksList;
|
||||
private static List<String> publicBooksList;
|
||||
private static Map<Character, Integer> publicLetterIndex;
|
||||
private static Map<UUID, Map<Character, Integer>> playerLetterIndex;
|
||||
private static BooksWithoutBorders booksWithoutBorders;
|
||||
private static ConsoleCommandSender consoleSender;
|
||||
|
||||
@@ -88,28 +93,48 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
if (!playerBooksList.containsKey(playerUUID)) {
|
||||
List<String> newFiles = BookFileHelper.listFiles(sender, false);
|
||||
playerBooksList.put(playerUUID, newFiles);
|
||||
playerLetterIndex.put(playerUUID, BookFileHelper.populateLetterIndices(newFiles));
|
||||
}
|
||||
return playerBooksList.get(playerUUID);
|
||||
return new ArrayList<>(playerBooksList.get(playerUUID));
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the letter index map for public books, or a specific player's books
|
||||
*
|
||||
* @param playerIndex <p>The player to get the index for, or null for the public index</p>
|
||||
* @return <p>An index mapping between a character and the first index containing that character</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static Map<Character, Integer> getLetterIndex(@Nullable UUID playerIndex) {
|
||||
if (playerIndex == null) {
|
||||
return publicLetterIndex;
|
||||
} else {
|
||||
Map<Character, Integer> letterIndex = playerLetterIndex.get(playerIndex);
|
||||
return Objects.requireNonNullElseGet(letterIndex, HashMap::new);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates available books
|
||||
*
|
||||
* @param sender <p>The sender to update books for</p>
|
||||
* @param updatePublic <p>Whether to update public books</p>
|
||||
*/
|
||||
public static void updateBooks(CommandSender sender, boolean updatePublic) {
|
||||
public static void updateBooks(@NotNull CommandSender sender, boolean updatePublic) {
|
||||
List<String> newFiles = BookFileHelper.listFiles(sender, updatePublic);
|
||||
if (updatePublic) {
|
||||
publicBooksList = newFiles;
|
||||
publicLetterIndex = BookFileHelper.populateLetterIndices(newFiles);
|
||||
} else if (sender instanceof Player player) {
|
||||
playerBooksList.put(player.getUniqueId(), newFiles);
|
||||
playerLetterIndex.put(player.getUniqueId(), BookFileHelper.populateLetterIndices(newFiles));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
FileConfiguration config = this.getConfig();
|
||||
@@ -123,8 +148,10 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
booksWithoutBorders = this;
|
||||
consoleSender = this.getServer().getConsoleSender();
|
||||
playerBooksList = new HashMap<>();
|
||||
playerLetterIndex = new HashMap<>();
|
||||
BooksWithoutBordersConfig.initialize(this);
|
||||
publicBooksList = BookFileHelper.listFiles(consoleSender, true);
|
||||
publicLetterIndex = BookFileHelper.populateLetterIndices(publicBooksList);
|
||||
|
||||
PluginManager pluginManager = this.getServer().getPluginManager();
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.gui.PagedBookIndex;
|
||||
import net.knarcraft.bookswithoutborders.state.BookDirectory;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookHelper;
|
||||
@@ -21,34 +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) {
|
||||
//List deletable files
|
||||
if (args.length == 0) {
|
||||
BookFileHelper.printBooks(sender, deletePublic);
|
||||
boolean deleteBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean deletePublic) {
|
||||
String command = deletePublic ? "deletepublicbook" : "deletebook";
|
||||
if (PagedBookIndex.displayPage(arguments, sender, deletePublic, command)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Delete the file
|
||||
if (args.length == 1) {
|
||||
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;
|
||||
|
@@ -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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
|
||||
import net.knarcraft.bookswithoutborders.gui.PagedBookIndex;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookLoader;
|
||||
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.TabCompletionTypeHelper;
|
||||
@@ -25,48 +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) {
|
||||
if (args.length == 1 || args.length > 4) {
|
||||
boolean giveBook(@NotNull CommandSender sender, String[] arguments, boolean givePublic, String folder) {
|
||||
String command = givePublic ? "givepublicbook" : "givebook";
|
||||
if (PagedBookIndex.displayPage(arguments, sender, givePublic, command)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arguments.length == 1 || arguments.length > 4) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Incorrect number of arguments for this command!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
BookFileHelper.printBooks(sender, givePublic);
|
||||
return true;
|
||||
}
|
||||
|
||||
//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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
|
||||
import net.knarcraft.bookswithoutborders.gui.PagedBookIndex;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookLoader;
|
||||
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.TabCompletionTypeHelper;
|
||||
@@ -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,26 +47,25 @@ public class CommandLoad implements TabExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
int argumentCount = args.length;
|
||||
int argumentCount = arguments.length;
|
||||
|
||||
//Show books available to the player
|
||||
if (argumentCount == 0) {
|
||||
BookFileHelper.printBooks(sender, loadPublic);
|
||||
String command = loadPublic ? "loadpublicbook" : "loadbook";
|
||||
if (PagedBookIndex.displayPage(arguments, sender, loadPublic, command)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Organize and parse input
|
||||
String bookIdentifier = args[0];
|
||||
String bookIdentifier = arguments[0];
|
||||
String copies = "1";
|
||||
String isSigned = "true";
|
||||
if (args.length == 3) {
|
||||
copies = args[1];
|
||||
isSigned = args[2];
|
||||
} else if (args.length == 2) {
|
||||
if (args[1].equalsIgnoreCase("true") || args[1].equalsIgnoreCase("false")) {
|
||||
isSigned = args[1];
|
||||
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];
|
||||
} else {
|
||||
copies = args[1];
|
||||
copies = arguments[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -8,6 +8,7 @@ import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookToFromTextHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
@@ -87,6 +88,11 @@ public class CommandSave implements TabExecutor {
|
||||
String savePath = BookHelper.getBookDirectoryPathString(
|
||||
saveToPublicFolder ? BookDirectory.PUBLIC : BookDirectory.PLAYER, player);
|
||||
|
||||
if (savePath == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Saving Failed! Unable to find the save path!");
|
||||
return;
|
||||
}
|
||||
|
||||
//Generate book filename
|
||||
String fileName = BookHelper.getBookFile(book, player, saveToPublicFolder);
|
||||
|
||||
@@ -142,7 +148,7 @@ public class CommandSave implements TabExecutor {
|
||||
|
||||
//Update the relevant book list
|
||||
BooksWithoutBorders.updateBooks(player, saveToPublicFolder);
|
||||
BooksWithoutBorders.sendSuccessMessage(player, "Book Saved as \"" + fileName + "\"");
|
||||
BooksWithoutBorders.sendSuccessMessage(player, "Book Saved as \"" + fileName + ChatColor.RESET + "\"");
|
||||
} catch (IOException exception) {
|
||||
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to save book");
|
||||
}
|
||||
|
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
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.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A class for displaying a paged index of all available books
|
||||
*/
|
||||
public class PagedBookIndex extends BookIndex {
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, listPublic);
|
||||
|
||||
Map<Character, Integer> firstInstances;
|
||||
if (listPublic) {
|
||||
firstInstances = BooksWithoutBorders.getLetterIndex(null);
|
||||
} else if (sender instanceof Player player) {
|
||||
firstInstances = BooksWithoutBorders.getLetterIndex(player.getUniqueId());
|
||||
} else {
|
||||
firstInstances = new HashMap<>();
|
||||
}
|
||||
|
||||
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, firstInstances);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a menu listing available books
|
||||
*
|
||||
* @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 firstInstances <p>The map between a character, and the index of the first instance of that character in the book list</p>
|
||||
*/
|
||||
private static void showBookMenu(@NotNull CommandSender sender, @NotNull String command, int page,
|
||||
int totalPages, @NotNull List<String> availableBooks,
|
||||
@NotNull Map<Character, Integer> firstInstances) {
|
||||
ComponentBuilder componentBuilder = new ComponentBuilder();
|
||||
|
||||
// Display the alphabet index as the header
|
||||
displayAlphabetIndex(componentBuilder, command, firstInstances);
|
||||
|
||||
// Display the list of books, with the next and previous buttons
|
||||
displayPreviousButton(componentBuilder, command, page);
|
||||
displayBookList(componentBuilder, command, page, availableBooks);
|
||||
displayNextButton(componentBuilder, command, 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);
|
||||
displayPageCommand(componentBuilder, command, page);
|
||||
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("[" + (bookIndex + 1) + "]").color(ChatColor.GOLD).event(
|
||||
new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " +
|
||||
(bookIndex + 1))).event(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new Text("Select book by index")));
|
||||
|
||||
componentBuilder.append(" ", ComponentBuilder.FormatRetention.NONE);
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -4,6 +4,7 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFormatter;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookLoader;
|
||||
import net.knarcraft.bookswithoutborders.utility.EncryptionHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
|
||||
@@ -144,7 +145,7 @@ public class SignEventListener implements Listener {
|
||||
player.closeInventory();
|
||||
|
||||
//Converts user supplied key into integer form
|
||||
String lineText = ChatColor.stripColor(sign.getSide(Side.FRONT).getLine(2));
|
||||
String lineText = BookFormatter.stripColor(sign.getSide(Side.FRONT).getLine(2));
|
||||
String key = EncryptionHelper.getNumberKeyFromStringKey(lineText);
|
||||
|
||||
ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, false);
|
||||
@@ -163,7 +164,7 @@ public class SignEventListener implements Listener {
|
||||
*/
|
||||
private ChatColor getSignLine2Color(Sign sign) {
|
||||
String line = sign.getSide(Side.FRONT).getLine(2);
|
||||
if (!ChatColor.stripColor(line).equals(line)) {
|
||||
if (!BookFormatter.stripColor(line).equals(line)) {
|
||||
return ChatColor.getByChar(sign.getSide(Side.FRONT).getLine(2).substring(1, 2).charAt(0));
|
||||
} else {
|
||||
return null;
|
||||
@@ -291,8 +292,8 @@ public class SignEventListener implements Listener {
|
||||
boolean mainHand = hand == EquipmentSlot.HAND;
|
||||
if (heldItemType == Material.WRITTEN_BOOK) {
|
||||
player.closeInventory();
|
||||
eBook = EncryptionHelper.encryptBook(player, mainHand, ChatColor.stripColor(lines[2]),
|
||||
EncryptionStyle.getFromString(ChatColor.stripColor(lines[3])));
|
||||
eBook = EncryptionHelper.encryptBook(player, mainHand, BookFormatter.stripColor(lines[2]),
|
||||
EncryptionStyle.getFromString(BookFormatter.stripColor(lines[3])));
|
||||
if (eBook != null) {
|
||||
player.getInventory().setItem(hand, eBook);
|
||||
}
|
||||
@@ -306,7 +307,7 @@ public class SignEventListener implements Listener {
|
||||
* @param player <p>The player which clicked the sign</p>
|
||||
*/
|
||||
private void giveBook(Sign sign, Player player) {
|
||||
String fileName = ChatColor.stripColor(sign.getSide(Side.FRONT).getLine(2));
|
||||
String fileName = BookFormatter.stripColor(sign.getSide(Side.FRONT).getLine(2));
|
||||
boolean isLoadListNumber = false;
|
||||
|
||||
try {
|
||||
@@ -318,7 +319,7 @@ public class SignEventListener implements Listener {
|
||||
//Add the third line to the second line for the full filename
|
||||
String thirdLine = sign.getSide(Side.FRONT).getLine(3);
|
||||
if (!isLoadListNumber && thirdLine.length() >= 2) {
|
||||
fileName += ChatColor.stripColor(thirdLine);
|
||||
fileName += BookFormatter.stripColor(thirdLine);
|
||||
}
|
||||
|
||||
ItemStack newBook = BookLoader.loadBook(player, fileName, "true", "public");
|
||||
|
@@ -3,12 +3,16 @@ package net.knarcraft.bookswithoutborders.utility;
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.state.BookDirectory;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -102,31 +106,27 @@ public final class BookFileHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the available books
|
||||
* Gets a map between characters, and the first instance of a book's title starting with that character
|
||||
*
|
||||
* @param sender <p>The sender to display the books to</p>
|
||||
* @param listPublic <p>Whether to display public books</p>
|
||||
* @param books <p>The books to look through</p>
|
||||
* @return <p>The map of the first index containing each character</p>
|
||||
*/
|
||||
public static void printBooks(CommandSender sender, boolean listPublic) {
|
||||
List<String> availableBooks = BooksWithoutBorders.getAvailableBooks(sender, listPublic);
|
||||
BookFileHelper.printFiles(sender, availableBooks);
|
||||
}
|
||||
@NotNull
|
||||
public static Map<Character, Integer> populateLetterIndices(@NotNull List<String> books) {
|
||||
List<Character> firstCharacter = new ArrayList<>(books.size());
|
||||
for (String bookIdentifier : books) {
|
||||
firstCharacter.add(BookFormatter.stripColor(bookIdentifier).toLowerCase().charAt(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a list of files
|
||||
*
|
||||
* @param sender <p>The command sender to show the list to</p>
|
||||
* @param fileList <p>The files to list</p>
|
||||
*/
|
||||
public static void printFiles(CommandSender sender, List<String> fileList) {
|
||||
BooksWithoutBorders.sendSuccessMessage(sender, "Available Books:");
|
||||
if (fileList == null) {
|
||||
return;
|
||||
}
|
||||
int listSize = fileList.size();
|
||||
for (int fileIndex = 0; fileIndex < listSize; fileIndex++) {
|
||||
sender.sendMessage(ChatColor.GRAY + "[" + (fileIndex + 1) + "] " + fileList.get(fileIndex));
|
||||
Map<Character, Integer> firstEncounter = new HashMap<>();
|
||||
for (int characterIndex = 0; characterIndex <= 25; characterIndex++) {
|
||||
char character = (char) ('a' + characterIndex);
|
||||
int index = Collections.binarySearch(firstCharacter, character);
|
||||
if (index >= 0) {
|
||||
firstEncounter.put(character, index);
|
||||
}
|
||||
}
|
||||
return firstEncounter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +163,9 @@ public final class BookFileHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the book list
|
||||
Comparator<String> bookComparator = Comparator.naturalOrder();
|
||||
fileList.sort((a, b) -> bookComparator.compare(BookFormatter.stripColor(a), BookFormatter.stripColor(b)));
|
||||
return fileList;
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ package net.knarcraft.bookswithoutborders.utility;
|
||||
import net.knarcraft.knarlib.property.ColorConversion;
|
||||
import net.knarcraft.knarlib.util.ColorHelper;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -114,4 +115,15 @@ public final class BookFormatter {
|
||||
return bookMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the color from the given input
|
||||
*
|
||||
* @param input <p>The input to strip</p>
|
||||
* @return <p>The color stripped input</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static String stripColor(@NotNull String input) {
|
||||
return ColorHelper.stripColorCodes(input, ColorConversion.RGB);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -8,6 +8,8 @@ import org.bukkit.command.CommandSender;
|
||||
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.io.File;
|
||||
import java.util.UUID;
|
||||
@@ -31,7 +33,8 @@ public final class BookHelper {
|
||||
* @param author <p>The author string</p>
|
||||
* @return <p>The author string, converted if it was a UUID</p>
|
||||
*/
|
||||
public static String authorFromUUID(String author) {
|
||||
@NotNull
|
||||
public static String authorFromUUID(@NotNull String author) {
|
||||
try {
|
||||
UUID authorID = UUID.fromString(author);
|
||||
Player player = Bukkit.getPlayer(authorID);
|
||||
@@ -50,7 +53,7 @@ public final class BookHelper {
|
||||
* @param sender <p>The command sender trying to get the directory</p>
|
||||
* @return <p>The path of the directory, or null if not possible to get</p>
|
||||
*/
|
||||
public static File getBookDirectoryPath(BookDirectory bookDirectory, CommandSender sender) {
|
||||
public static File getBookDirectoryPath(@NotNull BookDirectory bookDirectory, @NotNull CommandSender sender) {
|
||||
String bookFolderString = getBookDirectoryPathString(bookDirectory, sender);
|
||||
if (bookFolderString == null) {
|
||||
return null;
|
||||
@@ -65,7 +68,8 @@ public final class BookHelper {
|
||||
* @param sender <p>The command sender trying to get the directory</p>
|
||||
* @return <p>The path of the directory, or null if not possible to get</p>
|
||||
*/
|
||||
public static String getBookDirectoryPathString(BookDirectory bookDirectory, CommandSender sender) {
|
||||
@Nullable
|
||||
public static String getBookDirectoryPathString(@NotNull BookDirectory bookDirectory, @NotNull CommandSender sender) {
|
||||
String folder = null;
|
||||
String bookFolder = BooksWithoutBordersConfig.getBookFolder();
|
||||
if (bookDirectory == BookDirectory.PUBLIC) {
|
||||
@@ -81,7 +85,7 @@ public final class BookHelper {
|
||||
*
|
||||
* @param bookItem <p>The book item to increase the generation of</p>
|
||||
*/
|
||||
public static void increaseGeneration(ItemStack bookItem) {
|
||||
public static void increaseGeneration(@NotNull ItemStack bookItem) {
|
||||
BookMeta bookMeta = (BookMeta) bookItem.getItemMeta();
|
||||
if (BooksWithoutBordersConfig.changeGenerationOnCopy() && bookMeta != null) {
|
||||
bookMeta.setGeneration(BookHelper.getNextGeneration(bookMeta.getGeneration()));
|
||||
@@ -98,7 +102,8 @@ public final class BookHelper {
|
||||
* @param currentGeneration <p>The current generation of the book</p>
|
||||
* @return <p>The next generation of the book</p>
|
||||
*/
|
||||
public static BookMeta.Generation getNextGeneration(BookMeta.Generation currentGeneration) {
|
||||
@NotNull
|
||||
public static BookMeta.Generation getNextGeneration(@Nullable BookMeta.Generation currentGeneration) {
|
||||
if (currentGeneration == null) {
|
||||
return BookMeta.Generation.COPY_OF_ORIGINAL;
|
||||
}
|
||||
@@ -116,7 +121,8 @@ public final class BookHelper {
|
||||
* @param player <p>The player trying to do something with the book</p>
|
||||
* @return <p>The book file</p>
|
||||
*/
|
||||
public static String getBookFile(BookMeta book, Player player, boolean isPublic) {
|
||||
@NotNull
|
||||
public static String getBookFile(@NotNull BookMeta book, @NotNull Player player, boolean isPublic) {
|
||||
String titleAuthorSeparator = BooksWithoutBordersConfig.getTitleAuthorSeparator();
|
||||
String bookName;
|
||||
if (book.hasTitle()) {
|
||||
@@ -145,7 +151,7 @@ public final class BookHelper {
|
||||
* @param book <p>The book to check</p>
|
||||
* @return <p>True if the player is not the book's author</p>
|
||||
*/
|
||||
public static boolean isNotAuthor(Player player, BookMeta book) {
|
||||
public static boolean isNotAuthor(@NotNull Player player, @NotNull BookMeta book) {
|
||||
if (isAuthor(player.getName(), book.getAuthor())) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -162,7 +168,7 @@ public final class BookHelper {
|
||||
* @param author <p>The author to check</p>
|
||||
* @return <p>True if the player is the author</p>
|
||||
*/
|
||||
private static boolean isAuthor(String playerName, String author) {
|
||||
private static boolean isAuthor(@NotNull String playerName, @Nullable String author) {
|
||||
playerName = InputCleaningHelper.cleanString(playerName);
|
||||
return author != null && playerName.equalsIgnoreCase(InputCleaningHelper.cleanString(author));
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@ import org.bukkit.command.CommandSender;
|
||||
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.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -31,7 +33,9 @@ public final class BookLoader {
|
||||
* @param directory <p>The directory to save the book in</p>
|
||||
* @return <p>The loaded book</p>
|
||||
*/
|
||||
public static ItemStack loadBook(CommandSender sender, String fileName, String isSigned, String directory) {
|
||||
@Nullable
|
||||
public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, @NotNull String isSigned,
|
||||
@NotNull String directory) {
|
||||
return loadBook(sender, fileName, isSigned, directory, 1);
|
||||
}
|
||||
|
||||
@@ -45,7 +49,9 @@ public final class BookLoader {
|
||||
* @param numCopies <p>The number of copies to load</p>
|
||||
* @return <p>The loaded book</p>
|
||||
*/
|
||||
public static ItemStack loadBook(CommandSender sender, String fileName, String isSigned, String directory, int numCopies) {
|
||||
@Nullable
|
||||
public static ItemStack loadBook(@NotNull CommandSender sender, @NotNull String fileName, @NotNull String isSigned,
|
||||
@NotNull String directory, int numCopies) {
|
||||
BookDirectory bookDirectory = BookDirectory.getFromString(directory);
|
||||
|
||||
//Find the filename if a book index is given
|
||||
@@ -96,8 +102,13 @@ public final class BookLoader {
|
||||
book = new ItemStack(Material.WRITABLE_BOOK);
|
||||
}
|
||||
|
||||
if (bookMetadata == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Unable to create blank book metadata!");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Load the book from the given file
|
||||
BookToFromTextHelper.bookFromFile(file, bookMetadata);
|
||||
bookMetadata = BookToFromTextHelper.bookFromFile(file, bookMetadata);
|
||||
if (bookMetadata == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "File was blank!!");
|
||||
return null;
|
||||
|
@@ -6,6 +6,8 @@ import net.knarcraft.knarlib.util.FileHelper;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@@ -37,7 +39,7 @@ public final class BookToFromTextHelper {
|
||||
* @param bookMetadata <p>Metadata about the book to save</p>
|
||||
* @throws IOException <p>If unable to save the book</p>
|
||||
*/
|
||||
public static void bookToYml(String path, String fileName, BookMeta bookMetadata) throws IOException {
|
||||
public static void bookToYml(@NotNull String path, @NotNull String fileName, @NotNull BookMeta bookMetadata) throws IOException {
|
||||
FileConfiguration bookYml = YamlConfiguration.loadConfiguration(new File(path, "blank"));
|
||||
|
||||
if (bookMetadata.hasTitle()) {
|
||||
@@ -58,7 +60,7 @@ public final class BookToFromTextHelper {
|
||||
bookYml.set("Lore", bookMetadata.getLore());
|
||||
}
|
||||
|
||||
bookYml.save(path + fileName + ".yml");
|
||||
bookYml.save(path + fileName.replace("§", "&") + ".yml");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +70,8 @@ public final class BookToFromTextHelper {
|
||||
* @param bookMetadata <p>The book metadata to use for saving the book</p>
|
||||
* @return <p>The book metadata of the loaded book</p>
|
||||
*/
|
||||
public static BookMeta bookFromFile(File file, BookMeta bookMetadata) {
|
||||
@Nullable
|
||||
public static BookMeta bookFromFile(@NotNull File file, @NotNull BookMeta bookMetadata) {
|
||||
if (file.getName().endsWith(".txt")) {
|
||||
return bookFromTXT(file.getName(), file, bookMetadata);
|
||||
} else if (file.getName().endsWith(".yml")) {
|
||||
@@ -86,8 +89,8 @@ public final class BookToFromTextHelper {
|
||||
* @param bookMetadata <p>Metadata about the book to save</p>
|
||||
* @throws IOException <p>If unable to save the book</p>
|
||||
*/
|
||||
public static void bookToTXT(String folderPath, String fileName, BookMeta bookMetadata) throws IOException {
|
||||
FileWriter fileWriter = new FileWriter(folderPath + fileName + ".txt", StandardCharsets.UTF_8);
|
||||
public static void bookToTXT(@NotNull String folderPath, @NotNull String fileName, @NotNull BookMeta bookMetadata) throws IOException {
|
||||
FileWriter fileWriter = new FileWriter(folderPath + fileName.replace("§", "&") + ".txt", StandardCharsets.UTF_8);
|
||||
PrintWriter printWriter = new PrintWriter(fileWriter);
|
||||
List<String> pages = bookMetadata.getPages();
|
||||
|
||||
@@ -112,7 +115,8 @@ public final class BookToFromTextHelper {
|
||||
* @param bookMetadata <p>Metadata which will be altered with the book's contents</p>
|
||||
* @return <p>Metadata for the loaded book</p>
|
||||
*/
|
||||
private static BookMeta bookFromYml(File file, BookMeta bookMetadata) {
|
||||
@Nullable
|
||||
private static BookMeta bookFromYml(@NotNull File file, @NotNull BookMeta bookMetadata) {
|
||||
try {
|
||||
FileConfiguration bookYml = YamlConfiguration.loadConfiguration(file);
|
||||
|
||||
@@ -135,7 +139,8 @@ public final class BookToFromTextHelper {
|
||||
* @param bookMetadata <p>Metadata which will be altered with the book's contents</p>
|
||||
* @return <p>Metadata for the loaded book</p>
|
||||
*/
|
||||
private static BookMeta bookFromTXT(String fileName, File file, BookMeta bookMetadata) {
|
||||
@Nullable
|
||||
private static BookMeta bookFromTXT(@NotNull String fileName, @NotNull File file, @NotNull BookMeta bookMetadata) {
|
||||
String author;
|
||||
String title;
|
||||
String titleAuthorSeparator = BooksWithoutBordersConfig.getTitleAuthorSeparator();
|
||||
@@ -188,7 +193,8 @@ public final class BookToFromTextHelper {
|
||||
* @return <p>A string list where each string is the text on one page</p>
|
||||
* @throws IOException <p>If unable to read from the file</p>
|
||||
*/
|
||||
private static List<String> readTextFile(File file) throws IOException {
|
||||
@Nullable
|
||||
private static List<String> readTextFile(@NotNull File file) throws IOException {
|
||||
List<String> rawPages = new ArrayList<>();
|
||||
BufferedReader bufferedReader = FileHelper.getBufferedReaderFromInputStream(new FileInputStream(file));
|
||||
|
||||
|
@@ -1,7 +1,12 @@
|
||||
package net.knarcraft.bookswithoutborders.utility;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Helper class for cleaning input and names
|
||||
@@ -58,4 +63,41 @@ public final class InputCleaningHelper {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user