Starts adding string translations and cleanup

This commit is contained in:
2025-08-07 16:00:37 +02:00
parent 2146f00014
commit b1da544109
12 changed files with 563 additions and 149 deletions

View File

@@ -24,16 +24,22 @@ import net.knarcraft.bookswithoutborders.command.CommandSetLore;
import net.knarcraft.bookswithoutborders.command.CommandSetTitle;
import net.knarcraft.bookswithoutborders.command.CommandUnSign;
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
import net.knarcraft.bookswithoutborders.config.BwBCommand;
import net.knarcraft.bookswithoutborders.config.StaticMessage;
import net.knarcraft.bookswithoutborders.config.Translatable;
import net.knarcraft.bookswithoutborders.handler.BookshelfHandler;
import net.knarcraft.bookswithoutborders.listener.BookEventListener;
import net.knarcraft.bookswithoutborders.listener.BookshelfListener;
import net.knarcraft.bookswithoutborders.listener.PlayerEventListener;
import net.knarcraft.bookswithoutborders.listener.SignEventListener;
import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.Translator;
import net.knarcraft.knarlib.property.ColorConversion;
import net.knarcraft.knarlib.util.UpdateChecker;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
@@ -69,17 +75,16 @@ public class BooksWithoutBorders extends JavaPlugin {
private static Map<Character, Integer> publicLetterIndex;
private static Map<UUID, Map<Character, Integer>> playerLetterIndex;
private static BooksWithoutBorders booksWithoutBorders;
private static ConsoleCommandSender consoleSender;
private static BookshelfHandler bookshelfHandler;
private static StringFormatter stringFormatter;
/**
* Gets the console sender for printing to the console
* Gets the string formatter
*
* @return <p>The console's console sender</p>
* @return <p>The string formatter</p>
*/
@NotNull
public static ConsoleCommandSender getConsoleSender() {
return consoleSender;
public static StringFormatter getStringFormatter() {
return stringFormatter;
}
/**
@@ -163,12 +168,18 @@ public class BooksWithoutBorders extends JavaPlugin {
PluginDescriptionFile pluginDescriptionFile = this.getDescription();
String pluginVersion = pluginDescriptionFile.getVersion();
Translator translator = new Translator();
translator.registerMessageCategory(Translatable.PREFIX);
stringFormatter = new StringFormatter(this.getDescription().getName(), translator);
stringFormatter.setColorConversion(ColorConversion.RGB);
stringFormatter.setSuccessColor(ChatColor.of("#A9FF84"));
stringFormatter.setErrorColor(ChatColor.of("#FF84A9"));
booksWithoutBorders = this;
consoleSender = this.getServer().getConsoleSender();
playerBooksList = new HashMap<>();
playerLetterIndex = new HashMap<>();
BooksWithoutBordersConfig.initialize(this);
@Nullable List<String> files = BookFileHelper.listFiles(consoleSender, true);
BooksWithoutBordersConfig.initialize(this, translator);
@Nullable List<String> files = BookFileHelper.listFiles(this.getServer().getConsoleSender(), true);
if (files != null) {
publicBooksList = files;
publicLetterIndex = BookFileHelper.populateLetterIndices(files);
@@ -207,29 +218,29 @@ public class BooksWithoutBorders extends JavaPlugin {
* Registers all commands used by this plugin
*/
private void registerCommands() {
registerCommand("giveBook", new CommandGive());
registerCommand("givePublicBook", new CommandGivePublic());
registerCommand("decryptBook", new CommandDecrypt());
registerCommand("groupEncryptBook", new CommandGroupEncrypt());
registerCommand("deleteBook", new CommandDelete());
registerCommand("deletePublicBook", new CommandDeletePublic());
registerCommand("copyBook", new CommandCopy());
registerCommand("unSignBook", new CommandUnSign());
registerCommand("encryptBook", new CommandEncrypt());
registerCommand("setBookPrice", new CommandSetBookPrice());
registerCommand("setLore", new CommandSetLore());
registerCommand("savePublicBook", new CommandSavePublic());
registerCommand("saveBook", new CommandSave());
registerCommand("setBookAuthor", new CommandSetAuthor());
registerCommand("setTitle", new CommandSetTitle());
registerCommand("loadBook", new CommandLoad());
registerCommand("loadPublicBook", new CommandLoadPublic());
registerCommand("booksWithoutBorders", new CommandBooksWithoutBorders());
registerCommand("reload", new CommandReload());
registerCommand("formatBook", new CommandFormat());
registerCommand("setBookGeneration", new CommandSetGeneration());
registerCommand("clearBook", new CommandClear());
registerCommand("setBookshelfData", new CommandSetBookshelfData());
registerCommand(BwBCommand.GIVE_BOOK.toString(), new CommandGive());
registerCommand(BwBCommand.GIVE_PUBLIC_BOOK.toString(), new CommandGivePublic());
registerCommand(BwBCommand.DECRYPT_BOOK.toString(), new CommandDecrypt());
registerCommand(BwBCommand.GROUP_ENCRYPT_BOOK.toString(), new CommandGroupEncrypt());
registerCommand(BwBCommand.DELETE_BOOK.toString(), new CommandDelete());
registerCommand(BwBCommand.DELETE_PUBLIC_BOOK.toString(), new CommandDeletePublic());
registerCommand(BwBCommand.COPY_BOOK.toString(), new CommandCopy());
registerCommand(BwBCommand.UNSIGN_BOOK.toString(), new CommandUnSign());
registerCommand(BwBCommand.ENCRYPT_BOOK.toString(), new CommandEncrypt());
registerCommand(BwBCommand.SET_BOOK_PRICE.toString(), new CommandSetBookPrice());
registerCommand(BwBCommand.SET_LORE.toString(), new CommandSetLore());
registerCommand(BwBCommand.SAVE_PUBLIC_BOOK.toString(), new CommandSavePublic());
registerCommand(BwBCommand.SAVE_BOOK.toString(), new CommandSave());
registerCommand(BwBCommand.SET_BOOK_AUTHOR.toString(), new CommandSetAuthor());
registerCommand(BwBCommand.SET_TITLE.toString(), new CommandSetTitle());
registerCommand(BwBCommand.LOAD_BOOK.toString(), new CommandLoad());
registerCommand(BwBCommand.LOAD_PUBLIC_BOOK.toString(), new CommandLoadPublic());
registerCommand(BwBCommand.BOOKS_WITHOUT_BORDERS.toString(), new CommandBooksWithoutBorders());
registerCommand(BwBCommand.RELOAD.toString(), new CommandReload());
registerCommand(BwBCommand.FORMAT_BOOK.toString(), new CommandFormat());
registerCommand(BwBCommand.SET_BOOK_GENERATION.toString(), new CommandSetGeneration());
registerCommand(BwBCommand.CLEAR_BOOK.toString(), new CommandClear());
registerCommand(BwBCommand.SET_BOOKSHELF_DATA.toString(), new CommandSetBookshelfData());
}
/**
@@ -243,7 +254,7 @@ public class BooksWithoutBorders extends JavaPlugin {
if (pluginCommand != null) {
pluginCommand.setExecutor(executor);
} else {
sendErrorMessage(consoleSender, "Failed to register command " + commandName);
getLogger().log(Level.SEVERE, "Failed to register command " + commandName);
}
}
@@ -256,10 +267,11 @@ public class BooksWithoutBorders extends JavaPlugin {
//Initialize Item Factory
try {
itemFactory = this.getServer().getItemFactory();
} catch (java.lang.NoSuchMethodError nsmE) {
sendErrorMessage(consoleSender, "Warning! [BooksWithoutBorders] failed to initialize!");
sendErrorMessage(consoleSender, "Please confirm the correct version of [BooksWithoutBorders] is");
sendErrorMessage(consoleSender, "being run for this version of bukkit!");
} catch (java.lang.NoSuchMethodError noSuchMethodError) {
getLogger().log(Level.SEVERE, """
Warning! [BooksWithoutBorders] failed to initialize!
Please confirm the correct version of [BooksWithoutBorders] is
being run for this version of spigot!""");
return false;
}
@@ -304,22 +316,22 @@ public class BooksWithoutBorders extends JavaPlugin {
if (!fileTest.exists()) {
try {
if (!fileTest.mkdir()) {
sendErrorMessage(consoleSender, "Saving failed! Aborting...");
getLogger().log(Level.SEVERE, StaticMessage.BOOK_SAVING_FAILED.toString());
return false;
}
} catch (Exception exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to create necessary folders");
getLogger().log(Level.SEVERE, StaticMessage.BOOK_FOLDER_CREATE_FAILED.toString());
return false;
}
}
if (!encryptedFileTest.exists()) {
try {
if (!encryptedFileTest.mkdir()) {
sendErrorMessage(consoleSender, "Saving failed! Aborting...");
getLogger().log(Level.SEVERE, StaticMessage.BOOK_SAVING_FAILED.toString());
return false;
}
} catch (Exception exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to create necessary folders");
getLogger().log(Level.SEVERE, StaticMessage.BOOK_FOLDER_CREATE_FAILED.toString());
return false;
}
}

View File

@@ -2,7 +2,12 @@ package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
import net.knarcraft.bookswithoutborders.config.BwBCommand;
import net.knarcraft.bookswithoutborders.config.Permission;
import net.knarcraft.bookswithoutborders.config.StaticMessage;
import net.knarcraft.bookswithoutborders.config.Translatable;
import net.knarcraft.bookswithoutborders.utility.EconomyHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -13,10 +18,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.sendErrorMessage;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getCommandColor;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getSuccessColor;
import java.util.logging.Level;
/**
* Command executor for the books without borders (bwb) command
@@ -24,29 +26,68 @@ import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig
public class CommandBooksWithoutBorders implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
sender.sendMessage(getCommandColor() + "[] denote optional parameters");
sender.sendMessage(getCommandColor() + "<> denote required parameters");
sender.sendMessage(getCommandColor() + "{} denote required permission");
sender.sendMessage(getCommandColor() + "In some cases, commands with required parameters can be called with no parameters");
if (sender instanceof Player) {
showPlayerCommands(sender);
} else {
showConsoleCommands(sender);
}
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] arguments) {
StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter();
String header = stringFormatter.replacePlaceholders(Translatable.NEUTRAL_COMMANDS_HEADER,
List.of("{bookPrice}", "{commands}"), List.of(getBookPrice(), getCommands(sender)));
sender.sendMessage(header);
return true;
}
/**
* Gets the list of commands
*
* @param sender <p>The command sender trying to see available commands</p>
* @return <p>The string representation of all commands</p>
*/
@NotNull
private String getCommands(@NotNull CommandSender sender) {
if (sender instanceof Player) {
return showPlayerCommands(sender);
} else {
return showConsoleCommands(sender);
}
}
/**
* Gets the price of duplicating a book
*
* @return <p>The book price</p>
*/
@NotNull
private String getBookPrice() {
if (!BooksWithoutBordersConfig.booksHavePrice()) {
return "";
}
StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter();
Material bookPriceType = BooksWithoutBordersConfig.getBookPriceType();
double bookPriceQuantity = BooksWithoutBordersConfig.getBookPriceQuantity();
if (bookPriceType != Material.AIR) {
return stringFormatter.replacePlaceholders(Translatable.NEUTRAL_COMMANDS_BOOK_PRICE_ITEM,
List.of("{quantity}", "{type}"),
List.of(String.valueOf((int) bookPriceQuantity), bookPriceType.toString()));
} else {
return stringFormatter.replacePlaceholder(Translatable.NEUTRAL_COMMANDS_BOOK_PRICE_ECO,
"{price}", EconomyHelper.getEconomy().format(bookPriceQuantity));
}
}
/**
* Shows all commands available to the console
*
* @param sender <p>The console which sent the command</p>
*/
private void showConsoleCommands(@NotNull CommandSender sender) {
sender.sendMessage(getCommandColor() + "Commands:");
showCommandInfo("deletePublicBook", sender);
showCommandInfo("givePublicBook", sender);
showCommandInfo("reload", sender);
@NotNull
private String showConsoleCommands(@NotNull CommandSender sender) {
StringBuilder builder = new StringBuilder();
for (BwBCommand command : BwBCommand.values()) {
if (!command.requiresPlayer()) {
builder.append(showCommandInfo(command.toString(), sender));
}
}
return builder.toString();
}
/**
@@ -54,44 +95,13 @@ public class CommandBooksWithoutBorders implements TabExecutor {
*
* @param sender <p>The player which sent the command</p>
*/
private void showPlayerCommands(@NotNull CommandSender sender) {
//Lists all commands
Material bookPriceType = BooksWithoutBordersConfig.getBookPriceType();
double bookPriceQuantity = BooksWithoutBordersConfig.getBookPriceQuantity();
if (BooksWithoutBordersConfig.booksHavePrice()) {
if (bookPriceType != Material.AIR) {
sendErrorMessage(sender, "[" + (int) bookPriceQuantity + " " + bookPriceType.toString() +
"(s) are required to create a book]");
} else {
sendErrorMessage(sender, "[" + EconomyHelper.getEconomy().format(bookPriceQuantity) +
" is required to create a book]");
}
@NotNull
private String showPlayerCommands(@NotNull CommandSender sender) {
StringBuilder builder = new StringBuilder();
for (BwBCommand command : BwBCommand.values()) {
builder.append(showCommandInfo(command.toString(), sender));
}
sender.sendMessage(getCommandColor() + "Commands:");
showCommandInfo("booksWithoutBorders", sender);
showCommandInfo("copyBook", sender);
showCommandInfo("decryptBook", sender);
showCommandInfo("deleteBook", sender);
showCommandInfo("deletePublicBook", sender);
showCommandInfo("encryptBook", sender);
showCommandInfo("formatBook", sender);
showCommandInfo("giveBook", sender);
showCommandInfo("givePublicBook", sender);
showCommandInfo("groupEncryptBook", sender);
showCommandInfo("loadBook", sender);
showCommandInfo("loadPublicBook", sender);
showCommandInfo("reload", sender);
showCommandInfo("saveBook", sender);
showCommandInfo("savePublicBook", sender);
showCommandInfo("setAuthor", sender);
showCommandInfo("setBookGeneration", sender);
showCommandInfo("setBookPrice", sender);
showCommandInfo("setLore", sender);
showCommandInfo("setTitle", sender);
showCommandInfo("unsignBook", sender);
showCommandInfo("clearBook", sender);
showCommandInfo("setBookshelfData", sender);
return builder.toString();
}
/**
@@ -100,22 +110,32 @@ public class CommandBooksWithoutBorders implements TabExecutor {
* @param command <p>The command to get information about</p>
* @param sender <p>The sender asking to see command info</p>
*/
private void showCommandInfo(@NotNull String command, @NotNull CommandSender sender) {
@NotNull
private String showCommandInfo(@NotNull String command, @NotNull CommandSender sender) {
PluginCommand pluginCommand = BooksWithoutBorders.getInstance().getCommand(command);
if (pluginCommand != null) {
String permission = pluginCommand.getPermission();
if (permission == null || sender.hasPermission(permission)) {
String commandInfo = "\n" + getCommandColor() + pluginCommand.getUsage().replace("<command>",
pluginCommand.getName()) + ": " + getSuccessColor() + pluginCommand.getDescription();
if (sender.hasPermission("bookswithoutborders.admin")) {
if (permission == null) {
permission = "None";
}
commandInfo += getCommandColor() + " {" + permission + "}";
}
sender.sendMessage(commandInfo);
}
if (pluginCommand == null) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, StringFormatter.replacePlaceholder(
StaticMessage.COMMAND_NOT_REGISTERED.toString(), "{command}", command));
return "";
}
String permission = pluginCommand.getPermission();
if (permission != null && !sender.hasPermission(permission)) {
return "";
}
StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter();
String commandDescription = stringFormatter.replacePlaceholders(Translatable.NEUTRAL_COMMANDS_COMMAND,
List.of("{usage}", "{description}"), List.of(pluginCommand.getUsage().replace("<command>",
pluginCommand.getName()), pluginCommand.getDescription()));
if (sender.hasPermission(Permission.ADMIN.toString())) {
if (permission == null) {
permission = stringFormatter.getUnFormattedColoredMessage(Translatable.NEUTRAL_COMMANDS_COMMAND_NO_PERMISSION_REQUIRED);
}
commandDescription += stringFormatter.replacePlaceholder(Translatable.NEUTRAL_COMMANDS_COMMAND_PERMISSION, "{permission}", permission);
}
return commandDescription;
}
@Override

View File

@@ -1,6 +1,7 @@
package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.config.Translatable;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -23,7 +24,7 @@ public class CommandClear implements TabExecutor {
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!");
BooksWithoutBorders.getStringFormatter().displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY);
return false;
}

View File

@@ -2,10 +2,13 @@ package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
import net.knarcraft.bookswithoutborders.config.Permission;
import net.knarcraft.bookswithoutborders.config.Translatable;
import net.knarcraft.bookswithoutborders.utility.BookHelper;
import net.knarcraft.bookswithoutborders.utility.EconomyHelper;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import net.knarcraft.bookswithoutborders.utility.TabCompletionTypeHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.util.TabCompletionHelper;
import org.bukkit.Material;
import org.bukkit.command.Command;
@@ -28,18 +31,21 @@ public class CommandCopy implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] arguments) {
StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter();
if (!(sender instanceof Player player)) {
BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!");
stringFormatter.displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY);
return false;
}
if (InventoryHelper.notHoldingOneWrittenBookCheck(player, "You must be holding a written book to copy it!",
"You cannot copy two books at once!")) {
if (InventoryHelper.notHoldingOneWrittenBookCheck(player,
stringFormatter.getUnFormattedColoredMessage(Translatable.ERROR_NOT_HOLDING_BOOK_COPY),
stringFormatter.getUnFormattedColoredMessage(Translatable.ERROR_ONLY_ONE_BOOK_COPY))) {
return false;
}
if (arguments.length < 1) {
BooksWithoutBorders.sendErrorMessage(player, "You must specify the number of copies to be made!");
stringFormatter.displayErrorMessage(player, Translatable.ERROR_COPY_COUNT_NOT_SPECIFIED);
return false;
}
@@ -47,12 +53,12 @@ public class CommandCopy implements TabExecutor {
ItemStack heldBook = InventoryHelper.getHeldBook(player, true);
int copies = Integer.parseInt(arguments[0]);
if (copies <= 0) {
throw new NumberFormatException("Number of copies must be larger than 0");
stringFormatter.displayErrorMessage(player, Translatable.ERROR_COPY_NEGATIVE_AMOUNT);
return false;
}
return performCopy(copies, player, heldBook);
} catch (NumberFormatException ignored) {
BooksWithoutBorders.sendErrorMessage(player, "Book not copied!");
BooksWithoutBorders.sendErrorMessage(player, "Number specified was invalid!");
stringFormatter.displayErrorMessage(player, Translatable.ERROR_COPY_INVALID_AMOUNT);
return false;
}
}
@@ -68,7 +74,7 @@ public class CommandCopy implements TabExecutor {
private boolean performCopy(int copies, @NotNull Player player, @NotNull ItemStack heldBook) {
//Make sure the player owns the book if authorOnlyCopy is enabled
if (BooksWithoutBordersConfig.getAuthorOnlyCopy() &&
!player.hasPermission("bookswithoutborders.bypassAuthorOnlyCopy")) {
!player.hasPermission(Permission.BYPASS_AUTHOR_ONLY_COPY.toString())) {
if (BookHelper.isNotAuthor(player, (BookMeta) Objects.requireNonNull(heldBook.getItemMeta()))) {
return false;
}
@@ -84,7 +90,7 @@ public class CommandCopy implements TabExecutor {
}
heldBook.setAmount(heldBook.getAmount() + copies);
BooksWithoutBorders.sendSuccessMessage(player, "Book copied!");
BooksWithoutBorders.getStringFormatter().displaySuccessMessage(player, Translatable.SUCCESS_COPY);
return true;
}
}
@@ -98,7 +104,7 @@ public class CommandCopy implements TabExecutor {
*/
private boolean paymentUnSuccessful(@NotNull Player player, int copies) {
return BooksWithoutBordersConfig.booksHavePrice() &&
!player.hasPermission("bookswithoutborders.bypassBookPrice") &&
!player.hasPermission(Permission.BYPASS_BOOK_PRICE.toString()) &&
EconomyHelper.cannotPayForBookPrinting(player, copies);
}
@@ -114,14 +120,13 @@ public class CommandCopy implements TabExecutor {
//Copy the vanilla behavior of refusing copying any further
if (bookMeta.getGeneration() == BookMeta.Generation.COPY_OF_COPY ||
bookMeta.getGeneration() == BookMeta.Generation.TATTERED) {
BooksWithoutBorders.sendErrorMessage(player, "You cannot copy this book any further. " +
"You must have the original or a direct copy.");
BooksWithoutBorders.getStringFormatter().displayErrorMessage(player, Translatable.ERROR_BOOK_COPIED_TOO_FAR);
return false;
}
//Make sure the player can fit the book in their inventory
int nextAvailableSlot = player.getInventory().firstEmpty();
if (nextAvailableSlot == -1) {
BooksWithoutBorders.sendErrorMessage(player, "You need an available slot in your inventory.");
BooksWithoutBorders.getStringFormatter().displayErrorMessage(player, Translatable.ERROR_INVENTORY_FULL);
return false;
}
//Make sure the player can pay for the copying

View File

@@ -2,18 +2,18 @@ package net.knarcraft.bookswithoutborders.config;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.utility.EconomyHelper;
import net.knarcraft.knarlib.formatting.Translator;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.Configuration;
import org.jetbrains.annotations.NotNull;
import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.sendErrorMessage;
import static net.knarcraft.bookswithoutborders.BooksWithoutBorders.sendSuccessMessage;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.cleanString;
/**
@@ -44,15 +44,18 @@ public class BooksWithoutBordersConfig {
private static boolean changeGenerationOnCopy;
private static boolean enableBookshelfPeeking;
private static Translator translator;
/**
* Initializes the books without borders settings class
*
* @param booksWithoutBorders <p>The books without borders object used for getting required data</p>
*/
public static void initialize(@NotNull BooksWithoutBorders booksWithoutBorders) {
public static void initialize(@NotNull BooksWithoutBorders booksWithoutBorders, @NotNull Translator translator) {
if (isInitialized) {
throw new IllegalArgumentException("Settings class initialized twice. This should not happen!");
}
BooksWithoutBordersConfig.translator = translator;
isInitialized = true;
bookFolder = booksWithoutBorders.getDataFolder().getAbsolutePath() + getSlash() + "Books" + getSlash();
loadConfig();
@@ -275,7 +278,7 @@ public class BooksWithoutBordersConfig {
* Saves the config
*/
public static void saveConfigValues() {
ConsoleCommandSender consoleSender = BooksWithoutBorders.getInstance().getServer().getConsoleSender();
Logger logger = BooksWithoutBorders.getInstance().getLogger();
Configuration config = BooksWithoutBorders.getInstance().getConfig();
config.set(ConfigOption.USE_YAML.getConfigNode(), useYml);
config.set(ConfigOption.MAX_DUPLICATES.getConfigNode(), bookDuplicateLimit);
@@ -306,9 +309,8 @@ public class BooksWithoutBordersConfig {
//Handles old book and quill settings
if (config.contains("Options.Require_book_and_quill_to_create_book")) {
sendSuccessMessage(consoleSender, "[BooksWithoutBorders] Found old config setting " +
"\"Require_book_and_quill_to_create_book\"");
sendSuccessMessage(consoleSender, "Updating to \"Price_to_create_book\" settings");
logger.log(Level.INFO, "[BooksWithoutBorders] Found old config setting " +
"\"Require_book_and_quill_to_create_book\"\nUpdating to \"Price_to_create_book\" settings");
if (config.getBoolean("Options.Require_book_and_quill_to_create_book")) {
bookPriceType = Material.WRITABLE_BOOK;
@@ -327,7 +329,7 @@ public class BooksWithoutBordersConfig {
* @return <p>True if the config was loaded successfully</p>
*/
public static boolean loadConfig() {
ConsoleCommandSender consoleSender = BooksWithoutBorders.getInstance().getServer().getConsoleSender();
Logger logger = BooksWithoutBorders.getInstance().getLogger();
BooksWithoutBorders.getInstance().reloadConfig();
Configuration config = BooksWithoutBorders.getInstance().getConfig();
try {
@@ -345,6 +347,8 @@ public class BooksWithoutBordersConfig {
formatBooks = getBoolean(config, ConfigOption.FORMAT_AFTER_SIGNING);
changeGenerationOnCopy = getBoolean(config, ConfigOption.CHANGE_GENERATION_ON_COPY);
enableBookshelfPeeking = getBoolean(config, ConfigOption.ENABLE_BOOKSHELF_PEEKING);
String language = config.getString("language", "en");
translator.loadLanguages(BooksWithoutBorders.getInstance().getDataFolder(), "en", language);
//Convert string into material
String paymentMaterial = getString(config, ConfigOption.PRICE_ITEM_TYPE);
@@ -352,8 +356,7 @@ public class BooksWithoutBordersConfig {
if (EconomyHelper.setupEconomy()) {
bookPriceType = Material.AIR;
} else {
sendErrorMessage(consoleSender,
"BooksWithoutBorders failed to hook into Vault! Book price not set!");
logger.log(Level.SEVERE, "BooksWithoutBorders failed to hook into Vault! Book price not set!");
bookPriceType = null;
}
} else if (!paymentMaterial.trim().isEmpty()) {
@@ -368,14 +371,14 @@ public class BooksWithoutBordersConfig {
//Make sure titleAuthorSeparator is a valid value
titleAuthorSeparator = cleanString(titleAuthorSeparator);
if (titleAuthorSeparator.length() != 1) {
sendErrorMessage(consoleSender, "Title-Author_Separator is set to an invalid value!");
sendErrorMessage(consoleSender, "Reverting to default value of \",\"");
logger.log(Level.SEVERE, "Title-Author_Separator is set to an invalid value!\n" +
"Reverting to default value of \",\"");
titleAuthorSeparator = ",";
config.set("Options.Title-Author_Separator", titleAuthorSeparator);
}
} catch (Exception e) {
sendErrorMessage(consoleSender, "Warning! Config.yml failed to load!");
sendErrorMessage(consoleSender, "Try Looking for settings that are missing values!");
logger.log(Level.SEVERE, "Warning! Config.yml failed to load!\n" +
"Try Looking for settings that are missing values!");
return false;
}

View File

@@ -0,0 +1,160 @@
package net.knarcraft.bookswithoutborders.config;
import org.jetbrains.annotations.NotNull;
/**
* A representation of a BwB command
*/
public enum BwBCommand {
/**
* The help command
*/
BOOKS_WITHOUT_BORDERS("booksWithoutBorders", false),
/**
* Clears the contents of a book
*/
CLEAR_BOOK("clearBook", true),
/**
* Copies the held book
*/
COPY_BOOK("copyBook", true),
/**
* Decrypts the held encrypted book
*/
DECRYPT_BOOK("decryptBook", true),
/**
* Deletes a book from a player's private collection
*/
DELETE_BOOK("deleteBook", true),
/**
* Deletes a book from the public collection
*/
DELETE_PUBLIC_BOOK("deletePublicBook", false),
/**
* Encrypts the held book
*/
ENCRYPT_BOOK("encryptBook", true),
/**
* Executes formatting codes in the held book
*/
FORMAT_BOOK("formatBook", true),
/**
* Gives a book from a player's private collection to another player
*/
GIVE_BOOK("giveBook", true),
/**
* Gives a book from the public collection to a player
*/
GIVE_PUBLIC_BOOK("givePublicBook", false),
/**
* Encrypts a book for specific group
*/
GROUP_ENCRYPT_BOOK("groupEncryptBook", true),
/**
* Loads a book from a player's private collection
*/
LOAD_BOOK("loadBook", true),
/**
* Loads a book from the public collection
*/
LOAD_PUBLIC_BOOK("loadPublicBook", true),
/**
* Reloads the plugin's configuration and the book lists
*/
RELOAD("reload", false),
/**
* Saves a book to a player's private collection
*/
SAVE_BOOK("saveBook", true),
/**
* Saves a book to the public collection
*/
SAVE_PUBLIC_BOOK("savePublicBook", true),
/**
* Sets the author of the held book
*/
SET_BOOK_AUTHOR("setBookAuthor", true),
/**
* Sets the generation of the held book
*/
SET_BOOK_GENERATION("setBookGeneration", true),
/**
* Sets the price of copying, loading and giving books
*/
SET_BOOK_PRICE("setBookPrice", false),
/**
* Sets the name/lore for the chiseled bookshelf in front of the player, displayed when peeking the bookshelf
*/
SET_BOOKSHELF_DATA("setBookshelfData", true),
/**
* Sets the lore of the held book/item
*/
SET_LORE("setLore", true),
/**
* Sets the book title of the held signed book, or the display name of the held item
*/
SET_TITLE("setTitle", true),
/**
* Un-signs the held signed book
*/
UNSIGN_BOOK("unsignBook", true),
;
private final @NotNull String commandName;
private final boolean requiresPlayer;
/**
* Instantiates a new command
*
* @param commandName <p>The name of the command</p>
* @param requiresPlayer <p>Whether the command requires to be run by a player</p>
*/
BwBCommand(@NotNull String commandName, boolean requiresPlayer) {
this.commandName = commandName;
this.requiresPlayer = requiresPlayer;
}
/**
* Gets whether this command can only be used by a player
*
* @return <p>True if this command must be run by a player</p>
*/
public boolean requiresPlayer() {
return this.requiresPlayer;
}
/**
* Return name instead of enum when displayed as a string
*
* @return <p>The command name</p>
*/
@Override
@NotNull
public String toString() {
return this.commandName;
}
}

View File

@@ -0,0 +1,59 @@
package net.knarcraft.bookswithoutborders.config;
import org.jetbrains.annotations.NotNull;
/**
* A representation of a BwB permission
*/
public enum Permission {
/**
* The permission for bypassing paying the set book printing price
*/
BYPASS_BOOK_PRICE("bypassBookPrice"),
/**
* The admin permission, giving most/all other permissions
*/
ADMIN("admin"),
/**
* The permission for bypassing the setting making sure a book can only be copied by its author
*/
BYPASS_AUTHOR_ONLY_COPY("bypassAuthorOnlyCopy"),
;
private final @NotNull String node;
/**
* Instantiates a new permission
*
* @param node <p>The permission's permission node</p>
*/
Permission(@NotNull String node) {
this.node = node;
}
/**
* Gets the node of this permission
*
* @return <p>The permission node</p>
*/
@NotNull
public String getNode() {
return "bookswithoutborders." + this.node;
}
/**
* Return node instead of enum when displayed as a string
*
* @return <p>The permission node string</p>
*/
@Override
@NotNull
public String toString() {
return getNode();
}
}

View File

@@ -0,0 +1,31 @@
package net.knarcraft.bookswithoutborders.config;
import org.jetbrains.annotations.NotNull;
/**
* Messages shown in the console that cannot be altered by users
*/
public enum StaticMessage {
BOOK_SAVING_FAILED("Saving failed! Aborting..."),
BOOK_FOLDER_CREATE_FAILED("Unable to create necessary folders"),
COMMAND_NOT_REGISTERED("Command {command} has not been registered!");
private final @NotNull String messageString;
/**
* Instantiates a new static message
*
* @param messageString <p>The message string</p>
*/
StaticMessage(@NotNull String messageString) {
this.messageString = messageString;
}
@Override
@NotNull
public String toString() {
return this.messageString;
}
}

View File

@@ -0,0 +1,97 @@
package net.knarcraft.bookswithoutborders.config;
import net.knarcraft.knarlib.formatting.TranslatableMessage;
import org.jetbrains.annotations.NotNull;
/**
* An enum representing all translatable messages
*/
public enum Translatable implements TranslatableMessage {
/**
* The prefix to display in messages
*/
PREFIX,
/**
* The success message displayed when the copy command succeeds
*/
SUCCESS_COPY,
/**
* The error to display when the console attempts to run a player-only command
*/
ERROR_PLAYER_ONLY,
/**
* The error displayed when running the copy command without holding a written book
*/
ERROR_NOT_HOLDING_BOOK_COPY,
/**
* The error displayed when running the copy command while holding one book in each hand
*/
ERROR_ONLY_ONE_BOOK_COPY,
/**
* The error displayed when running the copy command without specifying the amount of copies
*/
ERROR_COPY_COUNT_NOT_SPECIFIED,
/**
* The error displayed when supplying the copy command with a negative number
*/
ERROR_COPY_NEGATIVE_AMOUNT,
/**
* The error displayed when supplying the copy command with a non-number
*/
ERROR_COPY_INVALID_AMOUNT,
/**
* The error displayed when trying to copy a tattered book or a copy of a copy
*/
ERROR_BOOK_COPIED_TOO_FAR,
/**
* The error displayed when trying to receive a book with a full inventory
*/
ERROR_INVENTORY_FULL,
/**
* The header displayed before printing all commands
*/
NEUTRAL_COMMANDS_HEADER,
/**
* The format used when displaying a book's economy price
*/
NEUTRAL_COMMANDS_BOOK_PRICE_ECO,
/**
* The format used when displaying a book's item price
*/
NEUTRAL_COMMANDS_BOOK_PRICE_ITEM,
/**
* The format used when displaying one command entry
*/
NEUTRAL_COMMANDS_COMMAND,
/**
* The string used when displaying that a command requires no permission
*/
NEUTRAL_COMMANDS_COMMAND_NO_PERMISSION_REQUIRED,
/**
* The format used when displaying a command's required permission
*/
NEUTRAL_COMMANDS_COMMAND_PERMISSION,
;
@Override
public @NotNull TranslatableMessage[] getAllMessages() {
return Translatable.values();
}
}

View File

@@ -7,7 +7,6 @@ import net.knarcraft.bookswithoutborders.encryption.SubstitutionCipher;
import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
@@ -19,6 +18,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getBookFolder;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getSlash;
@@ -238,19 +238,18 @@ public final class EncryptionHelper {
}
if (deleteEncryptedFile) {
ConsoleCommandSender consoleSender = BooksWithoutBorders.getConsoleSender();
Logger logger = BooksWithoutBorders.getInstance().getLogger();
try {
if (!file.delete()) {
BooksWithoutBorders.sendErrorMessage(consoleSender, "Book encryption data failed to delete upon decryption!");
BooksWithoutBorders.sendErrorMessage(consoleSender, "File location:" + file.getPath());
logger.log(Level.SEVERE, "Book encryption data failed to delete upon decryption!\n" +
"File location:" + file.getPath());
}
} catch (Exception e) {
BooksWithoutBorders.sendErrorMessage(consoleSender, "Book encryption data failed to delete upon decryption!");
BooksWithoutBorders.sendErrorMessage(consoleSender, "File location:" + file.getPath());
logger.log(Level.SEVERE, "Book encryption data failed to delete upon decryption!\nFile location:" + file.getPath());
}
}
ItemStack newBook = new ItemStack(Material.WRITTEN_BOOK);//Book(book.getAuthor(), book.getTitle(), pages, 1, 387);
ItemStack newBook = new ItemStack(Material.WRITTEN_BOOK);
newBook.setItemMeta(bookMetadata);
newBook.setAmount(InventoryHelper.getHeldBook(player, true).getAmount());
return newBook;
@@ -273,7 +272,7 @@ public final class EncryptionHelper {
if (!dirTest.exists()) {
try {
if (!dirTest.mkdir()) {
BooksWithoutBorders.sendErrorMessage(BooksWithoutBorders.getConsoleSender(), "Unable to create encryption group folder!");
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to create encryption group folder!");
return null;
}
} catch (Exception exception) {

View File

@@ -1,4 +1,6 @@
Options:
# The language to use. Only "en" is built-in, but custom languages can be added
Language: "en"
# Whether to use YAML for saved books instead of just storing them as text
Save_Books_in_Yaml_Format: true
# The maximum number of duplicates of a saved book allowed

View File

@@ -0,0 +1,25 @@
en:
PREFIX: "[BwB]"
SUCCESS_COPY: "Book copied!"
ERROR_PLAYER_ONLY: "This command can only be used by a player!"
ERROR_NOT_HOLDING_BOOK_COPY: "You must be holding a written book to copy it!"
ERROR_ONLY_ONE_BOOK_COPY: "You cannot copy two books at once!"
ERROR_COPY_COUNT_NOT_SPECIFIED: "You must specify the number of copies to be made!"
ERROR_COPY_NEGATIVE_AMOUNT: "Number of copies must be larger than 0!"
ERROR_COPY_INVALID_AMOUNT: |
Book not copied!
Number specified was invalid!
ERROR_BOOK_COPIED_TOO_FAR: "You cannot copy this book any further. You must have the original or a direct copy."
ERROR_INVENTORY_FULL: "You need an available slot in your inventory."
NEUTRAL_COMMANDS_HEADER: |
&e[] denote optional parameters
<> denote required parameters
{} denote required permission
In some cases, commands with required parameters can be called with no parameters
{bookPrice}&eCommands:
{commands}
NEUTRAL_COMMANDS_BOOK_PRICE_ECO: "\n&c[{price} is required to create a book]"
NEUTRAL_COMMANDS_BOOK_PRICE_ITEM: "&c[{quantity} {type} (s) are required to create a book]\n"
NEUTRAL_COMMANDS_COMMAND: "\n \n&e{usage}: &a{description}"
NEUTRAL_COMMANDS_COMMAND_NO_PERMISSION_REQUIRED: "None"
NEUTRAL_COMMANDS_COMMAND_PERMISSION: " &7{{permission}}"