9 Commits

Author SHA1 Message Date
0b701ddef1 Bumps version for development
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good
2024-09-07 01:44:40 +02:00
0fe9ccb590 Bumps version for release
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good
2024-09-07 01:34:42 +02:00
1a7236cebd Updates KnarLib and fixes pom 2024-09-07 01:33:38 +02:00
e482e494f8 Fixes some warnings 2024-09-07 01:27:00 +02:00
0f76c8f869 Changes unsign behavior to work on 1.21 2024-09-07 01:26:52 +02:00
6b4e87d33a Bumps Spigot version 2024-09-07 01:16:49 +02:00
40b0fa0baf Updates dependencies
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good
2024-05-03 15:53:55 +02:00
31bb26b755 Makes it clear that use includes peekbookshelf
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good
2023-06-24 12:40:55 +02:00
0e134fcdab Bumps version back to dev version
All checks were successful
EpicKnarvik97/Books-Without-Borders/pipeline/head This commit looks good
2023-06-24 12:34:18 +02:00
15 changed files with 127 additions and 86 deletions

View File

@ -30,7 +30,7 @@ Books without Borders has got your back!
value
- Change generation of books. Create tattered books for your RPG server!
- Optionally, make it impossible to duplicate the original version of a book
- Optionally, hit a bookshelf to display the contained books. Sneak to destroy bookshelves with this enabled
- Optionally, hit a bookshelf while sneaking to display the contained books
#### Group encryption
@ -67,39 +67,39 @@ An in-game description of available commands is available through the /bwb comma
### Permissions:
| 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 |
| bookswithoutborders.peekbookshelf | Allows player to left-click a bookshelf to see the contents of the shelf |
| Node | Description |
|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|
| bookswithoutborders.* | Grants all permissions |
| bookswithoutborders.admin | Grants all permissions |
| bookswithoutborders.use | bookswithoutborders.use - Allows player to use commands to save/load/delete in their personal directory, and peeking at bookshelves if enabled |
| 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 |
| bookswithoutborders.peekbookshelf | Allows player to left-click a bookshelf to see the contents of the shelf |
### Signs

36
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>net.knarcraft</groupId>
<artifactId>BooksWithoutBorders</artifactId>
<version>1.3.4</version>
<version>1.3.6-SNAPSHOT</version>
<packaging>jar</packaging>
<licenses>
@ -38,7 +38,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
@ -47,6 +47,16 @@
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>net.knarcraft.knarlib</pattern>
<shadedPattern>net.knarcraft.bookswithoutborders.lib.knarlib</shadedPattern>
</relocation>
<relocation>
<pattern>org.jetbrains.annotations</pattern>
<shadedPattern>net.knarcraft.bookswithoutborders.lib.annotations</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>net.knarcraft:knarlib</artifact>
@ -55,10 +65,10 @@
</includes>
</filter>
<filter>
<excludes>
<exclude>*.MF</exclude>
<exclude>*.yml</exclude>
</excludes>
<artifact>org.jetbrains:annotations</artifact>
<includes>
<include>org/jetbrains/annotations/**</include>
</includes>
</filter>
</filters>
</configuration>
@ -103,26 +113,32 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.1-R0.1-SNAPSHOT</version>
<version>1.21-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<version>1.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.knarcraft</groupId>
<artifactId>knarlib</artifactId>
<version>1.1</version>
<version>1.2.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.0.1</version>
<scope>provided</scope>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -46,6 +46,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getBookFolder;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getErrorColor;
@ -244,8 +245,8 @@ public class BooksWithoutBorders extends JavaPlugin {
sendErrorMessage(consoleSender, "Saving failed! Aborting...");
return false;
}
} catch (Exception e) {
e.printStackTrace();
} catch (Exception exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to create necessary folders");
return false;
}
}
@ -255,8 +256,8 @@ public class BooksWithoutBorders extends JavaPlugin {
sendErrorMessage(consoleSender, "Saving failed! Aborting...");
return false;
}
} catch (Exception e) {
e.printStackTrace();
} catch (Exception exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to create necessary folders");
return false;
}
}

View File

@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getCommandColor;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getErrorColor;
@ -142,8 +143,8 @@ public class CommandSave implements TabExecutor {
//Update the relevant book list
BooksWithoutBorders.updateBooks(player, saveToPublicFolder);
BooksWithoutBorders.sendSuccessMessage(player, "Book Saved as \"" + fileName + "\"");
} catch (IOException e) {
e.printStackTrace();
} catch (IOException exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to save book");
}
}

View File

@ -12,11 +12,13 @@ import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.WritableBookMeta;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
/**
* Command executor for the unsign command
@ -49,21 +51,36 @@ public class CommandUnSign implements TabExecutor {
*/
public void unSignHeldBook(Player player, boolean mainHand) {
//Get the old book
BookMeta oldBook = InventoryHelper.getHeldBookMetadata(player, mainHand);
BookMeta oldMetadata = 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")) {
if (BookHelper.isNotAuthor(player, Objects.requireNonNull(oldBook))) {
if (BookHelper.isNotAuthor(player, Objects.requireNonNull(oldMetadata))) {
return;
}
}
//UnSign the book
ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK);
newBook.setAmount(heldBook.getAmount());
newBook.setItemMeta(oldBook);
WritableBookMeta newMetadata = (BookMeta) BooksWithoutBorders.getItemFactory().getItemMeta(Material.WRITABLE_BOOK);
if (newMetadata == null) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to create writable book metadata");
return;
}
//Create a new unsigned book with the same data
ItemStack newBook = new ItemStack(Material.WRITABLE_BOOK, heldBook.getAmount());
if (oldMetadata.hasLore()) {
List<String> oldLore = oldMetadata.getLore();
if (oldLore != null) {
List<String> newLore = new ArrayList<>(oldLore);
newLore.remove(0);
newMetadata.setLore(newLore);
}
}
newMetadata.setPages(oldMetadata.getPages());
newBook.setItemMeta(newMetadata);
// Give the player the new book
InventoryHelper.replaceHeldItem(player, newBook, mainHand);
}

