diff --git a/src/main/java/net/licks92/wirelessredstone/ConfigManager.java b/src/main/java/net/licks92/wirelessredstone/ConfigManager.java
new file mode 100644
index 0000000..5944666
--- /dev/null
+++ b/src/main/java/net/licks92/wirelessredstone/ConfigManager.java
@@ -0,0 +1,198 @@
+package net.licks92.wirelessredstone;
+
+import net.licks92.wirelessredstone.storage.StorageType;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.util.FileUtil;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Objects;
+
+
+public class ConfigManager {
+
+ private static final ConfigManager configuration = new ConfigManager("config");
+
+ public static ConfigManager getConfig() {
+ return configuration;
+ }
+
+ private final File file;
+ private final YamlConfiguration config;
+
+ private ConfigManager(final String fileName) {
+ if (!WirelessRedstone.getInstance().getDataFolder().exists()) {
+ WirelessRedstone.getInstance().getDataFolder().mkdir();
+ }
+
+ file = new File(WirelessRedstone.getInstance().getDataFolder(), fileName + ".yml");
+
+ if (!file.exists()) {
+ try {
+ file.createNewFile();
+ copyStream(Objects.requireNonNull(WirelessRedstone.getInstance().getResource("config.yml")), new FileOutputStream(file));
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ config = YamlConfiguration.loadConfiguration(file);
+
+ if (getCacheRefreshRate() < 60 || getCacheRefreshRate() > 480)
+ setValue(ConfigPaths.CACHEREFRESHRATE, (getCacheRefreshRate() < 60) ? 60 : 480);
+ }
+
+ /* Extract files out of the jar file. */
+ private void copyStream(InputStream input, OutputStream output)
+ throws IOException {
+ // Reads up to 8K at a time.
+ byte[] buffer = new byte[8192];
+ int read;
+
+ while ((read = input.read(buffer)) != -1) {
+ output.write(buffer, 0, read);
+ }
+ }
+
+ /* Save the config.
+ * Very imported if something has changed. */
+ public void save() {
+ try {
+ config.save(file);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public void copyDefaults(){
+ if (config == null)
+ return;
+
+ config.options().copyHeader(true);
+ config.options().copyDefaults(true);
+ }
+
+ public void update(String channelFolder) {
+ switch (getConfigVersion()) {
+ case 1: {
+ File channelFolderFile = new File(WirelessRedstone.getInstance().getDataFolder(), channelFolder);
+ channelFolderFile.mkdir();
+
+ if (getStorageType() == StorageType.SQLITE
+ && new File(channelFolderFile + File.separator + "channels.db").exists()
+ && !(new File(channelFolderFile + File.separator + "WirelessRedstoneDatabase.db").exists())) {
+ new File(channelFolderFile + File.separator + "WirelessRedstoneDatabase.db").delete();
+ FileUtil.copy(
+ new File(channelFolderFile + File.separator + "channels.db"),
+ new File(channelFolderFile + File.separator + "WirelessRedstoneDatabase.db"));
+ }
+
+ copyDefaults();
+
+ setValue(ConfigPaths.CONFIGVERSION, 2);
+
+ // no break; because we want the switch to fall through next versions
+ }
+ case 2: {
+ removeValue("cancelChunkUnloads");
+ removeValue("cancelChunkUnloadRange");
+
+ copyDefaults();
+
+ setValue(ConfigPaths.CONFIGVERSION, 3);
+
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ public void setStorageType(StorageType storageType) {
+ config.set(ConfigPaths.SAVEMODE.getValue(), storageType.toString().toUpperCase());
+ save();
+ }
+
+ public void setValue(ConfigPaths configPaths, Object object) {
+ config.set(configPaths.getValue(), object);
+ save();
+ }
+
+ public void removeValue(String path) {
+ config.set(path, null);
+ save();
+ }
+
+ public Integer getConfigVersion() {
+ return config.getInt(ConfigPaths.CONFIGVERSION.getValue(), 1);
+ }
+
+ public boolean getDebugMode() {
+ return config.getBoolean(ConfigPaths.DEBUGMODE.getValue(), false);
+ }
+
+ public boolean getColorLogging() {
+ return config.getBoolean(ConfigPaths.COLORLOGGING.getValue(), true);
+ }
+
+ public boolean getVault() {
+ return config.getBoolean(ConfigPaths.USEVAULT.getValue(), true);
+ }
+
+ public boolean getSilentMode() {
+ return config.getBoolean(ConfigPaths.SILENTMODE.getValue(), false);
+ }
+
+ public boolean getDropSignBroken() {
+ return config.getBoolean(ConfigPaths.DROPSIGNBROKEN.getValue(), true);
+ }
+
+ public boolean useORLogic() {
+ return !config.getString(ConfigPaths.GATELOGIC.getValue(), "OR").equalsIgnoreCase("IGNORE");
+ }
+
+ public Integer getInteractTransmitterTime() {
+ return config.getInt(ConfigPaths.INTERACTTRANSMITTERTIME.getValue(), 1000);
+ }
+
+ public Integer getCacheRefreshRate() {
+ return config.getInt(ConfigPaths.CACHEREFRESHRATE.getValue(), 150);
+ }
+
+ public String getLanguage() {
+ return config.getString(ConfigPaths.LANGUAGE.getValue(), "en");
+ }
+
+ public StorageType getStorageType() {
+ switch (config.getString(ConfigPaths.SAVEMODE.getValue(), "YML").toUpperCase()) {
+ case "YAML":
+ case "YML":
+ return StorageType.YAML;
+ case "SQLITE":
+ return StorageType.SQLITE;
+ default:
+ return StorageType.YAML;
+ }
+ }
+
+ public enum ConfigPaths {
+ CONFIGVERSION("ConfigVersion"), DEBUGMODE("DebugMode"), LANGUAGE("Language"), COLORLOGGING("ColourfulLogging"),
+ USEVAULT("UseVault"), SILENTMODE("SilentMode"),
+ INTERACTTRANSMITTERTIME("InteractTransmitterTime"), CACHEREFRESHRATE("CacheRefreshFrequency"),
+ GATELOGIC("gateLogic"), SAVEMODE("saveOption"), DROPSIGNBROKEN("DropSignWhenBroken");
+
+ private final String name;
+
+ ConfigPaths(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return name;
+ }
+ }
+
+}
diff --git a/src/main/java/net/licks92/wirelessredstone/Permissions.java b/src/main/java/net/licks92/wirelessredstone/Permissions.java
new file mode 100644
index 0000000..951b219
--- /dev/null
+++ b/src/main/java/net/licks92/wirelessredstone/Permissions.java
@@ -0,0 +1,30 @@
+package net.licks92.wirelessredstone;
+
+public class Permissions {
+
+ //Create
+ public static final String canCreateReceiver = "wirelessredstone.create.receiver";
+ public static final String canCreateTransmitter = "wirelessredstone.create.transmitter";
+ public static final String canCreateScreen = "wirelessredstone.create.screen";
+ //Remove
+ public static final String canRemoveReceiver = "wirelessredstone.remove.receiver";
+ public static final String canRemoveTransmitter = "wirelessredstone.remove.transmitter";
+ public static final String canRemoveScreen = "wirelessredstone.remove.screen";
+ //Commands
+ public static final String canRemoveChannel = "wirelessredstone.commands.removechannel";
+ public static final String canUseListCommand = "wirelessredstone.commands.list";
+ public static final String canSeeHelp = "wirelessredstone.commands.help";
+ public static final String canSeeChannelInfo = "wirelessredstone.commands.info";
+ public static final String canLockChannel = "wirelessredstone.commands.lock";
+ public static final String canActivateChannel = "wirelessredstone.commands.activate";
+ public static final String canSeeVersion = "wirelessredstone.commands.version";
+ public static final String canTeleportToSign = "wirelessredstone.commands.tp";
+ //Admin
+ public static final String isWirelessAdmin = "wirelessredstone.Admin.isAdmin";
+ public static final String canWipeData = "wirelessredstone.Admin.wipedata";
+ public static final String canBackupData = "wirelessredstone.Admin.backupdata";
+ public static final String canPurgeData = "wirelessredstone.Admin.purgedata";
+ public static final String canConvertData = "wirelessredstone.Admin.convertdata";
+ public static final String canRestoreData = "wirelessredstone.Admin.restoredata";
+
+}
diff --git a/src/main/java/net/licks92/wirelessredstone/SignManager.java b/src/main/java/net/licks92/wirelessredstone/SignManager.java
new file mode 100644
index 0000000..943f50e
--- /dev/null
+++ b/src/main/java/net/licks92/wirelessredstone/SignManager.java
@@ -0,0 +1,335 @@
+package net.licks92.wirelessredstone;
+
+import net.licks92.wirelessredstone.compat.InternalProvider;
+import net.licks92.wirelessredstone.materiallib.data.CrossMaterial;
+import net.licks92.wirelessredstone.signs.SignType;
+import net.licks92.wirelessredstone.signs.WirelessChannel;
+import net.licks92.wirelessredstone.signs.WirelessPoint;
+import net.licks92.wirelessredstone.signs.WirelessReceiver;
+import net.licks92.wirelessredstone.signs.WirelessReceiverClock;
+import net.licks92.wirelessredstone.signs.WirelessReceiverDelayer;
+import net.licks92.wirelessredstone.signs.WirelessReceiverInverter;
+import net.licks92.wirelessredstone.signs.WirelessReceiverSwitch;
+import net.licks92.wirelessredstone.signs.WirelessScreen;
+import net.licks92.wirelessredstone.signs.WirelessTransmitter;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.Sign;
+import org.bukkit.entity.Player;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SignManager {
+
+ /**
+ * Check if the player has access to a WirelessChannel.
+ * Player passed if the player is OP, has isAdmin permission or is an owner of the channel.
+ *
+ * @param player Player
+ * @param channelName WirelessChannel name
+ * @return If the player has access
+ */
+ public boolean hasAccessToChannel(Player player, String channelName) {
+ WirelessChannel channel = WirelessRedstone.getStorageManager().getChannel(channelName);
+
+ if (channel == null) {
+ return true;
+ }
+
+ return channel.getOwners().contains(player.getUniqueId().toString()) || player.hasPermission(Permissions.isWirelessAdmin) || player.isOp();
+ }
+
+ /**
+ * Check if the player has the permissions to place a sign.
+ *
+ * @param player Player
+ * @param signType SignType
+ * @return Boolean
+ */
+ public boolean canPlaceSign(Player player, SignType signType) {
+ if (player.isOp() || player.hasPermission(Permissions.isWirelessAdmin)) {
+ return true;
+ }
+
+ if (signType == SignType.TRANSMITTER) {
+ return player.hasPermission(Permissions.canCreateTransmitter);
+ } else if (signType == SignType.SCREEN) {
+ return player.hasPermission(Permissions.canCreateScreen);
+ } else {
+ return player.hasPermission(Permissions.canCreateReceiver);
+ }
+ }
+
+ /**
+ * Place a sign with the correct sign lines at a location.
+ * Extra data for certain receivers is set at 0.
+ *
+ * @param channelName WirelessChannel name
+ * @param location Location of the sign
+ * @param type SignType
+ * @return Boolean; Success or failure
+ */
+ public boolean placeSign(String channelName, Location location, SignType type) {
+ return placeSign(channelName, location, type, 0);
+ }
+
+ /**
+ * Place a sign with the correct sign lines at a location.
+ *
+ * @param channelName WirelessChannel name
+ * @param location Location of the sign
+ * @param type SignType
+ * @param extraData Extra data needed for certain receivers
+ * @return Boolean; Success or failure
+ */
+ public boolean placeSign(String channelName, Location location, SignType type, int extraData) {
+ Block block = location.getBlock();
+ if (block.getType() != Material.AIR) {
+ return false;
+ }
+
+ if (!(CrossMaterial.SIGN.equals(block.getType()) || CrossMaterial.WALL_SIGN.equals(block.getType()))) {
+ block = CrossMaterial.SIGN.setMaterial(block);
+ }
+
+ if (!(location.getBlock().getState() instanceof Sign)) {
+ return false;
+ }
+
+ Sign sign = (Sign) block.getState();
+ sign.setLine(1, channelName);
+
+ switch (type) {
+ case TRANSMITTER:
+ sign.setLine(0, WirelessRedstone.getStringManager().tagsTransmitter.get(0));
+ break;
+ case SCREEN:
+ sign.setLine(0, WirelessRedstone.getStringManager().tagsScreen.get(0));
+ break;
+ case RECEIVER:
+ sign.setLine(0, WirelessRedstone.getStringManager().tagsReceiver.get(0));
+ sign.setLine(2, WirelessRedstone.getStringManager().tagsReceiverDefaultType.get(0));
+ break;
+ case RECEIVER_INVERTER:
+ sign.setLine(0, WirelessRedstone.getStringManager().tagsReceiver.get(0));
+ sign.setLine(2, WirelessRedstone.getStringManager().tagsReceiverInverterType.get(0));
+ break;
+ case RECEIVER_SWITCH:
+ sign.setLine(0, WirelessRedstone.getStringManager().tagsReceiver.get(0));
+ sign.setLine(2, WirelessRedstone.getStringManager().tagsReceiverSwitchType.get(0));
+ break;
+ case RECEIVER_DELAYER:
+ sign.setLine(0, WirelessRedstone.getStringManager().tagsReceiver.get(0));
+ sign.setLine(2, WirelessRedstone.getStringManager().tagsReceiverDelayerType.get(0));
+ sign.setLine(3, Integer.toString(extraData));
+ break;
+ case RECEIVER_CLOCK:
+ sign.setLine(0, WirelessRedstone.getStringManager().tagsReceiver.get(0));
+ sign.setLine(2, WirelessRedstone.getStringManager().tagsReceiverClockType.get(0));
+ sign.setLine(3, Integer.toString(extraData));
+ break;
+ }
+
+ sign.update();
+ InternalProvider.getCompatBlockData().setSignRotation(block, Utils.yawToFace(location.getYaw()));
+ return true;
+ }
+
+ /**
+ * Save a WirelessRedstone sign to the database.
+ *
+ * @param channelName Name of the WirelessRedstone channel
+ * @param block Place where the block is located
+ * @param type What WirelessPoint type
+ * @param direction Which direction is the sign facing
+ * @param owners All the owners of the channel
+ * @param delay Amount of delay for clock & delayer; this can be 0 if it is not one of these types
+ * @return Return value
+ * 0 - Success; extended a channel
+ * 1 - Success; created a channel
+ * -1 - Failure; Delayer delay must be >= 50
+ * -2 - Failure; Clock delay must be >= 50
+ */
+ public int registerSign(String channelName, Block block, SignType type, BlockFace direction, List owners, int delay) {
+ int result = 0;
+
+ if (type == SignType.RECEIVER_DELAYER) {
+ if (delay < 50) {
+ result = -1;
+ return result;
+ }
+ } else if (type == SignType.RECEIVER_CLOCK) {
+ if (delay < 50) {
+ result = -2;
+ return result;
+ }
+ }
+
+ if (WirelessRedstone.getStorageManager().getChannel(channelName) == null) {
+ result = 1;
+ WirelessRedstone.getStorage().createChannel(new WirelessChannel(channelName, owners));
+ }
+
+ boolean isWallSign = CrossMaterial.WALL_SIGN.equals(block.getType());
+
+ WirelessPoint point = null;
+ switch (type) {
+ case TRANSMITTER:
+ point = new WirelessTransmitter(
+ block.getLocation().getBlockX(),
+ block.getLocation().getBlockY(),
+ block.getLocation().getBlockZ(),
+ block.getLocation().getWorld().getName(),
+ isWallSign,
+ direction,
+ owners.get(0)
+ );
+ break;
+ case SCREEN:
+ point = new WirelessScreen(
+ block.getLocation().getBlockX(),
+ block.getLocation().getBlockY(),
+ block.getLocation().getBlockZ(),
+ block.getLocation().getWorld().getName(),
+ isWallSign,
+ direction,
+ owners.get(0)
+ );
+ break;
+ case RECEIVER:
+ point = new WirelessReceiver(
+ block.getLocation().getBlockX(),
+ block.getLocation().getBlockY(),
+ block.getLocation().getBlockZ(),
+ block.getLocation().getWorld().getName(),
+ isWallSign,
+ direction,
+ owners.get(0)
+ );
+ break;
+ case RECEIVER_INVERTER:
+ point = new WirelessReceiverInverter(
+ block.getLocation().getBlockX(),
+ block.getLocation().getBlockY(),
+ block.getLocation().getBlockZ(),
+ block.getLocation().getWorld().getName(),
+ isWallSign,
+ direction,
+ owners.get(0)
+ );
+ break;
+ case RECEIVER_SWITCH:
+ point = new WirelessReceiverSwitch(
+ block.getLocation().getBlockX(),
+ block.getLocation().getBlockY(),
+ block.getLocation().getBlockZ(),
+ block.getLocation().getWorld().getName(),
+ isWallSign,
+ direction,
+ owners.get(0)
+ );
+ break;
+ case RECEIVER_DELAYER:
+ point = new WirelessReceiverDelayer(
+ block.getLocation().getBlockX(),
+ block.getLocation().getBlockY(),
+ block.getLocation().getBlockZ(),
+ block.getLocation().getWorld().getName(),
+ isWallSign,
+ direction,
+ owners.get(0),
+ delay
+ );
+ break;
+ case RECEIVER_CLOCK:
+ point = new WirelessReceiverClock(
+ block.getLocation().getBlockX(),
+ block.getLocation().getBlockY(),
+ block.getLocation().getBlockZ(),
+ block.getLocation().getWorld().getName(),
+ isWallSign,
+ direction,
+ owners.get(0),
+ delay
+ );
+ break;
+ }
+
+ WirelessRedstone.getStorage().createWirelessPoint(channelName, point);
+ return result;
+ }
+
+ /**
+ * Remove a sign from the database based on a location.
+ *
+ * @param channelName WirelessChannel name
+ * @param location Location of the sign
+ * @return Boolean; Success or failure (channel/sign not found)
+ */
+ public boolean removeSign(String channelName, Location location) {
+ if (WirelessRedstone.getStorageManager().getChannel(channelName) == null) {
+ return false;
+ }
+
+ WirelessChannel channel = WirelessRedstone.getStorageManager().getChannel(channelName);
+ WirelessPoint point = channel.getSigns().stream()
+ .filter(pointList -> Utils.sameLocation(pointList.getLocation(), location))
+ .findFirst()
+ .orElse(null);
+
+ if (point == null) {
+ return false;
+ }
+
+ WirelessRedstone.getStorage().removeWirelessPoint(channelName, point);
+ return true;
+ }
+
+ /**
+ * Check if a sign is registred at a location.
+ *
+ * @param location Location of the sign
+ * @return Boolean; Sign registred or not
+ */
+ public boolean isSignRegistred(Location location) {
+ return WirelessRedstone.getStorageManager().getAllSigns().stream()
+ .anyMatch(point -> Utils.sameLocation(point.getLocation(), location));
+ }
+
+ public boolean isWirelessRedstoneSign(Block block) {
+ if (!(block.getState() instanceof Sign)) {
+ return false;
+ }
+
+ Sign sign = (Sign) block.getState();
+
+ if (Utils.getSignType(sign.getLine(0)) == null || sign.getLine(1).equalsIgnoreCase("")) {
+ return false;
+ }
+
+ return isSignRegistred(block.getLocation());
+ }
+
+ public HashMap> getAllInvalidPoints() {
+ HashMap> map = new HashMap<>();
+
+ for (WirelessChannel channel : WirelessRedstone.getStorageManager().getChannels()) {
+ List points = channel.getSigns().stream()
+ .filter(point -> Bukkit.getWorld(point.getWorld()) == null)
+ .collect(Collectors.toList());
+
+ if (!points.isEmpty()) {
+ map.put(channel, points);
+ }
+ }
+
+ return map;
+ }
+
+}
diff --git a/src/main/java/net/licks92/wirelessredstone/Utils.java b/src/main/java/net/licks92/wirelessredstone/Utils.java
new file mode 100644
index 0000000..33fcf58
--- /dev/null
+++ b/src/main/java/net/licks92/wirelessredstone/Utils.java
@@ -0,0 +1,318 @@
+package net.licks92.wirelessredstone;
+
+import net.licks92.wirelessredstone.signs.SignType;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.block.BlockFace;
+import org.bukkit.command.CommandSender;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class Utils {
+ private static final BlockFace[] axis = {BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST};
+ private static final BlockFace[] fullAxis = {BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST, BlockFace.UP, BlockFace.DOWN};
+
+ /**
+ * This checks if the new material system is in place.
+ *
+ * @return If the new material system is needed
+ */
+ public static boolean isNewMaterialSystem() {
+ final String packageName = Bukkit.getServer().getClass().getPackage().getName();
+ String bukkitVersion = packageName.substring(packageName.lastIndexOf('.') + 1);
+
+ try {
+ String[] pieces = bukkitVersion.substring(1).split("_");
+
+ return Integer.parseInt(pieces[0]) >= 1 && Integer.parseInt(pieces[1]) >= 13;
+ } catch (NumberFormatException | NullPointerException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Display a message with prefix to a specific user. This ignores the silent mode.
+ *
+ * @param message Text message
+ * @param sender Where send the message to
+ * @param error Is the message an error
+ */
+ public static void sendFeedback(String message, CommandSender sender, boolean error) {
+ sendFeedback(message, sender, error, false);
+ }
+
+ /**
+ * Display a message with prefix to a specific user.
+ *
+ * @param message Text message
+ * @param sender Where send the message to
+ * @param error Is the message an error
+ * @param checkSilent Don't display message if silent mode is on
+ */
+ public static void sendFeedback(String message, CommandSender sender, boolean error, boolean checkSilent) {
+ if (ConfigManager.getConfig().getSilentMode() && checkSilent)
+ return;
+ sender.sendMessage(ChatColor.GRAY + "[" + ChatColor.RED + "WirelessRedstone" + ChatColor.GRAY + "] "
+ + (error ? ChatColor.RED : ChatColor.GREEN) + message);
+ }
+
+ /**
+ * Display a message to a specific user. This ignores the silent mode.
+ *
+ * @param message Text message
+ * @param sender Where send the message to
+ * @param error Is the message an error
+ */
+ public static void sendCommandFeedback(String message, CommandSender sender, boolean error) {
+ sendCommandFeedback(message, sender, error, false);
+ }
+
+ /**
+ * Display a message to a specific user.
+ *
+ * @param message Text message
+ * @param sender Where send the message to
+ * @param error Is the message an error
+ * @param checkSilent Don't display message if silent mode is on
+ */
+ public static void sendCommandFeedback(String message, CommandSender sender, boolean error, boolean checkSilent) {
+ if (ConfigManager.getConfig().getSilentMode() && checkSilent)
+ return;
+ sender.sendMessage((error ? ChatColor.RED : ChatColor.GREEN) + message);
+ }
+
+ /**
+ * Converts the old direction system to the new BlockFace system.
+ *
+ * @param isWallSign Is the sign against a wall
+ * @param direction Old sign facing id system
+ * @return BlockFace
+ */
+ public static BlockFace getBlockFace(boolean isWallSign, int direction) {
+ BlockFace blockFace;
+
+ if (isWallSign) {
+ if (direction == 2) {
+ blockFace = BlockFace.NORTH;
+ } else if (direction == 3) {
+ blockFace = BlockFace.SOUTH;
+ } else if (direction == 4) {
+ blockFace = BlockFace.WEST;
+ } else if (direction == 5) {
+ blockFace = BlockFace.EAST;
+ } else {
+ blockFace = BlockFace.NORTH;
+ }
+ } else {
+ if (direction == 0) {
+ blockFace = BlockFace.SOUTH;
+ } else if (direction == 1) {
+ blockFace = BlockFace.SOUTH_SOUTH_WEST;
+ } else if (direction == 2) {
+ blockFace = BlockFace.SOUTH_WEST;
+ } else if (direction == 3) {
+ blockFace = BlockFace.WEST_SOUTH_WEST;
+ } else if (direction == 4) {
+ blockFace = BlockFace.WEST;
+ } else if (direction == 5) {
+ blockFace = BlockFace.WEST_NORTH_WEST;
+ } else if (direction == 6) {
+ blockFace = BlockFace.NORTH_WEST;
+ } else if (direction == 7) {
+ blockFace = BlockFace.NORTH_NORTH_WEST;
+ } else if (direction == 8) {
+ blockFace = BlockFace.NORTH;
+ } else if (direction == 9) {
+ blockFace = BlockFace.NORTH_NORTH_EAST;
+ } else if (direction == 10) {
+ blockFace = BlockFace.NORTH_EAST;
+ } else if (direction == 11) {
+ blockFace = BlockFace.EAST_NORTH_EAST;
+ } else if (direction == 12) {
+ blockFace = BlockFace.EAST;
+ } else if (direction == 13) {
+ blockFace = BlockFace.EAST_SOUTH_EAST;
+ } else if (direction == 14) {
+ blockFace = BlockFace.SOUTH_EAST;
+ } else if (direction == 15) {
+ blockFace = BlockFace.SOUTH_SOUTH_EAST;
+ } else {
+ blockFace = BlockFace.SOUTH;
+ }
+ }
+
+ return blockFace;
+ }
+
+ /**
+ * Deprecated!
+ * Converts BlockFace to a raw byte direction for wall signs/torches.
+ *
+ * @param isTorch If the block is a torch
+ * @param blockFace The direction the wall sign/torch is facing
+ * @return raw byte code for direction
+ */
+ @Deprecated
+ public static byte getRawData(boolean isTorch, BlockFace blockFace) {
+ if (isTorch) {
+ if (blockFace == BlockFace.NORTH)
+ return (byte)4;
+ else if (blockFace == BlockFace.SOUTH)
+ return (byte)3;
+ else if (blockFace == BlockFace.WEST)
+ return (byte)2;
+ else if (blockFace == BlockFace.EAST)
+ return (byte)1;
+ return (byte)0;
+ } else {
+ if (blockFace == BlockFace.NORTH)
+ return (byte)2;
+ else if (blockFace == BlockFace.SOUTH)
+ return (byte)3;
+ else if (blockFace == BlockFace.WEST)
+ return (byte)4;
+ else if (blockFace == BlockFace.EAST)
+ return (byte)5;
+ return (byte)0;
+ }
+ }
+
+ /**
+ * Gives a collection of adjacent BlockFaces.
+ *
+ * @return All the possible adjacent BlockFaces
+ */
+ public static Collection getAxisBlockFaces() {
+ return getAxisBlockFaces(true);
+ }
+
+ /**
+ * Gives a collection of adjacent BlockFaces.
+ *
+ * @param upAndDown Include directions up and down
+ * @return All the possible adjacent BlockFaces
+ */
+ public static Collection getAxisBlockFaces(boolean upAndDown) {
+ return Arrays.asList(upAndDown ? fullAxis : axis);
+ }
+
+ /**
+ * Gets the horizontal Block Face from a given yaw angle
+ *
+ * @param yaw angle
+ * @return The Block Face of the angle
+ */
+ public static BlockFace yawToFace(float yaw) {
+ return axis[Math.round(yaw / 90f) & 0x3];
+ }
+
+ public static SignType getType(String text) {
+ switch (text.toUpperCase()) {
+ case "TRANSMITTERS":
+ case "TRANSMITTER":
+ case "T":
+ return SignType.TRANSMITTER;
+ case "RECEIVERS":
+ case "RECEIVER":
+ case "R":
+ return SignType.RECEIVER;
+ case "SCREENS":
+ case "SCREEN":
+ case "S":
+ return SignType.SCREEN;
+ case "INVERTERS":
+ case "INVERTER":
+ case "INVERT":
+ case "I":
+ return SignType.RECEIVER_INVERTER;
+ case "SWITCHERS":
+ case "SWITCHER":
+ case "SWITCHS":
+ case "SWITCH":
+ return SignType.RECEIVER_SWITCH;
+ case "CLOCKS":
+ case "CLOCK":
+ case "C":
+ return SignType.RECEIVER_CLOCK;
+ case "DELAYERS":
+ case "DELAYER":
+ case "DELAY":
+ case "D":
+ return SignType.RECEIVER_DELAYER;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a SignType based on the first line of a sign.
+ * All receiver types are returned as SignType.RECEIVER
+ *
+ * @param firstLine First line of a sign
+ * @return SignType
+ */
+ public static SignType getSignType(String firstLine) {
+ return getSignType(firstLine, "");
+ }
+
+ /**
+ * Returns a SignType based on the first and third line of a sign.
+ * This returns a specific receiver type.
+ *
+ * @param firstLine First line of a sign
+ * @param secondLine Third line of a sign
+ * @return SignType
+ */
+ public static SignType getSignType(String firstLine, String secondLine) {
+ if (WirelessRedstone.getStringManager().tagsTransmitter.contains(firstLine.toLowerCase())) {
+ return SignType.TRANSMITTER;
+ } else if (WirelessRedstone.getStringManager().tagsScreen.contains(firstLine.toLowerCase())) {
+ return SignType.SCREEN;
+ } else if (WirelessRedstone.getStringManager().tagsReceiver.contains(firstLine.toLowerCase())) {
+ if (WirelessRedstone.getStringManager().tagsReceiverInverterType.contains(secondLine.toLowerCase())) {
+ return SignType.RECEIVER_INVERTER;
+ } else if (WirelessRedstone.getStringManager().tagsReceiverSwitchType.contains(secondLine.toLowerCase())) {
+ return SignType.RECEIVER_SWITCH;
+ } else if (WirelessRedstone.getStringManager().tagsReceiverClockType.contains(secondLine.toLowerCase())) {
+ return SignType.RECEIVER_CLOCK;
+ } else if (WirelessRedstone.getStringManager().tagsReceiverDelayerType.contains(secondLine.toLowerCase())) {
+ return SignType.RECEIVER_DELAYER;
+ }
+
+ return SignType.RECEIVER;
+ }
+
+ return null;
+ }
+
+ /**
+ * Check if two locations are in the same place.
+ *
+ * @param loc1 Location
+ * @param loc2 Location
+ * @return Boolean
+ */
+ public static boolean sameLocation(Location loc1, Location loc2) {
+ if (loc1 == null || loc2 == null) {
+ return false;
+ } else if (loc1.getWorld() == null || loc2.getWorld() == null) {
+ return false;
+ }
+
+ return loc1.getBlockX() == loc2.getBlockX() && loc1.getBlockY() == loc2.getBlockY() && loc1.getBlockZ() == loc2.getBlockZ() &&
+ loc1.getWorld().getName().equalsIgnoreCase(loc2.getWorld().getName());
+ }
+
+ /**
+ * Mix teleport command together with a player name.
+ *
+ * @param playerName Player name
+ * @return Command
+ */
+ public static String getTeleportString(String playerName) {
+ return "tellraw " + playerName + " " + "[\"\",{\"text\":\"[\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"%%COMMAND\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"%%HOVERTEXT\"}]}}},{\"text\":\"\\u27A4\",\"color\":\"aqua\",\"bold\":true,\"clickEvent\":{\"action\":\"run_command\",\"value\":\"%%COMMAND\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"%%HOVERTEXT\"}]}}},{\"text\":\"] \",\"color\":\"gray\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"%%COMMAND\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"%%HOVERTEXT\"}]}},\"bold\":false},{\"text\":\"Name %%NAME, type: %%TYPE, world: %%WORLD, x: %%XCOORD, y: %%YCOORD, z: %%ZCOORD\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"%%COMMAND\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"%%HOVERTEXT\"}]}}}]";
+ }
+
+}
diff --git a/src/main/java/net/licks92/wirelessredstone/WRLogger.java b/src/main/java/net/licks92/wirelessredstone/WRLogger.java
new file mode 100644
index 0000000..2779498
--- /dev/null
+++ b/src/main/java/net/licks92/wirelessredstone/WRLogger.java
@@ -0,0 +1,72 @@
+package net.licks92.wirelessredstone;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.ConsoleCommandSender;
+
+public class WRLogger {
+
+ private final ConsoleCommandSender console;
+ private final String prefix;
+ private final boolean debug;
+ private final boolean color;
+
+ /**
+ * Creates an instance of WRLogger.
+ *
+ * @param prefix This is added before all messages
+ * @param console Console reference from bukkit/spigot
+ * @param debug Enable debug mode
+ * @param color Enable color messages
+ */
+ public WRLogger(String prefix, ConsoleCommandSender console, boolean debug, boolean color) {
+ this.debug = debug;
+ this.color = color;
+ this.console = console;
+ if (color) this.prefix = ChatColor.RED + prefix + ChatColor.RESET;
+ else this.prefix = prefix;
+ }
+
+ /**
+ * Display a info message to the console.
+ *
+ * @param msg Message
+ */
+ public void info(String msg) {
+ if (color) console.sendMessage(prefix + " " + msg);
+ else Bukkit.getLogger().info(msg);
+ }
+
+ /**
+ * Display a debug message to the console if debug mode is enabled.
+ *
+ * @param msg Message
+ */
+ public void debug(String msg) {
+ if (debug) {
+ if (color) console.sendMessage(prefix + ChatColor.GOLD + "[Debug] " + ChatColor.RESET + msg);
+ else Bukkit.getLogger().info(prefix + "[Debug] " + msg);
+ }
+ }
+
+ /**
+ * Display a severe message to the console.
+ *
+ * @param msg Message
+ */
+ public void severe(String msg) {
+ if (color) console.sendMessage(prefix + ChatColor.DARK_RED + "[SEVERE] " + ChatColor.RESET + msg);
+ else Bukkit.getLogger().severe(prefix + " " + msg);
+ }
+
+ /**
+ * Display a warning message to the console.
+ *
+ * @param msg Message
+ */
+ public void warning(String msg) {
+ if (color) console.sendMessage(prefix + ChatColor.YELLOW + "[WARNING] " + ChatColor.RESET + msg);
+ else Bukkit.getLogger().warning(prefix + " " + msg);
+ }
+
+}
diff --git a/src/main/java/net/licks92/wirelessredstone/WirelessRedstone.java b/src/main/java/net/licks92/wirelessredstone/WirelessRedstone.java
new file mode 100644
index 0000000..048ea87
--- /dev/null
+++ b/src/main/java/net/licks92/wirelessredstone/WirelessRedstone.java
@@ -0,0 +1,157 @@
+package net.licks92.wirelessredstone;
+
+import net.licks92.wirelessredstone.commands.Admin.AdminCommandManager;
+import net.licks92.wirelessredstone.commands.CommandManager;
+import net.licks92.wirelessredstone.compat.InternalProvider;
+import net.licks92.wirelessredstone.compat.InternalWorldEditHooker;
+import net.licks92.wirelessredstone.listeners.BlockListener;
+import net.licks92.wirelessredstone.listeners.PlayerListener;
+import net.licks92.wirelessredstone.listeners.WorldListener;
+import net.licks92.wirelessredstone.materiallib.MaterialLib;
+import net.licks92.wirelessredstone.storage.StorageConfiguration;
+import net.licks92.wirelessredstone.storage.StorageManager;
+import net.licks92.wirelessredstone.string.StringManager;
+import net.licks92.wirelessredstone.string.Strings;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class WirelessRedstone extends JavaPlugin {
+
+ public static final String CHANNEL_FOLDER = "channels";
+
+ private static WirelessRedstone instance;
+ private static WRLogger WRLogger;
+ private static StringManager stringManager;
+ private static StorageManager storageManager;
+ private static SignManager signManager;
+ private static CommandManager commandManager;
+ private static AdminCommandManager adminCommandManager;
+
+ private ConfigManager config;
+ private InternalWorldEditHooker worldEditHooker;
+ private boolean storageLoaded = false;
+
+ public static WirelessRedstone getInstance() {
+ return instance;
+ }
+
+ public static WRLogger getWRLogger() {
+ return WRLogger;
+ }
+
+ public static StringManager getStringManager() {
+ return stringManager;
+ }
+
+ public static Strings getStrings() {
+ return getStringManager().getStrings();
+ }
+
+ public static StorageManager getStorageManager() {
+ return storageManager;
+ }
+
+ public static StorageConfiguration getStorage() {
+ return getStorageManager().getStorage();
+ }
+
+ public static SignManager getSignManager() {
+ return signManager;
+ }
+
+ public static CommandManager getCommandManager() {
+ return commandManager;
+ }
+
+ public static AdminCommandManager getAdminCommandManager() {
+ return adminCommandManager;
+ }
+
+ public InternalWorldEditHooker getWorldEditHooker() {
+ return worldEditHooker;
+ }
+
+ public void setWorldEditHooker(InternalWorldEditHooker worldEditHooker) {
+ this.worldEditHooker = worldEditHooker;
+ }
+
+ @Override
+ public void onEnable() {
+ instance = this;
+
+ // Zuerst config initialisieren
+ config = ConfigManager.getConfig();
+
+ WRLogger = new WRLogger("[WirelessRedstone]", getServer().getConsoleSender(), config.getDebugMode(), config.getColorLogging());
+
+ new MaterialLib(this).initialize();
+
+ config.update(CHANNEL_FOLDER);
+ stringManager = new StringManager(config.getLanguage());
+
+ storageManager = new StorageManager(config.getStorageType(), CHANNEL_FOLDER);
+
+ if (!storageManager.getStorage().initStorage()) {
+ getPluginLoader().disablePlugin(this);
+ return;
+ }
+
+ storageLoaded = true;
+
+ signManager = new SignManager();
+ commandManager = new CommandManager();
+ adminCommandManager = new AdminCommandManager();
+
+ PluginManager pm = getServer().getPluginManager();
+ pm.registerEvents(new WorldListener(), this);
+ pm.registerEvents(new BlockListener(), this);
+ pm.registerEvents(new PlayerListener(), this);
+
+ getCommand("wirelessredstone").setExecutor(commandManager);
+ getCommand("wr").setExecutor(commandManager);
+ getCommand("wredstone").setExecutor(commandManager);
+ getCommand("wifi").setExecutor(commandManager);
+
+ getCommand("wirelessredstone").setTabCompleter(commandManager);
+ getCommand("wr").setTabCompleter(commandManager);
+ getCommand("wredstone").setTabCompleter(commandManager);
+ getCommand("wifi").setTabCompleter(commandManager);
+
+ getCommand("wradmin").setExecutor(adminCommandManager);
+ getCommand("wra").setExecutor(adminCommandManager);
+
+ getCommand("wradmin").setTabCompleter(adminCommandManager);
+ getCommand("wra").setTabCompleter(adminCommandManager);
+
+ if (pm.isPluginEnabled("WorldEdit")) {
+ InternalProvider.getCompatWorldEditHooker().register();
+ WirelessRedstone.getWRLogger().debug("Hooked into WorldEdit");
+ }
+ }
+
+ @Override
+ public void onDisable() {
+ if (storageLoaded) {
+ getStorage().close();
+ }
+
+ if (worldEditHooker != null) {
+ worldEditHooker.unRegister();
+ }
+
+ storageLoaded = false;
+ adminCommandManager = null;
+ commandManager = null;
+ signManager = null;
+ storageManager = null;
+ stringManager = null;
+ config = null;
+ WRLogger = null;
+ instance = null;
+ }
+
+ public void resetStrings() {
+ stringManager = null;
+ stringManager = new StringManager(config.getLanguage());
+ }
+}