First commit. Rewrite started
This commit is contained in:
commit
78828ac9fa
81
pom.xml
Normal file
81
pom.xml
Normal file
@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.knarcraft.bookswithoutborders</groupId>
|
||||
<artifactId>books-without-borders</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Books Without Borders</name>
|
||||
|
||||
<description>A continuation of the original Books Without Borders</description>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigotmc-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.17.1-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.MilkBowl</groupId>
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
<version>1.7</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,432 @@
|
||||
package net.knarcraft.bookswithoutborders;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
/**
|
||||
* A listener for relevant events
|
||||
*/
|
||||
public class BooksWithoutBordersListener implements Listener {
|
||||
|
||||
private final String slash = BooksWithoutBorders.SLASH;
|
||||
private final String bookFolder = BooksWithoutBorders.bwb.getDataFolder().getAbsolutePath() + slash + "Books" + slash;
|
||||
|
||||
/**
|
||||
* Updates old books to a newer format
|
||||
*
|
||||
* @param player <p>The player holding the book</p>
|
||||
* @param oldBook <p>Metadata about the held book</p>
|
||||
* @return <p>An updated book</p>
|
||||
*/
|
||||
public ItemStack updateBook(Player player, BookMeta oldBook) {
|
||||
//handles hacked title-less books
|
||||
if (oldBook.getTitle() == null || oldBook.getTitle().length() < 3) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (oldBook.getTitle().substring(oldBook.getTitle().length() - 3).equalsIgnoreCase("[U]")) {
|
||||
String fileName;
|
||||
|
||||
if (oldBook.getAuthor() != null && oldBook.getAuthor().equalsIgnoreCase("unknown")) {
|
||||
//Unknown author is ignored
|
||||
fileName = oldBook.getTitle();
|
||||
} else {
|
||||
fileName = oldBook.getTitle() + BooksWithoutBorders.titleAuthorSeparator + oldBook.getAuthor();
|
||||
}
|
||||
|
||||
String cleanPlayerName = BooksWithoutBorders.bwb.cleanString(player.getName());
|
||||
|
||||
String[] possiblePaths = new String[]{
|
||||
bookFolder + fileName + ".yml",
|
||||
bookFolder + fileName + ".txt",
|
||||
bookFolder + cleanPlayerName + slash + fileName + ".yml",
|
||||
bookFolder + cleanPlayerName + slash + fileName + ".txt"
|
||||
};
|
||||
|
||||
for (String path : possiblePaths) {
|
||||
File file = new File(path);
|
||||
if (file.isFile()) {
|
||||
return BooksWithoutBorders.bwb.loadBook(player, fileName, "true", "player");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onHold(PlayerItemHeldEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
int selectedSlot = e.getNewSlot();
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack selectedItem = playerInventory.getItem(selectedSlot);
|
||||
|
||||
//Ignore irrelevant items
|
||||
if (selectedItem == null || selectedItem.getType() != Material.WRITTEN_BOOK) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemMeta itemMetadata = selectedItem.getItemMeta();
|
||||
if (itemMetadata == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Update the book the user is viewing
|
||||
updateBookInHand(player, itemMetadata, true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||
//Handle new players
|
||||
if (!BooksWithoutBorders.bwb.hasPlayedBefore(e.getPlayer().getName())) {
|
||||
Player player = e.getPlayer();
|
||||
boolean sendMessage = true;
|
||||
|
||||
//Gives new players necessary books
|
||||
for (String bookName : BooksWithoutBorders.firstBooks) {
|
||||
sendMessage = giveBookToNewPlayer(bookName, player, sendMessage);
|
||||
}
|
||||
}
|
||||
|
||||
//Updates any books in either hand
|
||||
ItemStack mainHandItem = e.getPlayer().getInventory().getItemInMainHand();
|
||||
ItemStack offHandItem = e.getPlayer().getInventory().getItemInOffHand();
|
||||
if (mainHandItem.getType() == Material.WRITTEN_BOOK) {
|
||||
ItemMeta itemMetadata = mainHandItem.getItemMeta();
|
||||
updateBookInHand(e.getPlayer(), itemMetadata, true);
|
||||
}
|
||||
if (offHandItem.getType() == Material.WRITTEN_BOOK) {
|
||||
ItemMeta itemMetadata = offHandItem.getItemMeta();
|
||||
updateBookInHand(e.getPlayer(), itemMetadata, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a book to a player joining for the first time
|
||||
* @param bookName <p>The name of the book to give</p>
|
||||
* @param player <p>The player which just joined</p>
|
||||
* @param sendMessage <p>Whether to send a message to the joining player</p>
|
||||
* @return <p>True if a message has yet to be sent</p>
|
||||
*/
|
||||
private boolean giveBookToNewPlayer(String bookName, Player player, boolean sendMessage) {
|
||||
|
||||
if (!bookName.equalsIgnoreCase(" ")) {
|
||||
//handles loadlist numbers
|
||||
for (int x = 0; x < bookName.length(); x++) {
|
||||
if (!Character.isDigit(bookName.charAt(x))) {
|
||||
break;
|
||||
}
|
||||
if (x == bookName.length() - 1) {
|
||||
BooksWithoutBorders.loadList.put(player.getName(), BooksWithoutBorders.bwb.listFiles(player, true, 0, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ItemStack newBook = BooksWithoutBorders.bwb.loadBook(player, bookName, "true", "public");
|
||||
if (newBook != null) {
|
||||
player.getInventory().addItem(newBook);
|
||||
}
|
||||
|
||||
if (!BooksWithoutBorders.fBMessage.equalsIgnoreCase(" ") && newBook != null && sendMessage) {
|
||||
sendMessage = false;
|
||||
final Player fp = player;
|
||||
BooksWithoutBorders.bwb.getServer().getScheduler().scheduleSyncDelayedTask(BooksWithoutBorders.bwb,
|
||||
() -> fp.sendMessage(BooksWithoutBorders.fBMessage), 40L);
|
||||
}
|
||||
}
|
||||
return sendMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a book in one of the player's hands
|
||||
*
|
||||
* @param player <p>The player to update</p>
|
||||
* @param itemMetadata <p>Information about the held book</p>
|
||||
* @param mainHand <p>Whether to update the book in the player's main hand</p>
|
||||
*/
|
||||
private void updateBookInHand(Player player, ItemMeta itemMetadata, boolean mainHand) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack updatedBook = updateBook(player, (BookMeta) itemMetadata);
|
||||
if (updatedBook != null) {
|
||||
if (mainHand) {
|
||||
playerInventory.setItemInMainHand(updatedBook);
|
||||
} else {
|
||||
playerInventory.setItemInOffHand(updatedBook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSignChange(SignChangeEvent e) {
|
||||
if (e.getLine(0).equalsIgnoreCase("[BwB]") && e.getPlayer().hasPermission("bookswithoutborders.signs")) {
|
||||
e.setLine(0, ChatColor.DARK_GREEN + "[BwB]");
|
||||
|
||||
if ((e.getLine(1).equalsIgnoreCase("[Encrypt]") || e.getLine(1).equalsIgnoreCase("[Decrypt]") || e.getLine(1).equalsIgnoreCase("[Give]")) && e.getLine(2).replace(" ", "").length() > 0) {
|
||||
e.setLine(1, ChatColor.DARK_BLUE + e.getLine(1));
|
||||
if (e.getLine(1).equalsIgnoreCase(ChatColor.DARK_BLUE + "[Encrypt]") || e.getLine(1).equalsIgnoreCase(ChatColor.DARK_BLUE + "[Decrypt]")) {
|
||||
e.setLine(2, ChatColor.MAGIC + e.getLine(2));
|
||||
e.setLine(3, ChatColor.DARK_BLUE + e.getLine(3));
|
||||
}
|
||||
|
||||
if (e.getLine(1).equalsIgnoreCase(ChatColor.DARK_BLUE + "[Give]")) {
|
||||
if (e.getLine(2).length() > 13 || e.getLine(3).length() > 13) {
|
||||
e.getPlayer().sendMessage(ChatColor.RED + "[Give] signs' 3rd and 4th lines must be 13 characters or less!");
|
||||
e.setLine(2, ChatColor.DARK_RED + e.getLine(2));
|
||||
e.setLine(3, ChatColor.DARK_RED + e.getLine(3));
|
||||
return;
|
||||
}
|
||||
|
||||
//Tests if a full file name has been supplied
|
||||
if ((new File(BooksWithoutBorders.bwb.getDataFolder().getAbsolutePath() + BooksWithoutBorders.SLASH + "Books" + BooksWithoutBorders.SLASH + e.getLine(2) + e.getLine(3)).isFile()) ||
|
||||
(new File(BooksWithoutBorders.bwb.getDataFolder().getAbsolutePath() + BooksWithoutBorders.SLASH + "Books" + BooksWithoutBorders.SLASH + e.getLine(2) + e.getLine(3) + ".txt").isFile()) ||
|
||||
(new File(BooksWithoutBorders.bwb.getDataFolder().getAbsolutePath() + BooksWithoutBorders.SLASH + "Books" + BooksWithoutBorders.SLASH + e.getLine(2) + e.getLine(3) + ".yml").isFile())) {
|
||||
e.setLine(2, ChatColor.DARK_GREEN + e.getLine(2));
|
||||
e.setLine(3, ChatColor.DARK_GREEN + e.getLine(3));
|
||||
}
|
||||
|
||||
//Tests if a load list number has been supplied
|
||||
else {
|
||||
File dirFile = new File(BooksWithoutBorders.bwb.getDataFolder().getAbsolutePath() + BooksWithoutBorders.SLASH + "Books");
|
||||
for (int x = 0; x < e.getLine(2).length(); x++) {
|
||||
if (!Character.isDigit(e.getLine(2).charAt(x))) {
|
||||
e.setLine(2, ChatColor.DARK_RED + e.getLine(2));
|
||||
e.setLine(3, ChatColor.DARK_RED + e.getLine(3));
|
||||
break;
|
||||
}
|
||||
if (x == e.getLine(2).length() - 1) {
|
||||
List<String> fList = new ArrayList<>();
|
||||
for (int y = 0; y < dirFile.list().length; y++) {
|
||||
if (dirFile.listFiles()[y].isFile()) {
|
||||
fList.add(dirFile.listFiles()[y].getName());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (Integer.parseInt(e.getLine(2)) >= 0 && Integer.parseInt(e.getLine(2)) <= fList.size()) {
|
||||
BooksWithoutBorders.loadList.put(e.getPlayer().getName(), BooksWithoutBorders.bwb.listFiles(e.getPlayer(), true, 0, true));
|
||||
e.setLine(2, ChatColor.DARK_GREEN + e.getLine(2));
|
||||
e.setLine(3, ChatColor.DARK_GREEN + e.getLine(3));
|
||||
} else {
|
||||
e.setLine(2, ChatColor.DARK_RED + e.getLine(2));
|
||||
e.setLine(3, ChatColor.DARK_RED + e.getLine(3));
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
e.setLine(1, ChatColor.DARK_RED + e.getLine(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(PlayerInteractEvent e) {
|
||||
if (e.getClickedBlock() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material clickedBlockType = e.getClickedBlock().getType();
|
||||
Player player = e.getPlayer();
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
EquipmentSlot hand = e.getHand();
|
||||
if (hand == null) {
|
||||
return;
|
||||
}
|
||||
ItemStack heldItem = playerInventory.getItem(hand);
|
||||
Material heldItemType = heldItem.getType();
|
||||
|
||||
if (e.getAction() == Action.RIGHT_CLICK_BLOCK && (Tag.SIGNS.isTagged(clickedBlockType) || Tag.WALL_SIGNS.isTagged(clickedBlockType))) {
|
||||
//The player right-clicked a sign
|
||||
Sign sign = (Sign) e.getClickedBlock().getState();
|
||||
if (signLineEquals(sign, 0, "[BooksWithoutBorders]", ChatColor.DARK_GREEN)) {
|
||||
|
||||
if (signLineEquals(sign, 1, "[Encrypt]", ChatColor.DARK_BLUE)) {
|
||||
encryptHeldBookUsingSign(sign, heldItemType, player, hand);
|
||||
} else if (signLineEquals(sign, 1, "[Decrypt]", ChatColor.DARK_BLUE)) {
|
||||
decryptHeldBookUsingSign(sign, heldItemType, player, hand);
|
||||
} else if (signLineEquals(sign, 1, "[Give]", ChatColor.DARK_BLUE) &&
|
||||
getSignLineColor(sign, 2) == ChatColor.DARK_GREEN) {
|
||||
giveBook(sign, player);
|
||||
}
|
||||
}
|
||||
} else if (heldItemType == Material.WRITTEN_BOOK && (e.getAction() == Action.LEFT_CLICK_AIR
|
||||
|| e.getAction() == Action.LEFT_CLICK_BLOCK)) {
|
||||
BookMeta oldBook = (BookMeta) heldItem.getItemMeta();
|
||||
if (oldBook == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
decryptBook(oldBook, player, heldItem, hand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a book decryptable for a given group
|
||||
*
|
||||
* @param oldBook <p>Metadata for the encrypted book</p>
|
||||
* @param player <p>The player decrypting the book</p>
|
||||
* @param heldItem <p>The type of the held book</p>
|
||||
* @param hand <p>The hand the player is using to hold the book</p>
|
||||
*/
|
||||
private void decryptBook(BookMeta oldBook, Player player, ItemStack heldItem, EquipmentSlot hand) {
|
||||
ItemStack newBook;
|
||||
|
||||
//Check if the book is encrypted by Books Without Borders
|
||||
if (!oldBook.hasLore() || oldBook.getLore() == null || !oldBook.getLore().get(0).contains(" encrypted]")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String groupName = oldBook.getLore().get(0).substring(3).split(" encrypted")[0];
|
||||
|
||||
//Permission check
|
||||
if (!player.hasPermission("bookswithoutborders.decrypt." + groupName) &&
|
||||
!(BooksWithoutBorders.adminDecrypt && player.hasPermission("bookswithoutborders.admin"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fileName = oldBook.getTitle() + BooksWithoutBorders.titleAuthorSeparator + oldBook.getAuthor();
|
||||
|
||||
String encryptionFile = BooksWithoutBorders.bwb.cleanString(groupName) + slash + fileName + ".yml";
|
||||
|
||||
File file = new File(bookFolder + "Encrypted" + slash + encryptionFile);
|
||||
if (!file.isFile()) {
|
||||
file = new File(bookFolder + fileName + ".txt");
|
||||
if (!file.isFile()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
newBook = BooksWithoutBorders.bwb.loadBook(player, fileName, "true", groupName, heldItem.getAmount());
|
||||
|
||||
player.getInventory().setItem(hand, newBook);
|
||||
player.closeInventory();
|
||||
player.sendMessage(ChatColor.GREEN + "Book auto-decrypted!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts and replaces the player's used book
|
||||
*
|
||||
* @param sign <p>The clicked sign</p>
|
||||
* @param heldItemType <p>The item type used to click the sign</p>
|
||||
* @param player <p>The player which clicked the sign</p>
|
||||
* @param hand <p>The EquipmentSlot of the used hand</p>
|
||||
*/
|
||||
private void encryptHeldBookUsingSign(Sign sign, Material heldItemType, Player player, EquipmentSlot hand) {
|
||||
ItemStack eBook;
|
||||
if (heldItemType == Material.WRITTEN_BOOK) {
|
||||
player.closeInventory();
|
||||
eBook = BooksWithoutBorders.bwb.bookEncryption(player, sign.getLine(2).substring(2), sign.getLine(3).substring(2), "");
|
||||
if (eBook != null) {
|
||||
player.getInventory().setItem(hand, eBook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a player the book specified on a sign
|
||||
*
|
||||
* @param sign <p>The sign the user clicked</p>
|
||||
* @param player <p>The player which clicked the sign</p>
|
||||
*/
|
||||
private void giveBook(Sign sign, Player player) {
|
||||
String fileName = sign.getLine(2).substring(2);
|
||||
boolean isLoadListNumber = false;
|
||||
|
||||
for (int x = 0; x < fileName.length(); x++) {
|
||||
if (!Character.isDigit(fileName.charAt(x)))
|
||||
break;
|
||||
if (x == fileName.length() - 1) {
|
||||
BooksWithoutBorders.loadList.put(player.getName(), BooksWithoutBorders.bwb.listFiles(player, true, 0, true));
|
||||
isLoadListNumber = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isLoadListNumber && sign.getLine(3).length() >= 2)
|
||||
fileName = sign.getLine(2).substring(2) + sign.getLine(3).substring(2);
|
||||
|
||||
ItemStack newBook = BooksWithoutBorders.bwb.loadBook(player, fileName, "true", "public");
|
||||
|
||||
if (newBook != null) {
|
||||
player.getInventory().addItem(newBook);
|
||||
player.sendMessage(ChatColor.GREEN + "Received book!");
|
||||
} else {
|
||||
player.sendMessage(ChatColor.RED + "Book failed to load!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts and replaces the player's used book
|
||||
*
|
||||
* @param sign <p>The clicked sign</p>
|
||||
* @param heldItemType <p>The item type used to click the sign</p>
|
||||
* @param player <p>The player which clicked the sign</p>
|
||||
* @param hand <p>The EquipmentSlot of the used hand</p>
|
||||
*/
|
||||
private void decryptHeldBookUsingSign(Sign sign, Material heldItemType, Player player, EquipmentSlot hand) {
|
||||
//Decrypt the held book and replace it
|
||||
if (heldItemType == Material.WRITTEN_BOOK) {
|
||||
player.closeInventory();
|
||||
|
||||
//Converts user supplied key into integer form
|
||||
StringBuilder key = new StringBuilder();
|
||||
String lineText = ChatColor.stripColor(sign.getLine(2));
|
||||
for (int x = 0; x < lineText.length(); x++) {
|
||||
key.append(Character.getNumericValue(Character.codePointAt(lineText, x)));
|
||||
}
|
||||
|
||||
ItemStack book = BooksWithoutBorders.bwb.eLoad(player, key.toString(), false);
|
||||
if (book != null) {
|
||||
player.getInventory().setItem(hand, book);
|
||||
player.sendMessage(ChatColor.GREEN + "Book decrypted!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color of a line on a sign
|
||||
*
|
||||
* @param sign <p>The sign to check</p>
|
||||
* @param lineNumber <p>The line number to check</p>
|
||||
* @return <p>The color of the sign</p>
|
||||
*/
|
||||
private ChatColor getSignLineColor(Sign sign, int lineNumber) {
|
||||
return ChatColor.getByChar(sign.getLine(lineNumber).substring(0, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a line on a sign equals some string, and that the sign is the correct color
|
||||
*
|
||||
* @param sign <p>The sign to read</p>
|
||||
* @param lineNumber <p>The sign line to read</p>
|
||||
* @param compareTo <p>The string to look for</p>
|
||||
* @param color <p>The color to match</p>
|
||||
* @return <p>True if the given string is what's on the sign</p>
|
||||
*/
|
||||
private boolean signLineEquals(Sign sign, int lineNumber, String compareTo, ChatColor color) {
|
||||
String line = sign.getLine(lineNumber);
|
||||
return line.equalsIgnoreCase(color + compareTo);
|
||||
}
|
||||
|
||||
}
|
170
src/main/java/net/knarcraft/bookswithoutborders/GenenCrypt.java
Normal file
170
src/main/java/net/knarcraft/bookswithoutborders/GenenCrypt.java
Normal file
@ -0,0 +1,170 @@
|
||||
package net.knarcraft.bookswithoutborders;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class GenenCrypt {
|
||||
|
||||
private final Random ranGen;
|
||||
private final String[] bases;
|
||||
private final ArrayList<String> originalCodonList;
|
||||
private final ArrayList<String> shuffledCodonList;
|
||||
private final String[] charList;
|
||||
private final HashMap<String,String[]> codonTable;
|
||||
private final HashMap<String, String> decryptTable;
|
||||
private final String key;
|
||||
|
||||
public GenenCrypt(String key){
|
||||
|
||||
// define the initial, unshuffled codon list of 4 base codons
|
||||
originalCodonList = new ArrayList<>();
|
||||
bases = new String[]{"A", "T", "G", "C"};
|
||||
for(int i = 0; i < 4; i++){
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make a random number generator with a seed based on the key
|
||||
this.key = key;
|
||||
long longKey = 0;
|
||||
for(int i = 0; i < key.length(); i++){
|
||||
longKey += (int)key.charAt(i);
|
||||
}
|
||||
ranGen = new java.util.Random(longKey);
|
||||
|
||||
// use the random number generator and the originalCodonList to make a shuffled list
|
||||
shuffledCodonList = new ArrayList<>();
|
||||
while(originalCodonList.size() > 0){
|
||||
int index = ranGen.nextInt(originalCodonList.size());
|
||||
shuffledCodonList.add(originalCodonList.get(index));
|
||||
originalCodonList.remove(index);
|
||||
}
|
||||
|
||||
// define the characters that can be encoded, 64 in total
|
||||
// 26 capital letters
|
||||
// 10 digits
|
||||
// space, newline, and tab
|
||||
// the symbols . , ? " ! @ # $ % ^ & * ( ) - + = / _ \ : ; < >
|
||||
charList = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", " ", "\t", "\n", ".", ",", "?", "\"", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "+", "=", "/", "_", "\\", ":", ";", "<", ">", "|"};
|
||||
|
||||
// define the codon table to encode text
|
||||
codonTable = new HashMap<>();
|
||||
for(int i = 0; i < charList.length; i++){
|
||||
String[] tempArray = new String[]{shuffledCodonList.get(4 * i), shuffledCodonList.get(4 * i + 1), shuffledCodonList.get(4 * i + 2), shuffledCodonList.get(4 * i + 3)};
|
||||
//System.out.println(i);
|
||||
codonTable.put(charList[i], tempArray);
|
||||
}
|
||||
|
||||
// define the decryption table
|
||||
decryptTable = new HashMap<>();
|
||||
for(int i = 0; i < codonTable.size(); i++){
|
||||
String s = charList[i];
|
||||
String[] sa = codonTable.get(s);
|
||||
decryptTable.put(sa[0], s);
|
||||
decryptTable.put(sa[1], s);
|
||||
decryptTable.put(sa[2], s);
|
||||
decryptTable.put(sa[3], s);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void printShuffledList(){
|
||||
for (String s : shuffledCodonList) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
public void printOriginalList(){
|
||||
for (String s : originalCodonList) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
public void printCodonTable(){
|
||||
// print the codon table
|
||||
for(int i = 0; i < codonTable.size(); i++){
|
||||
String s = charList[i];
|
||||
String[] sa = codonTable.get(s);
|
||||
switch (s) {
|
||||
case "\t":
|
||||
System.out.println(i + "\t" + "\\t" + "\t" + sa[0] + ", " + sa[1] + ", " + sa[2] + ", " + sa[3]);
|
||||
break;
|
||||
case "\n":
|
||||
System.out.println(i + "\t" + "\\n" + "\t" + sa[0] + ", " + sa[1] + ", " + sa[2] + ", " + sa[3]);
|
||||
break;
|
||||
case " ":
|
||||
System.out.println(i + "\t" + "\" \"" + "\t" + sa[0] + ", " + sa[1] + ", " + sa[2] + ", " + sa[3]);
|
||||
break;
|
||||
default:
|
||||
System.out.println(i + "\t" + s + "\t" + sa[0] + ", " + sa[1] + ", " + sa[2] + ", " + sa[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String encrypt(String input){
|
||||
StringBuilder output = new StringBuilder();
|
||||
for(int i = 0; i < input.length(); i++){
|
||||
// insert junk bases
|
||||
int offset = key.charAt(i % key.length());
|
||||
StringBuilder junk = new StringBuilder();
|
||||
for(int j = 0; j < offset; j++){
|
||||
junk.append(bases[ranGen.nextInt(4)]);
|
||||
}
|
||||
output.append(junk);
|
||||
int choose = ranGen.nextInt(4);
|
||||
String s = ("" + input.charAt(i)).toUpperCase();
|
||||
if(codonTable.containsKey(s)){
|
||||
String[] sa = codonTable.get(s);
|
||||
output.append(sa[choose]);
|
||||
}
|
||||
}
|
||||
// add some junk bases to the end of the cipher text
|
||||
int offset = key.charAt(input.length() % key.length());
|
||||
StringBuilder junk = new StringBuilder();
|
||||
for(int j = 0; j < offset; j++){
|
||||
junk.append(bases[ranGen.nextInt(4)]);
|
||||
}
|
||||
output.append(junk);
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
public String decrypt(String in){
|
||||
String input = "" + in;
|
||||
StringBuilder output = new StringBuilder();
|
||||
int keyCount = 0;
|
||||
int junk = key.charAt(keyCount % key.length());
|
||||
while(input.length() > junk){
|
||||
// cuts out the junk bases
|
||||
input = input.substring(junk);
|
||||
// get the codon, decrypt the codon, remove it from the input string
|
||||
String codon = input.substring(0, 4);
|
||||
output.append(decryptTable.get(codon));
|
||||
input = input.substring(4);
|
||||
// increment the key counter and update junk
|
||||
keyCount++;
|
||||
junk = key.charAt(keyCount % key.length());
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/*public static void main(String[] args){
|
||||
GenenCrypt gc = new GenenCrypt("Another Key");
|
||||
gc.printCodonTable();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println("Encrypting the line \"Hello World!\"");
|
||||
String encrypted = gc.encrypt("Hello World!");
|
||||
System.out.println(encrypted);
|
||||
System.out.println();
|
||||
System.out.println("Decrypting the ciphertext");
|
||||
System.out.println(gc.decrypt(encrypted));
|
||||
|
||||
}*/
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package net.knarcraft.bookswithoutborders;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class SubstitutionCipher {
|
||||
|
||||
public SubstitutionCipher() {
|
||||
|
||||
}
|
||||
|
||||
// encrypts a string using a substitution cipher.
|
||||
// the substitution is made harder to crack by
|
||||
// using a string for the key, it is converted
|
||||
// a series of offsets that each character in the
|
||||
// original message is offset by
|
||||
public String encrypt(String in, String key) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
if (key != null && key.length() > 0) {
|
||||
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()];
|
||||
for (int i = 0; i < offsetArray.length; i++) {
|
||||
String nt = tokenizer.nextToken();
|
||||
|
||||
try {
|
||||
offsetArray[i] = Integer.parseInt(nt);
|
||||
} catch (NumberFormatException e) {
|
||||
BigInteger big = new BigInteger(nt);
|
||||
offsetArray[i] = Math.abs(big.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
int offsetPosition = 0;
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
output.append((char) (in.charAt(i) + offsetArray[offsetPosition])); //encrypts the letter and adds to the output string
|
||||
// uses the next offset in the key, goes back to first offset if at end of list
|
||||
if (offsetPosition < offsetArray.length - 1) {
|
||||
offsetPosition++;
|
||||
} else {
|
||||
offsetPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
// decrypts a string using the same substitution method,
|
||||
// but in reverse. Could probably be combined into one
|
||||
// method with a flag for encryption / decryption, but
|
||||
// I'm lazy.
|
||||
public String decrypt(String in, String key) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
if (key != null && key.length() > 0) {
|
||||
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()];
|
||||
for (int i = 0; i < offsetArray.length; i++) {
|
||||
offsetArray[i] = Integer.parseInt(tokenizer.nextToken());
|
||||
}
|
||||
int offsetPosition = 0;
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
output.append((char) (in.charAt(i) - offsetArray[offsetPosition])); //encrypts the letter and adds to the output string
|
||||
// uses the next offset in the key, goes back to first offset if at end of list
|
||||
if (offsetPosition < offsetArray.length - 1) {
|
||||
offsetPosition++;
|
||||
} else {
|
||||
offsetPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
|
||||
// the one time pad encryption is very secure, and
|
||||
// encryption works just like decryption, but is
|
||||
// vulnerable if the same key is used more than once.
|
||||
public String oneTimePad(String in, String key) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
output.append((char) (in.charAt(i) ^ key.charAt(i % key.length())));
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
}
|
||||
|
81
src/main/resources/plugin.yml
Normal file
81
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,81 @@
|
||||
name: Books-Without-Borders
|
||||
version: '${project.version}'
|
||||
main: net.knarcraft.bookswithoutborders.bookswithoutborders.BooksWithoutBorders
|
||||
api-version: 1.17
|
||||
prefix: Books Without Borders
|
||||
authors: [ EpicKnarvik97, AkiraAkiba ]
|
||||
description: A continuation of the original Books Without Borders
|
||||
softdepend:
|
||||
- Vault
|
||||
website: ????
|
||||
dev-url: ????
|
||||
commands:
|
||||
BooksWithoutBorders:
|
||||
description: Lists Books Without Borders's commands and uses.
|
||||
aliases: bwb
|
||||
permissions:
|
||||
bookswithoutborders.admin:
|
||||
description: Grants all permissions
|
||||
default: op
|
||||
children:
|
||||
bookswithoutborders.use: true
|
||||
bookswithoutborders.unsign: true
|
||||
bookswithoutborders.copy: true
|
||||
bookswithoutborders.loadpublic: true
|
||||
bookswithoutborders.savepublic: true
|
||||
bookswithoutborders.encrypt: true
|
||||
bookswithoutborders.decrypt: true
|
||||
bookswithoutborders.signs: true
|
||||
bookswithoutborders.give: true
|
||||
bookswithoutborders.givepublic: true
|
||||
bookswithoutborders.settitle: true
|
||||
bookswithoutborders.setauthor: true
|
||||
bookswithoutborders.setlore: true
|
||||
bookswithoutborders.bypassauthoronlycopy: true
|
||||
bookswithoutborders.bypassbookprice: true
|
||||
bookswithoutborders.groupencrypt: true
|
||||
bookswithoutborders.setbookprice: true
|
||||
bookswithoutborders.use:
|
||||
description: Allows player to use commands and to save/load/delete in their personal directory
|
||||
children:
|
||||
bookswithoutborders.save: true
|
||||
bookswithoutborders.load: true
|
||||
bookswithoutborders.delete: true
|
||||
bookswithoutborders.save:
|
||||
description: Allows player to save books to their personal directory
|
||||
bookswithoutborders.load:
|
||||
description: Allows player to load books from their personal directory
|
||||
bookswithoutborders.delete:
|
||||
description: Allows player to delete books from their personal directory
|
||||
bookswithoutborders.unsign:
|
||||
description: Allows player to use unsign command
|
||||
bookswithoutborders.copy:
|
||||
description: Allows player to use copy command
|
||||
bookswithoutborders.loadpublic:
|
||||
description: Allows player to load in the public directory
|
||||
bookswithoutborders.savepublic:
|
||||
description: Allows player to save in the public directory
|
||||
bookswithoutborders.encrypt:
|
||||
description: Allows player to encrypt books
|
||||
bookswithoutborders.groupencrypt:
|
||||
description: Allows player to set group based encryption
|
||||
bookswithoutborders.decrypt:
|
||||
description: Allows player to decrypt books
|
||||
bookswithoutborders.signs:
|
||||
description: Allows player to create signs that give/encrypt/decrypt books
|
||||
bookswithoutborders.give:
|
||||
description: Allows player to give another player one of their privately saved books
|
||||
bookswithoutborders.givepublic:
|
||||
description: Allows player to give another player a book from the public directory
|
||||
bookswithoutborders.settitle:
|
||||
description: Allows player to set the title of the currenlty held book
|
||||
bookswithoutborders.setauthor:
|
||||
description: Allows player to set the author of the currently held book
|
||||
bookswithoutborders.setlore:
|
||||
description: Allows player to set the lore of the currently held item
|
||||
bookswithoutborders.bypassauthoronlycopy:
|
||||
description: Allows player to ignore Author_Only_Copy config setting
|
||||
bookswithoutborders.bypassbookprice:
|
||||
description: Allows player to ignore Price_to_create_book config setting
|
||||
bookswithoutborders.setbookprice:
|
||||
description: Allows player to set the cost of creating a book
|
Loading…
Reference in New Issue
Block a user