View File

@ -7,6 +7,7 @@ import org.bukkit.Material;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.Configuration;
import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.List;
@ -22,7 +23,7 @@ public class BooksWithoutBordersConfig {
private static final ChatColor errorColor = ChatColor.RED;
private static final ChatColor successColor = ChatColor.GREEN;
private static final ChatColor commandColor = ChatColor.YELLOW;
private static final String SLASH = System.getProperty("file.separator");
private static final String SLASH = FileSystems.getDefault().getSeparator();
private static boolean isInitialized;
public static String bookFolder;

View File

@ -1,5 +1,7 @@
package net.knarcraft.bookswithoutborders.encryption;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
@ -15,6 +17,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import java.util.logging.Level;
/**
* This class represents and AES encryptor/decryptor
@ -66,16 +69,16 @@ public class AES {
//Initialize cipher
try {
aes.init(mode, secretKeySpec, ivParameterSpec);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException | InvalidAlgorithmParameterException exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Invalid AES input given!");
return null;
}
//Perform encryption/decryption and output result
try {
byte[] output = aes.doFinal(getInputBytes(input, encrypt));
return createResult(output, encrypt);
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException | BadPaddingException exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Invalid AES block size or padding");
return null;
}
}
@ -131,8 +134,8 @@ public class AES {
Cipher aes;
try {
aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException | NoSuchPaddingException exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Invalid AES algorithm or padding");
return null;
}
return aes;
@ -149,15 +152,15 @@ public class AES {
SecretKeyFactory keyFactory;
try {
keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Invalid AES algorithm");
return null;
}
SecretKey tmp;
try {
tmp = keyFactory.generateSecret(spec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeySpecException exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Invalid AES key specification");
return null;
}
return new SecretKeySpec(tmp.getEncoded(), "AES");

View File

@ -33,7 +33,7 @@ public class GenenCrypt {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
for (int l = 0; l < 4; l++) {
originalCodonList.add("" + bases[i] + bases[j] + bases[k] + bases[l]);
originalCodonList.add(bases[i] + bases[j] + bases[k] + bases[l]);
}
}
}
@ -49,7 +49,7 @@ public class GenenCrypt {
// use the random number generator and the originalCodonList to make a shuffled list
ArrayList<String> shuffledCodonList = new ArrayList<>();
while (originalCodonList.size() > 0) {
while (!originalCodonList.isEmpty()) {
int index = ranGen.nextInt(originalCodonList.size());
shuffledCodonList.add(originalCodonList.get(index));
originalCodonList.remove(index);

View File

@ -19,7 +19,7 @@ public class SubstitutionCipher {
// original message is offset by
public String encrypt(String in, String key) {
StringBuilder output = new StringBuilder();
if (key != null && key.length() > 0) {
if (key != null && !key.isEmpty()) {
StringTokenizer tokenizer = new StringTokenizer(key, ", "); // tokenizes the key
// converts each number in the key to an integer and adds to an array
int[] offsetArray = new int[tokenizer.countTokens()];
@ -55,7 +55,7 @@ public class SubstitutionCipher {
@SuppressWarnings("unused")
public String decrypt(String in, String key) {
StringBuilder output = new StringBuilder();
if (key != null && key.length() > 0) {
if (key != null && !key.isEmpty()) {
StringTokenizer tokenizer = new StringTokenizer(key, ", "); // tokenizes the key
// converts each number in the key to an integer and adds to an array
int[] offsetArray = new int[tokenizer.countTokens()];

View File

@ -33,7 +33,8 @@ public class BookshelfListener implements Listener {
Player player = event.getPlayer();
// If left-clicking a chiseled bookshelf and sneaking, display contents
if (!event.hasBlock() || !(event.getClickedBlock().getState() instanceof ChiseledBookshelf chiseledBookshelf) ||
if (!event.hasBlock() || event.getClickedBlock() == null ||
!(event.getClickedBlock().getState() instanceof ChiseledBookshelf chiseledBookshelf) ||
event.getAction() != Action.LEFT_CLICK_BLOCK || !player.isSneaking()) {
return;
}

View File

@ -57,7 +57,7 @@ public class SignEventListener implements Listener {
//Check if the sign is of a valid type
if (!((lines[1].equalsIgnoreCase("[Encrypt]") || lines[1].equalsIgnoreCase("[Decrypt]") ||
lines[1].equalsIgnoreCase("[Give]")) && lines[2].trim().length() > 0)) {
lines[1].equalsIgnoreCase("[Give]")) && !lines[2].trim().isEmpty())) {
//Mark the second line as invalid
event.setLine(1, ChatColor.DARK_RED + lines[1]);
return;

View File

@ -1,5 +1,6 @@
package net.knarcraft.bookswithoutborders.utility;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig;
import net.knarcraft.knarlib.util.FileHelper;
import org.bukkit.configuration.file.FileConfiguration;
@ -15,6 +16,7 @@ import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import static net.knarcraft.bookswithoutborders.utility.BookHelper.authorFromUUID;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName;
@ -157,13 +159,13 @@ public final class BookToFromTextHelper {
List<String> rawPages;
try {
rawPages = readTextFile(file);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to read text file");
return null;
}
//Parse the generation from the book data
if (rawPages != null && rawPages.size() > 0 && rawPages.get(0).startsWith("Generation:")) {
if (rawPages != null && !rawPages.isEmpty() && rawPages.get(0).startsWith("Generation:")) {
bookMetadata.setGeneration(BookMeta.Generation.valueOf(rawPages.get(0).split(":")[1]));
rawPages.remove(0);
}

View File

@ -16,6 +16,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getBookFolder;
import static net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig.getSlash;
@ -255,8 +256,8 @@ public final class EncryptionHelper {
BooksWithoutBorders.sendErrorMessage(BooksWithoutBorders.getConsoleSender(), "Unable to create encryption group folder!");
return null;
}
} catch (Exception e) {
e.printStackTrace();
} catch (Exception exception) {
BooksWithoutBorders.getInstance().getLogger().log(Level.SEVERE, "Unable to save group encrypted book");
return null;
}
}
@ -279,8 +280,7 @@ public final class EncryptionHelper {
if (!file.isFile()) {
try {
BookToFromTextHelper.bookToYml(path, fileName, bookMetadata);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException exception) {
BooksWithoutBorders.sendErrorMessage(player, "Group encrypted failed!");
return null;
}
@ -312,8 +312,7 @@ public final class EncryptionHelper {
try {
BookToFromTextHelper.bookToYml(path, fileName, bookMetaData);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException exception) {
BooksWithoutBorders.sendErrorMessage(player, "Encryption failed!");
return false;
}

View File

@ -126,7 +126,7 @@ permissions:
bookswithoutborders.reload: true
bookswithoutborders.setgeneration: true
bookswithoutborders.use:
description: Allows player to use commands to save/load/delete in their personal directory
description: Allows player to use commands to save/load/delete in their personal directory, and peeking at bookshelves if enabled
children:
bookswithoutborders.save: true
bookswithoutborders.load: true

View File

@ -1,9 +1,9 @@
package net.knarcraft.bookswithoutborders.encryption;
import junit.framework.Assert;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
public class AESTest {
@ -15,7 +15,7 @@ public class AESTest {
AES aes = new AES(AES.generateIV(), AES.generateIV());
String encrypted = aes.encryptDecryptText(plainText, password, true);
Assert.assertNotSame(encrypted, plainText);
assertNotSame(encrypted, plainText);
String decrypted = aes.encryptDecryptText(encrypted, password, false);
assertEquals(plainText, decrypted);
}