Moves some code to the Economy helper, and fixes code formatting

This commit is contained in:
Kristian Knarvik 2021-09-04 20:23:26 +02:00
parent a9f2017a40
commit ef3815f91a
12 changed files with 158 additions and 109 deletions

View File

@ -28,23 +28,20 @@ Books without Borders has got your back!
### Signs
This plugin supports several custom signs with special functionality.
Each plugin sign must have [BwB] on its first line.
This plugin supports several custom signs with special functionality. Each plugin sign must have [BwB] on its first
line.
#### Give sign
The **_give_** sign must have **[Give]** on its second line.
The third and fourth line contains the book to be loaded.
This can either be a numerical id pointing to a publicly saved book,
or the full text identifier of the book (book name, author).
The **_give_** sign must have **[Give]** on its second line. The third and fourth line contains the book to be loaded.
This can either be a numerical id pointing to a publicly saved book, or the full text identifier of the book (book name,
author).
#### Encrypt sign
The **_encrypt_** sign must have **[Encrypt]** on its second line.
The third line must contain the encryption key
The fourth line can be empty or contain "dna" for dna-based encryption.
The **_encrypt_** sign must have **[Encrypt]** on its second line. The third line must contain the encryption key The
fourth line can be empty or contain "dna" for dna-based encryption.
#### Decrypt sign
The **_decrypt_** sign must have **[Decrypt]** on its second line.
The third line must contain the decryption key
The **_decrypt_** sign must have **[Decrypt]** on its second line. The third line must contain the decryption key

View File

