Adds ability to set name and lore shown when chiseled bookshelves are peeked
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good
This commit is contained in:
@@ -18,11 +18,13 @@ import net.knarcraft.bookswithoutborders.command.CommandSave;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSavePublic;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetAuthor;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetBookPrice;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetBookshelfData;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSetGeneration;
|
||||
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.handler.BookshelfHandler;
|
||||
import net.knarcraft.bookswithoutborders.listener.BookEventListener;
|
||||
import net.knarcraft.bookswithoutborders.listener.BookshelfListener;
|
||||
import net.knarcraft.bookswithoutborders.listener.PlayerEventListener;
|
||||
@@ -68,6 +70,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
private static Map<UUID, Map<Character, Integer>> playerLetterIndex;
|
||||
private static BooksWithoutBorders booksWithoutBorders;
|
||||
private static ConsoleCommandSender consoleSender;
|
||||
private static BookshelfHandler bookshelfHandler;
|
||||
|
||||
/**
|
||||
* Gets the console sender for printing to the console
|
||||
@@ -170,6 +173,8 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
publicBooksList = files;
|
||||
publicLetterIndex = BookFileHelper.populateLetterIndices(files);
|
||||
}
|
||||
bookshelfHandler = new BookshelfHandler();
|
||||
bookshelfHandler.load();
|
||||
|
||||
PluginManager pluginManager = this.getServer().getPluginManager();
|
||||
|
||||
@@ -224,6 +229,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
registerCommand("formatBook", new CommandFormat());
|
||||
registerCommand("setBookGeneration", new CommandSetGeneration());
|
||||
registerCommand("clearBook", new CommandClear());
|
||||
registerCommand("setBookshelfData", new CommandSetBookshelfData());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,6 +274,15 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
return testFileSaving();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bookshelf handler
|
||||
*
|
||||
* @return <p>The bookshelf handler</p>
|
||||
*/
|
||||
public static BookshelfHandler getBookshelfHandler() {
|
||||
return bookshelfHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server's item factory
|
||||
*
|
||||
|
@@ -69,6 +69,7 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
}
|
||||
sender.sendMessage(getCommandColor() + "Commands:");
|
||||
|
||||
showCommandInfo("booksWithoutBorders", sender);
|
||||
showCommandInfo("copyBook", sender);
|
||||
showCommandInfo("decryptBook", sender);
|
||||
showCommandInfo("deleteBook", sender);
|
||||
@@ -89,6 +90,8 @@ public class CommandBooksWithoutBorders implements TabExecutor {
|
||||
showCommandInfo("setLore", sender);
|
||||
showCommandInfo("setTitle", sender);
|
||||
showCommandInfo("unsignBook", sender);
|
||||
showCommandInfo("clearBook", sender);
|
||||
showCommandInfo("setBookshelfData", sender);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,111 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.container.Bookshelf;
|
||||
import net.knarcraft.bookswithoutborders.handler.BookshelfHandler;
|
||||
import net.knarcraft.knarlib.util.TabCompletionHelper;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The command for setting information for a chiseled bookshelf
|
||||
*/
|
||||
public class CommandSetBookshelfData implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
if (!(commandSender instanceof Player player)) {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "This command must be used by a player!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Block targetBlock = player.getTargetBlockExact(7);
|
||||
if (targetBlock == null || targetBlock.getType() != Material.CHISELED_BOOKSHELF) {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "You are not looking at a bookshelf!");
|
||||
return false;
|
||||
}
|
||||
|
||||
BookshelfHandler shelfHandler = BooksWithoutBorders.getBookshelfHandler();
|
||||
Bookshelf bookshelf = shelfHandler.getFromLocation(targetBlock.getLocation());
|
||||
|
||||
if (arguments.length < 2) {
|
||||
if (arguments.length == 1 && arguments[0].equalsIgnoreCase("delete")) {
|
||||
if (bookshelf != null) {
|
||||
shelfHandler.unregisterBookshelf(bookshelf);
|
||||
shelfHandler.save();
|
||||
BooksWithoutBorders.sendSuccessMessage(commandSender, "Bookshelf successfully deleted");
|
||||
} else {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "The block you are looking at is not a registered bookshelf");
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get all arguments as a space-separated string
|
||||
StringBuilder builder = new StringBuilder(arguments[1]);
|
||||
for (int i = 2; i < arguments.length; i++) {
|
||||
builder.append(" ").append(arguments[i]);
|
||||
}
|
||||
|
||||
switch (arguments[0].toLowerCase()) {
|
||||
case "name":
|
||||
if (bookshelf == null) {
|
||||
Bookshelf newShelf = new Bookshelf(targetBlock.getLocation(), arguments[1], new ArrayList<>());
|
||||
shelfHandler.registerBookshelf(newShelf);
|
||||
} else {
|
||||
bookshelf.setTitle(builder.toString());
|
||||
}
|
||||
shelfHandler.save();
|
||||
BooksWithoutBorders.sendSuccessMessage(commandSender, "Title successfully saved");
|
||||
return true;
|
||||
case "lore":
|
||||
if (bookshelf == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(commandSender, "You must name the bookshelf before " +
|
||||
"assigning lore!");
|
||||
} else {
|
||||
List<String> loreParts = Arrays.asList(builder.toString().split(BooksWithoutBordersConfig.getLoreSeparator()));
|
||||
bookshelf.setLore(loreParts);
|
||||
shelfHandler.save();
|
||||
BooksWithoutBorders.sendSuccessMessage(commandSender, "Lore successfully saved");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
return TabCompletionHelper.filterMatchingStartsWith(List.of("delete", "name", "lore"), arguments[0]);
|
||||
} else if (arguments.length == 2) {
|
||||
return switch (arguments[0].toLowerCase()) {
|
||||
case "delete" -> new ArrayList<>();
|
||||
case "name" ->
|
||||
TabCompletionHelper.filterMatchingStartsWith(List.of("Epic Title", "Lame Title"), arguments[1]);
|
||||
case "lore" ->
|
||||
TabCompletionHelper.filterMatchingStartsWith(List.of("Interesting lore", "Line1~Line2~Line3"), arguments[1]);
|
||||
default -> null;
|
||||
};
|
||||
} else {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -47,8 +47,7 @@ public class CommandSetLore implements TabExecutor {
|
||||
|
||||
//Format lore
|
||||
rawLore = ColorHelper.translateColorCodes(rawLore, ColorConversion.RGB);
|
||||
String[] loreParts = rawLore.split(BooksWithoutBordersConfig.getLoreSeparator());
|
||||
List<String> newLore = new ArrayList<>(Arrays.asList(loreParts));
|
||||
List<String> newLore = Arrays.asList(rawLore.split(BooksWithoutBordersConfig.getLoreSeparator()));
|
||||
|
||||
//Update lore
|
||||
ItemMeta meta = heldItem.getItemMeta();
|
||||
|
@@ -0,0 +1,81 @@
|
||||
package net.knarcraft.bookswithoutborders.container;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A representation of a bookshelf with extra data used when displaying its contents
|
||||
*/
|
||||
public class Bookshelf {
|
||||
|
||||
private final @NotNull Location location;
|
||||
private @NotNull String title;
|
||||
private @NotNull List<String> lore;
|
||||
|
||||
/**
|
||||
* Instantiates a new bookshelf
|
||||
*
|
||||
* @param location <p>The location of the bookshelf</p>
|
||||
* @param title <p>The title of the bookshelf</p>
|
||||
* @param lore <p>The lore of the bookshelf</p>
|
||||
*/
|
||||
public Bookshelf(@NotNull Location location, @NotNull String title, @NotNull List<String> lore) {
|
||||
this.location = location;
|
||||
this.title = title;
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location of this bookshelf
|
||||
*
|
||||
* @return <p>The location of this bookshelf</p>
|
||||
*/
|
||||
@NotNull
|
||||
public Location getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the title of this bookshelf
|
||||
*
|
||||
* @return <p>The title of this bookshelf</p>
|
||||
*/
|
||||
@NotNull
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lore of this bookshelf
|
||||
*
|
||||
* @return <p>The lore of this bookshelf</p>
|
||||
*/
|
||||
@NotNull
|
||||
public List<String> getLore() {
|
||||
return this.lore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of this bookshelf
|
||||
*
|
||||
* @param title <p>The new title</p>
|
||||
*/
|
||||
public void setTitle(@NotNull String title) {
|
||||
if (title.isBlank()) {
|
||||
throw new IllegalArgumentException("Bookshelves cannot have empty titles!");
|
||||
}
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lore of this bookshelf
|
||||
*
|
||||
* @param lore <p>The new lore</p>
|
||||
*/
|
||||
public void setLore(@NotNull List<String> lore) {
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
package net.knarcraft.bookswithoutborders.handler;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.container.Bookshelf;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* A handler keeping track of all bookshelves
|
||||
*/
|
||||
public class BookshelfHandler {
|
||||
|
||||
private static final File bookshelfFile = new File(BooksWithoutBorders.getInstance().getDataFolder(),
|
||||
"bookShelves.yml");
|
||||
private Set<Bookshelf> bookShelves;
|
||||
private Map<Location, Bookshelf> locationLookup;
|
||||
|
||||
/**
|
||||
* Gets a bookshelf from the given location
|
||||
*
|
||||
* @param location <p>The location of the bookshelf</p>
|
||||
* @return <p>The bookshelf at the location, or null if no such bookshelf exists</p>
|
||||
*/
|
||||
@Nullable
|
||||
public Bookshelf getFromLocation(@NotNull Location location) {
|
||||
return locationLookup.get(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given bookshelf to this handler
|
||||
*
|
||||
* @param bookshelf <p>The bookshelf to register</p>
|
||||
*/
|
||||
public void registerBookshelf(@NotNull Bookshelf bookshelf) {
|
||||
this.bookShelves.add(bookshelf);
|
||||
this.locationLookup.put(bookshelf.getLocation(), bookshelf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the given bookshelf from this handler
|
||||
*
|
||||
* @param bookshelf <p>The bookshelf to unregister</p>
|
||||
*/
|
||||
public void unregisterBookshelf(@NotNull Bookshelf bookshelf) {
|
||||
this.locationLookup.remove(bookshelf.getLocation());
|
||||
this.bookShelves.remove(bookshelf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all stored bookshelves
|
||||
*/
|
||||
public void load() {
|
||||
this.bookShelves = new HashSet<>();
|
||||
this.locationLookup = new HashMap<>();
|
||||
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(bookshelfFile);
|
||||
ConfigurationSection bookshelfSection = configuration.getConfigurationSection("bookshelves");
|
||||
if (bookshelfSection == null) {
|
||||
BooksWithoutBorders.getInstance().getLogger().log(Level.INFO,
|
||||
"BooksWithoutBorders found no bookshelves to load");
|
||||
return;
|
||||
}
|
||||
|
||||
for (String key : bookshelfSection.getKeys(false)) {
|
||||
String[] locationInfo = key.split(",");
|
||||
World world = Bukkit.getWorld(UUID.fromString(locationInfo[0]));
|
||||
double x = Integer.parseInt(locationInfo[1]);
|
||||
double y = Integer.parseInt(locationInfo[2]);
|
||||
double z = Integer.parseInt(locationInfo[3]);
|
||||
Location bookshelfLocation = new Location(world, x, y, z);
|
||||
|
||||
String titleKey = key + ".title";
|
||||
String loreKey = key + ".lore";
|
||||
|
||||
String title = bookshelfSection.getString(titleKey, null);
|
||||
List<String> loreStrings = new ArrayList<>();
|
||||
List<?> lore = bookshelfSection.getList(loreKey);
|
||||
if (lore == null) {
|
||||
throw new IllegalArgumentException("Lore is missing from bookshelf data!");
|
||||
}
|
||||
lore.forEach((item) -> {
|
||||
if (item instanceof String) {
|
||||
loreStrings.add((String) item);
|
||||
}
|
||||
});
|
||||
|
||||
if (title != null) {
|
||||
registerBookshelf(new Bookshelf(bookshelfLocation, title, loreStrings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves all current bookshelves
|
||||
*/
|
||||
public void save() {
|
||||
try {
|
||||
YamlConfiguration configuration = new YamlConfiguration();
|
||||
ConfigurationSection bookshelfSection = configuration.createSection("bookshelves");
|
||||
for (Bookshelf bookshelf : bookShelves) {
|
||||
saveBookshelf(bookshelfSection, bookshelf);
|
||||
}
|
||||
configuration.save(bookshelfFile);
|
||||
} catch (IOException exception) {
|
||||
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to save bookshelves!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a bookshelf to the given configuration section
|
||||
*
|
||||
* @param section <p>The configuration section to save to</p>
|
||||
* @param bookshelf <p>The bookshelf to save</p>
|
||||
*/
|
||||
private void saveBookshelf(@NotNull ConfigurationSection section, @NotNull Bookshelf bookshelf) {
|
||||
Location location = bookshelf.getLocation();
|
||||
if (location.getWorld() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String key = location.getWorld().getUID() + "," + location.getBlockX() + "," + location.getBlockY() +
|
||||
"," + location.getBlockZ();
|
||||
String titleKey = key + ".title";
|
||||
String loreKey = key + ".lore";
|
||||
section.set(titleKey, bookshelf.getTitle());
|
||||
section.set(loreKey, bookshelf.getLore());
|
||||
}
|
||||
|
||||
}
|
@@ -1,15 +1,23 @@
|
||||
package net.knarcraft.bookswithoutborders.listener;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
|
||||
import net.knarcraft.bookswithoutborders.container.Bookshelf;
|
||||
import net.knarcraft.bookswithoutborders.handler.BookshelfHandler;
|
||||
import net.knarcraft.bookswithoutborders.utility.IntegerToRomanConverter;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.ChiseledBookshelf;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ChiseledBookshelfInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -27,6 +35,22 @@ import java.util.Map;
|
||||
*/
|
||||
public class BookshelfListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onBookshelfBreak(@NotNull BlockBreakEvent event) {
|
||||
Block block = event.getBlock();
|
||||
|
||||
if (block.getType() != Material.CHISELED_BOOKSHELF) {
|
||||
return;
|
||||
}
|
||||
|
||||
BookshelfHandler bookshelfHandler = BooksWithoutBorders.getBookshelfHandler();
|
||||
Bookshelf bookshelf = bookshelfHandler.getFromLocation(block.getLocation());
|
||||
if (bookshelf != null) {
|
||||
bookshelfHandler.unregisterBookshelf(bookshelf);
|
||||
bookshelfHandler.save();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBookshelfClick(@NotNull PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
@@ -48,19 +72,31 @@ public class BookshelfListener implements Listener {
|
||||
event.setUseItemInHand(Event.Result.DENY);
|
||||
|
||||
ChiseledBookshelfInventory bookshelfInventory = chiseledBookshelf.getInventory();
|
||||
player.sendMessage(getBookshelfDescription(bookshelfInventory));
|
||||
player.sendMessage(getBookshelfDescription(bookshelfInventory, event.getClickedBlock().getLocation()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description for a bookshelf's contents
|
||||
*
|
||||
* @param bookshelfInventory <p>The inventory of the bookshelf to describe</p>
|
||||
* @param location <p>The location of the clicked bookshelf</p>
|
||||
* @return <p>A textual description of the bookshelf's contents</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getBookshelfDescription(@NotNull ChiseledBookshelfInventory bookshelfInventory) {
|
||||
private String getBookshelfDescription(@NotNull ChiseledBookshelfInventory bookshelfInventory, @NotNull Location location) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(ChatColor.of("#FF5700")).append("Books in shelf:").append(ChatColor.RESET);
|
||||
|
||||
Bookshelf bookshelf = BooksWithoutBorders.getBookshelfHandler().getFromLocation(location);
|
||||
if (bookshelf != null) {
|
||||
builder.append(ChatColor.of("#FF5700")).append("Books in ").append(bookshelf.getTitle())
|
||||
.append(":").append(ChatColor.RESET);
|
||||
for (String lore : bookshelf.getLore()) {
|
||||
builder.append("\n ").append(ChatColor.LIGHT_PURPLE).append(lore);
|
||||
}
|
||||
} else {
|
||||
builder.append(ChatColor.of("#FF5700")).append("Books in shelf:").append(ChatColor.RESET);
|
||||
}
|
||||
|
||||
for (int i = 0; i < bookshelfInventory.getSize(); i++) {
|
||||
int index = (i % 3) + 1;
|
||||
if (i % 3 == 0) {
|
||||
|
@@ -97,6 +97,10 @@ commands:
|
||||
description: Reloads BwB's configuration file
|
||||
usage: /<command>
|
||||
permission: bookswithoutborders.reload
|
||||
setBookshelfData:
|
||||
description: Sets custom data for a chiseled bookshelf used when peeking at the bookshelf
|
||||
usage: /<command> <delete/name/lore> <text> [more text]
|
||||
permission: bookswithoutborders.editbookshelf
|
||||
permissions:
|
||||
bookswithoutborders.*:
|
||||
description: Grants all permissions
|
||||
@@ -125,6 +129,7 @@ permissions:
|
||||
bookswithoutborders.setbookprice: true
|
||||
bookswithoutborders.reload: true
|
||||
bookswithoutborders.setgeneration: true
|
||||
bookswithoutborders.editbookshelf: true
|
||||
bookswithoutborders.use:
|
||||
description: Allows player to use commands to save/load/delete in their personal directory, and peeking at bookshelves if enabled
|
||||
children:
|
||||
@@ -193,4 +198,6 @@ permissions:
|
||||
bookswithoutborders.setgeneration:
|
||||
description: Allows player to change the generation of a book (Original, Copy, Copy of Copy)
|
||||
bookswithoutborders.peekbookshelf:
|
||||
description: Allows player to left-click a bookshelf to see the contents of the shelf
|
||||
description: Allows player to left-click a bookshelf to see the contents of the shelf
|
||||
bookswithoutborders.editbookshelf:
|
||||
description: Allows player to set name/lore for bookshelves, used for peeking
|
Reference in New Issue
Block a user