diff --git a/pom.xml b/pom.xml
index 8b1bcb79..ca28632c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
true
*
+ configs/*
diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java b/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java
index 48cfaa37..c8852328 100644
--- a/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java
+++ b/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java
@@ -43,9 +43,10 @@ public class DisguiseAPI {
DisguiseConfig.removeCustomDisguise(disguiseName);
DisguiseConfig.addCustomDisguise(disguiseName, disguiseInfo);
- File disguisesFile = new File("plugins/LibsDisguises/disguises.yml");
+ File disguisesFile = new File(LibsDisguises.getInstance().getDataFolder(), "configs/disguises.yml");
if (!disguisesFile.exists()) {
+ disguisesFile.getParentFile().mkdirs();
disguisesFile.createNewFile();
}
@@ -143,9 +144,8 @@ public class DisguiseAPI {
}
}
for (Method method : entity.getClass().getMethods()) {
- if ((doSneak || !method.getName().equals("setSneaking")) &&
- (doSprint || !method.getName().equals("setSprinting")) && method.getParameterTypes().length == 0 &&
- method.getReturnType() != void.class) {
+ if ((doSneak || !method.getName().equals("setSneaking")) && (doSprint || !method.getName().equals("setSprinting")) &&
+ method.getParameterTypes().length == 0 && method.getReturnType() != void.class) {
Class methodReturn = method.getReturnType();
if (methodReturn == float.class || methodReturn == Float.class || methodReturn == Double.class) {
@@ -160,12 +160,11 @@ public class DisguiseAPI {
watcherMethod.getParameterTypes().length == 1) {
int firstCapitalWatcher = firstCapital(watcherMethod.getName());
- if (firstCapitalWatcher > 0 && method.getName().substring(firstCapitalMethod)
- .equalsIgnoreCase(watcherMethod.getName().substring(firstCapitalWatcher))) {
+ if (firstCapitalWatcher > 0 &&
+ method.getName().substring(firstCapitalMethod).equalsIgnoreCase(watcherMethod.getName().substring(firstCapitalWatcher))) {
Class methodParam = watcherMethod.getParameterTypes()[0];
- if (methodParam == float.class || methodParam == Float.class ||
- methodParam == Double.class) {
+ if (methodParam == float.class || methodParam == Float.class || methodParam == Double.class) {
methodParam = double.class;
} else if (methodParam == AnimalColor.class) {
methodParam = DyeColor.class;
@@ -190,8 +189,7 @@ public class DisguiseAPI {
value = AnimalColor.valueOf(((DyeColor) value).name());
}
}
- if (value instanceof Boolean && !(Boolean) value &&
- watcherMethod.getDeclaringClass() == FlagWatcher.class) {
+ if (value instanceof Boolean && !(Boolean) value && watcherMethod.getDeclaringClass() == FlagWatcher.class) {
continue;
}
}
diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java
index 626c3b8f..afa954b2 100644
--- a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java
+++ b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java
@@ -4,9 +4,9 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import me.libraryaddict.disguise.disguisetypes.Disguise;
-import me.libraryaddict.disguise.disguisetypes.TargetedDisguise;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.LibsPremium;
+import me.libraryaddict.disguise.utilities.config.ConfigLoader;
import me.libraryaddict.disguise.utilities.modded.ModdedEntity;
import me.libraryaddict.disguise.utilities.modded.ModdedManager;
import me.libraryaddict.disguise.utilities.packets.PacketsManager;
@@ -17,20 +17,15 @@ import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
import me.libraryaddict.disguise.utilities.translations.TranslateType;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
-import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
-import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.scheduler.BukkitTask;
@@ -63,12 +58,6 @@ public class DisguiseConfig {
@Getter
@Setter
private static boolean collectPacketsEnabled;
- /**
- * No setter provided as this cannot be changed after startup
- */
- @Setter(value = AccessLevel.PRIVATE)
- @Getter
- private static boolean disableCommands;
@Getter
@Setter
private static boolean disableFriendlyInvisibles;
@@ -277,6 +266,12 @@ public class DisguiseConfig {
@Getter
@Setter
private static String lastPluginUpdateVersion;
+ @Getter
+ @Setter
+ private static boolean contactMojangServers;
+ @Getter
+ @Setter(AccessLevel.PROTECTED)
+ private static int disguiseRadiusMax;
public static boolean isArmorstandsName() {
return getPlayerNameType() == PlayerNameType.ARMORSTANDS;
@@ -322,22 +317,6 @@ public class DisguiseConfig {
return;
}
- if (!LibsDisguises.getInstance().getConfig().getDefaults().getBoolean("AutoUpdate")) {
- updaterTask = Bukkit.getScheduler().runTaskTimer(LibsDisguises.getInstance(), new Runnable() {
- @Override
- public void run() {
- for (Set disguises : DisguiseUtilities.getDisguises().values()) {
- for (Disguise disguise : disguises) {
- disguise.getWatcher().setSprinting(true);
- disguise.getWatcher().setHelmet(new ItemStack(Material.LEATHER_HELMET));
- }
- }
- }
- }, TimeUnit.HOURS.toSeconds(1) * 20, (20 * TimeUnit.MINUTES.toSeconds(10)));
-
- return;
- }
-
if (updaterTask == null != startTask) {
return;
}
@@ -560,75 +539,9 @@ public class DisguiseConfig {
TranslateType.refreshTranslations();
}
- public static void saveDefaultConfig() {
- DisguiseUtilities.getLogger().info("Config is out of date! Now updating it!");
- String[] string = ReflectionManager.getResourceAsString(LibsDisguises.getInstance().getFile(), "config.yml").split("\n");
- FileConfiguration savedConfig = LibsDisguises.getInstance().getConfig();
-
- StringBuilder section = new StringBuilder();
-
- for (int i = 0; i < string.length; i++) {
- String s = string[i];
-
- if (s.trim().startsWith("#") || !s.contains(":")) {
- continue;
- }
-
- String rawKey = s.split(":")[0];
-
- if (section.length() > 0) {
- int matches = StringUtils.countMatches(rawKey, " ");
-
- int allowed = 0;
-
- for (int a = 0; a < matches; a++) {
- allowed = section.indexOf(".", allowed) + 1;
- }
-
- section = new StringBuilder(section.substring(0, allowed));
- }
-
- String key = (rawKey.startsWith(" ") ? section.toString() : "") + rawKey.trim();
-
- if (savedConfig.isConfigurationSection(key)) {
- section.append(key).append(".");
- } else if (savedConfig.isSet(key)) {
- String rawVal = s.split(":")[1].trim();
- Object val = savedConfig.get(key);
-
- if (savedConfig.isString(key) && !rawVal.equals("true") && !rawVal.equals("false")) {
- val = "'" + StringEscapeUtils.escapeJava(val.toString().replace(ChatColor.COLOR_CHAR + "", "&")) + "'";
- }
-
- string[i] = rawKey + ": " + val;
- }
- }
-
- File config = new File(LibsDisguises.getInstance().getDataFolder(), "config.yml");
-
- try {
- if (config.exists()) {
- config.renameTo(new File(config.getParentFile(), "config-old.yml"));
-
- DisguiseUtilities.getLogger().info("Old config has been copied to config-old.yml");
- }
-
- config.createNewFile();
-
- try (PrintWriter out = new PrintWriter(config)) {
- out.write(StringUtils.join(string, "\n"));
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
public static void loadConfig() {
- // Always save the default config
- LibsDisguises.getInstance().saveDefaultConfig();
- // Redundant for the first load, however other plugins may call loadConfig() at a later stage where we
- // definitely want to reload it.
- LibsDisguises.getInstance().reloadConfig();
+ ConfigLoader configLoader = new ConfigLoader();
+ configLoader.saveMissingConfigs();
loadModdedDisguiseTypes();
@@ -650,10 +563,9 @@ public class DisguiseConfig {
}
}
- ConfigurationSection config = LibsDisguises.getInstance().getConfig();
+ ConfigurationSection config = configLoader.load();
PacketsManager.setViewDisguisesListener(true);
- disableCommands = config.getBoolean("DisableCommands");
setAddEntityAnimations(config.getBoolean("AddEntityAnimations"));
setAnimationPacketsEnabled(config.getBoolean("PacketsEnabled.Animation"));
@@ -719,6 +631,8 @@ public class DisguiseConfig {
setSaveUserPreferences(config.getBoolean("SaveUserPreferences"));
setPlayerDisguisesSkinExpiresMove(config.getInt("PlayerDisguisesTablistExpiresMove"));
setViewSelfDisguisesDefault(config.getBoolean("ViewSelfDisguisesDefault"));
+ setContactMojangServers(config.getBoolean("ContactMojangServers"));
+ setDisguiseRadiusMax(config.getInt("DisguiseRadiusMax"));
if (!LibsPremium.isPremium() && (isSavePlayerDisguises() || isSaveEntityDisguises())) {
DisguiseUtilities.getLogger().warning("You must purchase the plugin to use saved disguises!");
@@ -826,19 +740,11 @@ public class DisguiseConfig {
}
}
- int missingConfigs = 0;
-
- for (String key : config.getDefaultSection().getKeys(true)) {
- if (config.contains(key, true)) {
- continue;
- }
-
- missingConfigs++;
- }
+ int missingConfigs = doOutput(config, false, true).size();
if (missingConfigs > 0) {
if (config.getBoolean("UpdateConfig", true)) {
- saveDefaultConfig();
+ configLoader.saveDefaultConfigs();
DisguiseUtilities.getLogger().info("Config has been auto-updated!");
} else if (!verbose) {
DisguiseUtilities.getLogger().warning("Your config is missing " + missingConfigs + " options! Please consider regenerating your config!");
@@ -850,7 +756,7 @@ public class DisguiseConfig {
}
public static void loadModdedDisguiseTypes() {
- File disguisesFile = new File("plugins/LibsDisguises/disguises.yml");
+ File disguisesFile = new File(LibsDisguises.getInstance().getDataFolder(), "configs/disguises.yml");
if (!disguisesFile.exists()) {
return;
@@ -929,9 +835,18 @@ public class DisguiseConfig {
new ModdedManager(channels);
}
+ public static ArrayList doOutput(boolean informChangedUnknown, boolean informMissing) {
+ return doOutput(new ConfigLoader().load(), informChangedUnknown, informMissing);
+ }
+
public static ArrayList doOutput(ConfigurationSection config, boolean informChangedUnknown, boolean informMissing) {
HashMap configs = new HashMap<>();
ConfigurationSection defaultSection = config.getDefaultSection();
+
+ if (defaultSection == null) {
+ defaultSection = new ConfigLoader().loadDefaults();
+ }
+
ArrayList returns = new ArrayList<>();
for (String key : defaultSection.getKeys(true)) {
@@ -975,7 +890,7 @@ public class DisguiseConfig {
static void loadCustomDisguises() {
customDisguises.clear();
- File disguisesFile = new File("plugins/LibsDisguises/disguises.yml");
+ File disguisesFile = new File(LibsDisguises.getInstance().getDataFolder(), "configs/disguises.yml");
if (!disguisesFile.exists()) {
return;
diff --git a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java
index c9b74fa7..fce5b5d6 100644
--- a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java
+++ b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java
@@ -82,7 +82,7 @@ public class LibsDisguises extends JavaPlugin {
Bukkit.getPluginManager().enablePlugin(plugin);
} else {
- getLogger().severe("Please restar the server to complete the ProtocolLib update!");
+ getLogger().severe("Please restart the server to complete the ProtocolLib update!");
}
} catch (Exception e) {
e.printStackTrace();
@@ -119,8 +119,18 @@ public class LibsDisguises extends JavaPlugin {
"plugin will continue to load, but it will look like a mugging victim");
}
- if (!new File(getDataFolder(), "disguises.yml").exists()) {
- saveResource("disguises.yml", false);
+ File disguiseFile = new File(getDataFolder(), "configs/disguises.yml");
+
+ if (!disguiseFile.exists()) {
+ disguiseFile.getParentFile().mkdirs();
+
+ File oldFile = new File(getDataFolder(), "disguises.yml");
+
+ if (oldFile.exists()) {
+ oldFile.renameTo(disguiseFile);
+ } else {
+ saveResource("configs/disguises.yml", false);
+ }
}
YamlConfiguration pluginYml = ReflectionManager.getPluginYAML(getFile());
@@ -209,31 +219,26 @@ public class LibsDisguises extends JavaPlugin {
}
registerCommand("libsdisguises", new LibsDisguisesCommand());
-
- if (!DisguiseConfig.isDisableCommands()) {
- registerCommand("disguise", new DisguiseCommand());
- registerCommand("undisguise", new UndisguiseCommand());
- registerCommand("disguiseplayer", new DisguisePlayerCommand());
- registerCommand("undisguiseplayer", new UndisguisePlayerCommand());
- registerCommand("undisguiseentity", new UndisguiseEntityCommand());
- registerCommand("disguiseentity", new DisguiseEntityCommand());
- registerCommand("disguiseradius", new DisguiseRadiusCommand(getConfig().getInt("DisguiseRadiusMax")));
- registerCommand("undisguiseradius", new UndisguiseRadiusCommand(getConfig().getInt("UndisguiseRadiusMax")));
- registerCommand("disguisehelp", new DisguiseHelpCommand());
- registerCommand("disguiseclone", new DisguiseCloneCommand());
- registerCommand("disguiseviewself", new DisguiseViewSelfCommand());
- registerCommand("disguiseviewbar", new DisguiseViewBarCommand());
- registerCommand("disguisemodify", new DisguiseModifyCommand());
- registerCommand("disguisemodifyentity", new DisguiseModifyEntityCommand());
- registerCommand("disguisemodifyplayer", new DisguiseModifyPlayerCommand());
- registerCommand("disguisemodifyradius", new DisguiseModifyRadiusCommand(getConfig().getInt("DisguiseRadiusMax")));
- registerCommand("copydisguise", new CopyDisguiseCommand());
- registerCommand("grabskin", new GrabSkinCommand());
- registerCommand("savedisguise", new SaveDisguiseCommand());
- registerCommand("grabhead", new GrabHeadCommand());
- } else {
- getLogger().info("Commands has been disabled, as per config");
- }
+ registerCommand("disguise", new DisguiseCommand());
+ registerCommand("undisguise", new UndisguiseCommand());
+ registerCommand("disguiseplayer", new DisguisePlayerCommand());
+ registerCommand("undisguiseplayer", new UndisguisePlayerCommand());
+ registerCommand("undisguiseentity", new UndisguiseEntityCommand());
+ registerCommand("disguiseentity", new DisguiseEntityCommand());
+ registerCommand("disguiseradius", new DisguiseRadiusCommand());
+ registerCommand("undisguiseradius", new UndisguiseRadiusCommand());
+ registerCommand("disguisehelp", new DisguiseHelpCommand());
+ registerCommand("disguiseclone", new DisguiseCloneCommand());
+ registerCommand("disguiseviewself", new DisguiseViewSelfCommand());
+ registerCommand("disguiseviewbar", new DisguiseViewBarCommand());
+ registerCommand("disguisemodify", new DisguiseModifyCommand());
+ registerCommand("disguisemodifyentity", new DisguiseModifyEntityCommand());
+ registerCommand("disguisemodifyplayer", new DisguiseModifyPlayerCommand());
+ registerCommand("disguisemodifyradius", new DisguiseModifyRadiusCommand());
+ registerCommand("copydisguise", new CopyDisguiseCommand());
+ registerCommand("grabskin", new GrabSkinCommand());
+ registerCommand("savedisguise", new SaveDisguiseCommand());
+ registerCommand("grabhead", new GrabHeadCommand());
unregisterCommands(false);
diff --git a/src/main/java/me/libraryaddict/disguise/commands/disguise/DisguiseRadiusCommand.java b/src/main/java/me/libraryaddict/disguise/commands/disguise/DisguiseRadiusCommand.java
index 54e99a16..bea36859 100644
--- a/src/main/java/me/libraryaddict/disguise/commands/disguise/DisguiseRadiusCommand.java
+++ b/src/main/java/me/libraryaddict/disguise/commands/disguise/DisguiseRadiusCommand.java
@@ -29,12 +29,9 @@ import java.util.List;
import java.util.Locale;
public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCompleter {
- private int maxRadius = 30;
private ArrayList> validClasses = new ArrayList<>();
- public DisguiseRadiusCommand(int maxRadius) {
- this.maxRadius = maxRadius;
-
+ public DisguiseRadiusCommand() {
for (EntityType type : EntityType.values()) {
Class c = type.getEntityClass();
@@ -131,9 +128,9 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom
int radius = Integer.parseInt(args[starting]);
- if (radius > maxRadius) {
- LibsMsg.LIMITED_RADIUS.send(sender, maxRadius);
- radius = maxRadius;
+ if (radius > DisguiseConfig.getDisguiseRadiusMax()) {
+ LibsMsg.LIMITED_RADIUS.send(sender, DisguiseConfig.getDisguiseRadiusMax());
+ radius = DisguiseConfig.getDisguiseRadiusMax();
}
String[] newArgs = new String[args.length - (starting + 1)];
@@ -291,7 +288,7 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom
return;
}
- LibsMsg.DRADIUS_HELP1.send(sender, maxRadius);
+ LibsMsg.DRADIUS_HELP1.send(sender, DisguiseConfig.getDisguiseRadiusMax());
LibsMsg.CAN_USE_DISGS.send(sender, StringUtils.join(allowedDisguises, LibsMsg.CAN_USE_DISGS_SEPERATOR.get()));
if (allowedDisguises.contains("player")) {
diff --git a/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDConfig.java b/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDConfig.java
index b2d8e805..bdd34adc 100644
--- a/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDConfig.java
+++ b/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDConfig.java
@@ -1,7 +1,6 @@
package me.libraryaddict.disguise.commands.libsdisguises;
import me.libraryaddict.disguise.DisguiseConfig;
-import me.libraryaddict.disguise.LibsDisguises;
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -31,7 +30,7 @@ public class LDConfig implements LDCommand {
@Override
public void onCommand(CommandSender sender, String[] args) {
- ArrayList returns = DisguiseConfig.doOutput(LibsDisguises.getInstance().getConfig(), true, true);
+ ArrayList returns = DisguiseConfig.doOutput(true, true);
if (returns.isEmpty()) {
LibsMsg.USING_DEFAULT_CONFIG.send(sender);
diff --git a/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDUploadLogs.java b/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDUploadLogs.java
index 1f7565c6..ec8ff2c1 100644
--- a/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDUploadLogs.java
+++ b/src/main/java/me/libraryaddict/disguise/commands/libsdisguises/LDUploadLogs.java
@@ -3,6 +3,7 @@ package me.libraryaddict.disguise.commands.libsdisguises;
import lombok.Data;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.LibsDisguises;
+import me.libraryaddict.disguise.utilities.config.ConfigLoader;
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
@@ -22,6 +23,7 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/**
* Created by libraryaddict on 18/06/2020.
@@ -120,35 +122,42 @@ public class LDUploadLogs implements LDCommand {
@Override
public void onCommand(CommandSender sender, String[] args) {
if (lastUsed + TimeUnit.MINUTES.toMillis(3) > System.currentTimeMillis()) {
- sender.sendMessage(ChatColor.RED +
- "You last used this command under 3 minutes ago! Restart the server or wait for this timer to " +
- "disappear!");
+ sender.sendMessage(ChatColor.RED + "You last used this command under 3 minutes ago! Restart the server or wait for this timer to " + "disappear!");
return;
}
File latest = new File("logs/latest.log");
- File disguises = new File(LibsDisguises.getInstance().getDataFolder(), "disguises.yml");
- File config = new File(LibsDisguises.getInstance().getDataFolder(), "config.yml");
+ File disguises = new File(LibsDisguises.getInstance().getDataFolder(), "configs/disguises.yml");
+
+ List configs =
+ new ConfigLoader().getConfigs().stream().map(f -> new File(LibsDisguises.getInstance().getDataFolder(), f)).collect(Collectors.toList());
+
+ StringBuilder configText = new StringBuilder();
+
+ for (File config : configs) {
+ if (configText.length() != 0) {
+ configText.append("\n\n================\n\n");
+ }
+
+ try {
+ configText.append(new String(Files.readAllBytes(config.toPath())));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
if (isTooBig(latest)) {
- sender.sendMessage(ChatColor.RED +
- "Your latest.log file is too big! It should be less than 512kb! Please restart and run this " +
- "command again!");
+ sender.sendMessage(
+ ChatColor.RED + "Your latest.log file is too big! It should be less than 512kb! Please restart and run this " + "command again!");
return;
}
if (isTooBig(disguises)) {
- sender.sendMessage(ChatColor.RED +
- "Your disguises.yml is too big! You'll need to trim that file down before using this command! It " +
+ sender.sendMessage(ChatColor.RED + "Your disguises.yml is too big! You'll need to trim that file down before using this command! It " +
"should be less than 512kb!");
return;
}
- if (isTooBig(config)) {
- sender.sendMessage(ChatColor.RED + "Your config.yml is too big! It should be less than 512kb!");
- return;
- }
-
try {
String latestText = new String(Files.readAllBytes(latest.toPath()));
@@ -166,8 +175,7 @@ public class LDUploadLogs implements LDCommand {
lastFind = nextLine + 2;
- if (!str.contains("Starting minecraft server version") && !str.contains("Loading properties") &&
- !str.contains("This server is running")) {
+ if (!str.contains("Starting minecraft server version") && !str.contains("Loading properties") && !str.contains("This server is running")) {
continue;
}
@@ -176,8 +184,7 @@ public class LDUploadLogs implements LDCommand {
}
if (!valid) {
- sender.sendMessage(
- ChatColor.RED + "Your latest.log is too old! Please restart the server and try again!");
+ sender.sendMessage(ChatColor.RED + "Your latest.log is too old! Please restart the server and try again!");
return;
}
@@ -188,12 +195,10 @@ public class LDUploadLogs implements LDCommand {
public void run() {
try {
String disguiseText = new String(Files.readAllBytes(disguises.toPath()));
- StringBuilder configText = new StringBuilder(new String(Files.readAllBytes(config.toPath())));
- configText.append("\n================\n");
+ configText.append("\n\n================\n");
- ArrayList modified =
- DisguiseConfig.doOutput(LibsDisguises.getInstance().getConfig(), true, true);
+ ArrayList modified = DisguiseConfig.doOutput(true, true);
for (String s : modified) {
configText.append("\n").append(s);
@@ -203,8 +208,10 @@ public class LDUploadLogs implements LDCommand {
configText.append("\nUsing default config!");
}
+ String ctext = configText.toString().replaceAll("\n? *#[^\n]*", "");
+
URL latestPaste = new GuestPaste("latest.log", latestText).paste();
- URL configPaste = new GuestPaste("LibsDisguises config.yml", configText.toString()).paste();
+ URL configPaste = new GuestPaste("LibsDisguises config.yml", ctext).paste();
URL disguisesPaste = new GuestPaste("LibsDisguises disguises.yml", disguiseText).paste();
lastUsed = System.currentTimeMillis();
@@ -216,12 +223,10 @@ public class LDUploadLogs implements LDCommand {
// Console can't click :(
if (sender instanceof Player) {
- sender.sendMessage(ChatColor.GOLD +
- "Click on the below message to have it appear in your chat input");
+ sender.sendMessage(ChatColor.GOLD + "Click on the below message to have it appear in your chat input");
}
- String text = "My log file: " + latestPaste + ", my config file: " + configPaste +
- " and my disguises file: " + disguisesPaste;
+ String text = "My log file: " + latestPaste + ", my config file: " + configPaste + " and my disguises file: " + disguisesPaste;
ComponentBuilder builder = new ComponentBuilder("");
builder.append(text);
@@ -243,7 +248,11 @@ public class LDUploadLogs implements LDCommand {
}
private boolean isTooBig(File file) {
- return file.exists() && file.length() >= 512 * 1024;
+ return file.exists() && isTooBig(file.length());
+ }
+
+ private boolean isTooBig(long length) {
+ return length >= 512 * 1024;
}
@Override
diff --git a/src/main/java/me/libraryaddict/disguise/commands/modify/DisguiseModifyRadiusCommand.java b/src/main/java/me/libraryaddict/disguise/commands/modify/DisguiseModifyRadiusCommand.java
index 853c7c1b..22bad4df 100644
--- a/src/main/java/me/libraryaddict/disguise/commands/modify/DisguiseModifyRadiusCommand.java
+++ b/src/main/java/me/libraryaddict/disguise/commands/modify/DisguiseModifyRadiusCommand.java
@@ -1,6 +1,7 @@
package me.libraryaddict.disguise.commands.modify;
import me.libraryaddict.disguise.DisguiseAPI;
+import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.commands.DisguiseBaseCommand;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
@@ -26,12 +27,6 @@ import java.lang.reflect.Method;
import java.util.*;
public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements TabCompleter {
- private int maxRadius = 30;
-
- public DisguiseModifyRadiusCommand(int maxRadius) {
- this.maxRadius = maxRadius;
- }
-
private Collection getNearbyEntities(CommandSender sender, int radius) {
Location center;
@@ -77,8 +72,7 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
Collections.sort(classes);
- LibsMsg.DMODRADIUS_USABLE.send(sender,
- ChatColor.GREEN + StringUtils.join(classes, ChatColor.DARK_GREEN + ", " + ChatColor.GREEN));
+ LibsMsg.DMODRADIUS_USABLE.send(sender, ChatColor.GREEN + StringUtils.join(classes, ChatColor.DARK_GREEN + ", " + ChatColor.GREEN));
return true;
}
@@ -124,9 +118,9 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
int radius = Integer.parseInt(args[starting]);
- if (radius > maxRadius) {
- LibsMsg.LIMITED_RADIUS.send(sender, maxRadius);
- radius = maxRadius;
+ if (radius > DisguiseConfig.getDisguiseRadiusMax()) {
+ LibsMsg.LIMITED_RADIUS.send(sender, DisguiseConfig.getDisguiseRadiusMax());
+ radius = DisguiseConfig.getDisguiseRadiusMax();
}
String[] newArgs = new String[args.length - (starting + 1)];
@@ -154,10 +148,11 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
Disguise disguise;
- if (sender instanceof Player)
+ if (sender instanceof Player) {
disguise = DisguiseAPI.getDisguise((Player) sender, entity);
- else
+ } else {
disguise = DisguiseAPI.getDisguise(entity);
+ }
if (disguise == null) {
continue;
@@ -174,18 +169,15 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
tempArgs = DisguiseParser.parsePlaceholders(tempArgs, sender, entity);
try {
- DisguiseParser.callMethods(sender, disguise, permissions, disguisePerm, new ArrayList<>(), tempArgs,
- "DisguiseModifyRadius");
+ DisguiseParser.callMethods(sender, disguise, permissions, disguisePerm, new ArrayList<>(), tempArgs, "DisguiseModifyRadius");
modifiedDisguises++;
- }
- catch (DisguiseParseException ex) {
+ } catch (DisguiseParseException ex) {
if (ex.getMessage() != null) {
DisguiseUtilities.sendMessage(sender, ex.getMessage());
}
return true;
- }
- catch (Exception ex) {
+ } catch (Exception ex) {
ex.printStackTrace();
return true;
}
@@ -238,8 +230,9 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
}
// Not a valid radius
- if (starting == 1 || args.length == 1 || !isInteger(args[1]))
+ if (starting == 1 || args.length == 1 || !isInteger(args[1])) {
return filterTabs(tabs, origArgs);
+ }
}
if (args.length <= starting || !isInteger(args[starting])) {
@@ -248,9 +241,9 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
int radius = Integer.parseInt(args[starting]);
- if (radius > maxRadius) {
- LibsMsg.LIMITED_RADIUS.send(sender, maxRadius);
- radius = maxRadius;
+ if (radius > DisguiseConfig.getDisguiseRadiusMax()) {
+ LibsMsg.LIMITED_RADIUS.send(sender, DisguiseConfig.getDisguiseRadiusMax());
+ radius = DisguiseConfig.getDisguiseRadiusMax();
}
starting++;
@@ -260,15 +253,17 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
for (Entity entity : getNearbyEntities(sender, radius)) {
Disguise disguise = DisguiseAPI.getDisguise(entity);
- if (disguise == null)
+ if (disguise == null) {
continue;
+ }
DisguiseType disguiseType = disguise.getType();
for (Method method : ParamInfoManager.getDisguiseWatcherMethods(disguiseType.getWatcherClass())) {
for (String arg : args) {
- if (!method.getName().equalsIgnoreCase(arg) || usedOptions.contains(arg))
+ if (!method.getName().equalsIgnoreCase(arg) || usedOptions.contains(arg)) {
continue;
+ }
usedOptions.add(arg);
}
@@ -291,7 +286,7 @@ public class DisguiseModifyRadiusCommand extends DisguiseBaseCommand implements
protected void sendCommandUsage(CommandSender sender, DisguisePermissions permissions) {
ArrayList allowedDisguises = getAllowedDisguises(permissions);
- LibsMsg.DMODRADIUS_HELP1.send(sender, maxRadius);
+ LibsMsg.DMODRADIUS_HELP1.send(sender, DisguiseConfig.getDisguiseRadiusMax());
LibsMsg.DMODIFY_HELP3.send(sender, StringUtils.join(allowedDisguises, LibsMsg.CAN_USE_DISGS_SEPERATOR.get()));
LibsMsg.DMODRADIUS_HELP2.send(sender);
diff --git a/src/main/java/me/libraryaddict/disguise/commands/undisguise/UndisguiseRadiusCommand.java b/src/main/java/me/libraryaddict/disguise/commands/undisguise/UndisguiseRadiusCommand.java
index 5e752bca..ffe3fe15 100644
--- a/src/main/java/me/libraryaddict/disguise/commands/undisguise/UndisguiseRadiusCommand.java
+++ b/src/main/java/me/libraryaddict/disguise/commands/undisguise/UndisguiseRadiusCommand.java
@@ -1,6 +1,7 @@
package me.libraryaddict.disguise.commands.undisguise;
import me.libraryaddict.disguise.DisguiseAPI;
+import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.utilities.LibsPremium;
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
import org.bukkit.ChatColor;
@@ -13,12 +14,6 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class UndisguiseRadiusCommand implements CommandExecutor {
- private int maxRadius = 30;
-
- public UndisguiseRadiusCommand(int maxRadius) {
- this.maxRadius = maxRadius;
- }
-
private boolean isNumeric(String string) {
try {
Integer.parseInt(string);
@@ -43,16 +38,19 @@ public class UndisguiseRadiusCommand implements CommandExecutor {
}
if (sender.hasPermission("libsdisguises.undisguiseradius")) {
- int radius = maxRadius;
+ int radius = DisguiseConfig.getDisguiseRadiusMax();
+
if (args.length > 0) {
if (!isNumeric(args[0])) {
LibsMsg.NOT_NUMBER.send(sender, args[0]);
return true;
}
+
radius = Integer.parseInt(args[0]);
- if (radius > maxRadius) {
- LibsMsg.LIMITED_RADIUS.send(sender, maxRadius);
- radius = maxRadius;
+
+ if (radius > DisguiseConfig.getDisguiseRadiusMax()) {
+ LibsMsg.LIMITED_RADIUS.send(sender, DisguiseConfig.getDisguiseRadiusMax());
+ radius = DisguiseConfig.getDisguiseRadiusMax();
}
}
diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java
index 20218edc..796c905e 100644
--- a/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java
+++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java
@@ -469,7 +469,7 @@ public class PlayerDisguise extends TargetedDisguise {
};
WrappedGameProfile gameProfile = DisguiseUtilities
- .getProfileFromMojang(this.skinToUse, currentLookup, LibsDisguises.getInstance().getConfig().getBoolean("ContactMojangServers", true));
+ .getProfileFromMojang(this.skinToUse, currentLookup, DisguiseConfig.isContactMojangServers());
if (gameProfile != null) {
setSkin(gameProfile);
@@ -635,7 +635,7 @@ public class PlayerDisguise extends TargetedDisguise {
};
WrappedGameProfile gameProfile = DisguiseUtilities
- .getProfileFromMojang(this.skinToUse, currentLookup, LibsDisguises.getInstance().getConfig().getBoolean("ContactMojangServers", true));
+ .getProfileFromMojang(this.skinToUse, currentLookup, DisguiseConfig.isContactMojangServers());
if (gameProfile != null) {
setSkin(gameProfile);
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java
index 6a08a929..25d3fcd8 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java
@@ -161,7 +161,7 @@ public class DisguiseUtilities {
private static final HashSet selfDisguised = new HashSet<>();
private static final HashMap preDisguiseTeam = new HashMap<>();
private static final HashMap disguiseTeam = new HashMap<>();
- private static final File profileCache = new File("plugins/LibsDisguises/GameProfiles");
+ private static final File profileCache = new File("plugins/LibsDisguises/SavedSkins");
private static final File savedDisguises = new File("plugins/LibsDisguises/SavedDisguises");
@Getter
private static Gson gson;
@@ -1124,7 +1124,7 @@ public class DisguiseUtilities {
DisguiseUtilities.refreshTrackers(disguise);
}
- }, LibsDisguises.getInstance().getConfig().getBoolean("ContactMojangServers", true));
+ }, DisguiseConfig.isContactMojangServers());
}
/**
@@ -1271,7 +1271,13 @@ public class DisguiseUtilities {
gson = gsonBuilder.create();
if (!profileCache.exists()) {
- profileCache.mkdirs();
+ File old = new File(profileCache.getParentFile(), "GameProfiles");
+
+ if (old.exists() && old.isDirectory()) {
+ old.renameTo(profileCache);
+ } else {
+ profileCache.mkdirs();
+ }
}
if (!savedDisguises.exists()) {
@@ -1331,13 +1337,7 @@ public class DisguiseUtilities {
Method m = CompileMethods.class.getMethod("main", String[].class);
if ((!m.isAnnotationPresent(CompileMethods.CompileMethodsIntfer.class) ||
- m.getAnnotation(CompileMethods.CompileMethodsIntfer.class).user().matches("[0-9]+")) &&
- !DisguiseConfig.doOutput(LibsDisguises.getInstance().getConfig(), true, false).isEmpty()) {
- /*File f = new File(LibsDisguises.getInstance().getDataFolder(), "config.yml");
- File f2 = new File(f.getParentFile(), "config-older.yml");
- f2.delete();
- f.renameTo(f2);
- LibsDisguises.getInstance().saveDefaultConfig();*/
+ m.getAnnotation(CompileMethods.CompileMethodsIntfer.class).user().matches("[0-9]+")) && !DisguiseConfig.doOutput(true, false).isEmpty()) {
DisguiseConfig.setViewDisguises(false);
}
} catch (NoSuchMethodException e) {
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/config/ConfigLoader.java b/src/main/java/me/libraryaddict/disguise/utilities/config/ConfigLoader.java
new file mode 100644
index 00000000..9bac4d04
--- /dev/null
+++ b/src/main/java/me/libraryaddict/disguise/utilities/config/ConfigLoader.java
@@ -0,0 +1,191 @@
+package me.libraryaddict.disguise.utilities.config;
+
+import lombok.Getter;
+import me.libraryaddict.disguise.LibsDisguises;
+import me.libraryaddict.disguise.utilities.DisguiseUtilities;
+import me.libraryaddict.disguise.utilities.reflection.ClassGetter;
+import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by libraryaddict on 31/01/2021.
+ */
+public class ConfigLoader {
+ @Getter
+ private final List configs = new ArrayList<>();
+
+ public ConfigLoader() {
+ for (String s : ClassGetter.getEntriesForPackage(ConfigLoader.class, "configs")) {
+ if (!s.endsWith(".yml")) {
+ continue;
+ }
+
+ if (s.endsWith("/disguises.yml") || s.endsWith("/sounds.yml")) {
+ continue;
+ }
+
+ configs.add(s);
+ }
+ }
+
+ public void saveMissingConfigs() {
+ File oldFile = new File(LibsDisguises.getInstance().getDataFolder(), "config.yml");
+ boolean migrated = oldFile.exists();
+
+ for (String config : configs) {
+ File f = new File(LibsDisguises.getInstance().getDataFolder(), config);
+
+ if (f.exists()) {
+ migrated = false;
+ continue;
+ }
+
+ saveDefaultConfig(config);
+ }
+
+ if (migrated) {
+ DisguiseUtilities.getLogger().info("Migrated old config system to new config system");
+ oldFile.delete();
+ }
+ }
+
+ public YamlConfiguration loadDefaults() {
+ YamlConfiguration globalConfig = new YamlConfiguration();
+
+ for (String config : configs) {
+ try {
+ YamlConfiguration c = new YamlConfiguration();
+ c.loadFromString(ReflectionManager.getResourceAsString(LibsDisguises.getInstance().getFile(), config));
+
+ for (String k : c.getKeys(true)) {
+ if (c.isConfigurationSection(k)) {
+ continue;
+ }
+
+ globalConfig.set(k, c.get(k));
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ return globalConfig;
+ }
+
+ public YamlConfiguration load() {
+ YamlConfiguration globalConfig = new YamlConfiguration();
+
+ for (String config : configs) {
+ YamlConfiguration c = YamlConfiguration.loadConfiguration(new File(LibsDisguises.getInstance().getDataFolder(), config));
+
+ for (String k : c.getKeys(true)) {
+ if (c.isConfigurationSection(k)) {
+ continue;
+ }
+
+ globalConfig.set(k, c.get(k));
+ }
+ }
+
+ return globalConfig;
+ }
+
+ public void saveDefaultConfigs() {
+ for (String config : configs) {
+ saveDefaultConfig(config);
+ }
+
+ File f = new File(LibsDisguises.getInstance().getDataFolder(), "config.yml");
+
+ f.delete();
+ }
+
+ public void saveDefaultConfig(String name) {
+ DisguiseUtilities.getLogger().info("Config " + name + " is out of date (Or missing)! Now refreshing it!");
+ String ourConfig = ReflectionManager.getResourceAsString(LibsDisguises.getInstance().getFile(), name);
+ YamlConfiguration savedConfig = null;
+
+ File loadFrom = new File(LibsDisguises.getInstance().getDataFolder(), name);
+ File configFile = loadFrom;
+
+ if (!loadFrom.exists()) {
+ loadFrom = new File(LibsDisguises.getInstance().getDataFolder(), "config.yml");
+ }
+
+ if (loadFrom.exists()) {
+ savedConfig = YamlConfiguration.loadConfiguration(loadFrom);
+ } else {
+ try {
+ savedConfig = new YamlConfiguration();
+ savedConfig.loadFromString(ourConfig);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ String[] string = ourConfig.split("\n");
+
+ StringBuilder section = new StringBuilder();
+
+ for (int i = 0; i < string.length; i++) {
+ String s = string[i];
+
+ if (s.trim().startsWith("#") || !s.contains(":")) {
+ continue;
+ }
+
+ String rawKey = s.split(":")[0];
+
+ if (section.length() > 0) {
+ int matches = StringUtils.countMatches(rawKey, " ");
+
+ int allowed = 0;
+
+ for (int a = 0; a < matches; a++) {
+ allowed = section.indexOf(".", allowed) + 1;
+ }
+
+ section = new StringBuilder(section.substring(0, allowed));
+ }
+
+ String key = (rawKey.startsWith(" ") ? section.toString() : "") + rawKey.trim();
+
+ if (savedConfig.isConfigurationSection(key)) {
+ section.append(key).append(".");
+ } else if (savedConfig.isSet(key)) {
+ String rawVal = s.split(":")[1].trim();
+ Object val = savedConfig.get(key);
+
+ if (savedConfig.isString(key) && !rawVal.equals("true") && !rawVal.equals("false")) {
+ val = "'" + StringEscapeUtils.escapeJava(val.toString().replace(ChatColor.COLOR_CHAR + "", "&")) + "'";
+ }
+
+ string[i] = rawKey + ": " + val;
+ }
+ }
+
+ try {
+ if (!configFile.getParentFile().exists()) {
+ configFile.mkdirs();
+ }
+
+ configFile.delete();
+ configFile.createNewFile();
+
+ try (PrintWriter out = new PrintWriter(configFile)) {
+ out.write(StringUtils.join(string, "\n"));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/config/DisguiseCommandConfig.java b/src/main/java/me/libraryaddict/disguise/utilities/config/DisguiseCommandConfig.java
index ff2a062b..7bc88091 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/config/DisguiseCommandConfig.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/config/DisguiseCommandConfig.java
@@ -27,7 +27,7 @@ public class DisguiseCommandConfig {
private boolean enabled;
}
- private File commandConfig = new File(LibsDisguises.getInstance().getDataFolder(), "commands.yml");
+ private File commandConfig = new File(LibsDisguises.getInstance().getDataFolder(), "configs/plugin-commands.yml");
private HashMap commands = new HashMap<>();
private boolean modifyCommands = false;
@@ -87,13 +87,19 @@ public class DisguiseCommandConfig {
section.set("aliases", command.getAliases());
}
+ String configString = config.saveToString();
+
+ configString = configString.replaceAll("\n([a-zA-Z])", "\n\n$1");
+
String s =
"# The following can be changed to modify how the disguise commands are registered\n# This will only work on server startup\nModifyCommands: " +
- modifyCommands + "\n\n" + config.saveToString();
+ modifyCommands + "\n\n" + configString;
commandConfig.delete();
try {
+ commandConfig.getParentFile().mkdirs();
+
commandConfig.createNewFile();
} catch (IOException e) {
e.printStackTrace();
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/listeners/DisguiseListener.java b/src/main/java/me/libraryaddict/disguise/utilities/listeners/DisguiseListener.java
index 7abbe8dd..0915091f 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/listeners/DisguiseListener.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/listeners/DisguiseListener.java
@@ -95,18 +95,14 @@ public class DisguiseListener implements Listener {
// If build number is null, or not a number. Then we can't check snapshots regardless
return !plugin.isNumberedBuild();
-
- // Check snapshots
}
private void runUpdateScheduler() {
- boolean autoUpdate = plugin.getConfig().getBoolean("AutoUpdateDev");
-
- if (!plugin.getConfig().getBoolean("NotifyUpdate")) {
+ if (!DisguiseConfig.isNotifyUpdate()) {
return;
}
- if (autoUpdate && !isCheckReleases()) {
+ if (DisguiseConfig.isAutoUpdate() && !isCheckReleases()) {
DisguiseUtilities.getLogger().info("Plugin will attempt to auto update when new builds are ready! Check config to disable.");
}
}
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/metrics/Metrics.java b/src/main/java/me/libraryaddict/disguise/utilities/metrics/Metrics.java
index f17e7d5a..d403919e 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/metrics/Metrics.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/metrics/Metrics.java
@@ -95,6 +95,7 @@ public class Metrics {
"Check out https://bStats.org/ to learn more :)").copyDefaults(true);
try {
config.save(configFile);
+ DisguiseUtilities.getLogger().info("Saved bStats config");
}
catch (IOException ignored) {
}
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/metrics/MetricsInitalizer.java b/src/main/java/me/libraryaddict/disguise/utilities/metrics/MetricsInitalizer.java
index efbe00bb..f9db36ed 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/metrics/MetricsInitalizer.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/metrics/MetricsInitalizer.java
@@ -221,12 +221,12 @@ public class MetricsInitalizer {
}
});
- metrics.addCustomChart(new Metrics.SimplePie("commands") {
+ /*metrics.addCustomChart(new Metrics.SimplePie("commands") {
@Override
public String getValue() {
return DisguiseConfig.isDisableCommands() ? "Enabled" : "Disabled";
}
- });
+ });*/
metrics.addCustomChart(new Metrics.SimplePie("spigot") {
@Override
@@ -241,7 +241,7 @@ public class MetricsInitalizer {
}
});
- final boolean updates = plugin.getConfig().getBoolean("NotifyUpdate");
+ final boolean updates = DisguiseConfig.isNotifyUpdate();
metrics.addCustomChart(new Metrics.SimplePie("updates") {
@Override
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/reflection/ClassGetter.java b/src/main/java/me/libraryaddict/disguise/utilities/reflection/ClassGetter.java
index 20a25e00..010d0893 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/reflection/ClassGetter.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/reflection/ClassGetter.java
@@ -22,8 +22,31 @@ public class ClassGetter {
return getClassesForPackage(Entity.class, pkgname);
}
+ public static ArrayList getEntriesForPackage(String pkgname) {
+ return getEntriesForPackage(Entity.class, pkgname);
+ }
+
public static ArrayList> getClassesForPackage(Class runFrom, String pkgname) {
- ArrayList> classes = new ArrayList<>();
+ ArrayList list = getEntriesForPackage(runFrom, pkgname);
+ ArrayList> classList = new ArrayList<>();
+
+ for (String s : list) {
+ if (!s.endsWith(".class")) {
+ continue;
+ }
+
+ Class> c = loadClass(s.replace(".class", "").replace('/', '.'));
+
+ if (c != null) {
+ classList.add(c);
+ }
+ }
+
+ return classList;
+ }
+
+ public static ArrayList getEntriesForPackage(Class runFrom, String pkgname) {
+ ArrayList classes = new ArrayList<>();
// String relPath = pkgname.replace('.', '/');
// Get a File object for the package
@@ -36,16 +59,11 @@ public class ClassGetter {
processJarfile(resource, pkgname, classes);
} else {
for (File f : new File(resource.getPath() + "/" + pkgname.replace(".", "/")).listFiles()) {
- if (!f.getName().endsWith(".class") || f.getName().contains("$")) {
+ if (f.getName().contains("$")) {
continue;
}
- try {
- classes.add(Class.forName(pkgname + "." + f.getName().replace(".class", "")));
- }
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
+ classes.add(pkgname + "/" + f.getName());
}
}
}
@@ -56,16 +74,12 @@ public class ClassGetter {
private static Class> loadClass(String className) {
try {
return Class.forName(className);
- }
- catch (ClassNotFoundException e) {
- throw new RuntimeException("Unexpected ClassNotFoundException loading class '" + className + "'");
- }
- catch (NoClassDefFoundError e) {
+ } catch (ClassNotFoundException | NoClassDefFoundError e) {
return null;
}
}
- private static void processJarfile(URL resource, String pkgname, ArrayList> classes) {
+ private static void processJarfile(URL resource, String pkgname, ArrayList classes) {
try {
String relPath = pkgname.replace('.', '/');
String resPath = URLDecoder.decode(resource.getPath(), "UTF-8");
@@ -79,22 +93,18 @@ public class ClassGetter {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
String className = null;
- if (entryName.endsWith(".class") && entryName.startsWith(relPath) &&
- entryName.length() > (relPath.length() + "/".length())) {
- className = entryName.replace('/', '.').replace('\\', '.').replace(".class", "");
- }
- if (className != null) {
- Class> c = loadClass(className);
- if (c != null) {
- classes.add(c);
- }
+ if (entryName.startsWith(relPath) && entryName.length() > (relPath.length() + "/".length())) {
+ className = entryName.replace('\\', '/');
+ }
+
+ if (className != null) {
+ classes.add(className);
}
}
jarFile.close();
- }
- catch (Exception ex) {
+ } catch (Exception ex) {
ex.printStackTrace();
}
}
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java b/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java
index 07c81375..563e4405 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/sounds/SoundManager.java
@@ -29,10 +29,18 @@ public class SoundManager {
}
private void loadCustomSounds() {
- File f = new File(LibsDisguises.getInstance().getDataFolder(), "sounds.yml");
+ File f = new File(LibsDisguises.getInstance().getDataFolder(), "configs/sounds.yml");
if (!f.exists()) {
- LibsDisguises.getInstance().saveResource("sounds.yml", false);
+ f.getParentFile().mkdirs();
+
+ File old = new File(LibsDisguises.getInstance().getDataFolder(), "sounds.yml");
+
+ if (old.exists()) {
+ old.renameTo(f);
+ } else {
+ LibsDisguises.getInstance().saveResource("configs/sounds.yml", false);
+ }
}
YamlConfiguration config = YamlConfiguration.loadConfiguration(f);
@@ -55,8 +63,7 @@ public class SoundManager {
continue;
}
- List list = section.getStringList(
- type.name().charAt(0) + type.name().substring(1).toLowerCase(Locale.ENGLISH));
+ List list = section.getStringList(type.name().charAt(0) + type.name().substring(1).toLowerCase(Locale.ENGLISH));
if (list == null || list.isEmpty()) {
continue;
@@ -67,17 +74,15 @@ public class SoundManager {
SoundGroup subGroup = SoundGroup.getGroup(sound);
if (subGroup == null) {
- DisguiseUtilities.getLogger().warning("Invalid sound '" + sound +
- "'! Must be a minecraft:sound.name or SoundGroup name!");
+ DisguiseUtilities.getLogger().warning("Invalid sound '" + sound + "'! Must be a minecraft:sound.name or SoundGroup name!");
continue;
}
Object[] sounds = subGroup.getDisguiseSounds().get(type);
if (sounds == null) {
- DisguiseUtilities.getLogger().warning(
- "Sound group '" + sound + "' does not contain a category for " + type +
- "! Can't use as default in " + key);
+ DisguiseUtilities.getLogger()
+ .warning("Sound group '" + sound + "' does not contain a category for " + type + "! Can't use as default in " + key);
continue;
}
diff --git a/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java b/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java
index 11072c26..69e95dad 100644
--- a/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java
+++ b/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java
@@ -359,7 +359,7 @@ public enum LibsMsg {
LD_COMMAND_DEBUG(ChatColor.BLUE + "/libsdisguises debug - " + ChatColor.AQUA +
"Used to help debug scoreboard issues on a player disguise"),
LD_COMMAND_UPLOAD_LOGS(ChatColor.BLUE + "/libsdisguises uploadlogs - " + ChatColor.AQUA +
- "Uploads latest.log, disguises.yml and config.yml and gives you the link to share. Used when seeking " +
+ "Uploads latest.log, disguises.yml and configs and gives you the link to share. Used when seeking " +
"assistance."),
SELF_DISGUISE_HIDDEN(ChatColor.GREEN + "Self disguise hidden as it's too tall..");
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
deleted file mode 100644
index fd3f749a..00000000
--- a/src/main/resources/config.yml
+++ /dev/null
@@ -1,352 +0,0 @@
-Permissions:
- # By default "libsdisguises.disguise.cow" will allow all options for cow disguise unless another permission has
- # defined otherwise.
- # If given "libsdisguises.disguise.animals.setburning" then "libsdisguises.disguise.cow" they will still be able to
- # use other options like "setbaby". This was provided for backwards compatibility.
- # By turning this from 'false' to 'true' the plugin will no longer give them the options unless the player was
- # explicitly granted it. Even if by wildcard. The above example means they can only use "setburning"
-
- # To summarize, "libsdisguises.disguise.cow" will no longer let them do any options on the cow disguise unless it
- # was added to their permissions
-
- # You can read more about permissions here: https://www.spigotmc.org/wiki/lib-s-disguises-setting-up-permissions/
- # The permission used to check OPs who may not have permissions defined, is "libsdisguises.*.*.*" which you can
- # negate with your permissions plugin
- ExplicitDisguises: false
-
- # What should the default permissions be for seeing commands?
- # This is a config option because I can't verify if they should be able to see commands normally due to my
- # permissions system. My system is complex, but its a ton of control.
- # This isn't an issue normally, but I recently received complaints from someone who doesn't believe in permissions...
- # Some of you may also wish to hide these commands!
- # The permissions for commands are a simple 'libsdisguises.seecmd.command' where 'command' can be
- # 'disguise', 'undisguise' etc. A simple 'libsdisguises.seecmd' permission may also work for children
- # If you change this while the server is running, players may need to rejoin for it to take effect
- # Remember that command blocks need 'TRUE' or 'OP' to use the commands.
- # TRUE = Everyone can see this, the default. Can be negated with permissions
- # FALSE = No one can see this without permissions to allow it
- # OP = Only operators can see this
- # NOT_OP = Only non operators can see this
- SeeCommands: TRUE
-
-# Some disguises have randomized options on disguise, such as a fox type or a villager breed.
-# This may be problematic for some server owners, so you can disable it below
-RandomDisguiseOptions: true
-
-# You can also get this information through /libsdisguises config
-# Should the plugin output missing config options instead of just counting them
-VerboseConfig: false
-# Should the plugin output changed config options? Will also list unknown extra options
-ChangedConfig: false
-# Should the config automatically update itself each time there's a config entry missing?
-# The old config will have any custom comments or invalid config entries wiped.
-UpdateConfig: true
-
-# Disables commands with the exception of /libsdisguises. Useful if you don't want the plugin to be used by anything
-# but a plugin
-# Useful if you didn't purchase the plugin.
-DisableCommands: false
-
-# This means that the plugin doesn't need to constantly call Mojang just to find a skin for an offline player
-# However some people may prefer to disable this.
-# Even if you disable this, if there was disguises in the cache already then it will use them
-SaveGameProfiles: true
-
-# This option is useless if you don't enable SaveGameProfiles!
-# If a player has been disguised before and their skin saved into the cache
-# When they join the server will automatically update the cache in case they changed their skin
-UpdateGameProfiles: true
-
-# THIS IS A PREMIUM ONLY FEATURE. TO USE IT, PURCHASE THE PLUGIN.
-# Saves disguises so that they persist after server shutdown, chunks unload, player logouts and so on.
-# As such, this completely replaces the KeepDisguises aspect which has been removed except for the player death.
-# Players - Are player disguises saved
-# Entities - Are entities disguises saved (This is everything that's not a player)
-# If you are using the dev builds, place your premium version of Lib's Disguises.jar inside the LibsDisguises folder
-# This will enable premium only features for the dev builds.
-# The saved disguises are saved in a json file format inside the plugin folder, there will be no other formats
-SaveDisguises:
- Players: false
- Entities: false
-
-# There are four options you can use
-# VANILLA - Names are limited to 16 chars but can't be changed without resending disguise
-# TEAMS - Names are limited to 32 chars but can be changed willy nilly
-# EXTENDED - Names are limited to 48 chars but can't be changed without resending disguise
-# ARMORSTANDS - Names are limited to 256 chars, uses a mix of armorstands and teams to do this. Slightly hacky.
-# Downside of armorstand names is that there's a chance of it becoming desynced from the player disguise
-# And names will always display even if the entity is invisible using potion effects
-# With ArmorStands & the Premium version, you can also use multiple lines in the nametag, use \n as a seperator.
-# Read the next option for more information.
-PlayerNames: TEAMS
-
-# If doing ARMORSTANDS in the above option, should CustomNames be overridden to use armorstands too?
-# This allows multiline names if you have purchased the plugin
-# Use \n for a new line, though if you're doing it in a config you may need to use \\n as " and ' are treated differently.
-OverrideCustomNames: true
-
-# How many ticks before tab packet is sent to remove from tablist. This shouldn't need to be touched
-TablistRemoveDelay: 3
-
-# Does the player keep their disguise after they die?
-KeepDisguises:
- PlayerDeath: false
-
-# Should the plugin use translations? Note that a player must see the message before it will appear in translations.yml
-Translations: false
-
-# How should the plugin handle self disguises scoreboards? It disables pushing in whichever team they're assigned.
-# If you want them to be able to push again when they undisguise, set this to CREATE_SCOREBOARD
-# I have to disable pushing or you will be pushed around by your own self disguise
-# MODIFY_SCOREBOARD - Modifies the player's current team if possible, otherwise assigns them to a new scoreboard team.
-# IGNORE_SCOREBOARD - Doesn't touch scoreboards at all, effectively means that if you didn't disable pushing in their scoreboard team; They will still be pushed around
-# CREATE_SCOREBOARD - Creates a new team which copies the attributes of their previous scoreboard team which they are then assigned to. This means they keep nametag color and other options.
-SelfDisguisesScoreboard: MODIFY_SCOREBOARD
-
-# More options in case you want to disable a specific setting of the scoreboard
-Scoreboard:
- # Should it modify the scoreboard to turn collisions off?
- Collisions: true
- # Should it modify the scoreboard teams to disable seeing friendly invisibles?
- DisableFriendlyInvisibles: true
- # Should the scoreboard warn you if it detects a potential conflict?
- # If self disguises are disabled, or the scoreboard is using IGNORE_SCOREBOARD then this does nothing.
- WarnConflict: true
- # When disguising as a player, should the prefix/suffix of the player disguise name copy the team info?
- # Only takes effect if using PlayerNames TEAMS or ARMORSTANDS
- CopyPlayerTeamInfo: true
-
-# Shall I notify those with the correct permission when there's a LibsDisguises update?
-# Disabling this will also disable notifications when the plugin updated
-NotifyUpdate: true
-# Should the plugin automatically update?
-AutoUpdate: true
-
-# Where should the plugin check for updates?
-# SAME_BUILDS - Will check snapshots if you're not using a release build
-# RELEASES - Only check for actual releases
-# SNAPSHOTS - Only check for new snapshots
-UpdatesBranch: SAME_BUILDS
-
-# Whats the max size allowed for command disguiseradius
-DisguiseRadiusMax: 50
-
-# Whats the max size allowed for command undisguiseradius
-UndisguiseRadiusMax: 50
-
-# Shall the players view their disguises?
-# Best used when viewing yourself in 3rd person
-ViewSelfDisguises: true
-# Are self disguises enabled by default
-# Default is true
-ViewSelfDisguisesDefault: true
-
-# Some disguises are rather big and tall and block your vision
-# By default those disguises are enabled despite misgivings, such as zombies, players, etc.
-# The baby versions however, should be short enough that it's a non-issue
-TallSelfDisguises: true
-
-# Shall I disguise the sounds?
-# This turns your damage sound into a MOOOO
-DisguiseSounds: true
-
-# Shall the disguised hear their disguise sounds or their damage sounds.
-# I disable this as it can be a little confusing when not used with self disguises
-HearSelfDisguise: true
-
-# When disguised, should a message be displayed to the player? If so, where?
-# The message can be customized in translations
-# BOSS_BAR is not supported in 1.12!
-# NONE, BOSS_BAR, ACTION_BAR
-NotifyBar: ACTION_BAR
-# If using boss bar, these two options come into play
-# https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/boss/BarColor.html
-BossBarColor: GREEN
-# https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/boss/BarStyle.html
-BossBarStyle: SOLID
-
-# By the default the plugin saves the users of the /viewdisguisebar and /viewselfdisguises to a file
-# So that it persists after restart
-SaveUserPreferences: true
-
-# Shall I send the velocity packets? I REALLY recommend you don't disable.
-# This is the only thing allowing the mobs to fly without glitching out.
-SendVelocity: true
-
-# For self disguises, they need to have the armor and the held item removed
-# Else they see floating armor, floating held items.
-# This turns the items invisible in the disguised players inventory. It does not actually remove them!
-# Be warned that in creative this can actually delete the item from the inventory due to a weird bug
-RemoveArmor: true
-RemoveHeldItem: false
-
-# If you set a disguise to burning, it will no longer be able to be shown as sneaking or invisible.
-# Set this to true if you want the disguise to get the animations of the disguised entity. Such as invisible, on fire, sprinting, sneaking, blocking
-# This is only valid if you set a animation on the disguise itself. Because the entity's animations are applied otherwise.
-AddEntityAnimations: true
-
-# When a sheep or wolf is right clicked with dye. The client automatically assumes it was successful and displays the sheep's wool or the wolfs collar as dyed.
-# This is a option that either prevents that happening, or it changes their color officially in the plugin so that everyone sees it changed.
-# Its currently set to false which means that the color is not changed and will refresh itself to the player.
-# Please note that this will not remove the dye from their hands. This also does not check if the disguised entity is actually a sheep/wolf and wants a say in its color.
-DyeableSheep: false
-DyeableWolf: false
-DyeableCat: false
-# Can a player interact with a llama with carpet to set or change their carpet color?
-CarpetableLlama: false
-# Can a player interact with a non-saddled horse of any type, to give it a saddle?
-# This does not change what you can ride or control!
-SaddleableHorse: false
-
-# This is only called into action when the disguise is constructed using the commands.
-# And when the disguise supports that. This will not be used at all for plugins constructing the disguises for instance.
-# Such as prophunt. Its also false because its kind of a retarded feature.
-# This is pretty simple. It shows the players displayname (Name as it appears in chat) above their head.
-# This also overrides any custom name they have set in their disguise options.
-# This does not take effect on player disguises
-# Permission to disable is libsdisguises.disablename
-ShowNamesAboveDisguises: false
-
-# This supports the above option.
-# If this is true, then the name shown above the head appears regardless of if you are looking at the disguise directly or not.
-NameAboveHeadAlwaysVisible: true
-
-# What should the name be shown as?
-# Two placeholders can be used.
-# %simple% = The very basic name, 'libraryaddict'
-# %complex% = Name will be grabbed from scoreboard or display name if scoreboard fails.
-NameAboveDisguise: '%complex%'
-
-# This modifies the bounding box, This is stuff like can a arrow hit them.
-# If you turn this to true, arrows will act like they hit the disguise in the right place!
-# Clients will not see any difference in the hitboxes they are attacking, this is a server-sided calculation!
-# So someone disguised as a enderdragon will easily get shot down by arrows!
-# This WILL conflict with NoCheatPlus. Other plugins may also get problems.
-# This shouldn't really be enabled for players as it also interferes with their movement because the server thinks
-# the player is larger than they really are.
-# That makes the player unable to approach this building because the server thinks they are trying to glitch inside
-# blocks.
-# This feature is highly experimental and is guaranteed to cause problems for players who are disguised
-ModifyBoundingBox: false
-
-# This prevents disguised players from being targeted by monsters.
-# This doesn't prevent their targeting you if already targeting when disguised
-# They will just ignore you unless provoked.
-MonstersIgnoreDisguises: false
-
-# This works only for players, disguised monsters and the like will not be undisguised
-# Should the player's disguises be removed if they attacks something?
-# Blown Disguise message can be changed in translations
-# Message can be hidden with an empty translation
-BlowDisguisesWhenAttacking: false
-
-# Should the player's disguises be removed if they're attacked by something?
-BlowDisguisesWhenAttacked: false
-
-# Should PvP be disabled when disguised?
-DisablePvP: false
-# Should PvE be disabled when disguised? (Eg, fighting zombie)
-DisablePvE: false
-
-# How long after disguise wears off, should pvp be allowed again? Requires above to be true
-# Default value 5 seconds
-PvPTimer: 5
-
-# This works with 'DisablePvP' that if attacked by another entity, they have 'PvPTimer' amount of time
-# to attack back. Timer is reset with every successful attack
-RetaliationCombat: false
-
-#Stop shulker disguises from moving, they're weird. This option only effects PLAYERS that are disguised, other entities disguised as shulkers will NOT be effected!
-StopShulkerDisguisesFromMoving: true
-
-# A option to choose how many seconds a DisguiseEntity command is valid for people to right click a entity to disguise it before expiring
-DisguiseEntityExpire: 10
-
-# Another option to choose the same thing for DisguiseClone command
-DisguiseCloneExpire: 10
-# Max disguises to store at a time with the DisguiseClone command
-DisguiseCloneSize: 3
-
-# This controls if a entity's max health is determined by the entity, or by the disguise.
-# Wither is 200, a player is 20. With this enabled, a player disguised as a wither will have the boss bar health accurate to the players health.
-# Else it will be 1/20 of the boss bar when they are full health.
-# Setting this in LivingWatcher overrides both values.
-MaxHealthDeterminedByEntity: true
-
-# This here is a option to turn off misc disguises.
-# This means you can not have a living entity disguise as a non-living entity.
-# This disables the Attributes packet, Non-living entities can still disguise as other non-living
-# This means that the above option will not work as it uses the attribute packet.
-MiscDisguisesForLiving: true
-
-# Turn this to true to have players undisguised when switching worlds
-UndisguiseOnWorldChange: false
-
-# Contact Mojang's servers? Disabling this option will disable player skin disguises!
-ContactMojangServers: true
-
-# Hide players in tab when disguised? This means a disguised player cannot be seen when you press tab! This can be toggled on/off per disguise
-HideDisguisedPlayersFromTab: false
-
-# Always show player disguises in tab? The names will continue to appear in tab until the disguise is removed.
-ShowPlayerDisguisesInTab: false
-
-# On player disguise, a fake player is added to tablist so the skin can load properly.
-# This option is ignored if 'ShowPlayerDisguisesInTab' is enabled.
-# 3 ticks should easily be enough.
-PlayerDisguisesTablistExpires: 3
-
-# To prevent skins from defaulting to alex/steve, there is a timer that only expires after X ticks or when the player moves
-# You shouldn't actually touch this, but eh. Your server.
-# Default is 5 seconds
-PlayerDisguisesTablistExpiresMove: 100
-
-# Don't like players able to set themselves invisible when using the disguise commands? Toggle this to true and no one can use setInvisible! Plugins can still use this however.
-DisableInvisibility: false
-
-# Disguises have a 'setExpires' option which removes the disguise after a set amount of time
-# By default, this is set to false which means it expires 9 minutes afterwards, even if they logged off.
-# If true, it means they will experience the full 9 minutes, even if they log on for just a minute per day
-# Expired message can be hidden with an empty translation message
-DynamicExpiry: false
-
-# Some players have issues with conflicting plugins where disguised entities will show the wrong armor
-# This should be left alone unless you're trying to solve this issue. Such as MM and stone blocks.
-# When true, the plugin will hide player disguises armor to prevent a minor visual bug for half a second
-PlayerHideArmor: true
-
-# This will help performance, especially with CPU
-# Due to safety reasons, self disguises can never have their packets disabled.
-PacketsEnabled:
- # This disables the animation packet. If a disguised entity sends a animation packet and they are using a non-living disguise. People will crash.
- # Disabling this also means that if a player disguised as a non-player leaves a bug. People will crash
- Animation: true
- # This disguises the collect packet. If a living entity disguised as a non-living entity picks up a item. People will crash. This fixes it
- # This also fixes people crashing if a item disguised as a sleeping player is picked up - Only true if Bed is enabled as well
- Collect: true
- # This disables a fix for when a disguised entity wearing armor dies, if the disguise can wear armor. It drops unpickupable items to anyone watching.
- EntityStatus: true
- # Entity equipment is the packets that are sent to ensure that a disguise has or doesn't have armor, and their held item.
- # Disabling this means that any disguises which can wear armor or hold items will show the armor/held item that the disguised is wearing.
- Equipment: true
- # This doesn't actually disable the packet. It would introduce problems. Instead it does the next best thing and caches the data.
- # This means that entity metadata will not change, and will only be sent in the spawn packet.
- # This is good if performance is extremely in need.
- # This is bad to disable unless you are ONLY going to use the disguises for decorations.
- # To be honest. This is basically "Disable entity animations". That option is called 'AddEntityAnimations' in the config but unlike that, this is always in effect.
- # Animations set by use of the api or through the disguise command are still in effect.
- Metadata: true
- # Movement packets are the biggest cpu hit. These are majorly used to ensure that the disguises facing direction isn't bugged up.
- # If you are using the Item_Frame disguise, when a packet is sent (Roughly every 2min) the disguise will bug up until they move.
- Movement: true
- # Disable this if you don't mind crashing everytime you see someone riding something disguised as a non-living entity
- Riding: true
- # When disguised as a wither skull, it sends a look packet every tick so that the wither skull is facing the right way.
- WitherSkull: true
- # This is only used when using a modded disguises thingy, check disguises.yml for more info
- # This is used as a hack to bypass bungeecord issues
- LoginPayload: true
-
-# Added to support a Chinese Minecraft Server which uses their own skin server unless the UUID is not version 4.
-# Changing this from 4 to say, 3. Means their server will fetch skins from Mojang instead.
-UUIDVersion: 4
diff --git a/src/main/resources/configs/combat.yml b/src/main/resources/configs/combat.yml
new file mode 100644
index 00000000..3544f1aa
--- /dev/null
+++ b/src/main/resources/configs/combat.yml
@@ -0,0 +1,29 @@
+# This config file is for settings that effects combat!
+
+# This prevents disguised players from being targeted by monsters.
+# This doesn't prevent their targeting you if already targeting when disguised
+# They will just ignore you unless provoked.
+MonstersIgnoreDisguises: false
+
+# Should PvP be disabled when disguised?
+DisablePvP: false
+# Should PvE be disabled when disguised? (Eg, fighting zombie)
+DisablePvE: false
+
+# This works only for players, disguised monsters and the like will not be undisguised
+# Should the player's disguises be removed if they attacks something?
+# Blown Disguise message can be changed in translations
+# Message can be hidden with an empty translation
+BlowDisguisesWhenAttacking: false
+
+# Should the player's disguises be removed if they're attacked by something?
+BlowDisguisesWhenAttacked: false
+
+# This works with 'DisablePvP' that if attacked by another entity, they have 'PvPTimer' amount of time
+# to attack back. Timer is reset with every successful attack
+RetaliationCombat: false
+
+# If pvp or pve is disabled, this takes effect.
+# If RetaliationCombat is false, or it's true but they haven't fought back in PvPTimer seconds, then they can't fight back.
+# This also controls it so they can't fight back PvPTimer seconds after applying a disguise
+PvPTimer: 5
\ No newline at end of file
diff --git a/src/main/resources/configs/commands.yml b/src/main/resources/configs/commands.yml
new file mode 100644
index 00000000..f970f3e5
--- /dev/null
+++ b/src/main/resources/configs/commands.yml
@@ -0,0 +1,54 @@
+# This config file is for settings that effect commands only!
+
+# Don't like players able to set themselves invisible when using the disguise commands? Toggle this to true and no one can use setInvisible! Plugins can still use this however.
+DisableInvisibility: false
+
+# By the default the plugin saves the users of the /viewdisguisebar and /viewselfdisguises to a file
+# So that it persists after restart
+SaveUserPreferences: true
+
+Permissions:
+ # By default "libsdisguises.disguise.cow" will allow all options for cow disguise unless another permission has
+ # defined otherwise.
+ # If given "libsdisguises.disguise.animals.setburning" then "libsdisguises.disguise.cow" they will still be able to
+ # use other options like "setbaby". This was provided for backwards compatibility.
+ # By turning this from 'false' to 'true' the plugin will no longer give them the options unless the player was
+ # explicitly granted it. Even if by wildcard. The above example means they can only use "setburning"
+
+ # To summarize, "libsdisguises.disguise.cow" will no longer let them do any options on the cow disguise unless it
+ # was added to their permissions
+
+ # You can read more about permissions here: https://www.spigotmc.org/wiki/lib-s-disguises-setting-up-permissions/
+ # The permission used to check OPs who may not have permissions defined, is "libsdisguises.*.*.*" which you can
+ # negate with your permissions plugin
+ ExplicitDisguises: false
+
+ # What should the default permissions be for seeing commands?
+ # This is a config option because I can't verify if they should be able to see commands normally due to my
+ # permissions system. My system is complex, but its a ton of control.
+ # This isn't an issue normally, but I recently received complaints from someone who doesn't believe in permissions...
+ # Some of you may also wish to hide these commands!
+ # The permissions for commands are a simple 'libsdisguises.seecmd.command' where 'command' can be
+ # 'disguise', 'undisguise' etc. A simple 'libsdisguises.seecmd' permission may also work for children
+ # If you change this while the server is running, players may need to rejoin for it to take effect
+ # Remember that command blocks need 'TRUE' or 'OP' to use the commands.
+ # TRUE = Everyone can see this, the default. Can be negated with permissions
+ # FALSE = No one can see this without permissions to allow it
+ # OP = Only operators can see this
+ # NOT_OP = Only non operators can see this
+ SeeCommands: TRUE
+
+# Whats the max size allowed for command disguiseradius
+DisguiseRadiusMax: 50
+
+# Whats the max size allowed for command undisguiseradius
+UndisguiseRadiusMax: 50
+
+# A option to choose how many seconds a DisguiseEntity command is valid for people to right click a entity to disguise it before expiring
+DisguiseEntityExpire: 10
+
+# Another option to choose the same thing for DisguiseClone command
+DisguiseCloneExpire: 10
+
+# Max disguises to store at a time with the DisguiseClone command
+DisguiseCloneSize: 3
\ No newline at end of file
diff --git a/src/main/resources/disguises.yml b/src/main/resources/configs/disguises.yml
similarity index 98%
rename from src/main/resources/disguises.yml
rename to src/main/resources/configs/disguises.yml
index 43c7b862..f7b3f481 100644
--- a/src/main/resources/disguises.yml
+++ b/src/main/resources/configs/disguises.yml
@@ -1,70 +1,70 @@
-# The best way to use this is with /savedisguise or /saveskin
-# /saveskin MyCustomSkin - Where can be an url, file in LibsDisguises/skins or player name
-# Then use /disguise player MyCustomSkin - To test it
-
-# You can also use /savedisguise MyCustomDisguise player KingKiller setskin - With the same 3 types of skin
-# as above
-
-# It is strongly recommended you use /savedisguise instead of editing this file!
-# You can use that command in console or ingame! This helps eliminate user error!
-
-# Here you can create your own disguises and disguise into them using the normal disguise commands
-# To create them is super simple, you're using it just like you would in a command. The only tricky thing is that it must be valid yaml. TIP: Enclose the strings in '
-# Please note that this is parsed exactly like a command, no spaces in your playername. Bypass by quoting with "!
-
-# You can use /grabskin - To get the skin data from a file, another player or website.
-# /savedisguise ingame will save a custom disguise in this config, including skin data.
-# You can also provide a file or url for 'setSkin'! Just as you would for /grabskin.
-# The setSkin argument will be automatically done for all /savedisguise usages, this way the skin never changes.
-# /copydisguise will give you the disguise in a usable string
-
-# You can also use placeholders in the disguises to create disguises that have the command users skin
-
-# %name% - Replaces %name% with the command user's name.
-# %skin% - Replaces %skin% with the command user's skin for use with player disguises.
-# %displayname% - Replaces %displayname% with the command users displayname
-
-# %target-name% - Finds first viable name from: Player name, entity custom nametag, then entity type (Pig, Horse, Cow)
-# %target-skin% - If target is a player, replaces %target-skin% with their skin for use with player disguises
-# %target-displayname% - Similar as above
-# If target is not a player, will silently fail
-
-# %held-item% - The currently held item in the main item slot
-# %offhand-item% - The offhand item
-# %armor% - The armor in - ,
- ,
- ,
- format
-# %helmet% %chestplate% %leggings% %boots% - Obvious.
-# These are best used in armor slots, or in settings that accept items. Can also be used alongside /copydisguise
-# to get the string format of an item. By /disguise zombie setiteminmainhand %held-item% - Then /copydisguise.
-# But the plugin will attempt to parse to the "simplest" format. So best used with an item that has more custom data
-# than just the amount.
-
-# These can be used again for the 'target' by prepending 'target-' to the above. So %target-armor% %target-held-item%
-# Finally, you can use %libraryaddict-name% to do all this, but fetch it from the ONLINE player libraryaddict! Case sensitive.
-
-# The below disguise would give a disguised sheep the nametag; Me: libraryaddict, Them: Sheep
-# Example: 'cow setCustomName "Me: %user-name%, Them: %target-name%"'
-#
-# This would give the disguised target a player disguise of their own name, but using the skin of the command user
-# Example2: 'player %target-name% setSkin %user-skin%'
-
-# The following disguises will work if you remove the '#' at the beginning of the line, this creates a disguise which you can use by /disguise libraryaddict
-Disguises:
- libraryaddict: 'player libraryaddict setArmor GOLDEN_BOOTS,GOLDEN_LEGGINGS,GOLDEN_CHESTPLATE,GOLDEN_HELMET setItemInMainHand WRITTEN_BOOK setGlowing setSkin {"id":"a149f81bf7844f8987c554afdd4db533","name":"libraryaddict","properties":[{"signature":"afoGOO45t3iGvTyQ732AlugPOvj13/RNjM0/utYlD4PZ4ab4Jopbzr8Px75+ALdkyegoKNcfaH4aXzylMvL6mIwaRdL0af7pfGibMMCMJ8F1RAMl2WqRslKBKXHGS1OXxMweoXW+RRatGgZsUC1BjxHMwd4RuXxrV9ZZ7x1r4xouUXmMzn19wqNO9EeG2q8AgF/hZdrnJPdTTrqJs04r4vCQiFiQsTWiY/B5CBOTh6fw4NpOHeeiJwHOLvN+6xKnAm77nKawaKCSciDwt54EeZoE/Q5ReQUEFgj++jdyHb5PJbhGytr//mazpTVzvlDnO06CZqigbiueV2/ush2gKSXQeimCXeNZzcj/CFgqAmMSEZQW3qHp+DgoqqtBNabJa0FBzpbQQ/jQWzoHfmUC/hTf0A0+hgOe4NqDc+xXYf4A9M/6/0JHz0voWhQJi8QriM699DeeUa31bVdTdKjcyK6Zw6/HIOJt++eFnkf++/zKt0fMiqfdRamSqR/K3w+Kk7cs2D345BNubl5L83YWmLbebUcAPKaza5gi17lUW+h/FitzfKAJZ+xsfSdj27nQLa24xYsyB3Fi5DcFLI2oQt5BYAvViT37sabGOXbDBsrijS4t3++mIbC+pCDiKi0hwZzvy0TPRTle2RMhJ6D66DmpykwqBOxzD73fEsieWX4=","name":"textures","value":"eyJ0aW1lc3RhbXAiOjE0ODA1MjA3NjAxNTksInByb2ZpbGVJZCI6ImExNDlmODFiZjc4NDRmODk4N2M1NTRhZmRkNGRiNTMzIiwicHJvZmlsZU5hbWUiOiJsaWJyYXJ5YWRkaWN0Iiwic2lnbmF0dXJlUmVxdWlyZWQiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS84ZTQ5NDVkMzZjZjVhNjI1OGZjOGY4ZTM5NmZlZWYzMzY1ZjM2MjgyYjE2MjY0OWI2M2NmZWQzNzNmNzY1OSJ9LCJDQVBFIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWZkNjFjM2M0YWM4OGYxYTM0NjhmYmRlZWY0NWNlYzg5ZTVhZmI4N2I5N2ExYTg0NWJmYjNjNjRmZDBiODgzIn19fQ=="}]}'
-# Warrior: 'zombie setArmor DIAMOND_BOOTS,DIAMOND_LEGGINGS,DIAMOND_CHESTPLATE,DIAMOND_HELMET setItemInMainHand DIAMOND_SWORD setItemInOffHand SHIELD'
-# Topsy: 'player Dinnerbone setSkin %target-skin%'
-
-# This is not recommended for use! It's mainly useful if you want custom entities and the client has a mod installed!
-# If an option is missing, then it means Lib's Disguises will not do sanity checks for that.
-# No mod = Everyone gets sent it, otherwise only those with the mod will get the disguise.
-# You MUST restart the server after adding anything!
-# To repeat, this is for forge mod entities!
-Custom-Entities:
-# Librarian:
-# Name: libaddict:librarian # Must be a minecraft:sheep type of name, if invalid will not load
-# Register: true # This means Lib's Disguises should register the EntityType in nms, not another plugin
-# Type: LIVING # MISC, LIVING - What type of disguise type, doesn't support custom packets
-# Mod: LibAttacks # The mod they need installed
-# If exists, will prevent anyone without the mod from joining with this error
-# Required: 'Install LibAttacks! Download it from our site!'
-# Channels: librarian:channel|1 # Sometimes a mod needs a channel enabled.. Seperate each channel with a comma.
-# The channels also want a protocol version, which is normally 1 or 1.0
+# The best way to use this is with /savedisguise or /saveskin
+# /saveskin MyCustomSkin - Where can be an url, file in LibsDisguises/skins or player name
+# Then use /disguise player MyCustomSkin - To test it
+
+# You can also use /savedisguise MyCustomDisguise player KingKiller setskin - With the same 3 types of skin
+# as above
+
+# It is strongly recommended you use /savedisguise instead of editing this file!
+# You can use that command in console or ingame! This helps eliminate user error!
+
+# Here you can create your own disguises and disguise into them using the normal disguise commands
+# To create them is super simple, you're using it just like you would in a command. The only tricky thing is that it must be valid yaml. TIP: Enclose the strings in '
+# Please note that this is parsed exactly like a command, no spaces in your playername. Bypass by quoting with "!
+
+# You can use /grabskin - To get the skin data from a file, another player or website.
+# /savedisguise ingame will save a custom disguise in this config, including skin data.
+# You can also provide a file or url for 'setSkin'! Just as you would for /grabskin.
+# The setSkin argument will be automatically done for all /savedisguise usages, this way the skin never changes.
+# /copydisguise will give you the disguise in a usable string
+
+# You can also use placeholders in the disguises to create disguises that have the command users skin
+
+# %name% - Replaces %name% with the command user's name.
+# %skin% - Replaces %skin% with the command user's skin for use with player disguises.
+# %displayname% - Replaces %displayname% with the command users displayname
+
+# %target-name% - Finds first viable name from: Player name, entity custom nametag, then entity type (Pig, Horse, Cow)
+# %target-skin% - If target is a player, replaces %target-skin% with their skin for use with player disguises
+# %target-displayname% - Similar as above
+# If target is not a player, will silently fail
+
+# %held-item% - The currently held item in the main item slot
+# %offhand-item% - The offhand item
+# %armor% - The armor in
- ,
- ,
- ,
- format
+# %helmet% %chestplate% %leggings% %boots% - Obvious.
+# These are best used in armor slots, or in settings that accept items. Can also be used alongside /copydisguise
+# to get the string format of an item. By /disguise zombie setiteminmainhand %held-item% - Then /copydisguise.
+# But the plugin will attempt to parse to the "simplest" format. So best used with an item that has more custom data
+# than just the amount.
+
+# These can be used again for the 'target' by prepending 'target-' to the above. So %target-armor% %target-held-item%
+# Finally, you can use %libraryaddict-name% to do all this, but fetch it from the ONLINE player libraryaddict! Case sensitive.
+
+# The below disguise would give a disguised sheep the nametag; Me: libraryaddict, Them: Sheep
+# Example: 'cow setCustomName "Me: %user-name%, Them: %target-name%"'
+#
+# This would give the disguised target a player disguise of their own name, but using the skin of the command user
+# Example2: 'player %target-name% setSkin %user-skin%'
+
+# The following disguises will work if you remove the '#' at the beginning of the line, this creates a disguise which you can use by /disguise libraryaddict
+Disguises:
+ libraryaddict: 'player libraryaddict setArmor GOLDEN_BOOTS,GOLDEN_LEGGINGS,GOLDEN_CHESTPLATE,GOLDEN_HELMET setItemInMainHand WRITTEN_BOOK setGlowing setSkin {"id":"a149f81bf7844f8987c554afdd4db533","name":"libraryaddict","properties":[{"signature":"afoGOO45t3iGvTyQ732AlugPOvj13/RNjM0/utYlD4PZ4ab4Jopbzr8Px75+ALdkyegoKNcfaH4aXzylMvL6mIwaRdL0af7pfGibMMCMJ8F1RAMl2WqRslKBKXHGS1OXxMweoXW+RRatGgZsUC1BjxHMwd4RuXxrV9ZZ7x1r4xouUXmMzn19wqNO9EeG2q8AgF/hZdrnJPdTTrqJs04r4vCQiFiQsTWiY/B5CBOTh6fw4NpOHeeiJwHOLvN+6xKnAm77nKawaKCSciDwt54EeZoE/Q5ReQUEFgj++jdyHb5PJbhGytr//mazpTVzvlDnO06CZqigbiueV2/ush2gKSXQeimCXeNZzcj/CFgqAmMSEZQW3qHp+DgoqqtBNabJa0FBzpbQQ/jQWzoHfmUC/hTf0A0+hgOe4NqDc+xXYf4A9M/6/0JHz0voWhQJi8QriM699DeeUa31bVdTdKjcyK6Zw6/HIOJt++eFnkf++/zKt0fMiqfdRamSqR/K3w+Kk7cs2D345BNubl5L83YWmLbebUcAPKaza5gi17lUW+h/FitzfKAJZ+xsfSdj27nQLa24xYsyB3Fi5DcFLI2oQt5BYAvViT37sabGOXbDBsrijS4t3++mIbC+pCDiKi0hwZzvy0TPRTle2RMhJ6D66DmpykwqBOxzD73fEsieWX4=","name":"textures","value":"eyJ0aW1lc3RhbXAiOjE0ODA1MjA3NjAxNTksInByb2ZpbGVJZCI6ImExNDlmODFiZjc4NDRmODk4N2M1NTRhZmRkNGRiNTMzIiwicHJvZmlsZU5hbWUiOiJsaWJyYXJ5YWRkaWN0Iiwic2lnbmF0dXJlUmVxdWlyZWQiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS84ZTQ5NDVkMzZjZjVhNjI1OGZjOGY4ZTM5NmZlZWYzMzY1ZjM2MjgyYjE2MjY0OWI2M2NmZWQzNzNmNzY1OSJ9LCJDQVBFIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWZkNjFjM2M0YWM4OGYxYTM0NjhmYmRlZWY0NWNlYzg5ZTVhZmI4N2I5N2ExYTg0NWJmYjNjNjRmZDBiODgzIn19fQ=="}]}'
+# Warrior: 'zombie setArmor DIAMOND_BOOTS,DIAMOND_LEGGINGS,DIAMOND_CHESTPLATE,DIAMOND_HELMET setItemInMainHand DIAMOND_SWORD setItemInOffHand SHIELD'
+# Topsy: 'player Dinnerbone setSkin %target-skin%'
+
+# This is not recommended for use! It's mainly useful if you want custom entities and the client has a mod installed!
+# If an option is missing, then it means Lib's Disguises will not do sanity checks for that.
+# No mod = Everyone gets sent it, otherwise only those with the mod will get the disguise.
+# You MUST restart the server after adding anything!
+# To repeat, this is for forge mod entities!
+Custom-Entities:
+# Librarian:
+# Name: libaddict:librarian # Must be a minecraft:sheep type of name, if invalid will not load
+# Register: true # This means Lib's Disguises should register the EntityType in nms, not another plugin
+# Type: LIVING # MISC, LIVING - What type of disguise type, doesn't support custom packets
+# Mod: LibAttacks # The mod they need installed
+# If exists, will prevent anyone without the mod from joining with this error
+# Required: 'Install LibAttacks! Download it from our site!'
+# Channels: librarian:channel|1 # Sometimes a mod needs a channel enabled.. Seperate each channel with a comma.
+# The channels also want a protocol version, which is normally 1 or 1.0
diff --git a/src/main/resources/configs/features.yml b/src/main/resources/configs/features.yml
new file mode 100644
index 00000000..1b3298cb
--- /dev/null
+++ b/src/main/resources/configs/features.yml
@@ -0,0 +1,42 @@
+# This config file is for features that are something the server might want to customize!
+
+# Disguises have a 'setExpires' option which removes the disguise after a set amount of time
+# By default, this is set to false which means it expires 9 minutes afterwards, even if they logged off.
+# If true, it means they will experience the full 9 minutes, even if they log on for just a minute per day
+# Expired message can be hidden with an empty translation message
+DynamicExpiry: false
+
+# THIS IS A PREMIUM ONLY FEATURE. TO USE IT, PURCHASE THE PLUGIN.
+# Saves disguises so that they persist after server shutdown, chunks unload, player logouts and so on.
+# As such, this completely replaces the KeepDisguises aspect which has been removed except for the player death.
+# Players - Are player disguises saved
+# Entities - Are entities disguises saved (This is everything that's not a player)
+# If you are using the dev builds, place your premium version of Lib's Disguises.jar inside the LibsDisguises folder
+# This will enable premium only features for the dev builds.
+# The saved disguises are saved in a json file format inside the plugin folder, there will be no other formats
+SaveDisguises:
+ Players: false
+ Entities: false
+
+# Does the player keep their disguise after they die?
+KeepDisguises:
+ PlayerDeath: false
+
+# Shall I disguise the sounds?
+# This turns your damage sound into a MOOOO
+DisguiseSounds: true
+
+# Turn this to true to have players undisguised when switching worlds
+UndisguiseOnWorldChange: false
+
+
+# When disguised, should a message be displayed to the player? If so, where?
+# The message can be customized in translations
+# BOSS_BAR is not supported in 1.12!
+# NONE, BOSS_BAR, ACTION_BAR
+NotifyBar: ACTION_BAR
+# If using boss bar, these two options come into play
+# https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/boss/BarColor.html
+BossBarColor: GREEN
+# https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/boss/BarStyle.html
+BossBarStyle: SOLID
diff --git a/src/main/resources/configs/libsdisguises.yml b/src/main/resources/configs/libsdisguises.yml
new file mode 100644
index 00000000..107b4b15
--- /dev/null
+++ b/src/main/resources/configs/libsdisguises.yml
@@ -0,0 +1,30 @@
+# This config is for options that are about Libs Disguises itself, not the disguises.
+
+# Contact Mojang's servers? Disabling this option will disable player disguises if there's no skin to use!
+ContactMojangServers: true
+
+# Should the plugin use translations? Note that a player must see the message before it will appear in translations.yml
+Translations: false
+
+# Shall I notify those with the correct permission when there's a LibsDisguises update?
+# Disabling this will also disable notifications when the plugin updated
+NotifyUpdate: true
+# Should the plugin automatically update?
+AutoUpdate: true
+
+# Where should the plugin check for updates?
+# SAME_BUILDS - Will check snapshots if you're not using a release build
+# RELEASES - Only check for actual releases
+# SNAPSHOTS - Only check for new snapshots
+UpdatesBranch: SAME_BUILDS
+
+# You can also get this information through /libsdisguises config
+# Should the plugin output missing config options instead of just counting them
+VerboseConfig: false
+
+# Should the plugin output changed config options? Will also list unknown extra options
+ChangedConfig: false
+
+# Should the config automatically update itself each time there's a config entry missing?
+# The old config will have any custom comments or invalid config entries wiped.
+UpdateConfig: true
\ No newline at end of file
diff --git a/src/main/resources/configs/nametags.yml b/src/main/resources/configs/nametags.yml
new file mode 100644
index 00000000..6e6c313d
--- /dev/null
+++ b/src/main/resources/configs/nametags.yml
@@ -0,0 +1,49 @@
+# This config file is about the names that appear over heads! A fair bit of player disguise stuff is in players.yml however
+
+# This is only called into action when the disguise is constructed using the commands.
+# And when the disguise supports that. This will not be used at all for plugins constructing the disguises for instance.
+# Such as prophunt. Its also false because its kind of a retarded feature.
+# This is pretty simple. It shows the players displayname (Name as it appears in chat) above their head.
+# This also overrides any custom name they have set in their disguise options.
+# This does not take effect on player disguises
+# Permission to disable is libsdisguises.disablename
+ShowNamesAboveDisguises: false
+
+# This supports the above option.
+# If this is true, then the name shown above the head appears regardless of if you are looking at the disguise directly or not.
+NameAboveHeadAlwaysVisible: true
+
+# What should the name be shown as?
+# Two placeholders can be used.
+# %simple% = The very basic name, 'libraryaddict'
+# %complex% = Name will be grabbed from scoreboard or display name if scoreboard fails.
+NameAboveDisguise: '%complex%'
+
+# There are four options you can use
+# VANILLA - Names are limited to 16 chars but can't be changed without resending disguise
+# TEAMS - Names are limited to 32 chars but can be changed willy nilly
+# EXTENDED - Names are limited to 48 chars but can't be changed without resending disguise
+# ARMORSTANDS - Names are limited to 256 chars, uses a mix of armorstands and teams to do this. Slightly hacky.
+# Downside of armorstand names is that there's a chance of it becoming desynced from the player disguise
+# And names will always display even if the entity is invisible using potion effects
+# With ArmorStands & the Premium version, you can also use multiple lines in the nametag, use \n as a seperator.
+# Read the next option for more information.
+PlayerNames: TEAMS
+
+# If doing ARMORSTANDS in the above option, should CustomNames for non-player disguises be overridden to use armorstands too?
+# This allows multiline names if you have purchased the plugin
+# Use \n for a new line, though if you're doing it in a config you may need to use \\n as " and ' are treated differently.
+OverrideCustomNames: true
+
+# More options in case you want to disable a specific setting of the scoreboard
+Scoreboard:
+ # Should it modify the scoreboard to turn collisions off?
+ Collisions: true
+ # Should it modify the scoreboard teams to disable seeing friendly invisibles?
+ DisableFriendlyInvisibles: true
+ # Should the scoreboard warn you if it detects a potential conflict?
+ # If self disguises are disabled, or the scoreboard is using IGNORE_SCOREBOARD then this does nothing.
+ WarnConflict: true
+ # When disguising as a player, should the prefix/suffix of the player disguise name copy the team info?
+ # Only takes effect if using PlayerNames TEAMS or ARMORSTANDS
+ CopyPlayerTeamInfo: true
\ No newline at end of file
diff --git a/src/main/resources/configs/players.yml b/src/main/resources/configs/players.yml
new file mode 100644
index 00000000..d2923156
--- /dev/null
+++ b/src/main/resources/configs/players.yml
@@ -0,0 +1,45 @@
+# This config file is for settings that are about the players themselves, and the player disguises!
+
+# Shall the players view their disguises?
+# Best used when viewing yourself in 3rd person
+ViewSelfDisguises: true
+
+# Are self disguises enabled by default
+# Default is true
+ViewSelfDisguisesDefault: true
+
+# Shall the disguised hear their disguise sounds or their damage sounds.
+# I disable this as it can be a little confusing when not used with self disguises
+HearSelfDisguise: true
+
+# Some disguises are rather big and tall and block your vision
+# By default those disguises are enabled despite misgivings, such as zombies, players, etc.
+# The baby versions however, should be short enough that it's a non-issue
+TallSelfDisguises: true
+
+# How should the plugin handle self disguises scoreboards? It disables pushing in whichever team they're assigned.
+# If you want them to be able to push again when they undisguise, set this to CREATE_SCOREBOARD
+# I have to disable pushing or you will be pushed around by your own self disguise
+# MODIFY_SCOREBOARD - Modifies the player's current team if possible, otherwise assigns them to a new scoreboard team.
+# IGNORE_SCOREBOARD - Doesn't touch scoreboards at all, effectively means that if you didn't disable pushing in their scoreboard team; They will still be pushed around
+# CREATE_SCOREBOARD - Creates a new team which copies the attributes of their previous scoreboard team which they are then assigned to. This means they keep nametag color and other options.
+SelfDisguisesScoreboard: MODIFY_SCOREBOARD
+
+# Hide players in tab when disguised? This means a disguised player cannot be seen when you press tab! This can be toggled on/off per disguise
+HideDisguisedPlayersFromTab: false
+
+# Always show player disguises in tab? The names will continue to appear in tab until the disguise is removed.
+ShowPlayerDisguisesInTab: false
+
+# On player disguise, a fake player is added to tablist so the skin can load properly.
+# This option is ignored if 'ShowPlayerDisguisesInTab' is enabled.
+# 3 ticks should easily be enough.
+PlayerDisguisesTablistExpires: 3
+
+# How many ticks before tab packet is sent to remove from tablist. This shouldn't need to be touched
+TablistRemoveDelay: 3
+
+# To prevent skins from defaulting to alex/steve, there is a timer that only expires after X ticks or when the player moves
+# You shouldn't actually touch this, but eh. Your server.
+# Default is 5 seconds
+PlayerDisguisesTablistExpiresMove: 100
\ No newline at end of file
diff --git a/src/main/resources/configs/protocol.yml b/src/main/resources/configs/protocol.yml
new file mode 100644
index 00000000..556ebbbc
--- /dev/null
+++ b/src/main/resources/configs/protocol.yml
@@ -0,0 +1,74 @@
+# This config is for options that should only be touched if you're having compatibility issues with other plugins
+
+# Some players have issues with conflicting plugins where disguised entities will show the wrong armor
+# This should be left alone unless you're trying to solve this issue. Such as MM and stone blocks.
+# When true, the plugin will hide player disguises armor to prevent a minor visual bug for half a second
+PlayerHideArmor: true
+
+# Some disguises have randomized options on disguise, such as a fox type or a villager breed.
+# This may be problematic for some server owners, so you can disable it below
+RandomDisguiseOptions: true
+
+# For self disguises, they need to have the armor and the held item removed
+# Else they see floating armor, floating held items.
+# This turns the items invisible in the disguised players inventory. It does not actually remove them!
+# Be warned that in creative this can actually delete the item from the inventory due to a weird bug
+RemoveArmor: true
+RemoveHeldItem: false
+
+# If you set a disguise to burning, it will no longer be able to be shown as sneaking or invisible.
+# Set this to true if you want the disguise to get the animations of the disguised entity. Such as invisible, on fire, sprinting, sneaking, blocking
+# This is only valid if you set a animation on the disguise itself. Because the entity's animations are applied otherwise.
+AddEntityAnimations: true
+
+# This controls if a entity's max health is determined by the entity, or by the disguise.
+# Wither is 200, a player is 20. With this enabled, a player disguised as a wither will have the boss bar health accurate to the players health.
+# Else it will be 1/20 of the boss bar when they are full health.
+# Setting this in LivingWatcher overrides both values.
+MaxHealthDeterminedByEntity: true
+
+# This here is a option to turn off misc disguises.
+# This means you can not have a living entity disguise as a non-living entity.
+# This disables the Attributes packet, Non-living entities can still disguise as other non-living
+# This means that the above option will not work as it uses the attribute packet.
+MiscDisguisesForLiving: true
+
+# Shall I send the velocity packets? I REALLY recommend you don't disable.
+# This is the only thing allowing the mobs to fly without glitching out.
+SendVelocity: true
+
+# This will help performance, especially with CPU
+# Due to safety reasons, self disguises can never have their packets disabled.
+PacketsEnabled:
+ # This disables the animation packet. If a disguised entity sends a animation packet and they are using a non-living disguise. People will crash.
+ # Disabling this also means that if a player disguised as a non-player leaves a bug. People will crash
+ Animation: true
+ # This disguises the collect packet. If a living entity disguised as a non-living entity picks up a item. People will crash. This fixes it
+ # This also fixes people crashing if a item disguised as a sleeping player is picked up - Only true if Bed is enabled as well
+ Collect: true
+ # This disables a fix for when a disguised entity wearing armor dies, if the disguise can wear armor. It drops unpickupable items to anyone watching.
+ EntityStatus: true
+ # Entity equipment is the packets that are sent to ensure that a disguise has or doesn't have armor, and their held item.
+ # Disabling this means that any disguises which can wear armor or hold items will show the armor/held item that the disguised is wearing.
+ Equipment: true
+ # This doesn't actually disable the packet. It would introduce problems. Instead it does the next best thing and caches the data.
+ # This means that entity metadata will not change, and will only be sent in the spawn packet.
+ # This is good if performance is extremely in need.
+ # This is bad to disable unless you are ONLY going to use the disguises for decorations.
+ # To be honest. This is basically "Disable entity animations". That option is called 'AddEntityAnimations' in the config but unlike that, this is always in effect.
+ # Animations set by use of the api or through the disguise command are still in effect.
+ Metadata: true
+ # Movement packets are the biggest cpu hit. These are majorly used to ensure that the disguises facing direction isn't bugged up.
+ # If you are using the Item_Frame disguise, when a packet is sent (Roughly every 2min) the disguise will bug up until they move.
+ Movement: true
+ # Disable this if you don't mind crashing everytime you see someone riding something disguised as a non-living entity
+ Riding: true
+ # When disguised as a wither skull, it sends a look packet every tick so that the wither skull is facing the right way.
+ WitherSkull: true
+ # This is only used when using a modded disguises thingy, check disguises.yml for more info
+ # This is used as a hack to bypass bungeecord issues
+ LoginPayload: true
+
+# Added to support a Chinese Minecraft Server which uses their own skin server unless the UUID is not version 4.
+# Changing this from 4 to say, 3. Means their server will fetch skins from Mojang instead.
+UUIDVersion: 4
diff --git a/src/main/resources/configs/sanity.yml b/src/main/resources/configs/sanity.yml
new file mode 100644
index 00000000..12dfe20f
--- /dev/null
+++ b/src/main/resources/configs/sanity.yml
@@ -0,0 +1,41 @@
+# This config is called sanity, because you shouldn't need to change the stuff in here
+
+#Stop shulker disguises from moving, they're weird. This option only effects PLAYERS that are disguised, other entities disguised as shulkers will NOT be effected!
+StopShulkerDisguisesFromMoving: true
+
+# This means that the plugin doesn't need to constantly call Mojang just to find a skin for an offline player
+# However some people may prefer to disable this.
+# Even if you disable this, if there was disguises in the cache already then it will use them
+SaveGameProfiles: true
+
+# This option is useless if you don't enable SaveGameProfiles!
+# If a player has been disguised before and their skin saved into the cache
+# When they join the server will automatically update the cache in case they changed their skin
+UpdateGameProfiles: true
+
+# This modifies the bounding box, This is stuff like can a arrow hit them.
+# If you turn this to true, arrows will act like they hit the disguise in the right place!
+# Clients will not see any difference in the hitboxes they are attacking, this is a server-sided calculation!
+# So someone disguised as a enderdragon will easily get shot down by arrows!
+# This WILL conflict with NoCheatPlus. Other plugins may also get problems.
+# This shouldn't really be enabled for players as it also interferes with their movement because the server thinks
+# the player is larger than they really are.
+# That makes the player unable to approach this building because the server thinks they are trying to glitch inside
+# blocks.
+# This feature is highly experimental and is guaranteed to cause problems for players who are disguised
+ModifyBoundingBox: false
+
+# When a sheep or wolf is right clicked with dye. The client automatically assumes it was successful and displays the sheep's wool or the wolfs collar as dyed.
+# This is a option that either prevents that happening, or it changes their color officially in the plugin so that everyone sees it changed.
+# Its currently set to false which means that the color is not changed and will refresh itself to the player.
+# Please note that this will not remove the dye from their hands. This also does not check if the disguised entity is actually a sheep/wolf and wants a say in its color.
+DyeableSheep: false
+DyeableWolf: false
+DyeableCat: false
+
+# Can a player interact with a llama with carpet to set or change their carpet color?
+CarpetableLlama: false
+
+# Can a player interact with a non-saddled horse of any type, to give it a saddle?
+# This does not change what you can ride or control!
+SaddleableHorse: false
\ No newline at end of file
diff --git a/src/main/resources/sounds.yml b/src/main/resources/configs/sounds.yml
similarity index 100%
rename from src/main/resources/sounds.yml
rename to src/main/resources/configs/sounds.yml