@ -36,7 +36,6 @@ import org.bukkit.configuration.Configuration;
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.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
@ -46,7 +45,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static net.knarcraft.bookswithoutborders.BooksWithoutBordersSettings.getBookFolder;
import static net.knarcraft.bookswithoutborders.BooksWithoutBordersSettings.getErrorColor;
@ -75,6 +73,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets the console sender for printing to the console
*
* @return <p>The console's console sender</p>
*/
public static ConsoleCommandSender getConsoleSender() {
@ -83,7 +82,8 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets available books
* @param sender <p>The sender wanting to see available books</p>
*
* @param sender <p>The sender wanting to see available books</p>
* @param getPublic <p>Whether to get available public books</p>
* @return <p>A list of available books</p>
*/
@ -102,7 +102,8 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Updates available books
* @param sender <p>The sender to update books for</p>
*
* @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) {
@ -137,6 +138,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets whether only the author of a book should be able to copy it
*
* @return <p>Whether only the book author can copy it</p>
*/
public static boolean getAuthorOnlyCopy() {
@ -145,6 +147,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets whether to use YML, not TXT, for saving books
*
* @return <p>Whether to use YML for saving books</p>
*/
public static boolean getUseYml() {
@ -153,6 +156,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets whether admins should be able to decrypt books without a password, and decrypt all group encrypted books
*
* @return <p>Whether admins can bypass the encryption password</p>
*/
public static boolean getAdminDecrypt() {
@ -161,6 +165,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Sets the quantity of items/currency necessary for copying books
*
* @param newQuantity <p>The new quantity necessary for payment</p>
*/
public static void setBookPriceQuantity(double newQuantity) {
@ -169,6 +174,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets the quantity of items/currency necessary for copying books
*
* @return <p>The quantity necessary for payment</p>
*/
public static double getBookPriceQuantity() {
@ -201,6 +207,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets the welcome message to show to new players
*
* @return <p>The welcome message to show new players</p>
*/
public static String getWelcomeMessage() {
@ -209,6 +216,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets the limit of duplicates for each book
*
* @return <p>The book duplicate limit</p>
*/
public static int getBookDuplicateLimit() {
@ -217,6 +225,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets the separator used to split book title from book author
*
* @return <p>The separator between title and author</p>
*/
public static String getTitleAuthorSeparator() {
@ -225,6 +234,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets the separator used to denote a newline in a lore string
*
* @return <p>The separator used to denote lore newline</p>
*/
public static String getLoreSeparator() {
@ -233,6 +243,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets a copy of the list of books to give new players
*
* @return <p>The books to give new players</p>
*/
public static List<String> getFirstBooks() {
@ -241,6 +252,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Gets an instance of this plugin
*
* @return <p>An instance of this plugin</p>
*/
public static BooksWithoutBorders getInstance() {
@ -314,6 +326,7 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Makes sure necessary folders exist
*
* @return <p>True if necessary folders exist</p>
*/
private boolean testFileSaving() {
@ -440,9 +453,10 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Loads the given book
* @param sender <p>The command sender trying to load the book</p>
* @param fileName <p>The index or file name of the book to load</p>
* @param isSigned <p>Whether to load the book as signed, and not unsigned</p>
*
* @param sender <p>The command sender trying to load the book</p>
* @param fileName <p>The index or file name of the book to load</p>
* @param isSigned <p>Whether to load the book as signed, and not unsigned</p>
* @param directory <p>The directory to save the book in</p>
* @return <p>The loaded book</p>
*/
@ -452,9 +466,10 @@ public class BooksWithoutBorders extends JavaPlugin {
/**
* Loads the given book
* @param sender <p>The command sender trying to load the book</p>
* @param fileName <p>The index or file name of the book to load</p>
* @param isSigned <p>Whether to load the book as signed, and not unsigned</p>
*
* @param sender <p>The command sender trying to load the book</p>
* @param fileName <p>The index or file name of the book to load</p>
* @param isSigned <p>Whether to load the book as signed, and not unsigned</p>
* @param directory <p>The directory to save the book in</p>
* @param numCopies <p>The number of copies to load</p>
* @return <p>The loaded book</p>
@ -469,26 +484,19 @@ public class BooksWithoutBorders extends JavaPlugin {
if (bookIndex <= availableFiles.size()) {
fileName = availableFiles.get(Integer.parseInt(fileName) - 1);
}
} catch (NumberFormatException ignored) {}
} catch (NumberFormatException ignored) {
}
//Get the full path of the book to load
File file = null;
if (bookDirectory == BookDirectory.PUBLIC) {
file = FileHelper.getBookFile(getBookFolder() + fileName);
} else if (bookDirectory == BookDirectory.PLAYER) {
file = FileHelper.getBookFile(getBookFolder() + cleanString(sender.getName()) + getSlash() + fileName);
} else if (bookDirectory == BookDirectory.ENCRYPTED) {
file = FileHelper.getBookFile(getBookFolder() + "Encrypted" + getSlash() + directory + getSlash() + fileName);
}
if (file == null || !file.isFile()) {
sendErrorMessage(sender, "Incorrect file name!");
File file = getFullPath(sender, fileName, bookDirectory, directory);
if (file == null) {
return null;
}
//Make sure the player can pay for the book
if (booksHavePrice() && !sender.hasPermission("bookswithoutborders.bypassBookPrice") &&
(bookDirectory == BookDirectory.PUBLIC || bookDirectory == BookDirectory.PLAYER) &&
cannotPayForBookPrinting((Player) sender, numCopies)) {
EconomyHelper.cannotPayForBookPrinting((Player) sender, numCopies)) {
return null;
}
@ -526,53 +534,28 @@ public class BooksWithoutBorders extends JavaPlugin {
}
/**
* Makes the player pay for printing a given number of books
* Gets a File pointing to the wanted book
*
* @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>
* @param sender <p>The sender to send errors to</p>
* @param fileName <p>The name of the book file</p>
* @param bookDirectory <p>The book directory the file resides in</p>
* @param directory <p>The relative directory given</p>
* @return <p>A file or null if it does not exist</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 !EconomyHelper.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;
}
private File getFullPath(CommandSender sender, String fileName, BookDirectory bookDirectory, String directory) {
File file = null;
if (bookDirectory == BookDirectory.PUBLIC) {
file = FileHelper.getBookFile(getBookFolder() + fileName);
} else if (bookDirectory == BookDirectory.PLAYER) {
file = FileHelper.getBookFile(getBookFolder() + cleanString(sender.getName()) + getSlash() + fileName);
} else if (bookDirectory == BookDirectory.ENCRYPTED) {
file = FileHelper.getBookFile(getBookFolder() + "Encrypted" + getSlash() + directory + getSlash() + fileName);
}
}
/**
* 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));
}
if (file == null || !file.isFile()) {
sendErrorMessage(sender, "Incorrect file name!");
return null;
} else {
return file;
}
}

View File

@ -87,8 +87,9 @@ public class CommandBooksWithoutBorders implements CommandExecutor {
/**
* Shows information about the given command
*
* @param command <p>The command to get information about</p>
* @param sender <p>The sender asking to see command info</p>
* @param sender <p>The sender asking to see command info</p>
*/
private void showCommandInfo(String command, CommandSender sender) {
PluginCommand pluginCommand = BooksWithoutBorders.getInstance().getCommand(command);

View File

@ -1,6 +1,7 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.EconomyHelper;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import org.bukkit.command.Command;
@ -48,23 +49,19 @@ public class CommandCopy implements CommandExecutor {
if (booksWithoutBorders.booksHavePrice() &&
!player.hasPermission("bookswithoutborders.bypassBookPrice") &&
booksWithoutBorders.cannotPayForBookPrinting(player, copies)) {
EconomyHelper.cannotPayForBookPrinting(player, copies)) {
return false;
}
heldBook.setAmount(heldBook.getAmount() + copies);
BooksWithoutBorders.sendSuccessMessage(player, "Book copied!");
} else {
BooksWithoutBorders.sendErrorMessage(player, "Book not copied!");
BooksWithoutBorders.sendErrorMessage(player, "Number specified was invalid!");
return false;
return true;
}
} catch (NumberFormatException e) {
BooksWithoutBorders.sendErrorMessage(player, "Book not copied!");
BooksWithoutBorders.sendErrorMessage(player, "Number specified was invalid!");
return false;
} catch (NumberFormatException ignored) {
}
return true;
BooksWithoutBorders.sendErrorMessage(player, "Book not copied!");
BooksWithoutBorders.sendErrorMessage(player, "Number specified was invalid!");
return false;
}
/**

View File

@ -28,10 +28,11 @@ public class CommandGive implements CommandExecutor {
/**
* 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 sender <p>The sender trying to give a book</p>
* @param args <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>
* @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) {

View File

@ -1,7 +1,6 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.FileHelper;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;

View File

@ -32,8 +32,9 @@ public class AES {
/**
* Instantiates a new AES encryptor
*
* @param initializationVector <p>The initialization vector to use for CBC</p>
* @param passwordSalt <p>The password salt to use</p>
* @param passwordSalt <p>The password salt to use</p>
*/
public AES(byte[] initializationVector, byte[] passwordSalt) {
this.ivParameterSpec = new IvParameterSpec(initializationVector);
@ -42,9 +43,10 @@ public class AES {
/**
* Encrypts or decrypts the given text
* @param input <p>The input to encrypt or decrypt</p>
*
* @param input <p>The input to encrypt or decrypt</p>
* @param password <p>The password to use for key generation</p>
* @param encrypt <p>Whether to encrypt or decrypt the input</p>
* @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) {
@ -80,6 +82,7 @@ public class AES {
/**
* Generates a 16-byte initialization vector
*
* @return <p>An initialization vector</p>
*/
public static byte[] generateIV() {
@ -91,7 +94,8 @@ public class AES {
/**
* Transforms the input string into bytes
* @param input <p>The input to encrypt or decrypt</p>
*
* @param input <p>The input to encrypt or decrypt</p>
* @param encryption <p>Whether the input should be encrypted or decrypted</p>
* @return <p>The input in byte format</p>
*/
@ -105,7 +109,8 @@ public class AES {
/**
* Transforms the result bytes into a string
* @param output <p>The output from encryption or decryption</p>
*
* @param output <p>The output from encryption or decryption</p>
* @param encryption <p>Whether the output came from encryption or decryption</p>
* @return <p>The output as a string</p>
*/
@ -119,6 +124,7 @@ public class AES {
/**
* Gets an AES cipher instance
*
* @return <p>An AES cipher instance, or null if something went wrong</p>
*/
private Cipher getAESCipher() {
@ -134,6 +140,7 @@ public class AES {
/**
* Gets an encryption key from a supplied password
*
* @param password <p>A user supplied password</p>
* @return <p>A secret key spec or null if something went wrong</p>
*/

View File

@ -96,11 +96,11 @@ public class SignEventListener implements Listener {
} else if (signLineEquals(sign, 1, "[Decrypt]", ChatColor.DARK_BLUE)) {
decryptHeldBookUsingSign(sign, heldItemType, player, hand);
} else if (signLineEquals(sign, 1, "[Give]", ChatColor.DARK_BLUE) &&
getSignLineColor(sign, 2) == ChatColor.DARK_GREEN) {
getSignLine2Color(sign) == ChatColor.DARK_GREEN) {
giveBook(sign, player);
} else {
player.sendMessage("Sign command " + sign.getLine(1) + " " + sign.getLine(2) + " invalid");
player.sendMessage(String.valueOf(getSignLineColor(sign, 2)));
player.sendMessage(String.valueOf(getSignLine2Color(sign)));
}
}
} else if (heldItemType == Material.WRITTEN_BOOK && (event.getAction() == Action.LEFT_CLICK_AIR
@ -142,14 +142,13 @@ public class SignEventListener implements Listener {
/**
* Gets the color of a line on a sign
*
* @param sign <p>The sign to check</p>
* @param lineNumber <p>The line number to check</p>
* @param sign <p>The sign to check</p>
* @return <p>The color of the sign</p>
*/
private ChatColor getSignLineColor(Sign sign, int lineNumber) {
String line = sign.getLine(lineNumber);
private ChatColor getSignLine2Color(Sign sign) {
String line = sign.getLine(2);
if (!ChatColor.stripColor(line).equals(line)) {
return ChatColor.getByChar(sign.getLine(lineNumber).substring(1, 2));
return ChatColor.getByChar(sign.getLine(2).substring(1, 2));
} else {
return null;
}
@ -296,7 +295,8 @@ public class SignEventListener implements Listener {
try {
Integer.parseInt(fileName);
isLoadListNumber = true;
} catch (NumberFormatException ignored){}
} catch (NumberFormatException ignored) {
}
//Add the third line to the second line for the full filename
String thirdLine = sign.getLine(3);

View File

@ -10,6 +10,7 @@ public enum BookDirectory {
/**
* Gets the relevant book directory given a directory name
*
* @param directory <p>The directory to transform</p>
* @return <p>A book directory, or null if the given directory is empty</p>
*/

View File

@ -53,7 +53,8 @@ public final class BookToFromTextHelper {
/**
* Loads a book from a file
* @param file <p>The file to load</p>
*
* @param file <p>The file to load</p>
* @param bookMetadata <p>The book metadata to use for saving the book</p>
* @return <p>The book metadata of the loaded book</p>
*/
@ -156,6 +157,7 @@ public final class BookToFromTextHelper {
/**
* Reads text from a .txt file
*
* @param file <p>The file to read</p>
* @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>

View File

@ -2,12 +2,17 @@ package net.knarcraft.bookswithoutborders.utility;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicesManager;
import java.util.Objects;
/**
* Helper class for economy related functions
*/
@ -21,6 +26,7 @@ public final class EconomyHelper {
/**
* Gets an economy instance for making transactions
*
* @return <p>An economy instance, or null if it's not initialized</p>
*/
public static Economy getEconomy() {
@ -29,6 +35,7 @@ public final class EconomyHelper {
/**
* Tries to set up economy
*
* @return <p>True if economy is set up and enabled</p>
*/
public static boolean setupEconomy() {
@ -50,6 +57,34 @@ public final class EconomyHelper {
return (economy != null);
}
/**
* 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 static 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
Material bookCurrency = BooksWithoutBorders.getBookPriceType();
double cost = BooksWithoutBorders.getBookPriceQuantity() * numCopies;
int itemCost = (int) cost;
if (bookCurrency == Material.AIR) {
return !EconomyHelper.payForBookPrintingEconomy(player, cost, numCopies);
} else {
if (player.getInventory().contains(bookCurrency, itemCost)) {
payForBookPrintingItem(player, itemCost);
return false;
} else {
BooksWithoutBorders.sendErrorMessage(player, itemCost + " " + bookCurrency +
"(s) are required for this command!");
return true;
}
}
}
/**
* Uses economy to take payment for printing a number of books
*
@ -58,7 +93,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>
*/
public static boolean payForBookPrintingEconomy(Player player, double cost, int numCopies) {
private static boolean payForBookPrintingEconomy(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 " + numCopies + " book(s)");
@ -70,4 +105,28 @@ public final class EconomyHelper {
}
}
/**
* 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 static void payForBookPrintingItem(Player player, int itemCost) {
PlayerInventory playerInventory = player.getInventory();
int clearedAmount = 0;
while (clearedAmount < itemCost) {
int firstItemIndex = playerInventory.first(BooksWithoutBorders.getBookPriceType());
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));
}
}
}
}

View File

@ -106,7 +106,8 @@ public final class FileHelper {
/**
* Prints the available books
* @param sender <p>The sender to display the books to</p>
*
* @param sender <p>The sender to display the books to</p>
* @param listPublic <p>Whether to display public books</p>
*/
public static void printBooks(CommandSender sender, boolean listPublic) {
@ -116,7 +117,8 @@ public final class FileHelper {
/**
* Prints a list of files
* @param sender <p>The command sender to show the list to</p>
*
* @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) {