Large config rewrite, updating creates incompatibility with older versions of LD. Probably need to clean up configs a bit more.

This commit is contained in:
libraryaddict 2021-01-31 21:28:07 +13:00
parent 7ab4a31c1f
commit bd0ca9ec8c
30 changed files with 841 additions and 703 deletions

@ -17,6 +17,7 @@
<filtering>true</filtering>
<includes>
<include>*</include>
<include>configs/*</include>
</includes>
</resource>
<resource>

@ -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;
}
}

@ -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<TargetedDisguise> 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<String> doOutput(boolean informChangedUnknown, boolean informMissing) {
return doOutput(new ConfigLoader().load(), informChangedUnknown, informMissing);
}
public static ArrayList<String> doOutput(ConfigurationSection config, boolean informChangedUnknown, boolean informMissing) {
HashMap<String, Object> configs = new HashMap<>();
ConfigurationSection defaultSection = config.getDefaultSection();
if (defaultSection == null) {
defaultSection = new ConfigLoader().loadDefaults();
}
ArrayList<String> 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;

@ -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);

@ -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<Class<? extends Entity>> 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")) {

@ -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<String> returns = DisguiseConfig.doOutput(LibsDisguises.getInstance().getConfig(), true, true);
ArrayList<String> returns = DisguiseConfig.doOutput(true, true);
if (returns.isEmpty()) {
LibsMsg.USING_DEFAULT_CONFIG.send(sender);

@ -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<File> 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<String> modified =
DisguiseConfig.doOutput(LibsDisguises.getInstance().getConfig(), true, true);
ArrayList<String> 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

@ -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<Entity> 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<String> 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);

@ -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();
}
}

@ -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);

@ -161,7 +161,7 @@ public class DisguiseUtilities {
private static final HashSet<UUID> selfDisguised = new HashSet<>();
private static final HashMap<UUID, String> preDisguiseTeam = new HashMap<>();
private static final HashMap<UUID, String> 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) {

@ -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<String> 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();
}
}
}

@ -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<String, DisguiseCommand> 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();

@ -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.");
}
}

@ -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) {
}

@ -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

@ -22,8 +22,31 @@ public class ClassGetter {
return getClassesForPackage(Entity.class, pkgname);
}
public static ArrayList<String> getEntriesForPackage(String pkgname) {
return getEntriesForPackage(Entity.class, pkgname);
}
public static ArrayList<Class<?>> getClassesForPackage(Class runFrom, String pkgname) {
ArrayList<Class<?>> classes = new ArrayList<>();
ArrayList<String> list = getEntriesForPackage(runFrom, pkgname);
ArrayList<Class<?>> 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<String> getEntriesForPackage(Class runFrom, String pkgname) {
ArrayList<String> 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<Class<?>> classes) {
private static void processJarfile(URL resource, String pkgname, ArrayList<String> 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();
}
}

@ -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<String> list = section.getStringList(
type.name().charAt(0) + type.name().substring(1).toLowerCase(Locale.ENGLISH));
List<String> 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;
}

@ -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..");

@ -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

@ -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

@ -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

@ -1,70 +1,70 @@
# The best way to use this is with /savedisguise or /saveskin
# /saveskin MyCustomSkin <SkinName> - Where <SkinName> 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 <SkinName> - 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 <Target> <Optional Name> - 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 <Optional Target Name/UUID> 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 <Item>,<Item>,<Item>,<Item> 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 <SkinName> - Where <SkinName> 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 <SkinName> - 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 <Target> <Optional Name> - 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 <Optional Target Name/UUID> 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 <Item>,<Item>,<Item>,<Item> 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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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