diff --git a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java index f0a9cbc..5809768 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java @@ -12,6 +12,7 @@ import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Objects; import net.milkbowl.vault.economy.Economy; import org.bukkit.ChatColor; @@ -25,6 +26,7 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.Plugin; @@ -400,6 +402,7 @@ public class BooksWithoutBorders extends JavaPlugin { //Player only commands if (sender instanceof Player) { + Player player = (Player) sender; if (args[0].equalsIgnoreCase("savePublic")) { if (!sender.hasPermission("bookswithoutborders.savepublic")) { @@ -407,9 +410,9 @@ public class BooksWithoutBorders extends JavaPlugin { return false; } - if (((Player) sender).getItemInHand().getType() == Material.WRITTEN_BOOK || ((Player) sender).getItemInHand().getType() == Material.WRITABLE_BOOK) { + if (player.getItemInHand().getType() == Material.WRITTEN_BOOK || player.getItemInHand().getType() == Material.WRITABLE_BOOK) { if (args.length == 2) { - saveBook((Player) sender, args[1], true); + saveBook(player, args[1], true); } else { saveBook((Player) sender, "false", true); } @@ -563,13 +566,13 @@ public class BooksWithoutBorders extends JavaPlugin { } ItemStack newBook; - Player player = this.getServer().getPlayer(args[2]); - if (player == null) { + Player receivingPlayer = this.getServer().getPlayer(args[2]); + if (receivingPlayer == null) { sender.sendMessage(ChatColor.RED + "Player not found!"); return false; } - if (player.getInventory().firstEmpty() == -1) { + if (receivingPlayer.getInventory().firstEmpty() == -1) { sender.sendMessage(ChatColor.RED + "Receiving player must have space in their inventory to receive books!"); return false; } @@ -588,9 +591,9 @@ public class BooksWithoutBorders extends JavaPlugin { newBook = loadBook(sender, cleanString(args[1]), "true", "player"); if (newBook != null) { - player.getInventory().addItem(newBook); + receivingPlayer.getInventory().addItem(newBook); sender.sendMessage(ChatColor.GREEN + "Book sent!"); - player.sendMessage(ChatColor.GREEN + "Book received!"); + receivingPlayer.sendMessage(ChatColor.GREEN + "Book received!"); return true; } else { sender.sendMessage(ChatColor.RED + "Book failed to load!"); @@ -641,7 +644,18 @@ public class BooksWithoutBorders extends JavaPlugin { return false; } - unsign((Player) sender); + boolean hasBookInMainHand = player.getInventory().getItemInMainHand().getType() == Material.WRITTEN_BOOK; + boolean hasBookInOffHand = player.getInventory().getItemInOffHand().getType() == Material.WRITTEN_BOOK; + + //Find which hand the player is using to hold the book. If holding one in each, throw an error + if (hasBookInMainHand && hasBookInOffHand) { + sender.sendMessage(ChatColor.RED + "You cannot un-sign two books at once. Please un-equip one " + + "of the books you're holding!"); + } else if (hasBookInMainHand) { + unSignHeldBook(player, true); + } else if (hasBookInOffHand) { + unSignHeldBook(player, false); + } return true; } @@ -668,9 +682,10 @@ public class BooksWithoutBorders extends JavaPlugin { return false; } - if (BooksHavePrice() && !sender.hasPermission("bookswithoutborders.bypassbookprice")) { - if (!printBook((Player) sender, Integer.parseInt(args[1]))) - return false; + if (BooksHavePrice() && + !sender.hasPermission("bookswithoutborders.bypassbookprice") && + cannotPayForBookPrinting((Player) sender, Integer.parseInt(args[1]))) { + return false; } ((Player) sender).getItemInHand().setAmount(((Player) sender).getItemInHand().getAmount() + Integer.parseInt(args[1])); @@ -959,13 +974,13 @@ public class BooksWithoutBorders extends JavaPlugin { } ItemStack newBook; - Player player = this.getServer().getPlayer(args[2]); - if (player == null) { + Player receivingPlayer = this.getServer().getPlayer(args[2]); + if (receivingPlayer == null) { sender.sendMessage(ChatColor.RED + "Player not found!"); return false; } - if (player.getInventory().firstEmpty() == -1) { + if (receivingPlayer.getInventory().firstEmpty() == -1) { sender.sendMessage(ChatColor.RED + "Receiving player must have space in their inventory to receive books!"); return false; } @@ -982,9 +997,9 @@ public class BooksWithoutBorders extends JavaPlugin { newBook = loadBook(sender, cleanString(args[1]), "true", "public"); if (newBook != null) { - player.getInventory().addItem(newBook); + receivingPlayer.getInventory().addItem(newBook); sender.sendMessage(ChatColor.GREEN + "Book sent!"); - player.sendMessage(ChatColor.GREEN + "Book received!"); + receivingPlayer.sendMessage(ChatColor.GREEN + "Book received!"); return true; } else { sender.sendMessage(ChatColor.RED + "Book failed to load!"); @@ -1420,9 +1435,10 @@ public class BooksWithoutBorders extends JavaPlugin { book.setAmount(numCopies); if (BooksHavePrice() && !sender.hasPermission("bookswithoutborders.bypassbookprice") && - (dir.equalsIgnoreCase("public") || dir.equalsIgnoreCase("player") || dir.equalsIgnoreCase(""))) { - if (!printBook((Player) sender, numCopies)) - return null; + (dir.equalsIgnoreCase("public") || dir.equalsIgnoreCase("player") || + dir.equalsIgnoreCase("")) && + cannotPayForBookPrinting((Player) sender, numCopies)) { + return null; } return book; @@ -1743,52 +1759,110 @@ public class BooksWithoutBorders extends JavaPlugin { sender.sendMessage(ChatColor.GREEN + "\"" + fname + "\" deleted successfully"); } - protected void unsign(Player player) { - BookMeta oldbook = (BookMeta) player.getItemInHand().getItemMeta(); - ItemStack newbook = new ItemStack(Material.WRITABLE_BOOK); - newbook.setItemMeta(oldbook); + /** + * Unsigns the player's currently held book + * @param player

The player holding the book

+ * @param mainHand

Whether the player is holding the book in its main hand or its off hand

+ */ + protected void unSignHeldBook(Player player, boolean mainHand) { + //Get the old book + BookMeta oldBook; + if (mainHand) { + oldBook = (BookMeta) player.getInventory().getItemInMainHand().getItemMeta(); + } else { + oldBook = (BookMeta) player.getInventory().getItemInOffHand().getItemMeta(); + } - player.setItemInHand(newbook); + //UnSign the book + ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK); + newBook.setItemMeta(oldBook); + + if (mainHand) { + player.getInventory().setItemInMainHand(newBook); + } else { + player.getInventory().setItemInOffHand(newBook); + } } protected boolean BooksHavePrice() { return (bookPriceType != null && bookPriceQuantity > 0); } - protected boolean printBook(Player player, int numCopies) { + /** + * Makes the player pay for printing a given number of books + * @param player

The player printing the books

+ * @param numCopies

The number of copies the player is trying to print

+ * @return

True if the player cannot pay for the printing of the books

+ */ + protected 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) { - if ((BooksWithoutBorders.eco.getBalance(player.getName()) - (bookPriceQuantity * numCopies)) >= 0) { - BooksWithoutBorders.eco.withdrawPlayer(player.getName(), (bookPriceQuantity * numCopies)); - player.sendMessage(ChatColor.GREEN + BooksWithoutBorders.eco.format(bookPriceQuantity * numCopies) + " withdrawn to create " + numCopies + " book(s)"); - player.sendMessage(ChatColor.GREEN + "New balance: " + BooksWithoutBorders.eco.format(BooksWithoutBorders.eco.getBalance(player.getName()))); - return true; - } else { - player.sendMessage(ChatColor.RED + BooksWithoutBorders.eco.format(bookPriceQuantity * numCopies) + " is required for this command!"); + return !payForBookPrintingEconomy(player, cost, numCopies); + } else { + if (player.getInventory().contains(bookPriceType, itemCost)) { + payForBookPrintingItem(player, itemCost); return false; + } else { + player.sendMessage(ChatColor.RED + String.valueOf(itemCost) + " " + bookPriceType.toString() + + "(s) are required for this command!"); + return true; } - } else if (player.getInventory().contains(bookPriceType, (int) bookPriceQuantity * numCopies)) { - - int clearedAmount = 0, reqAmount = (int) bookPriceQuantity * numCopies; - while (clearedAmount != reqAmount) { - if (player.getInventory().getItem(player.getInventory().first(bookPriceType)).getAmount() <= reqAmount - clearedAmount) { - clearedAmount += player.getInventory().getItem(player.getInventory().first(bookPriceType)).getAmount(); - player.getInventory().clear(player.getInventory().first(bookPriceType)); - } else { - clearedAmount = reqAmount; - player.getInventory().getItem(player.getInventory().first(bookPriceType)).setAmount(player.getInventory().getItem(player.getInventory().first(bookPriceType)).getAmount() - (clearedAmount)); - } - } - return true; } - - player.sendMessage(ChatColor.RED + String.valueOf((int) bookPriceQuantity * numCopies) + " " + bookPriceType.toString() + "(s) are required for this command!"); - return false; } - protected boolean printBook(Player player) { - return printBook(player, 1); + /** + * Takes payment for printing a number of books by withdrawing the correct item + * @param player

The player which needs to pay

+ * @param itemCost

The number of items to pay

+ */ + 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

The player which needs to pay

+ * @param cost

The cost of the book printing

+ * @param numCopies

The number of books the player is printing

+ * @return

True if the player had the money and it has been withdrawn

+ */ + private boolean payForBookPrintingEconomy(Player player, double cost, int numCopies) { + Economy economy = BooksWithoutBorders.eco; + if ((economy.getBalance(player) - cost) >= 0) { + economy.withdrawPlayer(player, cost); + player.sendMessage(ChatColor.GREEN + economy.format(cost) + " withdrawn to create " + numCopies + " book(s)"); + player.sendMessage(ChatColor.GREEN + "New balance: " + economy.format(economy.getBalance(player))); + return true; + } else { + player.sendMessage(ChatColor.RED + economy.format(cost) + " is required for this command!"); + return false; + } + } + + /** + * Checks whether the given player is the author of a given book + * @param player

The player to check

+ * @param book

The book to check

+ * @return

True if the player is the book's author

+ */ protected boolean isAuthor(Player player, BookMeta book) { String author = book.getAuthor(); if (author != null && cleanString(player.getName()).equalsIgnoreCase(cleanString(author))) {