Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
6ae15acc72 | |||
2c80e4117e | |||
6d539a14df | |||
184f78d935 | |||
95b0b42fd1 | |||
73eb903517 | |||
b577b1ff75 | |||
c27756f7dc | |||
90bab4a148 | |||
f005b8f8e5 | |||
0fdfd81579 | |||
6820b71dde | |||
28b7849ff5 | |||
e893684dec | |||
f1a8db4f5e | |||
47fabe5806 | |||
ec6def15f9 | |||
13cbe883ed |
149
README.md
149
README.md
@ -25,6 +25,7 @@ Books without Borders has got your back!
|
||||
- Add lore to any item with a simple command
|
||||
- Supports adding and saving color to title, lore, and book contents
|
||||
- Color and formatting codes can be manually turned into formatting using /formatbook
|
||||
- Clear a book, and start anew with /clearbook
|
||||
- Formatting and color codes can be turned into formatting once any book is signed. This is enabled through a config
|
||||
value
|
||||
- Change generation of books. Create tattered books for your RPG server!
|
||||
@ -39,70 +40,64 @@ Books without Borders has got your back!
|
||||
|
||||
An in-game description of available commands is available through the /bwb command.
|
||||
|
||||
- /bookswithoutborders - Displays information about commands (and permissions if the user has bookswithoutborders.admin)
|
||||
- /copybook <# of copies> - Copies the book the player is holding
|
||||
- /decryptbook <key> - Decrypts the book the player is holding. "key" is required and MUST be IDENTICAL to the key used
|
||||
to encrypt the held book
|
||||
- /deletebook <file name or number> - Deletes the specified file in the player's directory
|
||||
- /deletepublicbook <file name or number> - Same as deletebook, but deletes files in the public directory
|
||||
- encryptbook <key> \[encryption style] - Encrypts the book the player is holding. "key" is required and can be any
|
||||
phrase or number excluding spaces. "style" is not required. Possible values are "DNA" or ""
|
||||
- /formatbook - Formats the held written book (converts color and formatting codes to the corresponding formatted text)
|
||||
- /givebook <file name or number> <playername> \[# of copies (num)] \[signed (true/false)] - Gives the selected player a
|
||||
book from your personal directory
|
||||
- /givepublicbook <file name or number> <playername> \[# of copies (num)] \[signed (true/false)] - Same as givebook, but
|
||||
uses books from the public directory
|
||||
- /loadbook <file name or number> \[# of copies] \[signed (true/false)] - Creates a book from the specified file and
|
||||
gives it to the player. If no file is specified, a list of available files is returned. If true is specified, the book
|
||||
will be signed, if false it will be unsigned
|
||||
- /loadpublicbook <file name or number> \[# of copies] \[signed (true/false)] - Same as loadbook, but views files in the
|
||||
public directory
|
||||
- /reload - Reloads BwB's configuration file
|
||||
- /savebook \[overwrite (true/false)] - Saves the book the player is holding to a text file in a private directory. If
|
||||
true is specified, a book of the same name by the same author will be overwritten by the new book
|
||||
- /savepublicbook \[overwrite (true/false)] - Same as savebook, but saves files in the public directory
|
||||
- /setbookauthor <author> - Sets the author of the book the player is holding
|
||||
- /setbookgeneration <generation> - Sets the generation (ORIGINAL, COPY_OF_ORIGINAL, COPY_OF_COPY, TATTERED)
|
||||
- /setbookprice <item/eco> <quantity> - Sets the per-book price to create a book via commands. If "Item", the item in
|
||||
the player's hand in the amount of <quantity> will be the price. If "Eco", a Vault based economy will be used for
|
||||
price. If neither <Item/Eco> nor <quantity> are specified, the current price to create books will be removed.
|
||||
- /setlore <new lore> - Sets the lore of the item the player is holding. Insert the lore_line_separator character to
|
||||
force a new line ("~" by default)
|
||||
- /settitle <title> - Sets the title of the book/item the player is holding
|
||||
- /unsignbook - Un-signs the book the player is holding
|
||||
| Command | Arguments | Description |
|
||||
| --- | --- | --- |
|
||||
| /bookswithoutborders | None | Displays information about commands (and permissions if the user has bookswithoutborders.admin) |
|
||||
| /copybook | \<# of copies> | Copies the book the player is holding |
|
||||
| /decryptbook | \<key> | Decrypts the book the player is holding. "key" is required and MUST be IDENTICAL to the key used to encrypt the held book |
|
||||
| /deletebook | \<file name or number> | Deletes the specified file in the player's directory |
|
||||
| /deletepublicbook | \<file name or number> | Same as deletebook, but deletes files in the public directory |
|
||||
| /encryptbook | \<key> \[encryption style] | Encrypts the book the player is holding. "key" is required and can be any phrase or number excluding spaces. "style" is not required. Possible values are "DNA" or "" |
|
||||
| /formatbook | None | Formats the held written book (converts color and formatting codes to the corresponding formatted text) |
|
||||
| /givebook | \<file name or number> \<playername> \[# of copies (num)] \[signed (true/false)] | Gives the selected player a book from your personal directory |
|
||||
| /givepublicbook | \<file name or number> \<playername> \[# of copies (num)] \[signed (true/false)] | Same as givebook, but uses books from the public directory |
|
||||
| /loadbook | \<file name or number> \[# of copies] \[signed (true/false)] | Creates a book from the specified file and gives it to the player. If no file is specified, a list of available files is returned. If true is specified, the book will be signed, if false it will be unsigned |
|
||||
| /loadpublicbook | \<file name or number> \[# of copies] \[signed (true/false)] | Same as loadbook, but views files in the public directory |
|
||||
| /reload | None | Reloads BwB's configuration file |
|
||||
| /savebook | \[overwrite (true/false)] | Saves the book the player is holding to a text file in a private directory. If true is specified, a book of the same name by the same author will be overwritten by the new book |
|
||||
| /savepublicbook | \[overwrite (true/false)] | Same as savebook, but saves files in the public directory |
|
||||
| /setbookauthor | \<author> | Sets the author of the book the player is holding |
|
||||
| /setbookgeneration | \<generation> | Sets the generation of the held book (ORIGINAL, COPY_OF_ORIGINAL, COPY_OF_COPY, TATTERED) |
|
||||
| /setbookprice | \<item/eco> \<quantity> | Sets the per-book price to create a book via commands. If "Item", the item in the player's hand in the amount of \<quantity> will be the price. If "Eco", a Vault based economy will be used for price. If neither \<Item/Eco> nor \<quantity> are specified, the current price to create books will be removed. |
|
||||
| /setlore | \<new lore> | Sets the lore of the item the player is holding. Insert the lore_line_separator character to force a new line ("~" by default) |
|
||||
| /settitle | \<title> | Sets the title of the book/item the player is holding |
|
||||
| /unsignbook | None | Un-signs the book the player is holding |
|
||||
| /clearbook | None | Removes all text from the held un-signed book |
|
||||
|
||||
### Permissions:
|
||||
|
||||
- bookswithoutborders.* - Grants all permissions
|
||||
- bookswithoutborders.admin - Grants all permissions
|
||||
- bookswithoutborders.use - Allows player to use commands to save/load/delete in their personal directory
|
||||
- bookswithoutborders.alterbooks - Allows player to change books' data such as lore/title/author/formatting and
|
||||
unsigning books
|
||||
- bookswithoutborders.reload - Allows player to reload this plugin
|
||||
- bookswithoutborders.format - Allows a player to format a book
|
||||
- bookswithoutborders.save - Allows a player to save books to their personal directory
|
||||
- bookswithoutborders.load - Allows player to load books from their personal directory
|
||||
- bookswithoutborders.delete - Allows player to delete books from their personal directory
|
||||
- bookswithoutborders.unsign - Allows player to un-sign books
|
||||
- bookswithoutborders.copy - Allows player to copy books
|
||||
- bookswithoutborders.loadpublic - Allows player to load from the public directory
|
||||
- bookswithoutborders.savepublic - Allows player to save to the public directory
|
||||
- bookswithoutborders.encrypt - Allows player to encrypt books
|
||||
- bookswithoutborders.groupencrypt - Allows player to use group-based encryption
|
||||
- bookswithoutborders.decrypt - Allows player to decrypt books
|
||||
- bookswithoutborders.decrypt.agroup - Allows player to decrypt books group-encrypted for group "agroup"
|
||||
- bookswithoutborders.signs - Allows player to create signs that give/encrypt/decrypt books
|
||||
- bookswithoutborders.give - Allows player to give another player one of their privately saved books
|
||||
- bookswithoutborders.givepublic - Allows a player to give another player a book from the public directory
|
||||
- bookswithoutborders.settitle - Allows player to set the title of the currently held book
|
||||
- bookswithoutborders.setauthor - Allows player to set the author of the currently held book
|
||||
- bookswithoutborders.setlore - Allows player to set the lore of the currently held item
|
||||
- bookswithoutborders.bypassauthoronlycopy - Allows player to ignore Author_Only_Copy config setting
|
||||
- bookswithoutborders.bypassauthoronlyunsign - Allows player to ignore Author_Only_Unsign config setting
|
||||
- bookswithoutborders.bypassauthoronlysave - Allows player to ignore Author_Only_Save config setting
|
||||
- bookswithoutborders.bypassbookprice - Allows player to ignore Price_to_create_book config setting
|
||||
- bookswithoutborders.setbookprice - Allows player to set the cost of creating a book
|
||||
- bookswithoutborders.setgeneration - Allows player to change the generation of a book (Original, Copy, Copy of Copy)
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
| bookswithoutborders.* | Grants all permissions |
|
||||
| bookswithoutborders.admin | Grants all permissions |
|
||||
| bookswithoutborders.use | Allows player to use commands to save/load/delete in their personal directory |
|
||||
| bookswithoutborders.alterbooks | Allows player to change books' data such as lore/title/author/generation/formatting and un-signing books |
|
||||
| bookswithoutborders.reload | Allows player to reload this plugin |
|
||||
| bookswithoutborders.format | Allows a player to format a book |
|
||||
| bookswithoutborders.save | Allows a player to save books to their personal directory |
|
||||
| bookswithoutborders.load | Allows player to load books from their personal directory |
|
||||
| bookswithoutborders.delete | Allows player to delete books from their personal directory |
|
||||
| bookswithoutborders.unsign | Allows player to un-sign books |
|
||||
| bookswithoutborders.copy | Allows player to copy books |
|
||||
| bookswithoutborders.loadpublic | Allows player to load from the public directory |
|
||||
| bookswithoutborders.savepublic | Allows player to save to the public directory |
|
||||
| bookswithoutborders.encrypt | Allows player to encrypt books |
|
||||
| bookswithoutborders.groupencrypt | Allows player to use group-based encryption |
|
||||
| bookswithoutborders.decrypt | Allows player to decrypt books |
|
||||
| bookswithoutborders.decrypt.agroup | Allows player to decrypt books group-encrypted for group "agroup" |
|
||||
| bookswithoutborders.signs | Allows player to create signs that give/encrypt/decrypt books |
|
||||
| bookswithoutborders.give | Allows player to give another player one of their privately saved books |
|
||||
| bookswithoutborders.givepublic | Allows a player to give another player a book from the public directory |
|
||||
| bookswithoutborders.settitle | Allows player to set the title of the currently held book |
|
||||
| bookswithoutborders.setauthor | Allows player to set the author of the currently held book |
|
||||
| bookswithoutborders.setlore | Allows player to set the lore of the currently held item |
|
||||
| bookswithoutborders.bypassauthoronlycopy | Allows player to ignore Author_Only_Copy config setting |
|
||||
| bookswithoutborders.bypassauthoronlyunsign | Allows player to ignore Author_Only_Unsign config setting |
|
||||
| bookswithoutborders.bypassauthoronlysave | Allows player to ignore Author_Only_Save config setting |
|
||||
| bookswithoutborders.bypassbookprice | Allows player to ignore Price_to_create_book config setting |
|
||||
| bookswithoutborders.setbookprice | Allows player to set the cost of creating a book |
|
||||
| bookswithoutborders.setgeneration | Allows player to change the generation of a book (Original, Copy, Copy of Copy) |
|
||||
| bookswithoutborders.clear | Allows player to clear the contents of the held writable book |
|
||||
|
||||
### Signs
|
||||
|
||||
@ -126,19 +121,19 @@ The **_decrypt_** sign must have **\[Decrypt]** on its second line. The third li
|
||||
|
||||
### Configuration options:
|
||||
|
||||
- Save_Books_in_Yaml_Format - Whether to use YAML for saved books instead of just storing them as text
|
||||
- Max_Number_of_Duplicates - The maximum number of duplicates of a saved book allowed
|
||||
- Author_Separator - The separator used to separate the book title and the book author
|
||||
- Lore_line_separator - The separator used to denote a new line in the book/item lore
|
||||
- Books_for_new_players - A list of books given to new players the first time they join the server
|
||||
- Message_for_new_players - An optional message displayed to new players the first time they join the server
|
||||
- Price_to_create_book.Item_type - The item type used as currency for copying books. Use "Economy" to use money instead
|
||||
of items
|
||||
- Price_to_create_book.Required_quantity - The quantity of currency required to pay for each book produced
|
||||
- Admin_Auto_Decrypt - Whether any admin can decrypt any book regardless of the group it was encrypted for
|
||||
- Author_Only_Copy - Whether to only allow the author of a book to create copies
|
||||
- Author_Only_Unsign - Whether to only allow the author of a book to unsign it
|
||||
- Author_Only_Save - Whether to only allow saving a player's own books with /savebook
|
||||
- Format_Book_After_Signing - Whether to automatically format every book when it's signed
|
||||
- Change_Generation_On_Copy - Whether to display "COPY" or "COPY_OF_COPY" instead of "ORIGINAL" when a book is copied.
|
||||
This also uses the vanilla behavior where a copy of a copy or tattered book cannot be copied further.
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| Save_Books_in_Yaml_Format | Whether to use YAML for saved books instead of just storing them as text |
|
||||
| Max_Number_of_Duplicates | The maximum number of duplicates of a saved book allowed |
|
||||
| Author_Separator | The separator used to separate the book title and the book author |
|
||||
| Lore_line_separator | The separator used to denote a new line in the book/item lore |
|
||||
| Books_for_new_players | A list of books given to new players the first time they join the server |
|
||||
| Message_for_new_players | An optional message displayed to new players the first time they join the server |
|
||||
| Price_to_create_book.Item_type | The item type used as currency for copying books. Use "Economy" to use money instead of items |
|
||||
| Price_to_create_book.Required_quantity | The quantity of currency required to pay for each book produced |
|
||||
| Admin_Auto_Decrypt | Whether any admin can decrypt any book regardless of the group it was encrypted for |
|
||||
| Author_Only_Copy | Whether to only allow the author of a book to create copies |
|
||||
| Author_Only_Unsign | Whether to only allow the author of a book to unsign it |
|
||||
| Author_Only_Save | Whether to only allow saving a player's own books with /savebook |
|
||||
| Format_Book_After_Signing | Whether to automatically format every book when it's signed |
|
||||
| Change_Generation_On_Copy | Whether to display "COPY" or "COPY_OF_COPY" instead of "ORIGINAL" when a book is copied. This also uses the vanilla behavior where a copy of a copy or tattered book cannot be copied further. |
|
6
pom.xml
6
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>net.knarcraft</groupId>
|
||||
<artifactId>BooksWithoutBorders</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.3</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<licenses>
|
||||
@ -75,7 +75,7 @@
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.19.1-R0.1-SNAPSHOT</version>
|
||||
<version>1.19.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -88,7 +88,7 @@
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>23.0.0</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.knarcraft.bookswithoutborders;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.command.CommandBooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandClear;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandCopy;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandDecrypt;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandDelete;
|
||||
@ -173,6 +174,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
registerCommand("reload", new CommandReload());
|
||||
registerCommand("formatBook", new CommandFormat());
|
||||
registerCommand("setBookGeneration", new CommandSetGeneration());
|
||||
registerCommand("clearBook", new CommandClear());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,58 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Command executor for the clear command
|
||||
*/
|
||||
public class CommandClear implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (InventoryHelper.notHoldingOneWritableBookCheck(player, "You must be holding a writable book to " +
|
||||
"clear it!", "You cannot clear two books at once!")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Clear the player's held book
|
||||
ItemStack heldBook = InventoryHelper.getHeldBook(player, false);
|
||||
BookMeta bookMeta = (BookMeta) heldBook.getItemMeta();
|
||||
if (bookMeta == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Unable to get metadata for the held book!");
|
||||
return false;
|
||||
}
|
||||
bookMeta.setPages("");
|
||||
bookMeta.setAuthor(null);
|
||||
bookMeta.setGeneration(null);
|
||||
bookMeta.setTitle(null);
|
||||
heldBook.setItemMeta(bookMeta);
|
||||
BooksWithoutBorders.sendSuccessMessage(sender, "Book cleared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
@ -2,8 +2,8 @@ package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFormatter;
|
||||
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -44,7 +44,7 @@ public class CommandSetLore implements TabExecutor {
|
||||
String rawLore = String.join(" ", args);
|
||||
|
||||
//Format lore
|
||||
rawLore = ChatColor.translateAlternateColorCodes('&', rawLore);
|
||||
rawLore = BookFormatter.translateAllColorCodes(rawLore);
|
||||
String[] loreParts = rawLore.split(BooksWithoutBordersConfig.getLoreSeparator());
|
||||
List<String> newLore = new ArrayList<>(Arrays.asList(loreParts));
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFormatter;
|
||||
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -22,7 +22,8 @@ import java.util.List;
|
||||
public class CommandSetTitle 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[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
|
||||
return false;
|
||||
@ -40,7 +41,7 @@ public class CommandSetTitle implements TabExecutor {
|
||||
}
|
||||
|
||||
String title = String.join(" ", args);
|
||||
title = ChatColor.translateAlternateColorCodes('&', title);
|
||||
title = BookFormatter.translateAllColorCodes(title);
|
||||
|
||||
ItemMeta itemMetadata = heldItem.getItemMeta();
|
||||
if (itemMetadata == null) {
|
||||
@ -66,7 +67,8 @@ public class CommandSetTitle 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[] args) {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("<new title>");
|
||||
return options;
|
||||
|
@ -50,6 +50,7 @@ public class CommandUnSign implements TabExecutor {
|
||||
public void unSignHeldBook(Player player, boolean mainHand) {
|
||||
//Get the old book
|
||||
BookMeta oldBook = InventoryHelper.getHeldBookMetadata(player, mainHand);
|
||||
ItemStack heldBook = InventoryHelper.getHeldBook(player, mainHand);
|
||||
|
||||
//Only allow the owner to un-sign the book
|
||||
if (BooksWithoutBordersConfig.getAuthorOnlyUnsign() && !player.hasPermission("bookswithoutborders.bypassAuthorOnlyUnsign")) {
|
||||
@ -60,6 +61,7 @@ public class CommandUnSign implements TabExecutor {
|
||||
|
||||
//UnSign the book
|
||||
ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK);
|
||||
newBook.setAmount(heldBook.getAmount());
|
||||
newBook.setItemMeta(oldBook);
|
||||
|
||||
InventoryHelper.replaceHeldItem(player, newBook, mainHand);
|
||||
|
@ -2,7 +2,7 @@ package net.knarcraft.bookswithoutborders.config;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.utility.EconomyHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
|
@ -7,11 +7,12 @@ import net.knarcraft.bookswithoutborders.utility.BookLoader;
|
||||
import net.knarcraft.bookswithoutborders.utility.EncryptionHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.FileHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
@ -96,6 +97,7 @@ public class SignEventListener implements Listener {
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && (Tag.SIGNS.isTagged(clickedBlockType) ||
|
||||
Tag.WALL_SIGNS.isTagged(clickedBlockType))) {
|
||||
event.setUseItemInHand(Event.Result.DENY);
|
||||
//The player right-clicked a sign
|
||||
Sign sign = (Sign) event.getClickedBlock().getState();
|
||||
if (signLineEquals(sign, 0, "[BwB]", ChatColor.DARK_GREEN)) {
|
||||
@ -156,7 +158,7 @@ public class SignEventListener implements Listener {
|
||||
private ChatColor getSignLine2Color(Sign sign) {
|
||||
String line = sign.getLine(2);
|
||||
if (!ChatColor.stripColor(line).equals(line)) {
|
||||
return ChatColor.getByChar(sign.getLine(2).substring(1, 2));
|
||||
return ChatColor.getByChar(sign.getLine(2).substring(1, 2).charAt(0));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ public final class BookFormatter {
|
||||
* @param message <p>The string to search for color codes</p>
|
||||
* @return <p>The message with color codes translated</p>
|
||||
*/
|
||||
private static String translateAllColorCodes(String message) {
|
||||
public static String translateAllColorCodes(String message) {
|
||||
message = ChatColor.translateAlternateColorCodes('&', message);
|
||||
Pattern pattern = Pattern.compile("(#[a-fA-F0-9]{6})");
|
||||
Matcher matcher = pattern.matcher(message);
|
||||
|
@ -3,6 +3,7 @@ package net.knarcraft.bookswithoutborders.utility;
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.state.BookDirectory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -60,7 +61,22 @@ public final class BookLoader {
|
||||
//Get the full path of the book to load
|
||||
File file = getFullPath(sender, fileName, bookDirectory, directory);
|
||||
if (file == null) {
|
||||
return null;
|
||||
//Try converting the username to UUID
|
||||
String titleAuthorSeparator = BooksWithoutBordersConfig.getTitleAuthorSeparator();
|
||||
String[] data = fileName.split(titleAuthorSeparator);
|
||||
String extension = data[1].substring(data[1].length() - 4);
|
||||
String userName = data[1].substring(0, data[1].length() - 4);
|
||||
Player player = Bukkit.getPlayer(userName);
|
||||
if (player != null) {
|
||||
data[1] = player.getUniqueId() + extension;
|
||||
file = getFullPath(sender, String.join(titleAuthorSeparator, data), bookDirectory, directory);
|
||||
if (file == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Incorrect file name!");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//Make sure the player can pay for the book
|
||||
@ -124,9 +140,7 @@ public final class BookLoader {
|
||||
} else {
|
||||
file = FileHelper.getBookFile(BookHelper.getBookDirectoryPathString(bookDirectory, sender) + fileName);
|
||||
}
|
||||
|
||||
if (file == null || !file.isFile()) {
|
||||
BooksWithoutBorders.sendErrorMessage(sender, "Incorrect file name!");
|
||||
return null;
|
||||
} else {
|
||||
return file;
|
||||
|
@ -8,10 +8,13 @@ import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.ServicesManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -74,17 +77,89 @@ public final class EconomyHelper {
|
||||
if (bookCurrency == Material.AIR) {
|
||||
return !EconomyHelper.payForBookPrintingEconomy(player, cost, numCopies);
|
||||
} else {
|
||||
if (player.getInventory().contains(bookCurrency, itemCost)) {
|
||||
payForBookPrintingItem(player, itemCost);
|
||||
return false;
|
||||
if (bookCurrency == Material.WRITABLE_BOOK) {
|
||||
//Writable books are treated as a special case to prevent WIP books from being used
|
||||
return !takeWritableBookPayment(player, itemCost);
|
||||
} else {
|
||||
BooksWithoutBorders.sendErrorMessage(player, itemCost + " " + bookCurrency +
|
||||
"(s) are required for this command!");
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a writable book payment, ignoring any books containing text
|
||||
*
|
||||
* @param player <p>The player to take payment from</p>
|
||||
* @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) {
|
||||
List<ItemStack> books = getPlayersEmptyBooks(player);
|
||||
if (countItems(books) < itemCost) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, itemCost + " empty " + Material.WRITABLE_BOOK +
|
||||
"(s) are required for this command!");
|
||||
return false;
|
||||
} else {
|
||||
int clearedAmount = 0;
|
||||
for (ItemStack itemStack : books) {
|
||||
if (itemStack.getAmount() > itemCost) {
|
||||
//If encountering an item stack with more than enough books, remove the necessary books
|
||||
itemStack.setAmount(itemStack.getAmount() - itemCost);
|
||||
return true;
|
||||
} else {
|
||||
clearedAmount += itemStack.getAmount();
|
||||
player.getInventory().removeItem(itemStack);
|
||||
}
|
||||
if (clearedAmount >= itemCost) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of items contained in the given list of items
|
||||
*
|
||||
* @param items <p>The items to count</p>
|
||||
* @return <p>The total number of items</p>
|
||||
*/
|
||||
private static int countItems(List<ItemStack> items) {
|
||||
int totalItems = 0;
|
||||
for (ItemStack itemStack : items) {
|
||||
totalItems += itemStack.getAmount();
|
||||
}
|
||||
return totalItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all empty books in a player's inventory
|
||||
*
|
||||
* @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) {
|
||||
List<ItemStack> validBooks = new ArrayList<>();
|
||||
for (ItemStack itemStack : player.getInventory().getContents()) {
|
||||
if (itemStack == null || itemStack.getType() != Material.WRITABLE_BOOK) {
|
||||
continue;
|
||||
}
|
||||
BookMeta book = (BookMeta) itemStack.getItemMeta();
|
||||
//Only accept empty books
|
||||
if (book != null && (!book.hasPages() || (book.getPageCount() == 1 && book.getPage(1).trim().isEmpty()))) {
|
||||
validBooks.add(itemStack);
|
||||
}
|
||||
}
|
||||
return validBooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses economy to take payment for printing a number of books
|
||||
*
|
||||
@ -96,8 +171,10 @@ public final class EconomyHelper {
|
||||
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)");
|
||||
BooksWithoutBorders.sendSuccessMessage(player, "New balance: " + economy.format(economy.getBalance(player)));
|
||||
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!");
|
||||
|
@ -5,7 +5,7 @@ import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.encryption.GenenCrypt;
|
||||
import net.knarcraft.bookswithoutborders.encryption.SubstitutionCipher;
|
||||
import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
|
||||
import org.bukkit.ChatColor;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -3,7 +3,7 @@ package net.knarcraft.bookswithoutborders.utility;
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.state.BookDirectory;
|
||||
import org.bukkit.ChatColor;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@ -162,9 +162,8 @@ public final class FileHelper {
|
||||
String userName = data[1].substring(0, data[1].length() - 4);
|
||||
data[1] = BookHelper.authorFromUUID(userName) + extension;
|
||||
fileList.add(String.join(separator, data));
|
||||
} else {
|
||||
fileList.add(fileName);
|
||||
}
|
||||
fileList.add(fileName);
|
||||
}
|
||||
|
||||
return fileList;
|
||||
|
@ -51,6 +51,31 @@ public final class InventoryHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs checks to validate that a player contains exactly one unwritten book
|
||||
*
|
||||
* @param player <p>The player to validate</p>
|
||||
* @param noBookMessage <p>The message to display if the player is not holding a book</p>
|
||||
* @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) {
|
||||
BookHoldingState holdingState = getBookHoldingState(player);
|
||||
|
||||
if (holdingState == BookHoldingState.NONE || holdingState == BookHoldingState.SIGNED_BOTH_HANDS ||
|
||||
holdingState == BookHoldingState.SIGNED_MAIN_HAND || holdingState == BookHoldingState.SIGNED_OFF_HAND) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, noBookMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (holdingState == BookHoldingState.UNSIGNED_BOTH_HANDS) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, twoBooksMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs checks to validate that a player contains exactly one written book
|
||||
*
|
||||
|
@ -45,6 +45,10 @@ commands:
|
||||
description: Copies the book the player is holding
|
||||
usage: /<command> <# of copies>
|
||||
permission: bookswithoutborders.copy
|
||||
clearbook:
|
||||
description: Removes all text from the book the player is holding
|
||||
usage: /<command>
|
||||
permission: bookswithoutborders.clear
|
||||
unsignbook:
|
||||
description: Un-signs the book the player is holding
|
||||
usage: /<command>
|
||||
@ -128,8 +132,9 @@ permissions:
|
||||
bookswithoutborders.load: true
|
||||
bookswithoutborders.delete: true
|
||||
bookswithoutborders.alterbooks:
|
||||
description: Allows player to change books' data such as lore/title/author/formatting and unsigning books
|
||||
description: Allows player to change books' data such as lore/title/author/generation/formatting and unsigning books
|
||||
children:
|
||||
bookswithoutborders.clear: true
|
||||
bookswithoutborders.unsign: true
|
||||
bookswithoutborders.settitle: true
|
||||
bookswithoutborders.setauthor: true
|
||||
@ -145,9 +150,11 @@ permissions:
|
||||
bookswithoutborders.delete:
|
||||
description: Allows player to delete books from their personal directory
|
||||
bookswithoutborders.unsign:
|
||||
description: Allows player to use unsign command
|
||||
description: Allows player to use the unsign command
|
||||
bookswithoutborders.copy:
|
||||
description: Allows player to use copy command
|
||||
description: Allows player to use the copy command
|
||||
bookswithoutborders.clear:
|
||||
description: Allows player to use the clear command
|
||||
bookswithoutborders.loadpublic:
|
||||
description: Allows player to load from the public directory
|
||||
bookswithoutborders.savepublic:
|
||||
|
Reference in New Issue
Block a user