Finishes moving commands to separate classes

This commit is contained in:
Kristian Knarvik 2021-09-01 19:20:09 +02:00
parent db4f080ac8
commit 6c897b4ddf
14 changed files with 542 additions and 431 deletions

View File

@ -18,12 +18,12 @@ import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
import net.knarcraft.bookswithoutborders.utility.BookFormatter;
import net.knarcraft.bookswithoutborders.utility.EncryptionHelper;
import net.knarcraft.bookswithoutborders.utility.FileHelper;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
@ -40,6 +40,9 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.cleanString;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName;
public class BooksWithoutBorders extends JavaPlugin {
protected static int bookDuplicateLimit;
//The separating string between the book title and the book author
@ -62,7 +65,7 @@ public class BooksWithoutBorders extends JavaPlugin {
protected static ConsoleCommandSender consoleSender;
public static String bookFolder;
public static final ChatColor errorColor = ChatColor.RED;
protected static final ChatColor successColor = ChatColor.GREEN;
public static final ChatColor successColor = ChatColor.GREEN;
public static final ChatColor commandColor = ChatColor.YELLOW;
@Override
@ -86,7 +89,7 @@ public class BooksWithoutBorders extends JavaPlugin {
registerCommand("delete", new CommandDelete(this), null);
registerCommand("deletePublic", new CommandDeletePublic(this), null);
registerCommand("copy", new CommandCopy(this), null);
registerCommand("unSign", new CommandUnSign(this), null);
registerCommand("unSign", new CommandUnSign(), null);
registerCommand("encrypt", new CommandEncrypt(this), null);
registerCommand("setBookPrice", new CommandSetBookPrice(this), null);
registerCommand("setLore", new CommandSetLore(), null);
@ -96,10 +99,14 @@ public class BooksWithoutBorders extends JavaPlugin {
registerCommand("setTitle", new CommandSetTitle(), null);
registerCommand("load", new CommandLoad(this), null);
registerCommand("loadPublic", new CommandLoadPublic(this), null);
registerCommand("booksWithoutBorders", new CommandBooksWithoutBorders(this), null);
registerCommand("reload", new CommandReload(this), null);
registerCommand("givePublic", new CommandGivePublic(this), null);
}
/**
* Registers a command
*
* @param commandName <p>The name of the command to register</p>
* @param executor <p>The executor to register for the command</p>
*/
@ -196,7 +203,7 @@ public class BooksWithoutBorders extends JavaPlugin {
return loadExistingPlayers();
}
protected boolean loadConfig() {
public boolean loadConfig() {
this.reloadConfig();
try {
useYml = this.getConfig().getBoolean("Options.Save_Books_in_Yaml_Format", true);
@ -261,7 +268,7 @@ public class BooksWithoutBorders extends JavaPlugin {
return (eco != null);
}
protected boolean loadExistingPlayers() {
public boolean loadExistingPlayers() {
File fTest = new File(this.getDataFolder().getAbsolutePath() + SLASH + "Existing Players.txt");
existingPlayers = new ArrayList<>();
@ -325,236 +332,6 @@ public class BooksWithoutBorders extends JavaPlugin {
return true;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if ((command.getName().equalsIgnoreCase("BooksWithoutBorders") || command.getName().equalsIgnoreCase("bwb"))) {
if (args.length == 0 && sender instanceof Player) {
//Lists all commands
sender.sendMessage(commandColor + "Use: /bwb [Command]");
sender.sendMessage(commandColor + "[] denote parameters");
if (booksHavePrice()) {
if (bookPriceType != Material.AIR) {
sendErrorMessage(sender, "[" + (int) bookPriceQuantity + " " + bookPriceType.toString() + "(s) are required to create a book]");
} else {
sendErrorMessage(sender, "[" + BooksWithoutBorders.eco.format(bookPriceQuantity) + " is required to create a book]");
}
}
sender.sendMessage(commandColor + "Commands:");
if (sender.hasPermission("bookswithoutborders.load")) {
sender.sendMessage(commandColor + "\nLoad [file name or number] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Creates a book from the specified file and gives it to the player");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
sendSuccessMessage(sender, "If true is specified the book will be signed, if false it will be");
sendSuccessMessage(sender, "unsigned");
}
if (sender.hasPermission("bookswithoutborders.loadPublic")) {
sender.sendMessage(commandColor + "loadPublic [file name or number] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Same as Load, but views files in the public directory");
}
if (sender.hasPermission("bookswithoutborders.save")) {
sender.sendMessage("\n" + commandColor + "Save [true/false]: " + successColor + "Saves the book the player is");
sendSuccessMessage(sender, "holding to a text file in a private directory");
sendSuccessMessage(sender, "If true is specified, a book of the same name by the same");
sendSuccessMessage(sender, "author will be overwritten by the new book");
}
if (sender.hasPermission("bookswithoutborders.savePublic")) {
sender.sendMessage(commandColor + "savePublic [true/false]: " + successColor + "Same as Save,");
sendSuccessMessage(sender, "but saves files in the public directory");
}
if (sender.hasPermission("bookswithoutborders.give")) {
sender.sendMessage("\n" + commandColor + "Give [file name or number] [player name] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Gives the selected player a book from your personal directory");
}
if (sender.hasPermission("bookswithoutborders.givePublic")) {
sender.sendMessage(commandColor + "givePublic [file name or number] [player name] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Same as give, but uses books from the public directory");
}
if (sender.hasPermission("bookswithoutborders.delete")) {
sender.sendMessage(commandColor + "\nDelete [file name or number]: " + successColor + "Deletes the specified");
sendSuccessMessage(sender, "file in the player's directory");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
}
if (sender.hasPermission("bookswithoutborders.admin")) {
sender.sendMessage(commandColor + "deletePublic [file name or number]: " + successColor + "Same as Delete,");
sendSuccessMessage(sender, "but deletes files in the public directory");
sender.sendMessage(commandColor + "\nReload:" + successColor + " Reloads BwB's configuration file");
}
if (sender.hasPermission("bookswithoutborders.unsign")) {
sender.sendMessage("\n" + commandColor + "Unsign: " + successColor + "Un-signs the book the player is holding");
}
if (sender.hasPermission("bookswithoutborders.copy")) {
sender.sendMessage("\n" + commandColor + "Copy [number of copies]: " + successColor + "Copies the book the player is holding");
}
if (sender.hasPermission("bookswithoutborders.encrypt")) {
sender.sendMessage("\n" + commandColor + "Encrypt [key] [style]: " + successColor + "Encrypts the book the player is holding");
sender.sendMessage(commandColor + "[key]" + successColor + " is required and can be any phrase or number excluding spaces");
sender.sendMessage(commandColor + "[style]" + successColor + " is not required. Possible values are \"DNA\" or \"Magic\"");
}
if (sender.hasPermission("bookswithoutborders.groupEncrypt")) {
sender.sendMessage("\n" + commandColor + "groupEncrypt [group name] [key] [style]: " + successColor + "Encrypts book so that only players with the" +
"\n bookswithoutborders.decrypt." + commandColor + "[group name]" + successColor + " permission may decrypt the book by holding and left clicking the book");
}
if (sender.hasPermission("bookswithoutborders.decrypt")) {
sender.sendMessage("\n" + commandColor + "Decrypt [key]: " + successColor + "Decrypts the book the player is holding");
sender.sendMessage(commandColor + "[key]" + successColor + " is required and MUST be IDENTICAL to the key used to encrypt held book");
}
if (sender.hasPermission("bookswithoutborders.setTitle")) {
sender.sendMessage("\n" + commandColor + "setTitle [title]: " + successColor + "Sets the title of the book/item the player is holding");
}
if (sender.hasPermission("bookswithoutborders.setAuthor")) {
sender.sendMessage("\n" + commandColor + "setAuthor [author]: " + successColor + "Sets the author of the book the player is holding");
}
if (sender.hasPermission("bookswithoutborders.setLore")) {
sender.sendMessage("\n" + commandColor + "setLore [lore]: " + successColor + "Sets the lore of the item the player is holding");
sendSuccessMessage(sender, "Insert the lore_line_separator character to force a new line\n[\"~\" by default]");
}
if (sender.hasPermission("bookswithoutborders.setBookPrice")) {
sender.sendMessage("\n" + commandColor + "setBookPrice [Item/Eco] [quantity]: " + successColor + "Sets the per-book-price to create a book via commands." +
"\nIf [Item], the item in the player's hand in the amount of [quantity] will be the price.\nIf [Eco], a Vault based economy will be used for price." +
"\nIf neither [Item/Eco] or [quantity] are specified the current price to create books will be removed.");
}
return true;
}
if (args.length == 0) {
//lists commands from console
sender.sendMessage(commandColor + "Use: /bwb [Command]");
sender.sendMessage(commandColor + "[] denote parameters");
sender.sendMessage(commandColor + "Commands:");
sender.sendMessage(commandColor + "\nReload:" + successColor + " Reloads BwB's config file");
sender.sendMessage(commandColor + "givePublic [file name or number] [player name] [true/false]: " + successColor);
sendSuccessMessage(sender, "Gives the selected player a book from the public directory");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
sender.sendMessage(commandColor + "deletePublic [file name or number]: " + successColor + "Deletes the specified");
sendSuccessMessage(sender, "file in the public directory");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
return true;
}
if (args[0].equalsIgnoreCase("reload")) {
if (sender instanceof Player) {
if (!sender.hasPermission("bookswithoutborders.admin") && !sender.hasPermission("*")) {
sendErrorMessage(sender, "You don't have permission to use this command!");
return false;
}
}
if (loadConfig() && loadExistingPlayers()) {
sendSuccessMessage(sender, "BooksWithoutBorders configuration reloaded!");
} else {
sendErrorMessage(sender, "Reload Failed!");
sendErrorMessage(sender, "See console for details");
}
return true;
}
if (args[0].equalsIgnoreCase("givePublic")) {
if (sender instanceof Player) {
if (!sender.hasPermission("bookswithoutborders.givePublic")) {
sendErrorMessage(sender, " You don't have permission to use this command!");
return false;
}
}
if (args.length == 2 || args.length > 5) {
sendErrorMessage(sender, "Incorrect number of arguments for this command!");
return false;
}
if (args.length == 1) {
loadList.put(sender.getName(), listFiles(sender, true, false));
return true;
}
for (int x = 0; x < args[1].length(); x++) {
if (!Character.isDigit(args[1].charAt(x)))
break;
if (x == args[1].length() - 1)
loadList.put(sender.getName(), listFiles(sender, true, true));
}
ItemStack newBook;
Player receivingPlayer = this.getServer().getPlayer(args[2]);
if (receivingPlayer == null) {
sendErrorMessage(sender, "Player not found!");
return false;
}
if (receivingPlayer.getInventory().firstEmpty() == -1) {
sendErrorMessage(sender, "Receiving player must have space in their inventory to receive books!");
return false;
}
//bwb give [book name] [player] [numCopies] [is signed]
try {
if (args.length == 5)
newBook = loadBook(sender, cleanString(args[1]), args[4], "public", Integer.parseInt(args[3]));
else if (args.length == 4) {
if (args[3].equalsIgnoreCase("true") || args[3].equalsIgnoreCase("false"))
newBook = loadBook(sender, cleanString(args[1]), args[3], "public");
else
newBook = loadBook(sender, cleanString(args[1]), "true", "public", Integer.parseInt(args[3]));
} else
newBook = loadBook(sender, cleanString(args[1]), "true", "public");
if (newBook != null) {
receivingPlayer.getInventory().addItem(newBook);
sendSuccessMessage(sender, "Book sent!");
sendSuccessMessage(receivingPlayer, "Book received!");
return true;
} else {
sendErrorMessage(sender, "Book failed to load!");
return false;
}
} catch (NumberFormatException e) {
sendErrorMessage(sender, "Invalid number of book copies specified!");
return false;
}
}
sendErrorMessage(sender, "Command not recognized! Use " + commandColor + "/BwB" + errorColor + " for more info!");
}
return false;
}
/**
* Removes any special character from a filename
* @param fileName <p>The file name to clean</p>
* @return <p>The cleaned file name</p>
*/
public String cleanString(String fileName) {
fileName = fileName.replace("/", "");
fileName = fileName.replace("\\", "");
fileName = fileName.replace("*", "");
fileName = fileName.replace(":", "");
fileName = fileName.replace("|", "");
fileName = fileName.replace("<", "");
fileName = fileName.replace(">", "");
fileName = fileName.replace("?", "");
fileName = fileName.replace("\"", "");
return fileName;
}
/**
* Changes spaces to underscores or underscores to spaces, depending on context
* @param fileName <p>The file name to fix</p>
* @param isLoading <p>Whether loading from a file as opposed to saving to a file</p>
* @return <p>The fixed name</p>
*/
protected String fixName(String fileName, Boolean isLoading) {
if (isLoading) {
fileName = fileName.replace("_", " ");
} else {
fileName = fileName.replace(" ", "_");
}
return fileName;
}
protected void bookToYml(String path, String fileName, BookMeta book) throws IOException {
FileConfiguration bookYml = YamlConfiguration.loadConfiguration(new File(path, "blank"));
@ -650,7 +427,7 @@ public class BooksWithoutBorders extends JavaPlugin {
return null;
}
List<String> pages = new ArrayList<>(cleanList(rawPages));
List<String> pages = new ArrayList<>(InputCleaningHelper.cleanList(rawPages));
bDat.setAuthor(author);
bDat.setTitle(title);
@ -816,10 +593,90 @@ public class BooksWithoutBorders extends JavaPlugin {
return book;
}
protected Boolean eSave(Player player, BookMeta book, String key) {
/**
* Makes the player pay for printing a given number of books
*
* @param player <p>The player printing the books</p>
* @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 boolean cannotPayForBookPrinting(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
double cost = BooksWithoutBorders.bookPriceQuantity * numCopies;
int itemCost = (int) cost;
if (BooksWithoutBorders.bookPriceType == Material.AIR) {
return !payForBookPrintingEconomy(player, cost, numCopies);
} else {
if (player.getInventory().contains(BooksWithoutBorders.bookPriceType, itemCost)) {
payForBookPrintingItem(player, itemCost);
return false;
} else {
BooksWithoutBorders.sendErrorMessage(player, itemCost + " " + BooksWithoutBorders.bookPriceType.toString() +
"(s) are required for this command!");
return true;
}
}
}
/**
* Uses economy to take payment for printing a number of books
*
* @param player <p>The player which needs to pay</p>
* @param cost <p>The cost of the book printing</p>
* @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 boolean payForBookPrintingEconomy(Player player, double cost, int numCopies) {
Economy economy = BooksWithoutBorders.eco;
if ((economy.getBalance(player) - cost) >= 0) {
economy.withdrawPlayer(player, cost);
BooksWithoutBorders.sendSuccessMessage(player, economy.format(cost) + " withdrawn to create " + numCopies + " book(s)");
BooksWithoutBorders.sendSuccessMessage(player, "New balance: " + economy.format(economy.getBalance(player)));
return true;
} else {
BooksWithoutBorders.sendErrorMessage(player, economy.format(cost) + " is required for this command!");
return false;
}
}
/**
* Takes payment for printing a number of books by withdrawing the correct item
*
* @param player <p>The player which needs to pay</p>
* @param itemCost <p>The number of items to pay</p>
*/
private void payForBookPrintingItem(Player player, int itemCost) {
PlayerInventory playerInventory = player.getInventory();
int clearedAmount = 0;
while (clearedAmount < itemCost) {
int firstItemIndex = playerInventory.first(BooksWithoutBorders.bookPriceType);
ItemStack firstItem = playerInventory.getItem(firstItemIndex);
if (Objects.requireNonNull(firstItem).getAmount() <= itemCost - clearedAmount) {
clearedAmount += firstItem.getAmount();
player.getInventory().clear(firstItemIndex);
} else {
clearedAmount = itemCost;
firstItem.setAmount(firstItem.getAmount() - (clearedAmount));
}
}
}
/**
* Saves an encrypted book to be decryptable for the given user
*
* @param player <p>The player encrypting the book</p>
* @param bookMetaData <p>Metadata for the book to encrypt</p>
* @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>
*/
protected Boolean saveEncryptedBook(Player player, BookMeta bookMetaData, String key) {
String path = bookFolder + "Encrypted" + SLASH;
String fileName = (!book.hasTitle()) ? "Untitled," + player.getName() :
book.getTitle() + titleAuthorSeparator + book.getAuthor();
String fileName = (!bookMetaData.hasTitle()) ? "Untitled," + player.getName() :
bookMetaData.getTitle() + titleAuthorSeparator + bookMetaData.getAuthor();
fileName = "[" + key + "]" + fileName;
fileName = cleanString(fileName);
@ -832,7 +689,7 @@ public class BooksWithoutBorders extends JavaPlugin {
}
try {
bookToYml(path, fileName, book);
bookToYml(path, fileName, bookMetaData);
} catch (IOException e) {
e.printStackTrace();
sendErrorMessage(player, "Encryption failed!");
@ -841,7 +698,15 @@ public class BooksWithoutBorders extends JavaPlugin {
return true;
}
protected BookMeta groupESave(Player player, BookMeta bookMetadata, String groupName) {
/**
* Saves an encrypted book to be decryptable for the given group
*
* @param player <p>The player trying to encrypt the book</p>
* @param bookMetadata <p>Metadata for the book to encrypt</p>
* @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>
*/
protected BookMeta saveEncryptedBookForGroup(Player player, BookMeta bookMetadata, String groupName) {
String path = bookFolder + "Encrypted" + SLASH + cleanString(groupName) + SLASH;
File dirTest = new File(path);
//Creates group dir
@ -863,15 +728,15 @@ public class BooksWithoutBorders extends JavaPlugin {
fileName = cleanString(fileName);
fileName = fixName(fileName, false);
List<String> nuLore = new ArrayList<>();
nuLore.add(ChatColor.GRAY + "[" + groupName + " encrypted]");
List<String> newLore = new ArrayList<>();
newLore.add(ChatColor.GRAY + "[" + groupName + " encrypted]");
if (bookMetadata.hasLore()) {
List<String> oldLore = bookMetadata.getLore();
if (oldLore != null) {
nuLore.addAll(oldLore);
newLore.addAll(oldLore);
}
}
bookMetadata.setLore(nuLore);
bookMetadata.setLore(newLore);
//Save file
File file = (useYml) ? new File(path + fileName + ".yml") : new File(path + fileName + ".txt");
@ -888,7 +753,15 @@ public class BooksWithoutBorders extends JavaPlugin {
return bookMetadata;
}
public ItemStack eLoad(Player player, String key, boolean deleteEncryptedFile) {
/**
* Loads an encrypted book
*
* @param player <p>The player trying to load the book</p>
* @param key <p>The encryption key/password for decryption</p>
* @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 ItemStack loadEncryptedBook(Player player, String key, boolean deleteEncryptedFile) {
ItemStack heldBook = InventoryHelper.getHeldBook(player, true);
BookMeta bookMetadata = (BookMeta) heldBook.getItemMeta();
String path = bookFolder + "Encrypted" + SLASH;
@ -897,7 +770,8 @@ public class BooksWithoutBorders extends JavaPlugin {
return null;
}
String fileName = (!bookMetadata.hasTitle()) ? "Untitled," + player.getName() : bookMetadata.getTitle() + titleAuthorSeparator + bookMetadata.getAuthor();
String fileName = (!bookMetadata.hasTitle()) ? "Untitled," + player.getName() : bookMetadata.getTitle() +
titleAuthorSeparator + bookMetadata.getAuthor();
fileName = "[" + key + "]" + fileName;
fileName = cleanString(fileName);
fileName = fixName(fileName, false);
@ -955,18 +829,6 @@ public class BooksWithoutBorders extends JavaPlugin {
return FileHelper.listFiles(sender, file, silent);
}
/**
* Removes null and empty items from a list
*
* @param list <p>The list to clean</p>
* @return <p>A clean list containing all relevant values</p>
*/
protected List<String> cleanList(List<String> list) {
List<String> resultList = new ArrayList<>(list);
resultList.removeIf((item) -> item == null || item.trim().isEmpty());
return resultList;
}
/**
* Encrypts a book
*
@ -1016,7 +878,7 @@ public class BooksWithoutBorders extends JavaPlugin {
//Format the last page just in case
BookFormatter.formatLastPage(encryptedPages);
//Remove empty pages
List<String> newPages = cleanList(encryptedPages);
List<String> newPages = InputCleaningHelper.cleanList(encryptedPages);
ItemStack encryptedBook = createEncryptedBook(book, newPages, player, newMetadata);
@ -1060,9 +922,9 @@ public class BooksWithoutBorders extends JavaPlugin {
BookMeta newMetadata = book;
boolean wasSaved;
if (groupName.trim().isEmpty()) {
wasSaved = eSave(player, book, integerKey);
wasSaved = saveEncryptedBook(player, book, integerKey);
} else {
newMetadata = groupESave(player, book, groupName);
newMetadata = saveEncryptedBookForGroup(player, book, groupName);
wasSaved = newMetadata != null;
}
if (wasSaved) {
@ -1092,67 +954,6 @@ public class BooksWithoutBorders extends JavaPlugin {
sender.sendMessage(errorColor + message);
}
/**
* Deletes the given book
*
* @param sender <p>The sender of the command to delete the book</p>
* @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 deleteBook(CommandSender sender, String fileName, Boolean isPublic) {
//If the file name is an index of the load list, load the book
try {
int loadListIndex = Integer.parseInt(fileName);
String senderName = sender.getName();
if (loadList.containsKey(senderName) && loadListIndex <= loadList.get(senderName).size()) {
fileName = loadList.get(senderName).get(loadListIndex - 1);
}
} catch (NumberFormatException ignored) {
}
//Get the file to be deleted
File file;
if (isPublic) {
file = FileHelper.getBookFile(bookFolder + fileName);
} else {
file = FileHelper.getBookFile(bookFolder + cleanString(sender.getName()) + SLASH + fileName);
}
//Send message if no such file could be found
if (file == null) {
sendErrorMessage(sender, "Incorrect file name!");
return;
}
//Try to delete the file
try {
if (file.delete()) {
sendSuccessMessage(sender, "\"" + fileName + "\" deleted successfully");
} else {
sendErrorMessage(sender, "Deletion failed without an exception!");
}
} catch (Exception e) {
sendErrorMessage(sender, "Deletion failed!");
}
}
/**
* Un-signs the player's currently held book
*
* @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) {
//Get the old book
BookMeta oldBook = InventoryHelper.getHeldBookMetadata(player, mainHand);
//UnSign the book
ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK);
newBook.setItemMeta(oldBook);
InventoryHelper.replaceHeldItem(player, newBook, mainHand);
}
/**
* Checks whether books have a price for printing them
*
@ -1162,93 +963,4 @@ public class BooksWithoutBorders extends JavaPlugin {
return (bookPriceType != null && bookPriceQuantity > 0);
}
/**
* Makes the player pay for printing a given number of books
*
* @param player <p>The player printing the books</p>
* @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 boolean cannotPayForBookPrinting(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
double cost = bookPriceQuantity * numCopies;
int itemCost = (int) cost;
if (bookPriceType == Material.AIR) {
return !payForBookPrintingEconomy(player, cost, numCopies);
} else {
if (player.getInventory().contains(bookPriceType, itemCost)) {
payForBookPrintingItem(player, itemCost);
return false;
} else {
sendErrorMessage(player, itemCost + " " + bookPriceType.toString() +
"(s) are required for this command!");
return true;
}
}
}
/**
* Takes payment for printing a number of books by withdrawing the correct item
*
* @param player <p>The player which needs to pay</p>
* @param itemCost <p>The number of items to pay</p>
*/
private void payForBookPrintingItem(Player player, int itemCost) {
PlayerInventory playerInventory = player.getInventory();
int clearedAmount = 0;
while (clearedAmount < itemCost) {
int firstItemIndex = playerInventory.first(bookPriceType);
ItemStack firstItem = playerInventory.getItem(firstItemIndex);
if (Objects.requireNonNull(firstItem).getAmount() <= itemCost - clearedAmount) {
clearedAmount += firstItem.getAmount();
player.getInventory().clear(firstItemIndex);
} else {
clearedAmount = itemCost;
firstItem.setAmount(firstItem.getAmount() - (clearedAmount));
}
}
}
/**
* Uses economy to take payment for printing a number of books
*
* @param player <p>The player which needs to pay</p>
* @param cost <p>The cost of the book printing</p>
* @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 boolean payForBookPrintingEconomy(Player player, double cost, int numCopies) {
Economy economy = BooksWithoutBorders.eco;
if ((economy.getBalance(player) - cost) >= 0) {
economy.withdrawPlayer(player, cost);
sendSuccessMessage(player, economy.format(cost) + " withdrawn to create " + numCopies + " book(s)");
sendSuccessMessage(player, "New balance: " + economy.format(economy.getBalance(player)));
return true;
} else {
sendErrorMessage(player, economy.format(cost) + " is required for this command!");
return false;
}
}
/**
* Checks whether the given player is the author of a given book
*
* @param player <p>The player to check</p>
* @param book <p>The book to check</p>
* @return <p>True if the player is the book's author</p>
*/
public boolean isAuthor(Player player, BookMeta book) {
String author = book.getAuthor();
if (author != null && cleanString(player.getName()).equalsIgnoreCase(cleanString(author))) {
return true;
}
sendErrorMessage(player, "You must be the author of this book to use this command!");
return false;
}
}

View File

@ -7,6 +7,7 @@ import java.util.Objects;
import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
import net.knarcraft.bookswithoutborders.utility.EncryptionHelper;
import net.knarcraft.bookswithoutborders.utility.FileHelper;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -58,7 +59,7 @@ public class BooksWithoutBordersListener implements Listener {
fileName = oldBook.getTitle() + BooksWithoutBorders.titleAuthorSeparator + oldBook.getAuthor();
}
String cleanPlayerName = BooksWithoutBorders.bwb.cleanString(player.getName());
String cleanPlayerName = InputCleaningHelper.cleanString(player.getName());
String[] possiblePaths = new String[]{
bookFolder + fileName + ".yml",
@ -359,7 +360,7 @@ public class BooksWithoutBordersListener implements Listener {
String fileName = oldBook.getTitle() + BooksWithoutBorders.titleAuthorSeparator + oldBook.getAuthor();
String encryptionFile = BooksWithoutBorders.bwb.cleanString(groupName) + slash + fileName + ".yml";
String encryptionFile = InputCleaningHelper.cleanString(groupName) + slash + fileName + ".yml";
File file = new File(bookFolder + "Encrypted" + slash + encryptionFile);
if (!file.isFile()) {
@ -446,7 +447,7 @@ public class BooksWithoutBordersListener implements Listener {
String lineText = ChatColor.stripColor(sign.getLine(2));
String key = EncryptionHelper.getNumberKeyFromStringKey(lineText);
ItemStack book = BooksWithoutBorders.bwb.eLoad(player, key, false);
ItemStack book = BooksWithoutBorders.bwb.loadEncryptedBook(player, key, false);
if (book != null) {
player.getInventory().setItem(hand, book);
player.sendMessage(ChatColor.GREEN + "Book decrypted!");

View File

@ -1,12 +1,150 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.bookPriceQuantity;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.bookPriceType;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.commandColor;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.sendErrorMessage;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.sendSuccessMessage;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.successColor;
/**
* Command executor for the books without borders (bwb) command
*/
public class CommandBooksWithoutBorders implements CommandExecutor {
private final BooksWithoutBorders booksWithoutBorders;
public CommandBooksWithoutBorders(BooksWithoutBorders booksWithoutBorders) {
this.booksWithoutBorders = booksWithoutBorders;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return false;
if (sender instanceof Player) {
showPlayerCommands(sender);
} else {
showConsoleCommands(sender);
}
return true;
}
/**
* Shows all commands available to the console
* @param sender <p>The console which sent the command</p>
*/
private void showConsoleCommands(CommandSender sender) {
sender.sendMessage(commandColor + "Use: /bwb [Command]");
sender.sendMessage(commandColor + "[] denote parameters");
sender.sendMessage(commandColor + "Commands:");
sender.sendMessage(commandColor + "\nReload:" + successColor + " Reloads BwB's config file");
sender.sendMessage(commandColor + "givePublic [file name or number] [player name] [true/false]: " + successColor);
sendSuccessMessage(sender, "Gives the selected player a book from the public directory");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
sender.sendMessage(commandColor + "deletePublic [file name or number]: " + successColor + "Deletes the specified");
sendSuccessMessage(sender, "file in the public directory");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
}
/**
* Shows all commands available to the sending player
* @param sender <p>The player which sent the command</p>
*/
private void showPlayerCommands(CommandSender sender) {
//Lists all commands
sender.sendMessage(commandColor + "Use: /bwb [Command]");
sender.sendMessage(commandColor + "[] denote parameters");
if (booksWithoutBorders.booksHavePrice()) {
if (bookPriceType != Material.AIR) {
sendErrorMessage(sender, "[" + (int) bookPriceQuantity + " " + bookPriceType.toString() + "(s) are required to create a book]");
} else {
sendErrorMessage(sender, "[" + BooksWithoutBorders.eco.format(bookPriceQuantity) + " is required to create a book]");
}
}
sender.sendMessage(commandColor + "Commands:");
if (sender.hasPermission("bookswithoutborders.load")) {
sender.sendMessage(commandColor + "\nLoad [file name or number] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Creates a book from the specified file and gives it to the player");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
sendSuccessMessage(sender, "If true is specified the book will be signed, if false it will be");
sendSuccessMessage(sender, "unsigned");
}
if (sender.hasPermission("bookswithoutborders.loadPublic")) {
sender.sendMessage(commandColor + "loadPublic [file name or number] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Same as Load, but views files in the public directory");
}
if (sender.hasPermission("bookswithoutborders.save")) {
sender.sendMessage("\n" + commandColor + "Save [true/false]: " + successColor + "Saves the book the player is");
sendSuccessMessage(sender, "holding to a text file in a private directory");
sendSuccessMessage(sender, "If true is specified, a book of the same name by the same");
sendSuccessMessage(sender, "author will be overwritten by the new book");
}
if (sender.hasPermission("bookswithoutborders.savePublic")) {
sender.sendMessage(commandColor + "savePublic [true/false]: " + successColor + "Same as Save,");
sendSuccessMessage(sender, "but saves files in the public directory");
}
if (sender.hasPermission("bookswithoutborders.give")) {
sender.sendMessage("\n" + commandColor + "Give [file name or number] [player name] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Gives the selected player a book from your personal directory");
}
if (sender.hasPermission("bookswithoutborders.givePublic")) {
sender.sendMessage(commandColor + "givePublic [file name or number] [player name] [# of copies] [true/false]:");
sendSuccessMessage(sender, "Same as give, but uses books from the public directory");
}
if (sender.hasPermission("bookswithoutborders.delete")) {
sender.sendMessage(commandColor + "\nDelete [file name or number]: " + successColor + "Deletes the specified");
sendSuccessMessage(sender, "file in the player's directory");
sendSuccessMessage(sender, "If no file is specified, a list of available files is returned");
}
if (sender.hasPermission("bookswithoutborders.admin")) {
sender.sendMessage(commandColor + "deletePublic [file name or number]: " + successColor + "Same as Delete,");
sendSuccessMessage(sender, "but deletes files in the public directory");
sender.sendMessage(commandColor + "\nReload:" + successColor + " Reloads BwB's configuration file");
}
if (sender.hasPermission("bookswithoutborders.unsign")) {
sender.sendMessage("\n" + commandColor + "Unsign: " + successColor + "Un-signs the book the player is holding");
}
if (sender.hasPermission("bookswithoutborders.copy")) {
sender.sendMessage("\n" + commandColor + "Copy [number of copies]: " + successColor + "Copies the book the player is holding");
}
if (sender.hasPermission("bookswithoutborders.encrypt")) {
sender.sendMessage("\n" + commandColor + "Encrypt [key] [style]: " + successColor + "Encrypts the book the player is holding");
sender.sendMessage(commandColor + "[key]" + successColor + " is required and can be any phrase or number excluding spaces");
sender.sendMessage(commandColor + "[style]" + successColor + " is not required. Possible values are \"DNA\" or \"Magic\"");
}
if (sender.hasPermission("bookswithoutborders.groupEncrypt")) {
sender.sendMessage("\n" + commandColor + "groupEncrypt [group name] [key] [style]: " + successColor + "Encrypts book so that only players with the" +
"\n bookswithoutborders.decrypt." + commandColor + "[group name]" + successColor + " permission may decrypt the book by holding and left clicking the book");
}
if (sender.hasPermission("bookswithoutborders.decrypt")) {
sender.sendMessage("\n" + commandColor + "Decrypt [key]: " + successColor + "Decrypts the book the player is holding");
sender.sendMessage(commandColor + "[key]" + successColor + " is required and MUST be IDENTICAL to the key used to encrypt held book");
}
if (sender.hasPermission("bookswithoutborders.setTitle")) {
sender.sendMessage("\n" + commandColor + "setTitle [title]: " + successColor + "Sets the title of the book/item the player is holding");
}
if (sender.hasPermission("bookswithoutborders.setAuthor")) {
sender.sendMessage("\n" + commandColor + "setAuthor [author]: " + successColor + "Sets the author of the book the player is holding");
}
if (sender.hasPermission("bookswithoutborders.setLore")) {
sender.sendMessage("\n" + commandColor + "setLore [lore]: " + successColor + "Sets the lore of the item the player is holding");
sendSuccessMessage(sender, "Insert the lore_line_separator character to force a new line\n[\"~\" by default]");
}
if (sender.hasPermission("bookswithoutborders.setBookPrice")) {
sender.sendMessage("\n" + commandColor + "setBookPrice [Item/Eco] [quantity]: " + successColor + "Sets the per-book-price to create a book via commands." +
"\nIf [Item], the item in the player's hand in the amount of [quantity] will be the price.\nIf [Eco], a Vault based economy will be used for price." +
"\nIf neither [Item/Eco] or [quantity] are specified the current price to create books will be removed.");
}
}
}

View File

@ -1,6 +1,7 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -45,7 +46,7 @@ public class CommandCopy implements CommandExecutor {
int copies = Integer.parseInt(args[0]);
if (copies > 0) {
if (BooksWithoutBorders.authorOnlyCopy && !player.hasPermission("bookswithoutborders.bypassAuthorOnlyCopy")) {
if (!booksWithoutBorders.isAuthor(player, (BookMeta) Objects.requireNonNull(heldBook.getItemMeta())))
if (!isAuthor(player, (BookMeta) Objects.requireNonNull(heldBook.getItemMeta())))
return false;
}
@ -70,4 +71,22 @@ public class CommandCopy implements CommandExecutor {
return true;
}
/**
* Checks whether the given player is the author of a given book
*
* @param player <p>The player to check</p>
* @param book <p>The book to check</p>
* @return <p>True if the player is the book's author</p>
*/
private boolean isAuthor(Player player, BookMeta book) {
String author = book.getAuthor();
String playerName = InputCleaningHelper.cleanString(player.getName());
if (author != null && playerName.equalsIgnoreCase(InputCleaningHelper.cleanString(author))) {
return true;
}
BooksWithoutBorders.sendErrorMessage(player, "You must be the author of this book to use this command!");
return false;
}
}

View File

@ -71,7 +71,7 @@ public class CommandDecrypt implements CommandExecutor {
if (!key.equalsIgnoreCase("")) {
//Decrypt the book
ItemStack book = booksWithoutBorders.eLoad(player, key, false);
ItemStack book = booksWithoutBorders.loadEncryptedBook(player, key, false);
if (book != null) {
InventoryHelper.setHeldWrittenBook(player, book);
BooksWithoutBorders.sendSuccessMessage(player, "Book auto-decrypted!");
@ -91,7 +91,7 @@ public class CommandDecrypt implements CommandExecutor {
String key = EncryptionHelper.getNumberKeyFromStringKey(args[0]);
//Decrypt the book
ItemStack book = booksWithoutBorders.eLoad(player, key, true);
ItemStack book = booksWithoutBorders.loadEncryptedBook(player, key, true);
if (book != null) {
InventoryHelper.setHeldWrittenBook(player, book);
BooksWithoutBorders.sendSuccessMessage(player, "Book decrypted!");

View File

@ -1,11 +1,15 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.FileHelper;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.io.File;
/**
* Command executor for the delete command
*/
@ -47,7 +51,7 @@ public class CommandDelete implements CommandExecutor {
return false;
} else {
if (!BooksWithoutBorders.loadList.get(sender.getName()).isEmpty()) {
booksWithoutBorders.deleteBook(sender, args[0], deletePublic);
performBookDeletion(sender, args[0], deletePublic);
return true;
} else {
BooksWithoutBorders.sendErrorMessage(sender, "No files available to delete!");
@ -59,4 +63,49 @@ public class CommandDelete implements CommandExecutor {
return false;
}
/**
* Deletes the given book
*
* @param sender <p>The sender of the command to delete the book</p>
* @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) {
//If the file name is an index of the load list, load the book
try {
int loadListIndex = Integer.parseInt(fileName);
String senderName = sender.getName();
if (BooksWithoutBorders.loadList.containsKey(senderName) && loadListIndex <= BooksWithoutBorders.loadList.get(senderName).size()) {
fileName = BooksWithoutBorders.loadList.get(senderName).get(loadListIndex - 1);
}
} catch (NumberFormatException ignored) {
}
//Get the file to be deleted
File file;
if (isPublic) {
file = FileHelper.getBookFile(BooksWithoutBorders.bookFolder + fileName);
} else {
file = FileHelper.getBookFile(BooksWithoutBorders.bookFolder +
InputCleaningHelper.cleanString(sender.getName()) + BooksWithoutBorders.SLASH + fileName);
}
//Send message if no such file could be found
if (file == null) {
BooksWithoutBorders.sendErrorMessage(sender, "Incorrect file name!");
return;
}
//Try to delete the file
try {
if (file.delete()) {
BooksWithoutBorders.sendSuccessMessage(sender, "\"" + fileName + "\" deleted successfully");
} else {
BooksWithoutBorders.sendErrorMessage(sender, "Deletion failed without an exception!");
}
} catch (Exception e) {
BooksWithoutBorders.sendErrorMessage(sender, "Deletion failed!");
}
}
}

View File

@ -1,6 +1,7 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@ -68,7 +69,7 @@ public class CommandGive implements CommandExecutor {
return false;
}
String bookToLoad = booksWithoutBorders.cleanString(bookIdentifier);
String bookToLoad = InputCleaningHelper.cleanString(bookIdentifier);
try {
ItemStack newBook = booksWithoutBorders.loadBook(player, bookToLoad, isSigned, "player", Integer.parseInt(copies));
if (newBook != null) {

View File

@ -1,12 +1,87 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.cleanString;
/**
* Command executor for the give public command
*/
public class CommandGivePublic implements CommandExecutor {
private final BooksWithoutBorders booksWithoutBorders;
public CommandGivePublic(BooksWithoutBorders booksWithoutBorders) {
this.booksWithoutBorders = booksWithoutBorders;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (sender instanceof Player) {
if (!sender.hasPermission("bookswithoutborders.givePublic")) {
BooksWithoutBorders.sendErrorMessage(sender, " You don't have permission to use this command!");
return false;
}
}
if (args.length == 2 || args.length > 5) {
BooksWithoutBorders.sendErrorMessage(sender, "Incorrect number of arguments for this command!");
return false;
}
if (args.length == 1) {
BooksWithoutBorders.loadList.put(sender.getName(), booksWithoutBorders.listFiles(sender, true, false));
return true;
}
for (int x = 0; x < args[1].length(); x++) {
if (!Character.isDigit(args[1].charAt(x)))
break;
if (x == args[1].length() - 1)
BooksWithoutBorders.loadList.put(sender.getName(), booksWithoutBorders.listFiles(sender, true, true));
}
ItemStack newBook;
Player receivingPlayer = booksWithoutBorders.getServer().getPlayer(args[2]);
if (receivingPlayer == null) {
BooksWithoutBorders.sendErrorMessage(sender, "Player not found!");
return false;
}
if (receivingPlayer.getInventory().firstEmpty() == -1) {
BooksWithoutBorders.sendErrorMessage(sender, "Receiving player must have space in their inventory to receive books!");
return false;
}
//bwb give [book name] [player] [numCopies] [is signed]
try {
if (args.length == 5)
newBook = booksWithoutBorders.loadBook(sender, cleanString(args[1]), args[4], "public", Integer.parseInt(args[3]));
else if (args.length == 4) {
if (args[3].equalsIgnoreCase("true") || args[3].equalsIgnoreCase("false"))
newBook = booksWithoutBorders.loadBook(sender, cleanString(args[1]), args[3], "public");
else
newBook = booksWithoutBorders.loadBook(sender, cleanString(args[1]), "true", "public", Integer.parseInt(args[3]));
} else
newBook = booksWithoutBorders.loadBook(sender, cleanString(args[1]), "true", "public");
if (newBook != null) {
receivingPlayer.getInventory().addItem(newBook);
BooksWithoutBorders.sendSuccessMessage(sender, "Book sent!");
BooksWithoutBorders.sendSuccessMessage(receivingPlayer, "Book received!");
return true;
} else {
BooksWithoutBorders.sendErrorMessage(sender, "Book failed to load!");
return false;
}
} catch (NumberFormatException e) {
BooksWithoutBorders.sendErrorMessage(sender, "Invalid number of book copies specified!");
return false;
}
}
}

View File

@ -1,6 +1,7 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@ -71,7 +72,7 @@ public class CommandLoad implements CommandExecutor {
BooksWithoutBorders.loadList.put(player.getName(), booksWithoutBorders.listFiles(player, loadPublic, true));
} catch (NumberFormatException ignored) {}
String bookToLoad = booksWithoutBorders.cleanString(bookIdentifier);
String bookToLoad = InputCleaningHelper.cleanString(bookIdentifier);
try {
//Give the new book if it cannot be loaded
ItemStack newBook = booksWithoutBorders.loadBook(player, bookToLoad, isSigned, directory, Integer.parseInt(copies));

View File

@ -0,0 +1,30 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
/**
* Command executor for the reload command
*/
public class CommandReload implements CommandExecutor {
private final BooksWithoutBorders booksWithoutBorders;
public CommandReload(BooksWithoutBorders booksWithoutBorders) {
this.booksWithoutBorders = booksWithoutBorders;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (booksWithoutBorders.loadConfig() && booksWithoutBorders.loadExistingPlayers()) {
BooksWithoutBorders.sendSuccessMessage(sender, "BooksWithoutBorders configuration reloaded!");
} else {
BooksWithoutBorders.sendErrorMessage(sender, "Reload Failed!");
BooksWithoutBorders.sendErrorMessage(sender, "See console for details");
}
return true;
}
}

View File

@ -3,22 +3,19 @@ package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.state.ItemSlot;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
/**
* Command executor for the unsign command
*/
public class CommandUnSign implements CommandExecutor {
private final BooksWithoutBorders booksWithoutBorders;
public CommandUnSign(BooksWithoutBorders booksWithoutBorders) {
this.booksWithoutBorders = booksWithoutBorders;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
@ -33,7 +30,24 @@ public class CommandUnSign implements CommandExecutor {
//Find which hand the player is using to hold the book. If holding one in each, throw an error
ItemSlot holdingSlot = InventoryHelper.getHeldSlotBook(player, false, false, true, true);
booksWithoutBorders.unSignHeldBook(player, holdingSlot == ItemSlot.MAIN_HAND);
unSignHeldBook(player, holdingSlot == ItemSlot.MAIN_HAND);
return true;
}
/**
* Un-signs the player's currently held book
*
* @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) {
//Get the old book
BookMeta oldBook = InventoryHelper.getHeldBookMetadata(player, mainHand);
//UnSign the book
ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK);
newBook.setItemMeta(oldBook);
InventoryHelper.replaceHeldItem(player, newBook, mainHand);
}
}

View File

@ -11,6 +11,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Tab completer for the save command
*/
public class GiveTabCompleter implements TabCompleter {
final BooksWithoutBorders booksWithoutBorders;

View File

@ -0,0 +1,55 @@
package net.knarcraft.bookswithoutborders.utility;
import java.util.ArrayList;
import java.util.List;
public class InputCleaningHelper {
/**
* Removes null and empty items from a list
*
* @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) {
List<String> resultList = new ArrayList<>(list);
resultList.removeIf((item) -> item == null || item.trim().isEmpty());
return resultList;
}
/**
* Removes any special character from a filename
*
* @param fileName <p>The file name to clean</p>
* @return <p>The cleaned file name</p>
*/
public static String cleanString(String fileName) {
fileName = fileName.replace("/", "");
fileName = fileName.replace("\\", "");
fileName = fileName.replace("*", "");
fileName = fileName.replace(":", "");
fileName = fileName.replace("|", "");
fileName = fileName.replace("<", "");
fileName = fileName.replace(">", "");
fileName = fileName.replace("?", "");
fileName = fileName.replace("\"", "");
return fileName;
}
/**
* Changes spaces to underscores or underscores to spaces, depending on context
*
* @param fileName <p>The file name to fix</p>
* @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) {
if (isLoading) {
fileName = fileName.replace("_", " ");
} else {
fileName = fileName.replace(" ", "_");
}
return fileName;
}
}

View File

@ -17,6 +17,10 @@ commands:
description: Gives the held book to another player
usage: /<command> <file name or number> <playername> [# of copies (num)] [signed (true/false)]
permission: bookswithoutborders.give
givepublic:
description: Gives a public book to a player
usage: /<command>
permission: bookswithoutborders.givepublic
decrypt:
description: Decrypts the held book
usage: /<command> <key>
@ -77,7 +81,16 @@ commands:
description: Loads a previously saved book from the public books folder
usage: /<command> <file name or number> [copies] [is signed (true/false)]
permission: bookswithoutborders.loadpublic
reload:
description: Reloads configuration from disk
usage: /<command>
permission: bookswithoutborders.admin
permissions:
bookswithoutborders.*:
description: Grants all permissions
default: op
children:
bookswithoutborders.admin: true
bookswithoutborders.admin:
description: Grants all permissions
default: op