Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
3e3b8e7ad2 | |||
b2ce31234d | |||
e5aaa29c66 | |||
f9674568ba | |||
2203037b00 | |||
6b44ada84a | |||
9f979dd56e | |||
10ffd17c04 | |||
0aff3fad02 | |||
32d31fced6 | |||
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>
|
||||
|
@@ -18,11 +18,13 @@ import net.knarcraft.bookswithoutborders.command.CommandSave;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSavePublic;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetAuthor;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetBookPrice;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetBookshelfData;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetGeneration;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetLore;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetTitle;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandUnSign;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.handler.BookshelfHandler;
|
||||
import net.knarcraft.bookswithoutborders.listener.BookEventListener;
|
||||
import net.knarcraft.bookswithoutborders.listener.BookshelfListener;
|
||||
import net.knarcraft.bookswithoutborders.listener.PlayerEventListener;
|
||||
@@ -39,12 +41,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;
|
||||
|
||||
@@ -59,16 +64,20 @@ import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig
|
||||
public class BooksWithoutBorders extends JavaPlugin {
|
||||
|
||||
private static ItemFactory itemFactory;
|
||||
private static Map<UUID, List<String>> playerBooksList;
|
||||
private static List<String> publicBooksList;
|
||||
private static @NotNull Map<UUID, List<String>> playerBooksList = new HashMap<>();
|
||||
private static @NotNull List<String> publicBooksList = new ArrayList<>();
|
||||
private static Map<Character, Integer> publicLetterIndex;
|
||||
private static Map<UUID, Map<Character, Integer>> playerLetterIndex;
|
||||
private static BooksWithoutBorders booksWithoutBorders;
|
||||
private static ConsoleCommandSender consoleSender;
|
||||
private static BookshelfHandler bookshelfHandler;
|
||||
|
||||
/**
|
||||
* Gets the console sender for printing to the console
|
||||
*
|
||||
* @return <p>The console's console sender</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static ConsoleCommandSender getConsoleSender() {
|
||||
return consoleSender;
|
||||
}
|
||||
@@ -80,36 +89,70 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
* @param getPublic <p>Whether to get available public books</p>
|
||||
* @return <p>A list of available books</p>
|
||||
*/
|
||||
public static List<String> getAvailableBooks(CommandSender sender, boolean getPublic) {
|
||||
@NotNull
|
||||
public static List<String> getAvailableBooks(@NotNull CommandSender sender, boolean getPublic) {
|
||||
if (getPublic) {
|
||||
return new ArrayList<>(publicBooksList);
|
||||
} else if (sender instanceof Player player) {
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
if (!playerBooksList.containsKey(playerUUID)) {
|
||||
List<String> newFiles = BookFileHelper.listFiles(sender, false);
|
||||
playerBooksList.put(playerUUID, newFiles);
|
||||
if (newFiles != null) {
|
||||
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 (newFiles == null) {
|
||||
return;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears book data such as per-player lists and per-player character indexes
|
||||
*/
|
||||
public static void clearBookData() {
|
||||
playerBooksList = new HashMap<>();
|
||||
playerLetterIndex = new HashMap<>();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
FileConfiguration config = this.getConfig();
|
||||
@@ -123,8 +166,15 @@ 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);
|
||||
@Nullable List<String> files = BookFileHelper.listFiles(consoleSender, true);
|
||||
if (files != null) {
|
||||
publicBooksList = files;
|
||||
publicLetterIndex = BookFileHelper.populateLetterIndices(files);
|
||||
}
|
||||
bookshelfHandler = new BookshelfHandler();
|
||||
bookshelfHandler.load();
|
||||
|
||||
PluginManager pluginManager = this.getServer().getPluginManager();
|
||||
|
||||
@@ -148,6 +198,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
*
|
||||
* @return <p>An instance of this plugin</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static BooksWithoutBorders getInstance() {
|
||||
return booksWithoutBorders;
|
||||
}
|
||||
@@ -178,6 +229,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
registerCommand("formatBook", new CommandFormat());
|
||||
registerCommand("setBookGeneration", new CommandSetGeneration());
|
||||
registerCommand("clearBook", new CommandClear());
|
||||
registerCommand("setBookshelfData", new CommandSetBookshelfData());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +238,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
* @param commandName <p>The name of the command to register</p>
|
||||
* @param executor <p>The executor to register for the command</p>
|
||||
*/
|
||||
private void registerCommand(String commandName, CommandExecutor executor) {
|
||||
private void registerCommand(@NotNull String commandName, @NotNull CommandExecutor executor) {
|
||||
PluginCommand pluginCommand = this.getCommand(commandName);
|
||||
if (pluginCommand != null) {
|
||||
pluginCommand.setExecutor(executor);
|
||||
@@ -222,11 +274,21 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
return testFileSaving();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bookshelf handler
|
||||
*
|
||||
* @return <p>The bookshelf handler</p>
|
||||
*/
|
||||
public static BookshelfHandler getBookshelfHandler() {
|
||||
return bookshelfHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server's item factory
|
||||
*
|
||||
* @return <p>The server's item factory</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static ItemFactory getItemFactory() {
|
||||
return itemFactory;
|
||||
}
|
||||
@@ -270,7 +332,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
* @param sender <p>The sender to send the message to</p>
|
||||
* @param message <p>The message to send</p>
|
||||
*/
|
||||
public static void sendSuccessMessage(CommandSender sender, String message) {
|
||||
public static void sendSuccessMessage(@NotNull CommandSender sender, @NotNull String message) {
|
||||
sender.sendMessage(getSuccessColor() + message);
|
||||
}
|
||||
|
||||
@@ -280,7 +342,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
* @param sender <p>The sender to send the message to</p>
|
||||
* @param message <p>The message to send</p>
|
||||
*/
|
||||
public static void sendErrorMessage(CommandSender sender, String message) {
|
||||
public static void sendErrorMessage(@NotNull CommandSender sender, @NotNull String message) {
|
||||
sender.sendMessage(getErrorColor() + message);
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,7 @@ import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig
|
||||
public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(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[] args) {
|
||||
sender.sendMessage(getCommandColor() + "[] denote optional parameters");
|
||||
sender.sendMessage(getCommandColor() + "<> denote required parameters");
|
||||
sender.sendMessage(getCommandColor() + "{} denote required permission");
|
||||
@@ -42,7 +42,7 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
*
|
||||
* @param sender <p>The console which sent the command</p>
|
||||
*/
|
||||
private void showConsoleCommands(CommandSender sender) {
|
||||
private void showConsoleCommands(@NotNull CommandSender sender) {
|
||||
sender.sendMessage(getCommandColor() + "Commands:");
|
||||
showCommandInfo("deletePublicBook", sender);
|
||||
showCommandInfo("givePublicBook", sender);
|
||||
@@ -54,7 +54,7 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
*
|
||||
* @param sender <p>The player which sent the command</p>
|
||||
*/
|
||||
private void showPlayerCommands(CommandSender sender) {
|
||||
private void showPlayerCommands(@NotNull CommandSender sender) {
|
||||
//Lists all commands
|
||||
Material bookPriceType = BooksWithoutBordersConfig.getBookPriceType();
|
||||
double bookPriceQuantity = BooksWithoutBordersConfig.getBookPriceQuantity();
|
||||
@@ -69,6 +69,7 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
}
|
||||
sender.sendMessage(getCommandColor() + "Commands:");
|
||||
|
||||
showCommandInfo("booksWithoutBorders", sender);
|
||||
showCommandInfo("copyBook", sender);
|
||||
showCommandInfo("decryptBook", sender);
|
||||
showCommandInfo("deleteBook", sender);
|
||||
@@ -89,6 +90,8 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
showCommandInfo("setLore", sender);
|
||||
showCommandInfo("setTitle", sender);
|
||||
showCommandInfo("unsignBook", sender);
|
||||
showCommandInfo("clearBook", sender);
|
||||
showCommandInfo("setBookshelfData", sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +100,7 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
* @param command <p>The command to get information about</p>
|
||||
* @param sender <p>The sender asking to see command info</p>
|
||||
*/
|
||||
private void showCommandInfo(String command, CommandSender sender) {
|
||||
private void showCommandInfo(@NotNull String command, @NotNull CommandSender sender) {
|
||||
PluginCommand pluginCommand = BooksWithoutBorders.getInstance().getCommand(command);
|
||||
if (pluginCommand != null) {
|
||||
String permission = pluginCommand.getPermission();
|
||||
@@ -116,7 +119,8 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
@@ -51,7 +51,7 @@ public class CommandClear implements TabExecutor {
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,8 @@ import java.util.Objects;
|
||||
public class CommandCopy 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 player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
@@ -37,14 +38,14 @@ public class CommandCopy implements TabExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
if (arguments.length < 1) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "You must specify the number of copies to be made!");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
ItemStack heldBook = InventoryHelper.getHeldBook(player, true);
|
||||
int copies = Integer.parseInt(args[0]);
|
||||
int copies = Integer.parseInt(arguments[0]);
|
||||
if (copies <= 0) {
|
||||
throw new NumberFormatException("Number of copies must be larger than 0");
|
||||
}
|
||||
@@ -64,7 +65,7 @@ public class CommandCopy implements TabExecutor {
|
||||
* @param heldBook <p>The book to be copied</p>
|
||||
* @return <p>True if the copying was successful</p>
|
||||
*/
|
||||
private boolean performCopy(int copies, Player player, ItemStack heldBook) {
|
||||
private boolean performCopy(int copies, @NotNull Player player, @NotNull ItemStack heldBook) {
|
||||
//Make sure the player owns the book if authorOnlyCopy is enabled
|
||||
if (BooksWithoutBordersConfig.getAuthorOnlyCopy() &&
|
||||
!player.hasPermission("bookswithoutborders.bypassAuthorOnlyCopy")) {
|
||||
@@ -95,7 +96,7 @@ public class CommandCopy implements TabExecutor {
|
||||
* @param copies <p>The number of copies to create for the player</p>
|
||||
* @return <p>True if the payment failed</p>
|
||||
*/
|
||||
private boolean paymentUnSuccessful(Player player, int copies) {
|
||||
private boolean paymentUnSuccessful(@NotNull Player player, int copies) {
|
||||
return BooksWithoutBordersConfig.booksHavePrice() &&
|
||||
!player.hasPermission("bookswithoutborders.bypassBookPrice") &&
|
||||
EconomyHelper.cannotPayForBookPrinting(player, copies);
|
||||
@@ -109,7 +110,7 @@ public class CommandCopy implements TabExecutor {
|
||||
* @param copies <p>The number of copies requested</p>
|
||||
* @return <p>True if the book was successfully copied</p>
|
||||
*/
|
||||
private boolean copyNextGenerationBook(BookMeta bookMeta, Player player, int copies) {
|
||||
private boolean copyNextGenerationBook(@NotNull BookMeta bookMeta, @NotNull Player player, int copies) {
|
||||
//Copy the vanilla behavior of refusing copying any further
|
||||
if (bookMeta.getGeneration() == BookMeta.Generation.COPY_OF_COPY ||
|
||||
bookMeta.getGeneration() == BookMeta.Generation.TATTERED) {
|
||||
@@ -140,10 +141,10 @@ public class CommandCopy implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] args) {
|
||||
int argumentCount = args.length;
|
||||
@NotNull String[] arguments) {
|
||||
int argumentCount = arguments.length;
|
||||
if (argumentCount == 1) {
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getNumbers(1, 20), args[0]);
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getNumbers(1, 20), arguments[0]);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
@@ -99,8 +99,9 @@ public class CommandDecrypt implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
int argumentCount = args.length;
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
int argumentCount = arguments.length;
|
||||
if (argumentCount == 1) {
|
||||
List<String> info = new ArrayList<>();
|
||||
info.add("<password>");
|
||||
|
@@ -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,35 @@ 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);
|
||||
protected 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;
|
||||
@@ -68,7 +70,7 @@ public class CommandDelete implements TabExecutor {
|
||||
* @param fileName <p>The file name of the book</p>
|
||||
* @param isPublic <p>Whether the book to delete is public or not</p>
|
||||
*/
|
||||
public void performBookDeletion(CommandSender sender, String fileName, Boolean isPublic) {
|
||||
public void performBookDeletion(@NotNull CommandSender sender, @NotNull String fileName, @NotNull Boolean isPublic) {
|
||||
//If the file name is an index of the load list, load the book
|
||||
try {
|
||||
int loadListIndex = Integer.parseInt(fileName);
|
||||
@@ -103,8 +105,9 @@ public class CommandDelete implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
return doTabCompletion(sender, args, false);
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return doTabCompletion(sender, arguments, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,7 +118,8 @@ public class CommandDelete implements TabExecutor {
|
||||
* @param deletePublic <p>Whether to delete a public book</p>
|
||||
* @return <p>A list of available arguments</p>
|
||||
*/
|
||||
protected List<String> doTabCompletion(CommandSender sender, String[] args, boolean deletePublic) {
|
||||
@NotNull
|
||||
protected List<String> doTabCompletion(@NotNull CommandSender sender, @NotNull String[] args, boolean deletePublic) {
|
||||
int argumentCount = args.length;
|
||||
if (argumentCount == 1) {
|
||||
return TabCompletionHelper.filterMatchingContains(BooksWithoutBorders.getAvailableBooks(sender, deletePublic),
|
||||
|
@@ -13,13 +13,13 @@ 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
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
return doTabCompletion(sender, args, true);
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] arguments) {
|
||||
return doTabCompletion(sender, arguments, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ 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;
|
||||
@@ -23,25 +24,28 @@ import java.util.List;
|
||||
public class CommandEncrypt implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (performPreChecks(sender, args, 1, "You must specify a key to encrypt a book!") == null) {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] arguments) {
|
||||
if (performPreChecks(sender, arguments, 1, "You must specify a key to encrypt a book!") == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EncryptionStyle encryptionStyle = args.length == 2 ? EncryptionStyle.getFromString(args[1]) : EncryptionStyle.SUBSTITUTION;
|
||||
return encryptBook(encryptionStyle, (Player) sender, args[0], "");
|
||||
EncryptionStyle encryptionStyle = arguments.length == 2 ? EncryptionStyle.getFromString(arguments[1]) : EncryptionStyle.SUBSTITUTION;
|
||||
return encryptBook(encryptionStyle, (Player) sender, arguments[0], "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs necessary pre-checks before going through with the encryption
|
||||
*
|
||||
* @param sender <p>The sender trying to encrypt a book</p>
|
||||
* @param args <p>The arguments given</p>
|
||||
* @param arguments <p>The arguments given</p>
|
||||
* @param necessaryArguments <p>How many arguments is the minimum requirement</p>
|
||||
* @param missingArgumentsError <p>The error to show if a required argument is missing</p>
|
||||
* @return <p>The metadata of the book to encrypt, or null if any checks fail</p>
|
||||
*/
|
||||
BookMeta performPreChecks(CommandSender sender, String[] args, int necessaryArguments, String missingArgumentsError) {
|
||||
@Nullable
|
||||
protected BookMeta performPreChecks(@NotNull CommandSender sender, @NotNull String[] arguments,
|
||||
int necessaryArguments, @NotNull String missingArgumentsError) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return null;
|
||||
@@ -53,7 +57,7 @@ public class CommandEncrypt implements TabExecutor {
|
||||
return null;
|
||||
}
|
||||
|
||||
int argumentCount = args.length;
|
||||
int argumentCount = arguments.length;
|
||||
if (argumentCount < necessaryArguments) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, missingArgumentsError);
|
||||
return null;
|
||||
@@ -85,7 +89,8 @@ public class CommandEncrypt implements TabExecutor {
|
||||
* @param group <p>The group to encrypt for</p>
|
||||
* @return <p>True if the book was encrypted successfully</p>
|
||||
*/
|
||||
boolean encryptBook(EncryptionStyle encryptionStyle, Player player, String key, String group) {
|
||||
protected boolean encryptBook(@NotNull EncryptionStyle encryptionStyle, @NotNull Player player, @NotNull String key,
|
||||
@NotNull String group) {
|
||||
ItemSlot heldSlot = InventoryHelper.getHeldSlotBook(player, false, false, true, true);
|
||||
ItemStack encryptedBook = EncryptionHelper.encryptBook(player, heldSlot == ItemSlot.MAIN_HAND, key, encryptionStyle, group);
|
||||
|
||||
@@ -98,8 +103,10 @@ public class CommandEncrypt implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
return doTabCompletion(args, false);
|
||||
@NotNull
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return doTabCompletion(arguments, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +116,8 @@ public class CommandEncrypt implements TabExecutor {
|
||||
* @param groupEncrypt <p>Whether to auto-complete for group encryption</p>
|
||||
* @return <p>The strings to auto-complete</p>
|
||||
*/
|
||||
protected List<String> doTabCompletion(String[] args, boolean groupEncrypt) {
|
||||
@NotNull
|
||||
protected List<String> doTabCompletion(@NotNull String[] args, boolean groupEncrypt) {
|
||||
int argumentsCount = args.length;
|
||||
|
||||
List<String> encryptionStyles = new ArrayList<>();
|
||||
|
@@ -20,7 +20,8 @@ import java.util.List;
|
||||
public class CommandFormat 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 player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
@@ -32,7 +33,14 @@ public class CommandFormat implements TabExecutor {
|
||||
}
|
||||
|
||||
ItemStack heldBook = InventoryHelper.getHeldBook(player, true);
|
||||
heldBook.setItemMeta(BookFormatter.formatPages((BookMeta) heldBook.getItemMeta()));
|
||||
BookMeta meta = (BookMeta) heldBook.getItemMeta();
|
||||
|
||||
if (meta == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Unable to get metadata from the held book!");
|
||||
return false;
|
||||
}
|
||||
|
||||
heldBook.setItemMeta(BookFormatter.formatPages(meta));
|
||||
|
||||
BooksWithoutBorders.sendSuccessMessage(sender, "Book formatted!");
|
||||
|
||||
@@ -40,7 +48,8 @@ public class CommandFormat implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
@@ -13,6 +13,7 @@ import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -25,48 +26,50 @@ 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, @NotNull String[] arguments, boolean givePublic,
|
||||
@NotNull 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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +103,9 @@ public class CommandGive implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
return doTabCompletion(sender, args, false);
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return doTabCompletion(sender, arguments, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +116,8 @@ public class CommandGive implements TabExecutor {
|
||||
* @param listPublic <p>Whether to list public files or player files</p>
|
||||
* @return <p>A list of available choices</p>
|
||||
*/
|
||||
protected List<String> doTabCompletion(CommandSender sender, String[] args, boolean listPublic) {
|
||||
@Nullable
|
||||
protected List<String> doTabCompletion(@NotNull CommandSender sender, @NotNull String[] args, boolean listPublic) {
|
||||
Server server = booksWithoutBorders.getServer();
|
||||
|
||||
int argumentCount = args.length;
|
||||
@@ -157,8 +162,9 @@ public class CommandGive implements TabExecutor {
|
||||
* @param copies <p>The number of copies the player wants to give</p>
|
||||
* @return <p>True if the book was successfully given</p>
|
||||
*/
|
||||
private boolean loadAndGiveBook(String bookIdentifier, CommandSender sender, Player receivingPlayer,
|
||||
String isSigned, String folder, String copies) throws NumberFormatException {
|
||||
private boolean loadAndGiveBook(@NotNull String bookIdentifier, @NotNull CommandSender sender,
|
||||
@NotNull Player receivingPlayer, @NotNull String isSigned, @NotNull String folder,
|
||||
@NotNull String copies) throws NumberFormatException {
|
||||
String bookToLoad = InputCleaningHelper.cleanString(bookIdentifier);
|
||||
ItemStack newBook = BookLoader.loadBook(sender, bookToLoad, isSigned, folder, Integer.parseInt(copies));
|
||||
if (newBook != null) {
|
||||
|
@@ -4,6 +4,7 @@ import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -13,13 +14,16 @@ 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,
|
||||
@NotNull String[] arguments) {
|
||||
return giveBook(sender, arguments, true, "public");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
return doTabCompletion(sender, args, true);
|
||||
@Nullable
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return doTabCompletion(sender, arguments, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -17,8 +17,9 @@ import java.util.List;
|
||||
public class CommandGroupEncrypt extends CommandEncrypt implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
BookMeta bookMetadata = performPreChecks(sender, args, 2,
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] arguments) {
|
||||
BookMeta bookMetadata = performPreChecks(sender, arguments, 2,
|
||||
"You must specify a group name and key to encrypt a book!");
|
||||
|
||||
if (bookMetadata == null) {
|
||||
@@ -32,13 +33,14 @@ public class CommandGroupEncrypt extends CommandEncrypt implements TabExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
EncryptionStyle encryptionStyle = args.length == 3 ? EncryptionStyle.getFromString(args[2]) : EncryptionStyle.SUBSTITUTION;
|
||||
return encryptBook(encryptionStyle, (Player) sender, args[1], args[0]);
|
||||
EncryptionStyle encryptionStyle = arguments.length == 3 ? EncryptionStyle.getFromString(arguments[2]) : EncryptionStyle.SUBSTITUTION;
|
||||
return encryptBook(encryptionStyle, (Player) sender, arguments[1], arguments[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
return doTabCompletion(args, true);
|
||||
public @NotNull List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
||||
@NotNull String alias, @NotNull String[] arguments) {
|
||||
return doTabCompletion(arguments, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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,22 @@ 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 +48,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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,32 +96,34 @@ public class CommandLoad implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
return doTabCompletion(sender, args, false);
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return doTabCompletion(sender, arguments, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual tab completion
|
||||
*
|
||||
* @param sender <p>The sender of the command</p>
|
||||
* @param args <p>The arguments given</p>
|
||||
* @param arguments <p>The arguments given</p>
|
||||
* @param loadPublic <p>Whether to list public files or player files</p>
|
||||
* @return <p>A list of available choices</p>
|
||||
*/
|
||||
protected List<String> doTabCompletion(CommandSender sender, String[] args, boolean loadPublic) {
|
||||
int argumentCount = args.length;
|
||||
@NotNull
|
||||
protected List<String> doTabCompletion(@NotNull CommandSender sender, @NotNull String[] arguments, boolean loadPublic) {
|
||||
int argumentCount = arguments.length;
|
||||
if (argumentCount == 1) {
|
||||
//Return list of books
|
||||
return TabCompletionHelper.filterMatchingContains(BooksWithoutBorders.getAvailableBooks(sender, loadPublic),
|
||||
args[0]);
|
||||
arguments[0]);
|
||||
} else if (argumentCount == 2) {
|
||||
//Number of copies
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getBooleansAndNumbers(1, 3), args[1]);
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getBooleansAndNumbers(1, 3), arguments[1]);
|
||||
} else if (argumentCount == 3) {
|
||||
//Signed
|
||||
try {
|
||||
Integer.parseInt(args[1]);
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getBooleans(), args[2]);
|
||||
Integer.parseInt(arguments[1]);
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getBooleans(), arguments[2]);
|
||||
} catch (NumberFormatException e) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
@@ -13,13 +13,15 @@ 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,
|
||||
@NotNull String[] arguments) {
|
||||
return loadBook(sender, arguments, "public", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
return doTabCompletion(sender, args, true);
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return doTabCompletion(sender, arguments, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,18 +16,24 @@ import java.util.List;
|
||||
public class CommandReload 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 (BooksWithoutBordersConfig.loadConfig()) {
|
||||
BooksWithoutBorders.sendSuccessMessage(sender, "BooksWithoutBorders configuration reloaded!");
|
||||
} else {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Reload Failed!");
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "See console for details");
|
||||
}
|
||||
|
||||
// Reload books
|
||||
BooksWithoutBorders.updateBooks(sender, true);
|
||||
BooksWithoutBorders.clearBookData();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
@@ -32,28 +33,28 @@ import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig
|
||||
public class CommandSave implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
return saveHeldBook(sender, args, false);
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] arguments) {
|
||||
return saveHeldBook(sender, arguments, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the player's held book if it exists
|
||||
*
|
||||
* @param sender <p>The sender of the command</p>
|
||||
* @param args <p>The arguments given</p>
|
||||
* @param arguments <p>The arguments given</p>
|
||||
* @param savePublic <p>Whether to save the book in the public directory or the player directory</p>
|
||||
* @return <p>True if a book was saved successfully</p>
|
||||
*/
|
||||
boolean saveHeldBook(CommandSender sender, String[] args, boolean savePublic) {
|
||||
boolean saveHeldBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean savePublic) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemSlot holdingSlot = InventoryHelper.getHeldSlotBook(player, false, false, false, false);
|
||||
if (holdingSlot != null && holdingSlot != ItemSlot.NONE) {
|
||||
if (holdingSlot != ItemSlot.NONE) {
|
||||
ItemStack holdingItem = InventoryHelper.getHeldItem(player, holdingSlot == ItemSlot.MAIN_HAND);
|
||||
boolean duplicate = args.length == 1 && Boolean.parseBoolean(args[0]);
|
||||
boolean duplicate = arguments.length == 1 && Boolean.parseBoolean(arguments[0]);
|
||||
saveBook(player, holdingItem, duplicate, savePublic);
|
||||
return true;
|
||||
} else {
|
||||
@@ -70,7 +71,7 @@ public class CommandSave implements TabExecutor {
|
||||
* @param overwrite <p>Whether to overwrite any existing books</p>
|
||||
* @param saveToPublicFolder <p>Whether to save the book to the public folder instead of the player folder</p>
|
||||
*/
|
||||
public void saveBook(Player player, ItemStack heldBook, boolean overwrite, boolean saveToPublicFolder) {
|
||||
public void saveBook(@NotNull Player player, @NotNull ItemStack heldBook, boolean overwrite, boolean saveToPublicFolder) {
|
||||
BookMeta book = (BookMeta) heldBook.getItemMeta();
|
||||
if (book == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Unable to get metadata for your held book!");
|
||||
@@ -87,8 +88,19 @@ 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);
|
||||
String fileName;
|
||||
try {
|
||||
fileName = BookHelper.getBookFile(book, player, saveToPublicFolder);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, exception.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
//Make sure the used folders exist
|
||||
File file = new File(savePath);
|
||||
@@ -142,7 +154,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");
|
||||
}
|
||||
@@ -150,8 +162,9 @@ public class CommandSave implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] args) {
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
@@ -11,8 +11,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class CommandSavePublic extends CommandSave implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
return saveHeldBook(sender, args, true);
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] arguments) {
|
||||
return saveHeldBook(sender, arguments, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ 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;
|
||||
@@ -22,13 +23,14 @@ import java.util.List;
|
||||
public class CommandSetAuthor 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 player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
if (arguments.length < 1) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Too few command arguments!");
|
||||
return false;
|
||||
}
|
||||
@@ -43,8 +45,12 @@ public class CommandSetAuthor implements TabExecutor {
|
||||
boolean mainHand = heldBookSlot == ItemSlot.MAIN_HAND;
|
||||
ItemStack heldBook = InventoryHelper.getHeldItem(player, mainHand);
|
||||
BookMeta bookMetaData = InventoryHelper.getHeldBookMetadata(player, mainHand);
|
||||
if (bookMetaData == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Unable to get metadata for the held book!");
|
||||
return false;
|
||||
}
|
||||
|
||||
String author = ColorHelper.translateColorCodes(String.join(" ", args), ColorConversion.RGB);
|
||||
String author = ColorHelper.translateColorCodes(String.join(" ", arguments), ColorConversion.RGB);
|
||||
bookMetaData.setAuthor(author);
|
||||
heldBook.setItemMeta(bookMetaData);
|
||||
BooksWithoutBorders.sendSuccessMessage(player, "Book author set to " + author + "!");
|
||||
@@ -52,8 +58,10 @@ public class CommandSetAuthor implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
if (args.length == 1) {
|
||||
@Nullable
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
return null;
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
|
@@ -26,35 +26,36 @@ public class CommandSetBookPrice implements TabExecutor {
|
||||
private List<String> paymentTypes;
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] arguments) {
|
||||
//Clear the current price
|
||||
if (args.length == 0) {
|
||||
if (arguments.length == 0) {
|
||||
clearItemPrice(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
//Warn about missing arguments
|
||||
if (args.length < 2) {
|
||||
if (arguments.length < 2) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "[Item/Eco] and [quantity] must be specified!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Warn about invalid argument
|
||||
if (!args[0].equalsIgnoreCase("Item") && !args[0].equalsIgnoreCase("Eco")) {
|
||||
if (!arguments[0].equalsIgnoreCase("Item") && !arguments[0].equalsIgnoreCase("Eco")) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Price type must be \"Item\" or \"Eco\"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
double price = Double.parseDouble(args[1]);
|
||||
double price = Double.parseDouble(arguments[1]);
|
||||
if (price <= 0) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "[quantity] must be greater than 0!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args[0].equalsIgnoreCase("Item")) {
|
||||
if (arguments[0].equalsIgnoreCase("Item")) {
|
||||
return setItemPrice(sender, price);
|
||||
} else if (args[0].equalsIgnoreCase("Eco")) {
|
||||
} else if (arguments[0].equalsIgnoreCase("Eco")) {
|
||||
return setEconomyPrice(sender, price);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
@@ -68,7 +69,7 @@ public class CommandSetBookPrice implements TabExecutor {
|
||||
*
|
||||
* @param sender <p>The sender of the command</p>
|
||||
*/
|
||||
private void clearItemPrice(CommandSender sender) {
|
||||
private void clearItemPrice(@NotNull CommandSender sender) {
|
||||
BooksWithoutBordersConfig.setBookPriceType(null);
|
||||
BooksWithoutBordersConfig.setBookPriceQuantity(0);
|
||||
booksWithoutBorders.getConfig().set("Options.Price_to_create_book.Item_type", "Item type name");
|
||||
@@ -85,7 +86,7 @@ public class CommandSetBookPrice implements TabExecutor {
|
||||
* @param price <p>The new price</p>
|
||||
* @return <p>True if the price was changed successfully</p>
|
||||
*/
|
||||
private boolean setItemPrice(CommandSender sender, double price) {
|
||||
private boolean setItemPrice(@NotNull CommandSender sender, double price) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "[Item] price can only be used by a player!");
|
||||
return false;
|
||||
@@ -117,7 +118,7 @@ public class CommandSetBookPrice implements TabExecutor {
|
||||
* @param price <p>The new price</p>
|
||||
* @return <p>True if the price was changed successfully</p>
|
||||
*/
|
||||
private boolean setEconomyPrice(CommandSender sender, double price) {
|
||||
private boolean setEconomyPrice(@NotNull CommandSender sender, double price) {
|
||||
if (EconomyHelper.setupEconomy()) {
|
||||
BooksWithoutBordersConfig.setBookPriceQuantity(price);
|
||||
BooksWithoutBordersConfig.setBookPriceType(Material.AIR);
|
||||
@@ -136,16 +137,17 @@ public class CommandSetBookPrice implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
if (paymentTypes == null) {
|
||||
initializeTabCompleteLists();
|
||||
}
|
||||
|
||||
int argumentCount = args.length;
|
||||
int argumentCount = arguments.length;
|
||||
if (argumentCount == 1) {
|
||||
return TabCompletionHelper.filterMatchingStartsWith(paymentTypes, args[0]);
|
||||
return TabCompletionHelper.filterMatchingStartsWith(paymentTypes, arguments[0]);
|
||||
} else if (argumentCount == 2) {
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getNumbers(1, 3), args[1]);
|
||||
return TabCompletionHelper.filterMatchingStartsWith(TabCompletionTypeHelper.getNumbers(1, 3), arguments[1]);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
@@ -0,0 +1,111 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.container.Bookshelf;
|
||||
import net.knarcraft.bookswithoutborders.handler.BookshelfHandler;
|
||||
import net.knarcraft.knarlib.util.TabCompletionHelper;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The command for setting information for a chiseled bookshelf
|
||||
*/
|
||||
public class CommandSetBookshelfData implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
if (!(commandSender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "This command must be used by a player!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Block targetBlock = player.getTargetBlockExact(7);
|
||||
if (targetBlock == null || targetBlock.getType() != Material.CHISELED_BOOKSHELF) {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "You are not looking at a bookshelf!");
|
||||
return false;
|
||||
}
|
||||
|
||||
BookshelfHandler shelfHandler = BooksWithoutBorders.getBookshelfHandler();
|
||||
Bookshelf bookshelf = shelfHandler.getFromLocation(targetBlock.getLocation());
|
||||
|
||||
if (arguments.length < 2) {
|
||||
if (arguments.length == 1 && arguments[0].equalsIgnoreCase("delete")) {
|
||||
if (bookshelf != null) {
|
||||
shelfHandler.unregisterBookshelf(bookshelf);
|
||||
shelfHandler.save();
|
||||
BooksWithoutBorders.sendSuccessMessage(commandSender, "Bookshelf successfully deleted");
|
||||
} else {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "The block you are looking at is not a registered bookshelf");
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 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]);
|
||||
}
|
||||
|
||||
switch (arguments[0].toLowerCase()) {
|
||||
case "name":
|
||||
if (bookshelf == null) {
|
||||
Bookshelf newShelf = new Bookshelf(targetBlock.getLocation(), arguments[1], new ArrayList<>());
|
||||
shelfHandler.registerBookshelf(newShelf);
|
||||
} else {
|
||||
bookshelf.setTitle(builder.toString());
|
||||
}
|
||||
shelfHandler.save();
|
||||
BooksWithoutBorders.sendSuccessMessage(commandSender, "Title successfully saved");
|
||||
return true;
|
||||
case "lore":
|
||||
if (bookshelf == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "You must name the bookshelf before " +
|
||||
"assigning lore!");
|
||||
} else {
|
||||
List<String> loreParts = Arrays.asList(builder.toString().split(BooksWithoutBordersConfig.getLoreSeparator()));
|
||||
bookshelf.setLore(loreParts);
|
||||
shelfHandler.save();
|
||||
BooksWithoutBorders.sendSuccessMessage(commandSender, "Lore successfully saved");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
return TabCompletionHelper.filterMatchingStartsWith(List.of("delete", "name", "lore"), arguments[0]);
|
||||
} else if (arguments.length == 2) {
|
||||
return switch (arguments[0].toLowerCase()) {
|
||||
case "delete" -> new ArrayList<>();
|
||||
case "name" ->
|
||||
TabCompletionHelper.filterMatchingStartsWith(List.of("Epic Title", "Lame Title"), arguments[1]);
|
||||
case "lore" ->
|
||||
TabCompletionHelper.filterMatchingStartsWith(List.of("Interesting lore", "Line1~Line2~Line3"), arguments[1]);
|
||||
default -> null;
|
||||
};
|
||||
} else {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -21,7 +21,7 @@ public class CommandSetGeneration implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
@NotNull String[] arguments) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
@@ -32,14 +32,14 @@ public class CommandSetGeneration implements TabExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
if (arguments.length < 1) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "You must specify the new generation for your book!");
|
||||
return false;
|
||||
}
|
||||
|
||||
BookMeta.Generation generation;
|
||||
try {
|
||||
generation = BookMeta.Generation.valueOf(args[0]);
|
||||
generation = BookMeta.Generation.valueOf(arguments[0]);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Invalid book generation specified!");
|
||||
return false;
|
||||
@@ -60,8 +60,8 @@ public class CommandSetGeneration implements TabExecutor {
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
if (args.length == 1) {
|
||||
@NotNull String[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
List<String> generations = new ArrayList<>();
|
||||
for (BookMeta.Generation generation : BookMeta.Generation.values()) {
|
||||
generations.add(generation.name());
|
||||
|
@@ -24,13 +24,14 @@ import java.util.List;
|
||||
public class CommandSetLore 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 player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
if (arguments.length < 1) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Missing a command argument!");
|
||||
return false;
|
||||
}
|
||||
@@ -42,12 +43,11 @@ public class CommandSetLore implements TabExecutor {
|
||||
}
|
||||
|
||||
//Treat all arguments as lore input
|
||||
String rawLore = String.join(" ", args);
|
||||
String rawLore = String.join(" ", arguments);
|
||||
|
||||
//Format lore
|
||||
rawLore = ColorHelper.translateColorCodes(rawLore, ColorConversion.RGB);
|
||||
String[] loreParts = rawLore.split(BooksWithoutBordersConfig.getLoreSeparator());
|
||||
List<String> newLore = new ArrayList<>(Arrays.asList(loreParts));
|
||||
List<String> newLore = Arrays.asList(rawLore.split(BooksWithoutBordersConfig.getLoreSeparator()));
|
||||
|
||||
//Update lore
|
||||
ItemMeta meta = heldItem.getItemMeta();
|
||||
@@ -62,7 +62,8 @@ public class CommandSetLore implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
//TODO: Figure out if there is a better way to display that an argument is required
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("<new lore>");
|
||||
|
@@ -24,13 +24,13 @@ public class CommandSetTitle implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
@NotNull String[] arguments) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
if (arguments.length < 1) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Too few command arguments!");
|
||||
return false;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ public class CommandSetTitle implements TabExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
String title = String.join(" ", args);
|
||||
String title = String.join(" ", arguments);
|
||||
title = ColorHelper.translateColorCodes(title, ColorConversion.RGB);
|
||||
|
||||
ItemMeta itemMetadata = heldItem.getItemMeta();
|
||||
@@ -69,7 +69,7 @@ public class CommandSetTitle implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] args) {
|
||||
@NotNull String[] arguments) {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("<new title>");
|
||||
return options;
|
||||
|
@@ -26,7 +26,8 @@ import java.util.logging.Level;
|
||||
public class CommandUnSign 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 player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
@@ -49,9 +50,13 @@ public class CommandUnSign implements TabExecutor {
|
||||
* @param player <p>The player holding the book</p>
|
||||
* @param mainHand <p>Whether the player is holding the book in its main hand or its off hand</p>
|
||||
*/
|
||||
public void unSignHeldBook(Player player, boolean mainHand) {
|
||||
public void unSignHeldBook(@NotNull Player player, boolean mainHand) {
|
||||
//Get the old book
|
||||
BookMeta oldMetadata = InventoryHelper.getHeldBookMetadata(player, mainHand);
|
||||
if (oldMetadata == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Unable to get metadata from the held book!");
|
||||
return;
|
||||
}
|
||||
ItemStack heldBook = InventoryHelper.getHeldBook(player, mainHand);
|
||||
|
||||
//Only allow the owner to un-sign the book
|
||||
@@ -85,7 +90,9 @@ public class CommandUnSign implements TabExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
@NotNull
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@ import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.util.ArrayList;
|
||||
@@ -48,7 +49,7 @@ public class BooksWithoutBordersConfig {
|
||||
*
|
||||
* @param booksWithoutBorders <p>The books without borders object used for getting required data</p>
|
||||
*/
|
||||
public static void initialize(BooksWithoutBorders booksWithoutBorders) {
|
||||
public static void initialize(@NotNull BooksWithoutBorders booksWithoutBorders) {
|
||||
if (isInitialized) {
|
||||
throw new IllegalArgumentException("Settings class initialized twice. This should not happen!");
|
||||
}
|
||||
@@ -388,7 +389,7 @@ public class BooksWithoutBordersConfig {
|
||||
* @param configOption <p>The configuration option to get the value for</p>
|
||||
* @return <p>The value of the option</p>
|
||||
*/
|
||||
private static String getString(Configuration config, ConfigOption configOption) {
|
||||
private static String getString(@NotNull Configuration config, @NotNull ConfigOption configOption) {
|
||||
return config.getString(configOption.getConfigNode(), (String) configOption.getDefaultValue());
|
||||
}
|
||||
|
||||
@@ -399,7 +400,7 @@ public class BooksWithoutBordersConfig {
|
||||
* @param configOption <p>The configuration option to get the value for</p>
|
||||
* @return <p>The value of the option</p>
|
||||
*/
|
||||
private static boolean getBoolean(Configuration config, ConfigOption configOption) {
|
||||
private static boolean getBoolean(@NotNull Configuration config, @NotNull ConfigOption configOption) {
|
||||
return config.getBoolean(configOption.getConfigNode(), (Boolean) configOption.getDefaultValue());
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.config;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A representation of the different available config options
|
||||
*/
|
||||
@@ -90,7 +92,7 @@ public enum ConfigOption {
|
||||
* @param configNode <p>The config node in the config file this option represents</p>
|
||||
* @param defaultValue <p>The default value for this config option</p>
|
||||
*/
|
||||
ConfigOption(String configNode, Object defaultValue) {
|
||||
ConfigOption(@NotNull String configNode, @NotNull Object defaultValue) {
|
||||
this.configNode = configNode;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
@@ -0,0 +1,81 @@
|
||||
package net.knarcraft.bookswithoutborders.container;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A representation of a bookshelf with extra data used when displaying its contents
|
||||
*/
|
||||
public class Bookshelf {
|
||||
|
||||
private final @NotNull Location location;
|
||||
private @NotNull String title;
|
||||
private @NotNull List<String> lore;
|
||||
|
||||
/**
|
||||
* Instantiates a new bookshelf
|
||||
*
|
||||
* @param location <p>The location of the bookshelf</p>
|
||||
* @param title <p>The title of the bookshelf</p>
|
||||
* @param lore <p>The lore of the bookshelf</p>
|
||||
*/
|
||||
public Bookshelf(@NotNull Location location, @NotNull String title, @NotNull List<String> lore) {
|
||||
this.location = location;
|
||||
this.title = title;
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location of this bookshelf
|
||||
*
|
||||
* @return <p>The location of this bookshelf</p>
|
||||
*/
|
||||
@NotNull
|
||||
public Location getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the title of this bookshelf
|
||||
*
|
||||
* @return <p>The title of this bookshelf</p>
|
||||
*/
|
||||
@NotNull
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lore of this bookshelf
|
||||
*
|
||||
* @return <p>The lore of this bookshelf</p>
|
||||
*/
|
||||
@NotNull
|
||||
public List<String> getLore() {
|
||||
return this.lore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of this bookshelf
|
||||
*
|
||||
* @param title <p>The new title</p>
|
||||
*/
|
||||
public void setTitle(@NotNull String title) {
|
||||
if (title.isBlank()) {
|
||||
throw new IllegalArgumentException("Bookshelves cannot have empty titles!");
|
||||
}
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lore of this bookshelf
|
||||
*
|
||||
* @param lore <p>The new lore</p>
|
||||
*/
|
||||
public void setLore(@NotNull List<String> lore) {
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
}
|
@@ -1,6 +1,8 @@
|
||||
package net.knarcraft.bookswithoutborders.encryption;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
@@ -52,7 +54,8 @@ public class AES {
|
||||
* @param encrypt <p>Whether to encrypt or decrypt the input</p>
|
||||
* @return <p>The encrypted/decrypted input, or null if anything went wrong</p>
|
||||
*/
|
||||
public String encryptDecryptText(String input, String password, boolean encrypt) {
|
||||
@Nullable
|
||||
public String encryptDecryptText(@NotNull String input, @NotNull String password, boolean encrypt) {
|
||||
//Make a key from the password
|
||||
SecretKeySpec secretKeySpec = getKeyFromPassword(password);
|
||||
//Get cipher instance
|
||||
@@ -102,7 +105,7 @@ public class AES {
|
||||
* @param encryption <p>Whether the input should be encrypted or decrypted</p>
|
||||
* @return <p>The input in byte format</p>
|
||||
*/
|
||||
private byte[] getInputBytes(String input, boolean encryption) {
|
||||
private byte[] getInputBytes(@NotNull String input, boolean encryption) {
|
||||
if (encryption) {
|
||||
return input.getBytes();
|
||||
} else {
|
||||
@@ -117,6 +120,7 @@ public class AES {
|
||||
* @param encryption <p>Whether the output came from encryption or decryption</p>
|
||||
* @return <p>The output as a string</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String createResult(byte[] output, boolean encryption) {
|
||||
if (encryption) {
|
||||
return Base64.getEncoder().encodeToString(output);
|
||||
@@ -130,6 +134,7 @@ public class AES {
|
||||
*
|
||||
* @return <p>An AES cipher instance, or null if something went wrong</p>
|
||||
*/
|
||||
@Nullable
|
||||
private Cipher getAESCipher() {
|
||||
Cipher aes;
|
||||
try {
|
||||
@@ -147,7 +152,8 @@ public class AES {
|
||||
* @param password <p>A user supplied password</p>
|
||||
* @return <p>A secret key spec or null if something went wrong</p>
|
||||
*/
|
||||
private SecretKeySpec getKeyFromPassword(String password) {
|
||||
@Nullable
|
||||
private SecretKeySpec getKeyFromPassword(@NotNull String password) {
|
||||
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), this.passwordSalt, 1000, 128);
|
||||
SecretKeyFactory keyFactory;
|
||||
try {
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.encryption;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
@@ -24,7 +26,7 @@ public class GenenCrypt {
|
||||
*
|
||||
* @param key <p>The key used to generate the codon table</p>
|
||||
*/
|
||||
public GenenCrypt(String key) {
|
||||
public GenenCrypt(@NotNull String key) {
|
||||
|
||||
// define the initial, unshuffled codon list of 4 base codons
|
||||
ArrayList<String> originalCodonList = new ArrayList<>();
|
||||
@@ -114,7 +116,8 @@ public class GenenCrypt {
|
||||
* @param input <p>The input to encrypt</p>
|
||||
* @return <p>The encrypted input</p>
|
||||
*/
|
||||
public String encrypt(String input) {
|
||||
@NotNull
|
||||
public String encrypt(@NotNull String input) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
// insert junk bases
|
||||
@@ -147,7 +150,8 @@ public class GenenCrypt {
|
||||
* @param input <p>The input to decrypt</p>
|
||||
* @return <p>The decrypted input</p>
|
||||
*/
|
||||
public String decrypt(String input) {
|
||||
@NotNull
|
||||
public String decrypt(@NotNull String input) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
int keyCount = 0;
|
||||
int junk = key.charAt(0);
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.encryption;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
@@ -17,9 +19,10 @@ public class SubstitutionCipher {
|
||||
// using a string for the key, it is converted
|
||||
// a series of offsets that each character in the
|
||||
// original message is offset by
|
||||
public String encrypt(String in, String key) {
|
||||
@NotNull
|
||||
public String encrypt(@NotNull String in, @NotNull String key) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
if (key != null && !key.isEmpty()) {
|
||||
if (!key.isEmpty()) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(key, ", "); // tokenizes the key
|
||||
// converts each number in the key to an integer and adds to an array
|
||||
int[] offsetArray = new int[tokenizer.countTokens()];
|
||||
@@ -53,9 +56,10 @@ public class SubstitutionCipher {
|
||||
// method with a flag for encryption / decryption, but
|
||||
// I'm lazy.
|
||||
@SuppressWarnings("unused")
|
||||
public String decrypt(String in, String key) {
|
||||
@NotNull
|
||||
public String decrypt(@NotNull String in, @NotNull String key) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
if (key != null && !key.isEmpty()) {
|
||||
if (!key.isEmpty()) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(key, ", "); // tokenizes the key
|
||||
// converts each number in the key to an integer and adds to an array
|
||||
int[] offsetArray = new int[tokenizer.countTokens()];
|
||||
@@ -81,7 +85,8 @@ public class SubstitutionCipher {
|
||||
// encryption works just like decryption, but is
|
||||
// vulnerable if the same key is used more than once.
|
||||
@SuppressWarnings("unused")
|
||||
public String oneTimePad(String in, String key) {
|
||||
@NotNull
|
||||
public String oneTimePad(@NotNull String in, @NotNull String key) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
output.append((char) (in.charAt(i) ^ key.charAt(i % key.length())));
|
||||
|
@@ -0,0 +1,87 @@
|
||||
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);
|
||||
componentBuilder.append("\n");
|
||||
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,163 @@
|
||||
package net.knarcraft.bookswithoutborders.gui;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
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;
|
||||
protected final static @NotNull ChatColor interactColor = ChatColor.of("#FFD700");
|
||||
protected final static @NotNull ChatColor inactiveColor = ChatColor.of("#999999");
|
||||
|
||||
/**
|
||||
* 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).color(interactColor).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(inactiveColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
componentBuilder.append("[index] <", ComponentBuilder.FormatRetention.NONE).color(inactiveColor);
|
||||
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(interactColor).event(
|
||||
new ClickEvent(ClickEvent.Action.RUN_COMMAND,
|
||||
"/" + command + " page" + pageIndex)).event(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT, new Text("Books starting with " + character)));
|
||||
} else {
|
||||
componentBuilder.append(character + "", ComponentBuilder.FormatRetention.NONE).color(inactiveColor);
|
||||
}
|
||||
}
|
||||
componentBuilder.append(">", ComponentBuilder.FormatRetention.NONE).color(inactiveColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).color(interactColor)
|
||||
.event(prevPagePreview).event(prevPageClick);
|
||||
} else {
|
||||
componentBuilder.append("Previous [<]", ComponentBuilder.FormatRetention.NONE).color(inactiveColor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).color(interactColor)
|
||||
.event(nextPagePreview).event(nextPageClick);
|
||||
} else {
|
||||
componentBuilder.append("Next [>]", ComponentBuilder.FormatRetention.NONE).color(inactiveColor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
String separator = BooksWithoutBordersConfig.getTitleAuthorSeparator();
|
||||
bookPath = ChatColor.translateAlternateColorCodes('&', bookPath.substring(0, bookPath.length() - 4));
|
||||
if (bookPath.contains(separator)) {
|
||||
String[] parts = bookPath.split(separator);
|
||||
return parts[0].replace("_", " ") + ChatColor.RESET + " by " + parts[1] + ChatColor.RESET;
|
||||
} else {
|
||||
return bookPath + ChatColor.RESET + " by Unknown" + ChatColor.RESET;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,118 @@
|
||||
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 list of books, with the next and previous buttons
|
||||
displayPreviousButton(componentBuilder, command, page);
|
||||
componentBuilder.append("\n");
|
||||
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);
|
||||
componentBuilder.append("\n");
|
||||
|
||||
// Display the alphabet index as the header
|
||||
displayAlphabetIndex(componentBuilder, command, firstInstances);
|
||||
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(interactColor).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("Books by " +
|
||||
BookFormatter.stripColor(parts[1]))));
|
||||
componentBuilder.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
package net.knarcraft.bookswithoutborders.handler;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.container.Bookshelf;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* A handler keeping track of all bookshelves
|
||||
*/
|
||||
public class BookshelfHandler {
|
||||
|
||||
private static final File bookshelfFile = new File(BooksWithoutBorders.getInstance().getDataFolder(),
|
||||
"bookshelves.yml");
|
||||
private Set<Bookshelf> bookshelves;
|
||||
private Map<Location, Bookshelf> locationLookup;
|
||||
|
||||
/**
|
||||
* Gets a bookshelf from the given location
|
||||
*
|
||||
* @param location <p>The location of the bookshelf</p>
|
||||
* @return <p>The bookshelf at the location, or null if no such bookshelf exists</p>
|
||||
*/
|
||||
@Nullable
|
||||
public Bookshelf getFromLocation(@NotNull Location location) {
|
||||
return locationLookup.get(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given bookshelf to this handler
|
||||
*
|
||||
* @param bookshelf <p>The bookshelf to register</p>
|
||||
*/
|
||||
public void registerBookshelf(@NotNull Bookshelf bookshelf) {
|
||||
this.bookshelves.add(bookshelf);
|
||||
this.locationLookup.put(bookshelf.getLocation(), bookshelf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the given bookshelf from this handler
|
||||
*
|
||||
* @param bookshelf <p>The bookshelf to unregister</p>
|
||||
*/
|
||||
public void unregisterBookshelf(@NotNull Bookshelf bookshelf) {
|
||||
this.locationLookup.remove(bookshelf.getLocation());
|
||||
this.bookshelves.remove(bookshelf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all stored bookshelves
|
||||
*/
|
||||
public void load() {
|
||||
this.bookshelves = new HashSet<>();
|
||||
this.locationLookup = new HashMap<>();
|
||||
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(bookshelfFile);
|
||||
ConfigurationSection bookshelfSection = configuration.getConfigurationSection("bookshelves");
|
||||
if (bookshelfSection == null) {
|
||||
BooksWithoutBorders.getInstance().getLogger().log(Level.INFO,
|
||||
"BooksWithoutBorders found no bookshelves to load");
|
||||
return;
|
||||
}
|
||||
|
||||
for (String key : bookshelfSection.getKeys(false)) {
|
||||
String[] locationInfo = key.split(",");
|
||||
World world = Bukkit.getWorld(UUID.fromString(locationInfo[0]));
|
||||
double x = Integer.parseInt(locationInfo[1]);
|
||||
double y = Integer.parseInt(locationInfo[2]);
|
||||
double z = Integer.parseInt(locationInfo[3]);
|
||||
Location bookshelfLocation = new Location(world, x, y, z);
|
||||
|
||||
String titleKey = key + ".title";
|
||||
String loreKey = key + ".lore";
|
||||
|
||||
String title = bookshelfSection.getString(titleKey, null);
|
||||
List<String> loreStrings = new ArrayList<>();
|
||||
List<?> lore = bookshelfSection.getList(loreKey);
|
||||
if (lore == null) {
|
||||
throw new IllegalArgumentException("Lore is missing from bookshelf data!");
|
||||
}
|
||||
lore.forEach((item) -> {
|
||||
if (item instanceof String) {
|
||||
loreStrings.add((String) item);
|
||||
}
|
||||
});
|
||||
|
||||
if (title != null) {
|
||||
registerBookshelf(new Bookshelf(bookshelfLocation, title, loreStrings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves all current bookshelves
|
||||
*/
|
||||
public void save() {
|
||||
try {
|
||||
YamlConfiguration configuration = new YamlConfiguration();
|
||||
ConfigurationSection bookshelfSection = configuration.createSection("bookshelves");
|
||||
for (Bookshelf bookshelf : bookshelves) {
|
||||
saveBookshelf(bookshelfSection, bookshelf);
|
||||
}
|
||||
configuration.save(bookshelfFile);
|
||||
} catch (IOException exception) {
|
||||
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to save bookshelves!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a bookshelf to the given configuration section
|
||||
*
|
||||
* @param section <p>The configuration section to save to</p>
|
||||
* @param bookshelf <p>The bookshelf to save</p>
|
||||
*/
|
||||
private void saveBookshelf(@NotNull ConfigurationSection section, @NotNull Bookshelf bookshelf) {
|
||||
Location location = bookshelf.getLocation();
|
||||
if (location.getWorld() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String key = location.getWorld().getUID() + "," + location.getBlockX() + "," + location.getBlockY() +
|
||||
"," + location.getBlockZ();
|
||||
String titleKey = key + ".title";
|
||||
String loreKey = key + ".lore";
|
||||
section.set(titleKey, bookshelf.getTitle());
|
||||
section.set(loreKey, bookshelf.getLore());
|
||||
}
|
||||
|
||||
}
|
@@ -5,6 +5,7 @@ import net.knarcraft.bookswithoutborders.utility.BookFormatter;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerEditBookEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A listener for listening to book events
|
||||
@@ -14,7 +15,7 @@ import org.bukkit.event.player.PlayerEditBookEvent;
|
||||
public class BookEventListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBookSign(PlayerEditBookEvent event) {
|
||||
public void onBookSign(@NotNull PlayerEditBookEvent event) {
|
||||
if (event.isCancelled() || !event.isSigning() || !BooksWithoutBordersConfig.formatBooks()) {
|
||||
return;
|
||||
}
|
||||
|
@@ -1,35 +1,58 @@
|
||||
package net.knarcraft.bookswithoutborders.listener;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.container.Bookshelf;
|
||||
import net.knarcraft.bookswithoutborders.handler.BookshelfHandler;
|
||||
import net.knarcraft.bookswithoutborders.utility.IntegerToRomanConverter;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.ChiseledBookshelf;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ChiseledBookshelfInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getSuccessColor;
|
||||
|
||||
/**
|
||||
* A listener for bookshelf clicking
|
||||
*/
|
||||
public class BookshelfListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onBookshelfBreak(@NotNull BlockBreakEvent event) {
|
||||
Block block = event.getBlock();
|
||||
|
||||
if (block.getType() != Material.CHISELED_BOOKSHELF) {
|
||||
return;
|
||||
}
|
||||
|
||||
BookshelfHandler bookshelfHandler = BooksWithoutBorders.getBookshelfHandler();
|
||||
Bookshelf bookshelf = bookshelfHandler.getFromLocation(block.getLocation());
|
||||
if (bookshelf != null) {
|
||||
bookshelfHandler.unregisterBookshelf(bookshelf);
|
||||
bookshelfHandler.save();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBookshelfClick(PlayerInteractEvent event) {
|
||||
public void onBookshelfClick(@NotNull PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
// If left-clicking a chiseled bookshelf and sneaking, display contents
|
||||
@@ -49,29 +72,53 @@ public class BookshelfListener implements Listener {
|
||||
event.setUseItemInHand(Event.Result.DENY);
|
||||
|
||||
ChiseledBookshelfInventory bookshelfInventory = chiseledBookshelf.getInventory();
|
||||
player.sendMessage(getBookshelfDescription(bookshelfInventory));
|
||||
player.sendMessage(getBookshelfDescription(bookshelfInventory, event.getClickedBlock().getLocation()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description for a bookshelf's contents
|
||||
*
|
||||
* @param bookshelfInventory <p>The inventory of the bookshelf to describe</p>
|
||||
* @param location <p>The location of the clicked bookshelf</p>
|
||||
* @return <p>A textual description of the bookshelf's contents</p>
|
||||
*/
|
||||
private String getBookshelfDescription(ChiseledBookshelfInventory bookshelfInventory) {
|
||||
StringBuilder builder = new StringBuilder(getSuccessColor() + "Books in shelf:");
|
||||
for (ItemStack itemStack : bookshelfInventory.getStorageContents()) {
|
||||
@NotNull
|
||||
private String getBookshelfDescription(@NotNull ChiseledBookshelfInventory bookshelfInventory, @NotNull Location location) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
Bookshelf bookshelf = BooksWithoutBorders.getBookshelfHandler().getFromLocation(location);
|
||||
if (bookshelf != null) {
|
||||
builder.append(ChatColor.of("#FF5700")).append("Books in ").append(bookshelf.getTitle())
|
||||
.append(":").append(ChatColor.RESET);
|
||||
for (String lore : bookshelf.getLore()) {
|
||||
builder.append("\n ").append(ChatColor.LIGHT_PURPLE).append(lore);
|
||||
}
|
||||
} else {
|
||||
builder.append(ChatColor.of("#FF5700")).append("Books in shelf:").append(ChatColor.RESET);
|
||||
}
|
||||
|
||||
for (int i = 0; i < bookshelfInventory.getSize(); i++) {
|
||||
int index = (i % 3) + 1;
|
||||
if (i % 3 == 0) {
|
||||
builder.append("\n ").append(ChatColor.of("#FF5700")).append(
|
||||
i < 3 ? "Top Row:" : "Bottom Row:").append(ChatColor.RESET);
|
||||
}
|
||||
|
||||
builder.append("\n ").append(ChatColor.of("#ffd700")).append(index).append(". ").append(ChatColor.RESET);
|
||||
|
||||
ItemStack itemStack = bookshelfInventory.getItem(i);
|
||||
if (itemStack == null) {
|
||||
builder.append(ChatColor.GRAY).append("<empty>");
|
||||
continue;
|
||||
}
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
builder.append("\n ").append(ChatColor.GRAY).append(" - ");
|
||||
|
||||
if (meta instanceof BookMeta bookMeta) {
|
||||
builder.append(getBookDescription(bookMeta));
|
||||
} else if (meta instanceof EnchantmentStorageMeta enchantmentStorageMeta) {
|
||||
builder.append(getEnchantedBookDescription(enchantmentStorageMeta));
|
||||
} else if (meta != null) {
|
||||
builder.append(getPlainBookDescription(meta));
|
||||
builder.append(ChatColor.of("#A5682A")).append("[P]").append(ChatColor.RESET).append(getPlainBookDescription(meta));
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
@@ -83,7 +130,8 @@ public class BookshelfListener implements Listener {
|
||||
* @param itemMeta <p>The metadata for the book to describe</p>
|
||||
* @return <p>The description of the book</p>
|
||||
*/
|
||||
private String getPlainBookDescription(ItemMeta itemMeta) {
|
||||
@NotNull
|
||||
private String getPlainBookDescription(@NotNull ItemMeta itemMeta) {
|
||||
String name = itemMeta.getDisplayName();
|
||||
if (name.isEmpty()) {
|
||||
name = "Plain book";
|
||||
@@ -97,7 +145,8 @@ public class BookshelfListener implements Listener {
|
||||
* @param bookMeta <p>The metadata for the book to describe</p>
|
||||
* @return <p>The book's description</p>
|
||||
*/
|
||||
private String getBookDescription(BookMeta bookMeta) {
|
||||
@NotNull
|
||||
private String getBookDescription(@NotNull BookMeta bookMeta) {
|
||||
String title;
|
||||
String author;
|
||||
if (!bookMeta.hasTitle() || bookMeta.getTitle() == null) {
|
||||
@@ -110,7 +159,7 @@ public class BookshelfListener implements Listener {
|
||||
} else {
|
||||
author = bookMeta.getAuthor();
|
||||
}
|
||||
return title + " by " + author;
|
||||
return ChatColor.of("#686868") + "[Q]" + ChatColor.RESET + title + ChatColor.RESET + " by " + author;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,9 +168,10 @@ public class BookshelfListener implements Listener {
|
||||
* @param enchantmentStorageMeta <p>The metadata for the enchanted book to describe</p>
|
||||
* @return <p>The enchanted book's description</p>
|
||||
*/
|
||||
private String getEnchantedBookDescription(EnchantmentStorageMeta enchantmentStorageMeta) {
|
||||
@NotNull
|
||||
private String getEnchantedBookDescription(@NotNull EnchantmentStorageMeta enchantmentStorageMeta) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Enchanted book (");
|
||||
builder.append(ChatColor.of("#A64CFF")).append("[E]").append(ChatColor.RESET);
|
||||
Map<Enchantment, Integer> enchantmentMap = enchantmentStorageMeta.getStoredEnchants();
|
||||
List<String> enchantments = new ArrayList<>(enchantmentMap.size());
|
||||
for (Map.Entry<Enchantment, Integer> enchantmentEntry : enchantmentMap.entrySet()) {
|
||||
@@ -129,7 +179,6 @@ public class BookshelfListener implements Listener {
|
||||
IntegerToRomanConverter.getRomanNumber(enchantmentEntry.getValue()));
|
||||
}
|
||||
builder.append(String.join(", ", enchantments));
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -139,7 +188,8 @@ public class BookshelfListener implements Listener {
|
||||
* @param enchantment <p>The enchantment to get the name of</p>
|
||||
* @return <p>The prettified enchantment name</p>
|
||||
*/
|
||||
private String getEnchantmentName(Enchantment enchantment) {
|
||||
@NotNull
|
||||
private String getEnchantmentName(@NotNull Enchantment enchantment) {
|
||||
// Note: While depreciated, changing this is incompatible with Paper
|
||||
return uppercaseFirst(enchantment.getKey().getKey().replace("_", " "));
|
||||
}
|
||||
@@ -150,7 +200,8 @@ public class BookshelfListener implements Listener {
|
||||
* @param input <p>The input to uppercase</p>
|
||||
* @return <p>The input string with more uppercase</p>
|
||||
*/
|
||||
private String uppercaseFirst(String input) {
|
||||
@NotNull
|
||||
private String uppercaseFirst(@NotNull String input) {
|
||||
String[] parts = input.split(" ");
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
parts[i] = parts[i].substring(0, 1).toUpperCase() + parts[i].substring(1);
|
||||
|
@@ -17,6 +17,8 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
@@ -29,7 +31,7 @@ public class PlayerEventListener implements Listener {
|
||||
private final BooksWithoutBorders booksWithoutBorders = BooksWithoutBorders.getInstance();
|
||||
|
||||
@EventHandler
|
||||
public void onHold(PlayerItemHeldEvent event) {
|
||||
public void onHold(@NotNull PlayerItemHeldEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
@@ -54,7 +56,7 @@ public class PlayerEventListener implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
public void onPlayerJoin(@NotNull PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
//If a book directory exists with this player's name, move it to this player's UUID
|
||||
@@ -82,11 +84,15 @@ public class PlayerEventListener implements Listener {
|
||||
ItemStack offHandItem = InventoryHelper.getHeldItem(player, false);
|
||||
if (mainHandItem.getType() == Material.WRITTEN_BOOK) {
|
||||
ItemMeta itemMetadata = mainHandItem.getItemMeta();
|
||||
updateBookInHand(player, itemMetadata, true);
|
||||
if (itemMetadata != null) {
|
||||
updateBookInHand(player, itemMetadata, true);
|
||||
}
|
||||
}
|
||||
if (offHandItem.getType() == Material.WRITTEN_BOOK) {
|
||||
ItemMeta itemMetadata = offHandItem.getItemMeta();
|
||||
updateBookInHand(player, itemMetadata, false);
|
||||
if (itemMetadata != null) {
|
||||
updateBookInHand(player, itemMetadata, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +104,7 @@ public class PlayerEventListener implements Listener {
|
||||
* @param sendMessage <p>Whether to send a message to the joining player</p>
|
||||
* @return <p>True if a message has yet to be sent</p>
|
||||
*/
|
||||
private boolean giveBookToNewPlayer(String bookName, Player player, boolean sendMessage) {
|
||||
private boolean giveBookToNewPlayer(@NotNull String bookName, @NotNull Player player, boolean sendMessage) {
|
||||
if (!bookName.trim().isEmpty()) {
|
||||
|
||||
//Give the book to the player if it exists
|
||||
@@ -125,7 +131,7 @@ public class PlayerEventListener implements Listener {
|
||||
* @param itemMetadata <p>Information about the held book</p>
|
||||
* @param mainHand <p>Whether to update the book in the player's main hand</p>
|
||||
*/
|
||||
private void updateBookInHand(Player player, ItemMeta itemMetadata, boolean mainHand) {
|
||||
private void updateBookInHand(@NotNull Player player, @NotNull ItemMeta itemMetadata, boolean mainHand) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack updatedBook = updateBook(player, (BookMeta) itemMetadata);
|
||||
if (updatedBook != null) {
|
||||
@@ -144,7 +150,8 @@ public class PlayerEventListener implements Listener {
|
||||
* @param oldBook <p>Metadata about the held book</p>
|
||||
* @return <p>An updated book</p>
|
||||
*/
|
||||
public ItemStack updateBook(Player player, BookMeta oldBook) {
|
||||
@Nullable
|
||||
public ItemStack updateBook(@NotNull Player player, @NotNull BookMeta oldBook) {
|
||||
//handles hacked title-less books
|
||||
if (oldBook.getTitle() == null || oldBook.getTitle().length() < 3) {
|
||||
return null;
|
||||
|
@@ -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;
|
||||
@@ -24,6 +25,8 @@ import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -39,7 +42,7 @@ public class SignEventListener implements Listener {
|
||||
private final String slash = getSlash();
|
||||
|
||||
@EventHandler
|
||||
public void onSignChange(SignChangeEvent event) {
|
||||
public void onSignChange(@NotNull SignChangeEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
@@ -79,7 +82,7 @@ public class SignEventListener implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(PlayerInteractEvent event) {
|
||||
public void onClick(@NotNull PlayerInteractEvent event) {
|
||||
if (event.getClickedBlock() == null) {
|
||||
return;
|
||||
}
|
||||
@@ -138,13 +141,14 @@ public class SignEventListener implements Listener {
|
||||
* @param player <p>The player which clicked the sign</p>
|
||||
* @param hand <p>The EquipmentSlot of the used hand</p>
|
||||
*/
|
||||
private void decryptHeldBookUsingSign(Sign sign, Material heldItemType, Player player, EquipmentSlot hand) {
|
||||
private void decryptHeldBookUsingSign(@NotNull Sign sign, @NotNull Material heldItemType, @NotNull Player player,
|
||||
@NotNull EquipmentSlot hand) {
|
||||
//Decrypt the held book and replace it
|
||||
if (heldItemType == Material.WRITTEN_BOOK) {
|
||||
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);
|
||||
@@ -161,9 +165,10 @@ public class SignEventListener implements Listener {
|
||||
* @param sign <p>The sign to check</p>
|
||||
* @return <p>The color of the sign</p>
|
||||
*/
|
||||
private ChatColor getSignLine2Color(Sign sign) {
|
||||
@Nullable
|
||||
private ChatColor getSignLine2Color(@NotNull 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;
|
||||
@@ -179,7 +184,8 @@ public class SignEventListener implements Listener {
|
||||
* @param color <p>The color to match</p>
|
||||
* @return <p>True if the given string is what's on the sign</p>
|
||||
*/
|
||||
private boolean signLineEquals(Sign sign, int lineNumber, String compareTo, ChatColor color) {
|
||||
private boolean signLineEquals(@NotNull Sign sign, int lineNumber, @NotNull String compareTo,
|
||||
@NotNull ChatColor color) {
|
||||
String line = sign.getSide(Side.FRONT).getLine(lineNumber);
|
||||
return line.equalsIgnoreCase(color + compareTo);
|
||||
}
|
||||
@@ -191,7 +197,8 @@ public class SignEventListener implements Listener {
|
||||
* @param lines <p>The lines on the sign</p>
|
||||
* @param player <p>The player which edited the sign</p>
|
||||
*/
|
||||
private void generateGiveSign(SignChangeEvent event, String[] lines, Player player) {
|
||||
private void generateGiveSign(@NotNull SignChangeEvent event, @NotNull String[] lines,
|
||||
@NotNull Player player) {
|
||||
if (lines[2].length() > 13 || lines[3].length() > 13) {
|
||||
BooksWithoutBorders.sendErrorMessage(player,
|
||||
"[Give] signs' 3rd and 4th lines must be 13 characters or less!");
|
||||
@@ -220,7 +227,7 @@ public class SignEventListener implements Listener {
|
||||
* @param event <p>The event causing the creation of the give sign</p>
|
||||
* @param isValid <p>Whether the created sign is valid</p>
|
||||
*/
|
||||
private void markGiveSignValidity(SignChangeEvent event, boolean isValid) {
|
||||
private void markGiveSignValidity(@NotNull SignChangeEvent event, boolean isValid) {
|
||||
String[] lines = event.getLines();
|
||||
if (isValid) {
|
||||
event.setLine(2, ChatColor.DARK_GREEN + lines[2]);
|
||||
@@ -239,7 +246,8 @@ public class SignEventListener implements Listener {
|
||||
* @param heldItem <p>The type of the held book</p>
|
||||
* @param hand <p>The hand the player is using to hold the book</p>
|
||||
*/
|
||||
private void decryptBook(BookMeta oldBook, Player player, ItemStack heldItem, EquipmentSlot hand) {
|
||||
private void decryptBook(@NotNull BookMeta oldBook, @NotNull Player player, @NotNull ItemStack heldItem,
|
||||
@NotNull EquipmentSlot hand) {
|
||||
ItemStack newBook;
|
||||
|
||||
//Check if the book is encrypted by Books Without Borders
|
||||
@@ -285,14 +293,15 @@ public class SignEventListener implements Listener {
|
||||
* @param player <p>The player which clicked the sign</p>
|
||||
* @param hand <p>The EquipmentSlot of the used hand</p>
|
||||
*/
|
||||
private void encryptHeldBookUsingSign(Sign sign, Material heldItemType, Player player, EquipmentSlot hand) {
|
||||
private void encryptHeldBookUsingSign(@NotNull Sign sign, @NotNull Material heldItemType, @NotNull Player player,
|
||||
@NotNull EquipmentSlot hand) {
|
||||
ItemStack eBook;
|
||||
String[] lines = sign.getSide(Side.FRONT).getLines();
|
||||
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);
|
||||
}
|
||||
@@ -305,8 +314,8 @@ public class SignEventListener implements Listener {
|
||||
* @param sign <p>The sign the user clicked</p>
|
||||
* @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));
|
||||
private void giveBook(@NotNull Sign sign, @NotNull Player player) {
|
||||
String fileName = BookFormatter.stripColor(sign.getSide(Side.FRONT).getLine(2));
|
||||
boolean isLoadListNumber = false;
|
||||
|
||||
try {
|
||||
@@ -318,7 +327,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");
|
||||
|
@@ -1,5 +1,8 @@
|
||||
package net.knarcraft.bookswithoutborders.state;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* This enum represents the different directories books can be saved in
|
||||
*/
|
||||
@@ -26,7 +29,8 @@ public enum BookDirectory {
|
||||
* @param directory <p>The directory to transform</p>
|
||||
* @return <p>A book directory, or null if the given directory is empty</p>
|
||||
*/
|
||||
public static BookDirectory getFromString(String directory) {
|
||||
@Nullable
|
||||
public static BookDirectory getFromString(@NotNull String directory) {
|
||||
if (directory.equalsIgnoreCase("public")) {
|
||||
return BookDirectory.PUBLIC;
|
||||
} else if (directory.equalsIgnoreCase("player")) {
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.state;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This enum represents the different available encryption styles
|
||||
*/
|
||||
@@ -10,7 +12,7 @@ public enum EncryptionStyle {
|
||||
|
||||
private final String name;
|
||||
|
||||
EncryptionStyle(String name) {
|
||||
EncryptionStyle(@NotNull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -20,7 +22,8 @@ public enum EncryptionStyle {
|
||||
* @param name <p>The name of the encryption style</p>
|
||||
* @return <p>An encryption style or null if no match is found</p>
|
||||
*/
|
||||
public static EncryptionStyle getFromString(String name) {
|
||||
@NotNull
|
||||
public static EncryptionStyle getFromString(@NotNull String name) {
|
||||
for (EncryptionStyle style : EncryptionStyle.values()) {
|
||||
if (style.name.equalsIgnoreCase(name)) {
|
||||
return style;
|
||||
|
@@ -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 org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
|
||||
@@ -28,7 +32,7 @@ public final class BookFileHelper {
|
||||
* @param possibleIndex <p>The string which might be a book index</p>
|
||||
* @return <p>True if the number is a book index</p>
|
||||
*/
|
||||
public static boolean isBookListIndex(String possibleIndex) {
|
||||
public static boolean isBookListIndex(@NotNull String possibleIndex) {
|
||||
File bookDirectory = new File(getBookFolder().replaceAll("[\\\\/]$", ""));
|
||||
|
||||
try {
|
||||
@@ -49,7 +53,7 @@ public final class BookFileHelper {
|
||||
* @param bookFile <p>The path to a book</p>
|
||||
* @return <p>True if the file exists and points to a book file</p>
|
||||
*/
|
||||
public static boolean bookFileExists(String bookFile) {
|
||||
public static boolean bookFileExists(@NotNull String bookFile) {
|
||||
return ((new File(bookFile).isFile() && (bookFile.endsWith(".txt") ||
|
||||
bookFile.endsWith(".yml"))) || new File(bookFile + ".txt").isFile() ||
|
||||
new File(bookFile + ".yml").isFile()) && !bookFile.contains("../") && !bookFile.contains("..\\");
|
||||
@@ -63,7 +67,8 @@ public final class BookFileHelper {
|
||||
* @param bookPath <p>The path of the book to get</p>
|
||||
* @return <p>The file the path points to, or null otherwise</p>
|
||||
*/
|
||||
public static File getBookFile(String bookPath) {
|
||||
@Nullable
|
||||
public static File getBookFile(@NotNull String bookPath) {
|
||||
if (!bookFileExists(bookPath)) {
|
||||
return null;
|
||||
}
|
||||
@@ -93,7 +98,8 @@ public final class BookFileHelper {
|
||||
* @param listPublic <p>Whether to list public or personal files</p>
|
||||
* @return <p>A list of available files</p>
|
||||
*/
|
||||
public static List<String> listFiles(CommandSender sender, Boolean listPublic) {
|
||||
@Nullable
|
||||
public static List<String> listFiles(@NotNull CommandSender sender, @NotNull Boolean listPublic) {
|
||||
File file = BookHelper.getBookDirectoryPath(listPublic ? BookDirectory.PUBLIC : BookDirectory.PLAYER, sender);
|
||||
if (file == null) {
|
||||
return new ArrayList<>();
|
||||
@@ -102,31 +108,23 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
@NotNull
|
||||
public static Map<Character, Integer> populateLetterIndices(@NotNull List<String> books) {
|
||||
Map<Character, Integer> firstEncounter = new HashMap<>();
|
||||
Character current = null;
|
||||
for (int i = 0; i < books.size(); i++) {
|
||||
char first = BookFormatter.stripColor(books.get(i)).toLowerCase().charAt(0);
|
||||
if (current == null || current != first) {
|
||||
current = first;
|
||||
firstEncounter.put(first, i);
|
||||
}
|
||||
}
|
||||
return firstEncounter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +134,8 @@ public final class BookFileHelper {
|
||||
* @param searchDirectory <p>The directory to search for files</p>
|
||||
* @return <p>A list of available files</p>
|
||||
*/
|
||||
private static List<String> listFiles(CommandSender sender, File searchDirectory) {
|
||||
@Nullable
|
||||
private static List<String> listFiles(@NotNull CommandSender sender, @NotNull File searchDirectory) {
|
||||
List<String> fileList = new ArrayList<>();
|
||||
File[] existingFiles = searchDirectory.listFiles();
|
||||
|
||||
@@ -146,7 +145,8 @@ public final class BookFileHelper {
|
||||
}
|
||||
|
||||
for (File foundFile : existingFiles) {
|
||||
if (!foundFile.isFile()) {
|
||||
// Filter out invalid files
|
||||
if (!foundFile.isFile() || foundFile.getName().contains(" ") || foundFile.getName().contains("§")) {
|
||||
continue;
|
||||
}
|
||||
String fileName = foundFile.getName();
|
||||
@@ -163,6 +163,10 @@ public final class BookFileHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the book list
|
||||
Comparator<String> bookComparator = Comparator.naturalOrder();
|
||||
fileList.sort((a, b) -> bookComparator.compare(BookFormatter.stripColor(a).toLowerCase(),
|
||||
BookFormatter.stripColor(b).toLowerCase()));
|
||||
return fileList;
|
||||
}
|
||||
|
||||
@@ -173,7 +177,7 @@ public final class BookFileHelper {
|
||||
* @param fileName <p>The name of the file which might already exist</p>
|
||||
* @return <p>The number of found duplicates</p>
|
||||
*/
|
||||
public static int findDuplicates(File[] foundFiles, String fileName) {
|
||||
public static int findDuplicates(@NotNull File[] foundFiles, @NotNull String fileName) {
|
||||
int foundDuplicates = 0;
|
||||
for (File foundFile : foundFiles) {
|
||||
if (foundFile.getName().matches("(\\([0-9]+\\))?" + Pattern.quote(fileName) + "(\\.yml|\\.txt)?")) {
|
||||
|
@@ -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;
|
||||
@@ -24,7 +25,7 @@ public final class BookFormatter {
|
||||
*
|
||||
* @param rawPages <p>A list of pages</p>
|
||||
*/
|
||||
public static void formatLastPage(List<String> rawPages) {
|
||||
public static void formatLastPage(@NotNull List<String> rawPages) {
|
||||
int maxPageText = 256;
|
||||
int fitsNewline = maxPageText - 2;
|
||||
|
||||
@@ -49,7 +50,7 @@ public final class BookFormatter {
|
||||
* @param maxPageText <p>The max number of characters which fit on a page</p>
|
||||
* @param fitsNewline <p>The max number of characters on a page which still fits a newline character</p>
|
||||
*/
|
||||
public static void formatLastPageSplitOverflow(List<String> rawPages, int maxPageText, int fitsNewline) {
|
||||
public static void formatLastPageSplitOverflow(@NotNull List<String> rawPages, int maxPageText, int fitsNewline) {
|
||||
while (rawPages.get(rawPages.size() - 1).length() > maxPageText) {
|
||||
int splitPosition;
|
||||
String fittingText = rawPages.get(rawPages.size() - 1).substring(0, maxPageText);
|
||||
@@ -77,7 +78,7 @@ public final class BookFormatter {
|
||||
* @param rawPages <p>The raw pages to format</p>
|
||||
* @param maxPageText <p>The max number of characters which fit on a page</p>
|
||||
*/
|
||||
public static void formatLastPageCombinePages(List<String> rawPages, int maxPageText) {
|
||||
public static void formatLastPageCombinePages(@NotNull List<String> rawPages, int maxPageText) {
|
||||
int lastPageIndex = rawPages.size() - 1;
|
||||
int nextToLastIndex = rawPages.size() - 2;
|
||||
if (rawPages.get(nextToLastIndex).length() + rawPages.get(lastPageIndex).length() <= maxPageText) {
|
||||
@@ -92,7 +93,7 @@ public final class BookFormatter {
|
||||
* @param rawPages <p>The raw pages to format</p>
|
||||
* @param fitsNewline <p>The max number of characters on a page which still fits a newline character</p>
|
||||
*/
|
||||
public static void formatLastPageAddNewline(List<String> rawPages, int fitsNewline) {
|
||||
public static void formatLastPageAddNewline(@NotNull List<String> rawPages, int fitsNewline) {
|
||||
int pageIndex = rawPages.size() - 1;
|
||||
if (rawPages.get(pageIndex).length() <= fitsNewline && !rawPages.get(pageIndex).isEmpty()) {
|
||||
rawPages.set(pageIndex, (rawPages.get(pageIndex)) + "\n");
|
||||
@@ -105,7 +106,8 @@ public final class BookFormatter {
|
||||
* @param bookMeta <p>The book meta to change</p>
|
||||
* @return <p>The changed book meta</p>
|
||||
*/
|
||||
public static BookMeta formatPages(BookMeta bookMeta) {
|
||||
@NotNull
|
||||
public static BookMeta formatPages(@NotNull BookMeta bookMeta) {
|
||||
List<String> formattedPages = new ArrayList<>(Objects.requireNonNull(bookMeta).getPageCount());
|
||||
for (String page : bookMeta.getPages()) {
|
||||
formattedPages.add(ColorHelper.translateColorCodes(page, ColorConversion.RGB));
|
||||
@@ -114,4 +116,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,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 File getBookDirectoryPath(BookDirectory bookDirectory, CommandSender sender) {
|
||||
@Nullable
|
||||
public static File getBookDirectoryPath(@NotNull BookDirectory bookDirectory, @NotNull CommandSender sender) {
|
||||
String bookFolderString = getBookDirectoryPathString(bookDirectory, sender);
|
||||
if (bookFolderString == null) {
|
||||
return null;
|
||||
@@ -65,7 +69,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 +86,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 +103,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;
|
||||
}
|
||||
@@ -115,12 +121,17 @@ public final class BookHelper {
|
||||
* @param book <p>The book to get the file of</p>
|
||||
* @param player <p>The player trying to do something with the book</p>
|
||||
* @return <p>The book file</p>
|
||||
* @throws IllegalArgumentException <p>If the book title or author contains the title author separator</p>
|
||||
*/
|
||||
public static String getBookFile(BookMeta book, Player player, boolean isPublic) {
|
||||
@NotNull
|
||||
public static String getBookFile(@NotNull BookMeta book, @NotNull Player player, boolean isPublic) throws IllegalArgumentException {
|
||||
String titleAuthorSeparator = BooksWithoutBordersConfig.getTitleAuthorSeparator();
|
||||
String bookName;
|
||||
if (book.hasTitle()) {
|
||||
bookName = book.getTitle();
|
||||
if (bookName == null) {
|
||||
bookName = "Untitled";
|
||||
}
|
||||
} else {
|
||||
bookName = "Untitled";
|
||||
}
|
||||
@@ -133,6 +144,14 @@ public final class BookHelper {
|
||||
authorName = player.getName();
|
||||
} else {
|
||||
authorName = book.getAuthor();
|
||||
if (authorName == null) {
|
||||
authorName = "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
if (bookName.contains(titleAuthorSeparator) || authorName.contains(titleAuthorSeparator)) {
|
||||
throw new IllegalArgumentException("The author or title contains the title author separator. Saving this " +
|
||||
"book would lead to unexpected problems.");
|
||||
}
|
||||
|
||||
return fixName(cleanString(bookName + titleAuthorSeparator + authorName), false);
|
||||
@@ -145,7 +164,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 +181,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,8 +49,14 @@ 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);
|
||||
if (bookDirectory == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Unrecognized book directory!");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Find the filename if a book index is given
|
||||
try {
|
||||
@@ -96,8 +106,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;
|
||||
@@ -131,7 +146,9 @@ public final class BookLoader {
|
||||
* @param directory <p>The relative directory given</p>
|
||||
* @return <p>A file or null if it does not exist</p>
|
||||
*/
|
||||
private static File getFullPath(CommandSender sender, String fileName, BookDirectory bookDirectory, String directory) {
|
||||
@Nullable
|
||||
private static File getFullPath(@NotNull CommandSender sender, @NotNull String fileName,
|
||||
@NotNull BookDirectory bookDirectory, @NotNull String directory) {
|
||||
File file;
|
||||
String slash = BooksWithoutBordersConfig.getSlash();
|
||||
String bookFolder = BooksWithoutBordersConfig.getBookFolder();
|
||||
|
@@ -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 + InputCleaningHelper.cleanString(fileName) + ".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 + InputCleaningHelper.cleanString(fileName) + ".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();
|
||||
@@ -159,13 +164,17 @@ public final class BookToFromTextHelper {
|
||||
List<String> rawPages;
|
||||
try {
|
||||
rawPages = readTextFile(file);
|
||||
if (rawPages == null) {
|
||||
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Text file's first line was null");
|
||||
return null;
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to read text file");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Parse the generation from the book data
|
||||
if (rawPages != null && !rawPages.isEmpty() && rawPages.get(0).startsWith("Generation:")) {
|
||||
if (!rawPages.isEmpty() && rawPages.get(0).startsWith("Generation:")) {
|
||||
bookMetadata.setGeneration(BookMeta.Generation.valueOf(rawPages.get(0).split(":")[1]));
|
||||
rawPages.remove(0);
|
||||
}
|
||||
@@ -188,7 +197,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));
|
||||
|
||||
|
@@ -12,6 +12,7 @@ import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.ServicesManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -32,6 +33,7 @@ public final class EconomyHelper {
|
||||
*
|
||||
* @return <p>An economy instance, or null if it's not initialized</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static Economy getEconomy() {
|
||||
return economy;
|
||||
}
|
||||
@@ -67,7 +69,7 @@ public final class EconomyHelper {
|
||||
* @param numCopies <p>The number of copies the player is trying to print</p>
|
||||
* @return <p>True if the player cannot pay for the printing of the books</p>
|
||||
*/
|
||||
public static boolean cannotPayForBookPrinting(Player player, int numCopies) {
|
||||
public static boolean cannotPayForBookPrinting(@NotNull Player player, int numCopies) {
|
||||
//BookPriceQuantity: How many items are required to pay for each book
|
||||
//BookPriceType: Which item is used to pay for the books. AIR = use economy
|
||||
Material bookCurrency = BooksWithoutBordersConfig.getBookPriceType();
|
||||
@@ -100,7 +102,7 @@ public final class EconomyHelper {
|
||||
* @param itemCost <p>The number of writable books to pay</p>
|
||||
* @return <p>True if the payment was successful</p>
|
||||
*/
|
||||
private static boolean takeWritableBookPayment(Player player, int itemCost) {
|
||||
private static boolean takeWritableBookPayment(@NotNull Player player, int itemCost) {
|
||||
List<ItemStack> books = getPlayersEmptyBooks(player);
|
||||
if (countItems(books) < itemCost) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, itemCost + " empty " + Material.WRITABLE_BOOK +
|
||||
@@ -131,7 +133,7 @@ public final class EconomyHelper {
|
||||
* @param items <p>The items to count</p>
|
||||
* @return <p>The total number of items</p>
|
||||
*/
|
||||
private static int countItems(List<ItemStack> items) {
|
||||
private static int countItems(@NotNull List<ItemStack> items) {
|
||||
int totalItems = 0;
|
||||
for (ItemStack itemStack : items) {
|
||||
totalItems += itemStack.getAmount();
|
||||
@@ -145,7 +147,8 @@ public final class EconomyHelper {
|
||||
* @param player <p>The player to get books for</p>
|
||||
* @return <p>The empty books in the player's inventory</p>
|
||||
*/
|
||||
private static List<ItemStack> getPlayersEmptyBooks(Player player) {
|
||||
@NotNull
|
||||
private static List<ItemStack> getPlayersEmptyBooks(@NotNull Player player) {
|
||||
List<ItemStack> validBooks = new ArrayList<>();
|
||||
for (ItemStack itemStack : player.getInventory().getContents()) {
|
||||
if (itemStack == null || itemStack.getType() != Material.WRITABLE_BOOK) {
|
||||
@@ -168,7 +171,7 @@ public final class EconomyHelper {
|
||||
* @param numCopies <p>The number of books the player is printing</p>
|
||||
* @return <p>True if the player had the money and it has been withdrawn</p>
|
||||
*/
|
||||
private static boolean payForBookPrintingEconomy(Player player, double cost, int numCopies) {
|
||||
private static boolean payForBookPrintingEconomy(@NotNull Player player, double cost, int numCopies) {
|
||||
if ((economy.getBalance(player) - cost) >= 0) {
|
||||
economy.withdrawPlayer(player, cost);
|
||||
BooksWithoutBorders.sendSuccessMessage(player, economy.format(cost) + " withdrawn to create " +
|
||||
@@ -188,7 +191,7 @@ public final class EconomyHelper {
|
||||
* @param player <p>The player which needs to pay</p>
|
||||
* @param itemCost <p>The number of items to pay</p>
|
||||
*/
|
||||
private static void payForBookPrintingItem(Player player, int itemCost) {
|
||||
private static void payForBookPrintingItem(@NotNull Player player, int itemCost) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
|
||||
int clearedAmount = 0;
|
||||
|
@@ -11,6 +11,8 @@ import org.bukkit.command.ConsoleCommandSender;
|
||||
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.io.IOException;
|
||||
@@ -37,7 +39,8 @@ public final class EncryptionHelper {
|
||||
* @param key <p>The key to transform</p>
|
||||
* @return <p>The numbers representing the key's characters</p>
|
||||
*/
|
||||
public static String getNumberKeyFromStringKey(String key) {
|
||||
@NotNull
|
||||
public static String getNumberKeyFromStringKey(@NotNull String key) {
|
||||
StringBuilder integerKey = new StringBuilder();
|
||||
for (int x = 0; x < key.length(); x++) {
|
||||
integerKey.append(Character.getNumericValue(Character.codePointAt(key, x)));
|
||||
@@ -54,7 +57,9 @@ public final class EncryptionHelper {
|
||||
* @param player <p>The player trying to encrypt a book</p>
|
||||
* @return <p>The pages of the book in encrypted form</p>
|
||||
*/
|
||||
public static List<String> encryptBookPages(BookMeta book, EncryptionStyle style, String integerKey, Player player) {
|
||||
@Nullable
|
||||
public static List<String> encryptBookPages(@NotNull BookMeta book, @NotNull EncryptionStyle style,
|
||||
@NotNull String integerKey, @NotNull Player player) {
|
||||
List<String> encryptedPages = new ArrayList<>();
|
||||
//Scramble the book's contents
|
||||
if (style == EncryptionStyle.DNA) {
|
||||
@@ -86,7 +91,9 @@ public final class EncryptionHelper {
|
||||
* @param style <p>The encryption style to use</p>
|
||||
* @return <p>An encrypted version of the book</p>
|
||||
*/
|
||||
public static ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style) {
|
||||
@Nullable
|
||||
public static ItemStack encryptBook(@NotNull Player player, boolean mainHand, @NotNull String key,
|
||||
@NotNull EncryptionStyle style) {
|
||||
return encryptBook(player, mainHand, key, style, "");
|
||||
}
|
||||
|
||||
@@ -100,11 +107,17 @@ public final class EncryptionHelper {
|
||||
* @param groupName <p>The name of the group to encrypt for, or "" otherwise</p>
|
||||
* @return <p>An encrypted version of the book</p>
|
||||
*/
|
||||
public static ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style, String groupName) {
|
||||
@Nullable
|
||||
public static ItemStack encryptBook(Player player, boolean mainHand, @NotNull String key,
|
||||
@NotNull EncryptionStyle style, @NotNull String groupName) {
|
||||
//converts user supplied key into integer form
|
||||
String integerKey = EncryptionHelper.getNumberKeyFromStringKey(key);
|
||||
|
||||
BookMeta book = InventoryHelper.getHeldBookMetadata(player, mainHand);
|
||||
if (book == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Unable to get metadata from the held book!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!book.hasPages()) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Book is empty!");
|
||||
@@ -143,7 +156,9 @@ public final class EncryptionHelper {
|
||||
* @param newMetadata <p>The new metadata of the book</p>
|
||||
* @return <p>An encrypted version of the book</p>
|
||||
*/
|
||||
private static ItemStack createEncryptedBook(BookMeta book, List<String> newPages, Player player, BookMeta newMetadata) {
|
||||
@NotNull
|
||||
private static ItemStack createEncryptedBook(@NotNull BookMeta book, @NotNull List<String> newPages,
|
||||
@NotNull Player player, @NotNull BookMeta newMetadata) {
|
||||
//Create the encrypted book
|
||||
ItemStack encryptedBook = new ItemStack(Material.WRITTEN_BOOK);
|
||||
book.setPages(newPages);
|
||||
@@ -166,7 +181,9 @@ public final class EncryptionHelper {
|
||||
* @param integerKey <p>The key used to encrypt the book</p>
|
||||
* @return <p>The new metadata for the book, or null if it could not be saved</p>
|
||||
*/
|
||||
private static BookMeta saveBookPlaintext(String groupName, Player player, BookMeta book, String integerKey) {
|
||||
@Nullable
|
||||
private static BookMeta saveBookPlaintext(@NotNull String groupName, @NotNull Player player,
|
||||
@NotNull BookMeta book, @NotNull String integerKey) {
|
||||
BookMeta newMetadata = book;
|
||||
boolean wasSaved;
|
||||
if (groupName.trim().isEmpty()) {
|
||||
@@ -190,7 +207,8 @@ public final class EncryptionHelper {
|
||||
* @param deleteEncryptedFile <p>Whether to delete the plaintext file after decryption is finished</p>
|
||||
* @return <p>The loaded book, or null if no book could be loaded</p>
|
||||
*/
|
||||
public static ItemStack loadEncryptedBook(Player player, String key, boolean deleteEncryptedFile) {
|
||||
@Nullable
|
||||
public static ItemStack loadEncryptedBook(@NotNull Player player, @NotNull String key, boolean deleteEncryptedFile) {
|
||||
ItemStack heldBook = InventoryHelper.getHeldBook(player, true);
|
||||
BookMeta bookMetadata = (BookMeta) heldBook.getItemMeta();
|
||||
String path = getBookFolder() + "Encrypted" + getSlash();
|
||||
@@ -246,7 +264,9 @@ public final class EncryptionHelper {
|
||||
* @param groupName <p>The group which should be able to decrypt the book</p>
|
||||
* @return <p>The new encrypted metadata for the book, or null if encryption failed</p>
|
||||
*/
|
||||
private static BookMeta saveEncryptedBookForGroup(Player player, BookMeta bookMetadata, String groupName) {
|
||||
@Nullable
|
||||
private static BookMeta saveEncryptedBookForGroup(@NotNull Player player, @NotNull BookMeta bookMetadata,
|
||||
@NotNull String groupName) {
|
||||
String path = getBookFolder() + "Encrypted" + getSlash() + cleanString(groupName) + getSlash();
|
||||
File dirTest = new File(path);
|
||||
//Creates group dir
|
||||
@@ -297,7 +317,8 @@ public final class EncryptionHelper {
|
||||
* @param key <p>The key to use for encryption</p>
|
||||
* @return <p>The new encrypted metadata for the book, or null if encryption failed</p>
|
||||
*/
|
||||
private static Boolean saveEncryptedBook(Player player, BookMeta bookMetaData, String key) {
|
||||
@NotNull
|
||||
private static Boolean saveEncryptedBook(@NotNull Player player, @NotNull BookMeta bookMetaData, @NotNull String key) {
|
||||
String path = getBookFolder() + "Encrypted" + getSlash();
|
||||
|
||||
String fileName = "[" + key + "]" + BookHelper.getBookFile(bookMetaData, player, true);
|
||||
|
@@ -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
|
||||
@@ -17,7 +22,8 @@ public final class InputCleaningHelper {
|
||||
* @param list <p>The list to clean</p>
|
||||
* @return <p>A clean list containing all relevant values</p>
|
||||
*/
|
||||
public static List<String> cleanList(List<String> list) {
|
||||
@NotNull
|
||||
public static List<String> cleanList(@NotNull List<String> list) {
|
||||
List<String> resultList = new ArrayList<>(list);
|
||||
resultList.removeIf((item) -> item == null || item.trim().isEmpty());
|
||||
return resultList;
|
||||
@@ -29,7 +35,8 @@ public final class InputCleaningHelper {
|
||||
* @param fileName <p>The file name to clean</p>
|
||||
* @return <p>The cleaned file name</p>
|
||||
*/
|
||||
public static String cleanString(String fileName) {
|
||||
@NotNull
|
||||
public static String cleanString(@NotNull String fileName) {
|
||||
fileName = fileName.replace("/", "");
|
||||
fileName = fileName.replace("\\", "");
|
||||
fileName = fileName.replace("*", "");
|
||||
@@ -39,6 +46,7 @@ public final class InputCleaningHelper {
|
||||
fileName = fileName.replace(">", "");
|
||||
fileName = fileName.replace("?", "");
|
||||
fileName = fileName.replace("\"", "");
|
||||
fileName = fileName.replace("§", "&");
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@@ -49,7 +57,8 @@ public final class InputCleaningHelper {
|
||||
* @param isLoading <p>Whether loading from a file as opposed to saving to a file</p>
|
||||
* @return <p>The fixed name</p>
|
||||
*/
|
||||
public static String fixName(String fileName, Boolean isLoading) {
|
||||
@NotNull
|
||||
public static String fixName(@NotNull String fileName, @NotNull Boolean isLoading) {
|
||||
if (isLoading) {
|
||||
fileName = fileName.replace("_", " ");
|
||||
} else {
|
||||
@@ -58,4 +67,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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.utility;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -40,6 +42,7 @@ public final class IntegerToRomanConverter {
|
||||
* @param number <p>The number to convert</p>
|
||||
* @return <p>The roman representation of the number</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static String getRomanNumber(int number) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
int remainder = number;
|
||||
@@ -83,6 +86,7 @@ public final class IntegerToRomanConverter {
|
||||
* @param times <p>The number of times to repeat the character</p>
|
||||
* @return <p>The repeated string</p>
|
||||
*/
|
||||
@NotNull
|
||||
private static String repeat(char character, int times) {
|
||||
return String.valueOf(character).repeat(Math.max(0, times));
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import org.bukkit.Material;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The inventory helper mainly helps with getting and setting books
|
||||
@@ -23,7 +25,8 @@ public final class InventoryHelper {
|
||||
* @param signedBook <p>Whether to check for signed or unsigned books</p>
|
||||
* @return <p>The book the player is holding</p>
|
||||
*/
|
||||
public static ItemStack getHeldBook(Player player, boolean signedBook) {
|
||||
@NotNull
|
||||
public static ItemStack getHeldBook(@NotNull Player player, boolean signedBook) {
|
||||
ItemSlot heldSlot = getHeldSlotBook(player, false, false, true, signedBook);
|
||||
if (heldSlot == ItemSlot.MAIN_HAND) {
|
||||
return getHeldItem(player, true);
|
||||
@@ -40,7 +43,7 @@ public final class InventoryHelper {
|
||||
* @param player <p>The player holding the book</p>
|
||||
* @param newBook <p>The new book the player should hold</p>
|
||||
*/
|
||||
public static void setHeldWrittenBook(Player player, ItemStack newBook) {
|
||||
public static void setHeldWrittenBook(@NotNull Player player, @NotNull ItemStack newBook) {
|
||||
ItemSlot itemSlot = getHeldSlotBook(player, false, false, true, true);
|
||||
if (itemSlot == ItemSlot.MAIN_HAND) {
|
||||
replaceHeldItem(player, newBook, true);
|
||||
@@ -59,7 +62,8 @@ public final class InventoryHelper {
|
||||
* @param twoBooksMessage <p>The message to display if the player is holding one book in each hand</p>
|
||||
* @return <p>False if the player is holding exactly one book</p>
|
||||
*/
|
||||
public static boolean notHoldingOneWritableBookCheck(Player player, String noBookMessage, String twoBooksMessage) {
|
||||
public static boolean notHoldingOneWritableBookCheck(@NotNull Player player, @NotNull String noBookMessage,
|
||||
@NotNull String twoBooksMessage) {
|
||||
BookHoldingState holdingState = getBookHoldingState(player);
|
||||
|
||||
if (holdingState == BookHoldingState.NONE || holdingState == BookHoldingState.SIGNED_BOTH_HANDS ||
|
||||
@@ -84,7 +88,8 @@ public final class InventoryHelper {
|
||||
* @param twoBooksMessage <p>The message to display if the player is holding one book in each hand</p>
|
||||
* @return <p>False if the player is holding exactly one book</p>
|
||||
*/
|
||||
public static boolean notHoldingOneWrittenBookCheck(Player player, String noBookMessage, String twoBooksMessage) {
|
||||
public static boolean notHoldingOneWrittenBookCheck(@NotNull Player player, @NotNull String noBookMessage,
|
||||
@NotNull String twoBooksMessage) {
|
||||
BookHoldingState holdingState = getBookHoldingState(player);
|
||||
|
||||
if (holdingState == BookHoldingState.NONE || holdingState == BookHoldingState.UNSIGNED_BOTH_HANDS ||
|
||||
@@ -111,7 +116,8 @@ public final class InventoryHelper {
|
||||
* @param writtenBook <p>Whether to search for written or unwritten books, if it's relevant</p>
|
||||
* @return <p>The slot of the player's held book</p>
|
||||
*/
|
||||
public static ItemSlot getHeldSlotBook(Player player, boolean handMatters, boolean mainHand,
|
||||
@NotNull
|
||||
public static ItemSlot getHeldSlotBook(@NotNull Player player, boolean handMatters, boolean mainHand,
|
||||
boolean typeMatters, boolean writtenBook) {
|
||||
BookHoldingState state = getBookHoldingState(player);
|
||||
ItemStack mainHandItem = getHeldItem(player, true);
|
||||
@@ -168,7 +174,8 @@ public final class InventoryHelper {
|
||||
* @param player <p>The player to check</p>
|
||||
* @return <p>The state of the player's book holding</p>
|
||||
*/
|
||||
private static BookHoldingState getBookHoldingState(Player player) {
|
||||
@NotNull
|
||||
private static BookHoldingState getBookHoldingState(@NotNull Player player) {
|
||||
ItemStack mainHandItem = getHeldItem(player, true);
|
||||
ItemStack offHandItem = getHeldItem(player, false);
|
||||
|
||||
@@ -205,7 +212,8 @@ public final class InventoryHelper {
|
||||
* @param mainHand <p>Whether to get information about a book in the player's main hand or off hand</p>
|
||||
* @return <p>Information about the held book</p>
|
||||
*/
|
||||
public static BookMeta getHeldBookMetadata(Player player, boolean mainHand) {
|
||||
@Nullable
|
||||
public static BookMeta getHeldBookMetadata(@NotNull Player player, boolean mainHand) {
|
||||
return (BookMeta) getHeldItem(player, mainHand).getItemMeta();
|
||||
}
|
||||
|
||||
@@ -216,7 +224,8 @@ public final class InventoryHelper {
|
||||
* @param mainHand <p>Whether to get the item in the player's main hand or off hand</p>
|
||||
* @return <p>The item the player is holding in the given hand</p>
|
||||
*/
|
||||
public static ItemStack getHeldItem(Player player, boolean mainHand) {
|
||||
@NotNull
|
||||
public static ItemStack getHeldItem(@NotNull Player player, boolean mainHand) {
|
||||
if (mainHand) {
|
||||
return player.getInventory().getItemInMainHand();
|
||||
} else {
|
||||
@@ -231,7 +240,7 @@ public final class InventoryHelper {
|
||||
* @param newBook <p>The new book the player should hold</p>
|
||||
* @param mainHand <p>Whether to replace the item in the player's main hand or off hand</p>
|
||||
*/
|
||||
public static void replaceHeldItem(Player player, ItemStack newBook, boolean mainHand) {
|
||||
public static void replaceHeldItem(@NotNull Player player, @NotNull ItemStack newBook, boolean mainHand) {
|
||||
if (mainHand) {
|
||||
player.getInventory().setItemInMainHand(newBook);
|
||||
} else {
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders.utility;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -16,6 +18,7 @@ public final class TabCompletionTypeHelper {
|
||||
*
|
||||
* @return <p>A list of booleans</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> getBooleans() {
|
||||
List<String> booleans = new ArrayList<>();
|
||||
booleans.add("true");
|
||||
@@ -30,6 +33,7 @@ public final class TabCompletionTypeHelper {
|
||||
* @param end <p>The end number</p>
|
||||
* @return <p>A list of numbers</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> getNumbers(int start, int end) {
|
||||
List<String> numbers = new ArrayList<>();
|
||||
for (int i = start; i <= end; i++) {
|
||||
@@ -45,6 +49,7 @@ public final class TabCompletionTypeHelper {
|
||||
* @param end <p>The end number</p>
|
||||
* @return <p>A list of booleans and numbers</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> getBooleansAndNumbers(int start, int end) {
|
||||
List<String> booleansAndNumbers = new ArrayList<>();
|
||||
List<String> booleans = getBooleans();
|
||||
|
@@ -97,6 +97,10 @@ commands:
|
||||
description: Reloads BwB's configuration file
|
||||
usage: /<command>
|
||||
permission: bookswithoutborders.reload
|
||||
setBookshelfData:
|
||||
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
|
||||
permissions:
|
||||
bookswithoutborders.*:
|
||||
description: Grants all permissions
|
||||
@@ -125,6 +129,7 @@ permissions:
|
||||
bookswithoutborders.setbookprice: true
|
||||
bookswithoutborders.reload: true
|
||||
bookswithoutborders.setgeneration: true
|
||||
bookswithoutborders.editbookshelf: true
|
||||
bookswithoutborders.use:
|
||||
description: Allows player to use commands to save/load/delete in their personal directory, and peeking at bookshelves if enabled
|
||||
children:
|
||||
@@ -194,3 +199,5 @@ permissions:
|
||||
description: Allows player to change the generation of a book (Original, Copy, Copy of Copy)
|
||||
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
|
@@ -3,6 +3,7 @@ package net.knarcraft.bookswithoutborders.encryption;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
|
||||
public class AESTest {
|
||||
@@ -16,6 +17,7 @@ public class AESTest {
|
||||
|
||||
String encrypted = aes.encryptDecryptText(plainText, password, true);
|
||||
assertNotSame(encrypted, plainText);
|
||||
assertNotNull(encrypted);
|
||||
String decrypted = aes.encryptDecryptText(encrypted, password, false);
|
||||
assertEquals(plainText, decrypted);
|
||||
}
|
||||
|
Reference in New Issue
Block a user