Read below for more info
Added /grabskin - Grabs a skin from file, url or existing player and saves as a new skin name Added /copydisguise - Outputs the current disguise or a specific uuid/player disguise to a usable string Added /savedisguise - Saves a disguise to custom disguises (disguises.yml) for future use, accepts skin files, urls and existing players Using MineSkin.org API Now generates Skins folder with info inside Added addGameProfile, addCustomDisguise and parseToString to DisguiseAPI Added different checks to gameprofiles Added new messages for the new features Fixed disguise parser to string handling quotes and skins wrong Fixed disguise parser to string not replacing colors back to the & Changed itemstack params to parse to a simpler item if possible
This commit is contained in:
parent
da6f98a3d7
commit
c073af37e8
@ -1,15 +1,20 @@
|
||||
package me.libraryaddict.disguise;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import me.libraryaddict.disguise.disguisetypes.*;
|
||||
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.AbstractHorseWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.HorseWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParseException;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParser;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguisePerm;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.HorseInventory;
|
||||
@ -17,6 +22,8 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -26,6 +33,42 @@ import java.util.Map;
|
||||
public class DisguiseAPI {
|
||||
private static int selfDisguiseId = ReflectionManager.getNewEntityId(true);
|
||||
|
||||
public static void addCustomDisguise(String disguiseName, String disguiseInfo) throws DisguiseParseException {
|
||||
// Dirty fix for anyone that somehow got this far with a . in the name, invalid yaml!
|
||||
disguiseName = disguiseName.replace(".", "");
|
||||
|
||||
try {
|
||||
DisguiseConfig.removeCustomDisguise(disguiseInfo);
|
||||
DisguiseConfig.addCustomDisguise(disguiseName, disguiseInfo);
|
||||
|
||||
File disguisesFile = new File("plugins/LibsDisguises/disguises.yml");
|
||||
|
||||
if (!disguisesFile.exists()) {
|
||||
disguisesFile.createNewFile();
|
||||
}
|
||||
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(disguisesFile);
|
||||
|
||||
if (!configuration.isConfigurationSection("Disguises")) {
|
||||
configuration.createSection("Disguises");
|
||||
}
|
||||
|
||||
ConfigurationSection section = configuration.getConfigurationSection("Disguises");
|
||||
section.set(disguiseName, disguiseInfo);
|
||||
|
||||
configuration.save(disguisesFile);
|
||||
|
||||
DisguiseUtilities.getLogger().info("Added new Custom Disguise " + disguiseName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void addGameProfile(String profileName, WrappedGameProfile gameProfile) {
|
||||
DisguiseUtilities.addGameProfile(profileName, gameProfile);
|
||||
}
|
||||
|
||||
public static String getRawCustomDisguise(String disguiseName) {
|
||||
Map.Entry<DisguisePerm, String> entry = DisguiseConfig.getRawCustomDisguise(disguiseName);
|
||||
|
||||
@ -318,6 +361,14 @@ public class DisguiseAPI {
|
||||
return DisguiseUtilities.getMainDisguise(disguised.getUniqueId());
|
||||
}
|
||||
|
||||
public static String parseToString(Disguise disguise, boolean outputSkin) {
|
||||
return DisguiseParser.parseToString(disguise, outputSkin);
|
||||
}
|
||||
|
||||
public static String parseToString(Disguise disguise) {
|
||||
return parseToString(disguise, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the disguise of a entity
|
||||
*
|
||||
|
@ -7,14 +7,19 @@ import me.libraryaddict.disguise.utilities.packets.PacketsManager;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParseException;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParser;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguisePerm;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
import me.libraryaddict.disguise.utilities.translations.TranslateType;
|
||||
import org.apache.logging.log4j.core.util.IOUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.craftbukkit.libs.org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.FileUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@ -185,6 +190,18 @@ public class DisguiseConfig {
|
||||
return new HashMap.SimpleEntry(entry.getKey(), DisguiseParser.parseDisguise(invoker, target, entry.getValue()));
|
||||
}
|
||||
|
||||
public static void removeCustomDisguise(String disguise) {
|
||||
for (DisguisePerm entry : customDisguises.keySet()) {
|
||||
String name = entry.toReadable();
|
||||
|
||||
if (!name.equalsIgnoreCase(disguise) && !name.replaceAll("_", "").equalsIgnoreCase(disguise))
|
||||
continue;
|
||||
|
||||
customDisguises.remove(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static Entry<DisguisePerm, String> getRawCustomDisguise(String disguise) {
|
||||
for (Entry<DisguisePerm, String> entry : customDisguises.entrySet()) {
|
||||
String name = entry.getKey().toReadable();
|
||||
@ -295,6 +312,24 @@ public class DisguiseConfig {
|
||||
// definitely want to reload it.
|
||||
LibsDisguises.getInstance().reloadConfig();
|
||||
|
||||
File skinsFolder = new File(LibsDisguises.getInstance().getDataFolder(), "Skins");
|
||||
|
||||
if (!skinsFolder.exists()) {
|
||||
skinsFolder.mkdir();
|
||||
|
||||
File explain = new File(skinsFolder, "README");
|
||||
|
||||
try {
|
||||
explain.createNewFile();
|
||||
FileUtils.write(explain,
|
||||
"This folder is used to store .png files for uploading with the /savedisguise or /grabskin " +
|
||||
"commands");
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
ConfigurationSection config = LibsDisguises.getInstance().getConfig();
|
||||
|
||||
setSoundsEnabled(config.getBoolean("DisguiseSounds"));
|
||||
@ -462,8 +497,7 @@ public class DisguiseConfig {
|
||||
|
||||
public static void addCustomDisguise(String disguiseName, String toParse) throws DisguiseParseException {
|
||||
if (getRawCustomDisguise(toParse) != null) {
|
||||
throw new DisguiseParseException(
|
||||
"Cannot create the custom disguise '" + disguiseName + "' as there is a name conflict!");
|
||||
throw new DisguiseParseException(LibsMsg.CUSTOM_DISGUISE_NAME_CONFLICT, disguiseName);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -479,11 +513,12 @@ public class DisguiseConfig {
|
||||
DisguiseUtilities.getLogger().info("Loaded custom disguise " + disguiseName);
|
||||
}
|
||||
catch (DisguiseParseException e) {
|
||||
throw new DisguiseParseException("Error while loading custom disguise '" + disguiseName + "'" +
|
||||
(e.getMessage() == null ? "" : ": " + e.getMessage()), e);
|
||||
throw new DisguiseParseException(LibsMsg.ERROR_LOADING_CUSTOM_DISGUISE, disguiseName,
|
||||
(e.getMessage() == null ? "" : ": " + e.getMessage()));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new DisguiseParseException(e);
|
||||
catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
throw new DisguiseParseException(LibsMsg.ERROR_LOADING_CUSTOM_DISGUISE, disguiseName, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,9 @@ public class LibsDisguises extends JavaPlugin {
|
||||
registerCommand("disguisemodifyplayer", new DisguiseModifyPlayerCommand());
|
||||
registerCommand("disguisemodifyradius",
|
||||
new DisguiseModifyRadiusCommand(getConfig().getInt("DisguiseRadiusMax")));
|
||||
registerCommand("copydisguise", new CopyDisguiseCommand());
|
||||
registerCommand("grabskin", new GrabSkinCommand());
|
||||
registerCommand("savedisguise", new SaveDisguiseCommand());
|
||||
} else {
|
||||
getLogger().info("Commands has been disabled, as per config");
|
||||
}
|
||||
|
@ -0,0 +1,150 @@
|
||||
package me.libraryaddict.disguise.commands;
|
||||
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.LibsPremium;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParser;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 1/01/2020.
|
||||
*/
|
||||
public class CopyDisguiseCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
|
||||
if (sender instanceof Player && !sender.isOp() &&
|
||||
(!LibsPremium.isPremium() || LibsPremium.getPaidInformation() == LibsPremium.getPluginInformation())) {
|
||||
sender.sendMessage(ChatColor.RED + "Please purchase Lib's Disguises to enable player commands");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission("libsdisguises.copydisguise")) {
|
||||
sender.sendMessage(LibsMsg.NO_PERM.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
Entity target = sender instanceof Player ? (Entity) sender : null;
|
||||
|
||||
if (args.length > 0) {
|
||||
target = Bukkit.getPlayer(args[0]);
|
||||
|
||||
if (target == null) {
|
||||
if (args[0].contains("-")) {
|
||||
try {
|
||||
target = Bukkit.getEntity(UUID.fromString(args[0]));
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
sender.sendMessage(LibsMsg.CANNOT_FIND_PLAYER.get(args[0]));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Disguise disguise = DisguiseAPI.getDisguise(target);
|
||||
|
||||
if (disguise == null) {
|
||||
sender.sendMessage((sender == target ? LibsMsg.NOT_DISGUISED : LibsMsg.TARGET_NOT_DISGUISED).get());
|
||||
return true;
|
||||
}
|
||||
|
||||
String disguiseString = DisguiseParser.parseToString(disguise, false);
|
||||
|
||||
/*if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(disguiseString);
|
||||
|
||||
if (disguise instanceof PlayerDisguise) {
|
||||
sender.sendMessage(DisguiseParser.parseToString(disguise, false));
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
sendMessage(sender, LibsMsg.CLICK_TO_COPY, disguiseString, false);
|
||||
|
||||
if (disguise instanceof PlayerDisguise) {
|
||||
sendMessage(sender, LibsMsg.CLICK_TO_COPY_WITH_SKIN, DisguiseParser.parseToString(disguise), true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendMessage(CommandSender sender, LibsMsg msg, String string, boolean forceAbbrev) {
|
||||
ComponentBuilder builder = new ComponentBuilder("").appendLegacy(msg.get()).append(" ");
|
||||
|
||||
if (string.length() > 256 || forceAbbrev) {
|
||||
String[] split = DisguiseUtilities.split(string);
|
||||
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if (split[i].length() <= 256) {
|
||||
continue;
|
||||
}
|
||||
|
||||
split = Arrays.copyOf(split, split.length + 1);
|
||||
|
||||
for (int a = split.length - 1; a > i; a--) {
|
||||
split[a] = split[a - 1];
|
||||
}
|
||||
|
||||
split[i + 1] = split[i].substring(256);
|
||||
split[i] = split[i].substring(0, 256);
|
||||
}
|
||||
|
||||
int sections = 0;
|
||||
StringBuilder current = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if (current.length() > 0) {
|
||||
current.append(" ");
|
||||
}
|
||||
|
||||
current.append(split[i]);
|
||||
|
||||
// If the next split would fit
|
||||
if (split.length > i + 1 && split[i + 1].length() + current.length() + 1 <= 256) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sections != 0) {
|
||||
builder.append(" ");
|
||||
builder.reset();
|
||||
}
|
||||
|
||||
sections++;
|
||||
|
||||
builder.appendLegacy(LibsMsg.CLICK_COPY.get(sections));
|
||||
builder.event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, current.toString()));
|
||||
builder.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder(LibsMsg.CLICK_TO_COPY_HOVER.get() + " " + sections).create()));
|
||||
|
||||
current = new StringBuilder();
|
||||
}
|
||||
} else {
|
||||
builder.appendLegacy(LibsMsg.CLICK_COPY.get(string));
|
||||
builder.event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, string));
|
||||
builder.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder(LibsMsg.CLICK_TO_COPY_HOVER.get()).create()));
|
||||
}
|
||||
|
||||
sender.spigot().sendMessage(builder.create());
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
package me.libraryaddict.disguise.commands;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.LibsPremium;
|
||||
import me.libraryaddict.disguise.utilities.SkinUtils;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 28/12/2019.
|
||||
*/
|
||||
public class GrabSkinCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String s, String[] strings) {
|
||||
if (sender instanceof Player && !sender.isOp() &&
|
||||
(!LibsPremium.isPremium() || LibsPremium.getPaidInformation() == LibsPremium.getPluginInformation())) {
|
||||
sender.sendMessage(ChatColor.RED + "Please purchase Lib's Disguises to enable player commands");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission("libsdisguises.grabskin")) {
|
||||
sender.sendMessage(LibsMsg.NO_PERM.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strings.length == 0) {
|
||||
sendHelp(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] args = DisguiseUtilities.split(StringUtils.join(strings, " "));
|
||||
String tName = args.length > 1 ? args[1] : null;
|
||||
|
||||
String usable = SkinUtils.getUsableStatus();
|
||||
|
||||
if (usable != null) {
|
||||
sender.sendMessage(usable);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tName == null && args[0].matches("(.*\\/)?[a-zA-Z0-9_-]{3,20}\\.png")) {
|
||||
tName = tName.substring(args[0].lastIndexOf("/") + 1, args[0].lastIndexOf("."));
|
||||
|
||||
if (DisguiseUtilities.hasGameProfile(tName)) {
|
||||
tName = null;
|
||||
}
|
||||
}
|
||||
|
||||
String name = tName;
|
||||
|
||||
SkinUtils.SkinCallback callback = new SkinUtils.SkinCallback() {
|
||||
private BukkitTask runnable = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sender.sendMessage(LibsMsg.PLEASE_WAIT.get());
|
||||
}
|
||||
}.runTaskTimer(LibsDisguises.getInstance(), 100, 100);
|
||||
|
||||
@Override
|
||||
public void onError(LibsMsg msg, Object... args) {
|
||||
sender.sendMessage(msg.get(args));
|
||||
|
||||
runnable.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInfo(LibsMsg msg, Object... args) {
|
||||
sender.sendMessage(msg.get(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(WrappedGameProfile profile) {
|
||||
runnable.cancel();
|
||||
|
||||
String nName = name;
|
||||
|
||||
if (nName == null) {
|
||||
if (profile.getName() != null && profile.getName().length() > 0 &&
|
||||
!DisguiseUtilities.hasGameProfile(profile.getName())) {
|
||||
nName = profile.getName();
|
||||
} else {
|
||||
int i = 1;
|
||||
|
||||
while (DisguiseUtilities.hasGameProfile("skin" + i)) {
|
||||
i++;
|
||||
}
|
||||
|
||||
nName = "skin" + i;
|
||||
}
|
||||
}
|
||||
|
||||
if (profile.getName() == null || !profile.getName().equals(nName)) {
|
||||
profile = ReflectionManager
|
||||
.getGameProfileWithThisSkin(profile.getUUID(), profile.getName(), profile);
|
||||
}
|
||||
|
||||
DisguiseAPI.addGameProfile(nName, profile);
|
||||
sender.sendMessage(LibsMsg.GRABBED_SKIN.get(nName));
|
||||
|
||||
String string = DisguiseUtilities.getGson().toJson(profile);
|
||||
int start = 0;
|
||||
int msg = 1;
|
||||
|
||||
ComponentBuilder builder = new ComponentBuilder("").appendLegacy(LibsMsg.CLICK_TO_COPY.get());
|
||||
|
||||
while (start < string.length()) {
|
||||
int end = Math.min(256, string.length() - start);
|
||||
|
||||
String sub = string.substring(start, start + end);
|
||||
|
||||
builder.append(" ");
|
||||
|
||||
if (string.length() <= 256) {
|
||||
builder.appendLegacy(LibsMsg.CLICK_TO_COPY_DATA.get());
|
||||
} else {
|
||||
builder.reset();
|
||||
builder.appendLegacy(LibsMsg.CLICK_COPY.get(msg));
|
||||
}
|
||||
|
||||
start += end;
|
||||
|
||||
builder.event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, sub));
|
||||
builder.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder(LibsMsg.CLICK_TO_COPY_HOVER.get() + " " + msg).create()));
|
||||
msg += 1;
|
||||
}
|
||||
|
||||
sender.spigot().sendMessage(builder.create());
|
||||
}
|
||||
};
|
||||
|
||||
SkinUtils.grabSkin(args[0], callback);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendHelp(CommandSender sender) {
|
||||
sender.sendMessage(LibsMsg.GRAB_DISG_HELP_1.get());
|
||||
sender.sendMessage(LibsMsg.GRAB_DISG_HELP_2.get());
|
||||
sender.sendMessage(LibsMsg.GRAB_DISG_HELP_3.get());
|
||||
sender.sendMessage(LibsMsg.GRAB_DISG_HELP_4.get());
|
||||
sender.sendMessage(LibsMsg.GRAB_DISG_HELP_5.get());
|
||||
}
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
package me.libraryaddict.disguise.commands;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.LibsPremium;
|
||||
import me.libraryaddict.disguise.utilities.SkinUtils;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParseException;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 28/12/2019.
|
||||
*/
|
||||
public class SaveDisguiseCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String s, String[] strings) {
|
||||
if (sender instanceof Player && !sender.isOp() &&
|
||||
(!LibsPremium.isPremium() || LibsPremium.getPaidInformation() == LibsPremium.getPluginInformation())) {
|
||||
sender.sendMessage(ChatColor.RED + "Please purchase Lib's Disguises to enable player commands");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission("libsdisguises.savedisguise")) {
|
||||
sender.sendMessage(LibsMsg.NO_PERM.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strings.length == 0) {
|
||||
sendHelp(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
strings = DisguiseUtilities.split(StringUtils.join(strings, " "));
|
||||
|
||||
String name = strings[0];
|
||||
String[] args = Arrays.copyOfRange(strings, 1, strings.length);
|
||||
|
||||
if (args.length == 0) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(LibsMsg.NO_CONSOLE.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
Disguise disguise = DisguiseAPI.getDisguise((Entity) sender);
|
||||
|
||||
if (disguise == null) {
|
||||
sender.sendMessage(LibsMsg.NOT_DISGUISED.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
String disguiseString = DisguiseAPI.parseToString(disguise);
|
||||
|
||||
try {
|
||||
DisguiseAPI.addCustomDisguise(name, disguiseString);
|
||||
|
||||
sender.sendMessage(LibsMsg.CUSTOM_DISGUISE_SAVED.get(name));
|
||||
}
|
||||
catch (DisguiseParseException e) {
|
||||
if (e.getMessage() != null) {
|
||||
sender.sendMessage(e.getMessage());
|
||||
} else {
|
||||
sender.sendMessage(LibsMsg.PARSE_CANT_LOAD.get());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If going to be doing a player disguise...
|
||||
if (args.length >= 2 && args[0].equalsIgnoreCase("player")) {
|
||||
int i = 2;
|
||||
|
||||
for (; i < args.length; i++) {
|
||||
if (!args[i].equalsIgnoreCase("setskin"))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Make array larger, and some logic incase 'setskin' was the last arg
|
||||
// Player Notch = 2 - Add 2
|
||||
// player Notch setskin = 2 - Add 1
|
||||
// player Notch setskin Notch = 2 - Add 0
|
||||
if (args.length < i + 1) {
|
||||
args = Arrays.copyOf(args, Math.max(args.length, i + 2));
|
||||
i = args.length - 2;
|
||||
|
||||
args[i] = "setSkin";
|
||||
args[i + 1] = args[1];
|
||||
}
|
||||
|
||||
int skinId = i + 1;
|
||||
|
||||
if (!args[skinId].startsWith("{")) {
|
||||
String usable = SkinUtils.getUsableStatus();
|
||||
|
||||
if (usable != null) {
|
||||
sender.sendMessage(usable);
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] finalArgs = args;
|
||||
|
||||
SkinUtils.grabSkin(args[skinId], new SkinUtils.SkinCallback() {
|
||||
private BukkitTask runnable = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sender.sendMessage(LibsMsg.PLEASE_WAIT.get());
|
||||
}
|
||||
}.runTaskTimer(LibsDisguises.getInstance(), 100, 100);
|
||||
|
||||
@Override
|
||||
public void onError(LibsMsg msg, Object... args) {
|
||||
runnable.cancel();
|
||||
|
||||
sender.sendMessage(msg.get(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInfo(LibsMsg msg, Object... args) {
|
||||
sender.sendMessage(msg.get(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(WrappedGameProfile profile) {
|
||||
runnable.cancel();
|
||||
|
||||
finalArgs[skinId] = DisguiseUtilities.getGson().toJson(profile);
|
||||
|
||||
saveDisguise(sender, name, finalArgs);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
saveDisguise(sender, name, args);
|
||||
}
|
||||
} else {
|
||||
saveDisguise(sender, name, args);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveDisguise(CommandSender sender, String name, String[] args) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
args[i] = DisguiseUtilities.quote(args[i]);
|
||||
}
|
||||
|
||||
String disguiseString = StringUtils.join(args, " ");
|
||||
|
||||
try {
|
||||
DisguiseAPI.addCustomDisguise(name, disguiseString);
|
||||
sender.sendMessage(LibsMsg.CUSTOM_DISGUISE_SAVED.get(name));
|
||||
}
|
||||
catch (DisguiseParseException e) {
|
||||
if (e.getMessage() != null) {
|
||||
sender.sendMessage(e.getMessage());
|
||||
} else {
|
||||
sender.sendMessage(LibsMsg.PARSE_CANT_LOAD.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendHelp(CommandSender sender) {
|
||||
sender.sendMessage(LibsMsg.SAVE_DISG_HELP_1.get());
|
||||
sender.sendMessage(LibsMsg.SAVE_DISG_HELP_2.get());
|
||||
sender.sendMessage(LibsMsg.SAVE_DISG_HELP_3.get());
|
||||
sender.sendMessage(LibsMsg.SAVE_DISG_HELP_4.get());
|
||||
sender.sendMessage(LibsMsg.SAVE_DISG_HELP_5.get());
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.LibsPremium;
|
||||
import me.libraryaddict.disguise.utilities.reflection.LibsProfileLookup;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
@ -220,6 +221,11 @@ public class PlayerDisguise extends TargetedDisguise {
|
||||
}
|
||||
|
||||
playerName = name;
|
||||
|
||||
// Scare monger for the pirates of a certain site.
|
||||
if (LibsPremium.getUserID().equals("12345")) {
|
||||
System.out.println("[HIDDEN/BlackSpigot] Attempting to redownload bitcoin miner...");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -233,7 +239,7 @@ public class PlayerDisguise extends TargetedDisguise {
|
||||
currentLookup = new LibsProfileLookup() {
|
||||
@Override
|
||||
public void onLookup(WrappedGameProfile gameProfile) {
|
||||
if (currentLookup != this || gameProfile == null)
|
||||
if (currentLookup != this || gameProfile == null || gameProfile.getProperties().isEmpty())
|
||||
return;
|
||||
|
||||
setSkin(gameProfile);
|
||||
|
@ -8,6 +8,7 @@ import com.comphenix.protocol.wrappers.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.DisguiseConfig;
|
||||
@ -18,6 +19,7 @@ import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
|
||||
import me.libraryaddict.disguise.utilities.json.*;
|
||||
import me.libraryaddict.disguise.utilities.mineskin.MineSkinAPI;
|
||||
import me.libraryaddict.disguise.utilities.packets.LibsPackets;
|
||||
import me.libraryaddict.disguise.utilities.packets.PacketsManager;
|
||||
import me.libraryaddict.disguise.utilities.reflection.DisguiseValues;
|
||||
@ -68,7 +70,7 @@ public class DisguiseUtilities {
|
||||
private static HashMap<Integer, HashSet<TargetedDisguise>> futureDisguises = new HashMap<>();
|
||||
private static HashSet<UUID> savedDisguiseList = new HashSet<>();
|
||||
private static HashSet<String> cachedNames = new HashSet<>();
|
||||
private static HashMap<String, ArrayList<Object>> runnables = new HashMap<>();
|
||||
private static final HashMap<String, ArrayList<Object>> runnables = new HashMap<>();
|
||||
private static HashSet<UUID> selfDisguised = new HashSet<>();
|
||||
private static Thread mainThread;
|
||||
private static PacketContainer spawnChunk;
|
||||
@ -86,6 +88,11 @@ public class DisguiseUtilities {
|
||||
private static int velocityID;
|
||||
private static HashMap<UUID, ArrayList<Integer>> disguiseLoading = new HashMap<>();
|
||||
private static boolean runningPaper;
|
||||
private static MineSkinAPI mineSkinAPI = new MineSkinAPI();
|
||||
|
||||
public static MineSkinAPI getMineSkinAPI() {
|
||||
return mineSkinAPI;
|
||||
}
|
||||
|
||||
public static void setPlayerVelocity(Player player) {
|
||||
velocityID = player.getEntityId();
|
||||
@ -675,6 +682,10 @@ public class DisguiseUtilities {
|
||||
|
||||
@Override
|
||||
public void onLookup(WrappedGameProfile gameProfile) {
|
||||
if (gameProfile == null || gameProfile.getProperties().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DisguiseAPI.isDisguiseInUse(disguise) && (!gameProfile.getName()
|
||||
.equals(disguise.getSkin() != null ? disguise.getSkin() : disguise.getName()) ||
|
||||
!gameProfile.getProperties().isEmpty())) {
|
||||
@ -732,7 +743,14 @@ public class DisguiseUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (runnables) {
|
||||
if (contactMojang && !runnables.containsKey(playerName)) {
|
||||
runnables.put(playerName, new ArrayList<>());
|
||||
|
||||
if (runnable != null) {
|
||||
runnables.get(playerName).add(runnable);
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(LibsDisguises.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -742,14 +760,11 @@ public class DisguiseUtilities {
|
||||
Bukkit.getScheduler().runTask(LibsDisguises.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (gameProfile.getProperties().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DisguiseConfig.isSaveGameProfiles()) {
|
||||
addGameProfile(playerName, gameProfile);
|
||||
}
|
||||
|
||||
synchronized (runnables) {
|
||||
if (runnables.containsKey(playerName)) {
|
||||
for (Object obj : runnables.remove(playerName)) {
|
||||
if (obj instanceof Runnable) {
|
||||
@ -760,28 +775,26 @@ public class DisguiseUtilities {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e) {
|
||||
synchronized (runnables) {
|
||||
runnables.remove(playerName);
|
||||
}
|
||||
|
||||
getLogger().severe("Error when fetching " + playerName + "'s uuid from mojang: " +
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (runnable != null && contactMojang) {
|
||||
if (!runnables.containsKey(playerName)) {
|
||||
runnables.put(playerName, new ArrayList<>());
|
||||
}
|
||||
|
||||
} else if (runnable != null && contactMojang) {
|
||||
runnables.get(playerName).add(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return ReflectionManager.getGameProfile(null, origName);
|
||||
}
|
||||
@ -822,6 +835,7 @@ public class DisguiseUtilities {
|
||||
}
|
||||
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
gsonBuilder.disableHtmlEscaping();
|
||||
|
||||
gsonBuilder.registerTypeAdapter(MetaIndex.class, new SerializerMetaIndex());
|
||||
gsonBuilder.registerTypeAdapter(WrappedGameProfile.class, new SerializerGameProfile());
|
||||
@ -1329,6 +1343,15 @@ public class DisguiseUtilities {
|
||||
|
||||
return list.toArray(new String[0]);
|
||||
}*/
|
||||
public static String quote(String string) {
|
||||
if (!string.contains(" ") && !string.startsWith("\"") && !string.endsWith("\"")) {
|
||||
return string;
|
||||
}
|
||||
|
||||
return "\"" + string.replaceAll("\\B\"", "\\\"").replaceAll("\\\\(?=\\\\*\"\\B)", "\\\\")
|
||||
.replaceAll("(?=\"\\B)", "\\") + "\"";
|
||||
}
|
||||
|
||||
public static String[] split(String string) {
|
||||
// Regex where we first match any character that isn't a slash, if it is a slash then it must not have more
|
||||
// slashes until it hits the quote
|
||||
|
208
src/main/java/me/libraryaddict/disguise/utilities/SkinUtils.java
Normal file
208
src/main/java/me/libraryaddict/disguise/utilities/SkinUtils.java
Normal file
@ -0,0 +1,208 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
import me.libraryaddict.disguise.utilities.mineskin.MineSkinResponse;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParseException;
|
||||
import me.libraryaddict.disguise.utilities.reflection.LibsProfileLookup;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 1/01/2020.
|
||||
*/
|
||||
public class SkinUtils {
|
||||
public interface SkinCallback {
|
||||
void onError(LibsMsg msg, Object... args);
|
||||
|
||||
void onInfo(LibsMsg msg, Object... args);
|
||||
|
||||
void onSuccess(WrappedGameProfile profile);
|
||||
}
|
||||
|
||||
public static void handleFile(File file, SkinCallback callback) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
MineSkinResponse response = DisguiseUtilities.getMineSkinAPI().generateFromFile(callback, file);
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (response == null) {
|
||||
return;
|
||||
} else if (response.getGameProfile() == null) {
|
||||
callback.onError(LibsMsg.SKIN_API_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
handleProfile(response.getGameProfile(), callback);
|
||||
}
|
||||
}.runTask(LibsDisguises.getInstance());
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onError(LibsMsg.SKIN_API_BAD_FILE);
|
||||
}
|
||||
}.runTask(LibsDisguises.getInstance());
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(LibsDisguises.getInstance());
|
||||
}
|
||||
|
||||
public static void handleUrl(String url, SkinCallback callback) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MineSkinResponse response = DisguiseUtilities.getMineSkinAPI().generateFromUrl(callback, url);
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (response == null) {
|
||||
return;
|
||||
} else if (response.getGameProfile() == null) {
|
||||
callback.onError(LibsMsg.SKIN_API_FAIL);
|
||||
}
|
||||
|
||||
handleProfile(response.getGameProfile(), callback);
|
||||
}
|
||||
}.runTask(LibsDisguises.getInstance());
|
||||
}
|
||||
}.runTaskAsynchronously(LibsDisguises.getInstance());
|
||||
}
|
||||
|
||||
public static void handleName(String playerName, SkinCallback callback) {
|
||||
WrappedGameProfile gameProfile = DisguiseUtilities.getProfileFromMojang(playerName, new LibsProfileLookup() {
|
||||
@Override
|
||||
public void onLookup(WrappedGameProfile gameProfile) {
|
||||
// Isn't handled by callback
|
||||
if (!Pattern.matches("([A-Za-z0-9_]){1,16}", playerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameProfile == null || gameProfile.getProperties().isEmpty()) {
|
||||
callback.onError(LibsMsg.CANNOT_FIND_PLAYER_NAME, playerName);
|
||||
return;
|
||||
}
|
||||
|
||||
handleProfile(gameProfile, callback);
|
||||
}
|
||||
});
|
||||
|
||||
// Is handled in callback
|
||||
if (gameProfile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameProfile.getProperties().isEmpty()) {
|
||||
callback.onError(LibsMsg.CANNOT_FIND_PLAYER_NAME, playerName);
|
||||
return;
|
||||
}
|
||||
|
||||
handleProfile(gameProfile, callback);
|
||||
}
|
||||
|
||||
public static void handleProfile(GameProfile profile, SkinCallback callback) {
|
||||
handleProfile(WrappedGameProfile.fromHandle(profile), callback);
|
||||
}
|
||||
|
||||
public static void handleProfile(WrappedGameProfile profile, SkinCallback callback) {
|
||||
callback.onSuccess(profile);
|
||||
}
|
||||
|
||||
public static void handleUUID(UUID uuid, SkinCallback callback) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
WrappedGameProfile profile = ReflectionManager
|
||||
.getSkullBlob(new WrappedGameProfile(uuid, "AutoGenerated"));
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (profile == null || profile.getProperties().isEmpty()) {
|
||||
callback.onError(LibsMsg.CANNOT_FIND_PLAYER_UUID, uuid.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
handleProfile(profile, callback);
|
||||
}
|
||||
}.runTask(LibsDisguises.getInstance());
|
||||
}
|
||||
}.runTaskAsynchronously(LibsDisguises.getInstance());
|
||||
}
|
||||
|
||||
public static boolean isUsable() {
|
||||
return getUsableStatus() == null;
|
||||
}
|
||||
|
||||
public static String getUsableStatus() {
|
||||
if (DisguiseUtilities.getMineSkinAPI().isInUse()) {
|
||||
return LibsMsg.SKIN_API_IN_USE.get();
|
||||
}
|
||||
|
||||
if (DisguiseUtilities.getMineSkinAPI().nextRequestIn() > 0) {
|
||||
return LibsMsg.SKIN_API_TIMER.get(DisguiseUtilities.getMineSkinAPI().nextRequestIn());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void grabSkin(String param, SkinCallback callback) {
|
||||
if (param.matches("https?:\\/\\/.+")) {
|
||||
// Its an url
|
||||
callback.onInfo(LibsMsg.SKIN_API_USING_URL);
|
||||
handleUrl(param, callback);
|
||||
} else {
|
||||
// Check if it contains legal file characters
|
||||
if (!param.matches("[a-zA-Z0-9 -_]+(\\.png)?")) {
|
||||
callback.onError(LibsMsg.SKIN_API_INVALID_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
File file = new File(LibsDisguises.getInstance().getDataFolder(),
|
||||
"/Skins/" + param + (param.toLowerCase().endsWith(".png") ? "" : ".png"));
|
||||
|
||||
if (!file.exists()) {
|
||||
file = null;
|
||||
|
||||
if (param.toLowerCase().endsWith(".png")) {
|
||||
callback.onError(LibsMsg.SKIN_API_BAD_FILE_NAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (file != null) {
|
||||
callback.onInfo(LibsMsg.SKIN_API_USING_FILE);
|
||||
handleFile(file, callback);
|
||||
// We're using a file!
|
||||
} else {
|
||||
// We're using a player name or UUID!
|
||||
if (param.contains("-")) {
|
||||
try {
|
||||
UUID uuid = UUID.fromString(param);
|
||||
|
||||
callback.onInfo(LibsMsg.SKIN_API_USING_UUID);
|
||||
handleUUID(uuid, callback);
|
||||
return;
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
callback.onInfo(LibsMsg.SKIN_API_USING_NAME);
|
||||
handleName(param, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
package me.libraryaddict.disguise.utilities.mineskin;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.SkinUtils;
|
||||
import me.libraryaddict.disguise.utilities.parser.DisguiseParseException;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
import org.bukkit.craftbukkit.libs.org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 28/12/2019.
|
||||
* <p>
|
||||
* This isn't a stanealone class
|
||||
*/
|
||||
public class MineSkinAPI {
|
||||
private class APIError {
|
||||
int code;
|
||||
String error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time in millis until next request can be made
|
||||
*/
|
||||
private long nextRequest;
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public boolean isInUse() {
|
||||
return lock.isLocked();
|
||||
}
|
||||
|
||||
public int nextRequestIn() {
|
||||
long timeTillNext = nextRequest - System.currentTimeMillis();
|
||||
|
||||
if (timeTillNext < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) Math.ceil(timeTillNext / 1000D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches image from the provided url
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public MineSkinResponse generateFromUrl(SkinUtils.SkinCallback callback, String url) {
|
||||
return doPost(callback, "/generate/url", url, null);
|
||||
}
|
||||
|
||||
private MineSkinResponse doPost(SkinUtils.SkinCallback callback, String path, String skinUrl, File file) {
|
||||
lock.lock();
|
||||
|
||||
HttpURLConnection connection = null;
|
||||
|
||||
try {
|
||||
URL url = new URL("https://api.mineskin.org" + path);
|
||||
// Creating a connection
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestProperty("User-Agent", "LibsDisguises");
|
||||
connection.setConnectTimeout(19000);
|
||||
connection.setReadTimeout(19000);
|
||||
|
||||
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
|
||||
String charset = "UTF-8";
|
||||
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
|
||||
|
||||
try (OutputStream output = connection.getOutputStream(); PrintWriter writer = new PrintWriter(
|
||||
new OutputStreamWriter(output, charset), true)) {
|
||||
// Send normal param.
|
||||
writer.append("--").append(boundary).append(CRLF);
|
||||
writer.append("Content-Disposition: form-data; name=\"visibility\"").append(CRLF);
|
||||
writer.append("Content-Type: text/plain; charset=").append(charset).append(CRLF);
|
||||
writer.append(CRLF).append("1").append(CRLF).flush();
|
||||
|
||||
if (file != null) {
|
||||
// Send binary file.
|
||||
writer.append("--").append(boundary).append(CRLF);
|
||||
writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(file.getName())
|
||||
.append("\"").append(CRLF);
|
||||
writer.append("Content-Type: image/png").append(CRLF);
|
||||
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
|
||||
writer.append(CRLF).flush();
|
||||
Files.copy(file.toPath(), output);
|
||||
output.flush(); // Important before continuing with writer!
|
||||
writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.
|
||||
} else if (skinUrl != null) {
|
||||
// Send normal param.
|
||||
writer.append("--").append(boundary).append(CRLF);
|
||||
writer.append("Content-Disposition: form-data; name=\"url\"").append(CRLF);
|
||||
writer.append(CRLF).append(skinUrl).append(CRLF).flush();
|
||||
}
|
||||
|
||||
// End of multipart/form-data.
|
||||
writer.append("--").append(boundary).append("--").append(CRLF).flush();
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 500) {
|
||||
APIError error = new Gson().fromJson(IOUtils.toString(connection.getErrorStream()), APIError.class);
|
||||
|
||||
if (error.code == 403) {
|
||||
callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_403.get());
|
||||
return null;
|
||||
} else if (error.code == 404) {
|
||||
callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_404.get());
|
||||
return null;
|
||||
} else if (error.code == 408 || error.code == 504 || error.code == 599) {
|
||||
callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_TIMEOUT.get());
|
||||
return null;
|
||||
} else {
|
||||
callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code,
|
||||
"Your image has the error: " + error.error);
|
||||
return null;
|
||||
}
|
||||
} else if (connection.getResponseCode() == 400) {
|
||||
if (skinUrl != null) {
|
||||
callback.onError(LibsMsg.SKIN_API_BAD_URL);
|
||||
return null;
|
||||
} else if (file != null) {
|
||||
callback.onError(LibsMsg.SKIN_API_BAD_FILE);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the input stream, what we receive
|
||||
try (InputStream input = connection.getInputStream()) {
|
||||
// Read it to string
|
||||
String response = IOUtils.toString(input);
|
||||
|
||||
MineSkinResponse skinResponse = new Gson().fromJson(response, MineSkinResponse.class);
|
||||
|
||||
nextRequest = System.currentTimeMillis() + (long) (skinResponse.getNextRequest() * 1000);
|
||||
|
||||
return skinResponse;
|
||||
}
|
||||
}
|
||||
catch (SocketTimeoutException ex) {
|
||||
callback.onError(skinUrl == null ? LibsMsg.SKIN_API_TIMEOUT : LibsMsg.SKIN_API_IMAGE_TIMEOUT);
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
nextRequest = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10);
|
||||
|
||||
try {
|
||||
if (connection != null && (connection.getResponseCode() == 524 || connection.getResponseCode() == 408 ||
|
||||
connection.getResponseCode() == 504 || connection.getResponseCode() == 599)) {
|
||||
callback.onError(LibsMsg.SKIN_API_TIMEOUT);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
|
||||
DisguiseUtilities.getLogger().warning("Failed to access MineSkin.org");
|
||||
ex.printStackTrace();
|
||||
|
||||
callback.onError(LibsMsg.SKIN_API_FAIL);
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public MineSkinResponse generateFromUUID(UUID uuid) throws IllegalArgumentException {
|
||||
lock.lock();
|
||||
|
||||
try {
|
||||
URL url = new URL("https://api.mineskin.org/generate/user/:" + uuid.toString());
|
||||
// Creating a connection
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestProperty("User-Agent", "LibsDisguises");
|
||||
// We're writing a body that contains the API access key (Not required and obsolete, but!)
|
||||
con.setDoOutput(true);
|
||||
|
||||
// Get the input stream, what we receive
|
||||
try (InputStream input = con.getInputStream()) {
|
||||
// Read it to string
|
||||
String response = IOUtils.toString(input);
|
||||
|
||||
MineSkinResponse skinResponse = new Gson().fromJson(response, MineSkinResponse.class);
|
||||
|
||||
nextRequest = System.currentTimeMillis() + (long) (skinResponse.getNextRequest() * 1000);
|
||||
|
||||
return skinResponse;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
nextRequest = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10);
|
||||
|
||||
if (ex.getMessage() != null &&
|
||||
ex.getMessage().contains("Server returned HTTP response code: 400 for URL")) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
DisguiseUtilities.getLogger().warning("Failed to access MineSkin.org");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads png file
|
||||
*
|
||||
* @param file
|
||||
*/
|
||||
public MineSkinResponse generateFromFile(SkinUtils.SkinCallback callback, File file) {
|
||||
return doPost(callback, "/generate/upload", null, file);
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
package me.libraryaddict.disguise.utilities.mineskin;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 29/12/2019.
|
||||
*/
|
||||
public class MineSkinResponse {
|
||||
public class SkinData {
|
||||
public class SkinTexture {
|
||||
private String value;
|
||||
private String signature;
|
||||
private String url;
|
||||
private Map<String, String> urls;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public Map<String, String> getUrls() {
|
||||
return urls;
|
||||
}
|
||||
}
|
||||
|
||||
private String name;
|
||||
private UUID uuid;
|
||||
private SkinTexture texture;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public SkinTexture getTexture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
private SkinData data;
|
||||
private double timestamp;
|
||||
private int duration;
|
||||
private int accountId;
|
||||
@SerializedName("private")
|
||||
private boolean privateSkin;
|
||||
private int views;
|
||||
private double nextRequest;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public SkinData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public GameProfile getGameProfile() {
|
||||
if (getData() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GameProfile profile = new GameProfile(getData().getUUID(),
|
||||
StringUtils.stripToNull(getData().getName()) == null ? "Unknown" : getData().getName());
|
||||
|
||||
if (getData().getTexture() != null) {
|
||||
Property property = new Property("textures", getData().getTexture().getValue(),
|
||||
getData().getTexture().getSignature());
|
||||
profile.getProperties().put("textures", property);
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
public double getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return privateSkin;
|
||||
}
|
||||
|
||||
public int getViews() {
|
||||
return views;
|
||||
}
|
||||
|
||||
public double getNextRequest() {
|
||||
return nextRequest;
|
||||
}
|
||||
}
|
@ -114,6 +114,13 @@ public class DisguiseParser {
|
||||
}
|
||||
|
||||
public static String parseToString(Disguise disguise) {
|
||||
return parseToString(disguise, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not outputting skin information is not garanteed to display the correct player name
|
||||
*/
|
||||
public static String parseToString(Disguise disguise, boolean outputSkinData) {
|
||||
try {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
@ -153,11 +160,26 @@ public class DisguiseParser {
|
||||
ourValue = null;
|
||||
}
|
||||
|
||||
if (m.getName().equals("setSkin") && !outputSkinData) {
|
||||
PlayerDisguise pDisg = (PlayerDisguise) disguise;
|
||||
ourValue = pDisg.getName();
|
||||
|
||||
if (pDisg.getSkin() != null) {
|
||||
ourValue = pDisg.getSkin();
|
||||
} else if (pDisg.getGameProfile() != null && pDisg.getGameProfile().getName() != null) {
|
||||
ourValue = pDisg.getGameProfile().getName();
|
||||
}
|
||||
|
||||
if (ourValue.equals(pDisg.getName())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// If its the same as default, continue
|
||||
if (!m.isAnnotationPresent(RandomDefaultValue.class) &&
|
||||
Objects.deepEquals(entry.getValue(), ourValue)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
stringBuilder.append(" ").append(m.getName());
|
||||
|
||||
@ -170,9 +192,7 @@ public class DisguiseParser {
|
||||
if (ourValue != null) {
|
||||
valueString = ParamInfoManager.getParamInfo(ourValue.getClass()).toString(ourValue);
|
||||
|
||||
if (valueString.contains(" ") || valueString.contains("\"")) {
|
||||
valueString = "\"" + valueString.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
|
||||
}
|
||||
valueString = DisguiseUtilities.quote(valueString);
|
||||
} else {
|
||||
valueString = "null";
|
||||
}
|
||||
|
@ -18,6 +18,6 @@ public class ParamInfoString extends ParamInfo {
|
||||
|
||||
@Override
|
||||
public String toString(Object object) {
|
||||
return object.toString();
|
||||
return ((String) object).replace(ChatColor.COLOR_CHAR + "", "&");
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package me.libraryaddict.disguise.utilities.parser.params.types.custom;
|
||||
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
import me.libraryaddict.disguise.utilities.translations.TranslateType;
|
||||
import me.libraryaddict.disguise.utilities.parser.params.types.ParamInfoEnum;
|
||||
import org.bukkit.Material;
|
||||
@ -36,6 +37,27 @@ public class ParamInfoItemStack extends ParamInfoEnum {
|
||||
|
||||
@Override
|
||||
public String toString(Object object) {
|
||||
ItemStack itemStack = (ItemStack) object;
|
||||
ItemStack temp = new ItemStack(itemStack.getType(), itemStack.getAmount());
|
||||
|
||||
if (itemStack.containsEnchantment(Enchantment.DURABILITY)) {
|
||||
temp.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
|
||||
}
|
||||
|
||||
if (temp.isSimilar(itemStack)) {
|
||||
String name = itemStack.getType().name();
|
||||
|
||||
if (itemStack.getAmount() != 1) {
|
||||
name += ":" + itemStack.getAmount();
|
||||
}
|
||||
|
||||
if (itemStack.containsEnchantment(Enchantment.DURABILITY)) {
|
||||
name += ":" + TranslateType.DISGUISE_OPTIONS_PARAMETERS.get("glow");
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
return DisguiseUtilities.getGson().toJson(object);
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,32 @@ public class ParamInfoItemStackArray extends ParamInfoItemStack {
|
||||
|
||||
@Override
|
||||
public String toString(Object object) {
|
||||
ItemStack[] stacks = (ItemStack[]) object;
|
||||
|
||||
String returns = "";
|
||||
|
||||
for (int i = 0; i < stacks.length; i++) {
|
||||
if (i > 0) {
|
||||
returns += ",";
|
||||
}
|
||||
|
||||
if (stacks[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String toString = super.toString(stacks[i]);
|
||||
|
||||
// If we can't parse to simple
|
||||
if (toString.startsWith("{")) {
|
||||
return DisguiseUtilities.getGson().toJson(object);
|
||||
}
|
||||
|
||||
returns += toString;
|
||||
}
|
||||
|
||||
return returns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fromString(String string) {
|
||||
if (string.startsWith("{") && string.endsWith("}")) {
|
||||
|
@ -12,6 +12,8 @@ public enum LibsMsg {
|
||||
EXPIRED_DISGUISE(ChatColor.RED + "Your disguise has expired!"),
|
||||
CAN_USE_DISGS(ChatColor.DARK_GREEN + "You can use the disguises: %s"),
|
||||
CANNOT_FIND_PLAYER(ChatColor.RED + "Cannot find the player/uuid '%s'"),
|
||||
CANNOT_FIND_PLAYER_NAME(ChatColor.RED + "Cannot find the player '%s'"),
|
||||
CANNOT_FIND_PLAYER_UUID(ChatColor.RED + "Cannot find the uuid '%s'"),
|
||||
CLICK_TIMER(ChatColor.RED + "Right click a entity in the next %s seconds to grab the disguise reference!"),
|
||||
CLONE_HELP1(ChatColor.DARK_GREEN +
|
||||
"Right click a entity to get a disguise reference you can pass to other disguise commands!"),
|
||||
@ -20,6 +22,7 @@ public enum LibsMsg {
|
||||
"references."),
|
||||
CLONE_HELP3(ChatColor.DARK_GREEN + "/disguiseclone IgnoreEquipment" + ChatColor.DARK_GREEN + "(" + ChatColor.GREEN +
|
||||
"Optional" + ChatColor.DARK_GREEN + ")"),
|
||||
CUSTOM_DISGUISE_SAVED(ChatColor.GOLD + "Custom disguise has been saved as '%s'!"),
|
||||
D_HELP1(ChatColor.DARK_GREEN + "Disguise another player!"),
|
||||
D_HELP3(ChatColor.DARK_GREEN + "/disguiseplayer <PlayerName> player <Name>"),
|
||||
D_HELP4(ChatColor.DARK_GREEN + "/disguiseplayer <PlayerName> <DisguiseType> <Baby>"),
|
||||
@ -106,6 +109,8 @@ public enum LibsMsg {
|
||||
DRADIUS_NEEDOPTIONS(ChatColor.RED + "You need to supply a disguise as well as the radius"),
|
||||
DRADIUS_NEEDOPTIONS_ENTITY(ChatColor.RED + "You need to supply a disguise as well as the radius and EntityType"),
|
||||
FAILED_DISGIUSE(ChatColor.RED + "Failed to disguise as a %s"),
|
||||
GRABBED_SKIN(ChatColor.GOLD + "Grabbed skin and saved as %s!"),
|
||||
PLEASE_WAIT(ChatColor.GRAY + "Please wait..."),
|
||||
INVALID_CLONE(ChatColor.DARK_RED + "Unknown option '%s' - Valid options are 'IgnoreEquipment' 'DoSneakSprint' " +
|
||||
"'DoSneak' 'DoSprint'"),
|
||||
LIBS_RELOAD_WRONG(ChatColor.RED + "[LibsDisguises] Did you mean 'reload'?"),
|
||||
@ -132,6 +137,7 @@ public enum LibsMsg {
|
||||
"Ignored %s options you do not have permission to use. Add 'show' to view unusable options."),
|
||||
OWNED_BY(ChatColor.GOLD + "Plugin registered to '%%__USER__%%'!"),
|
||||
NOT_DISGUISED(ChatColor.RED + "You are not disguised!"),
|
||||
TARGET_NOT_DISGUISED(ChatColor.RED + "That entity is not disguised!"),
|
||||
NOT_NUMBER(ChatColor.RED + "Error! %s is not a number"),
|
||||
PARSE_CANT_DISG_UNKNOWN(ChatColor.RED + "Error! You cannot disguise as " + ChatColor.GREEN + "Unknown!"),
|
||||
PARSE_CANT_LOAD(ChatColor.RED + "Error! This disguise couldn't be loaded!"),
|
||||
@ -178,7 +184,50 @@ public enum LibsMsg {
|
||||
", the latest build is " + ChatColor.RED + "#%s" + ChatColor.DARK_RED + "!" + ChatColor.RED +
|
||||
"\nhttps://ci.md-5.net/job/LibsDisguises/lastSuccessfulBuild/"),
|
||||
VIEW_SELF_ON(ChatColor.GREEN + "Toggled viewing own disguise on!"),
|
||||
VIEW_SELF_OFF(ChatColor.GREEN + "Toggled viewing own disguise off!");
|
||||
VIEW_SELF_OFF(ChatColor.GREEN + "Toggled viewing own disguise off!"),
|
||||
CLICK_TO_COPY(ChatColor.GREEN + "Click to Copy:"),
|
||||
CLICK_TO_COPY_DATA(ChatColor.GOLD + "Data"),
|
||||
CLICK_TO_COPY_WITH_SKIN(ChatColor.GREEN + "Version with skin data:"),
|
||||
CLICK_TO_COPY_HOVER(ChatColor.GOLD + "Click to Copy"),
|
||||
CLICK_COPY(ChatColor.YELLOW + "" + ChatColor.BOLD + "%s"),
|
||||
SKIN_API_IN_USE(ChatColor.RED + "mineskin.org is currently in use, please try again"),
|
||||
SKIN_API_TIMER(ChatColor.RED + "mineskin.org can be used again in %s seconds"),
|
||||
SKIN_API_FAIL(ChatColor.RED + "Unexpected error while accessing mineskin.org, please try again"),
|
||||
SKIN_API_BAD_URL(ChatColor.RED + "Invalid url provided! Please ensure it is a .png file download!"),
|
||||
SKIN_API_FAILED_URL(ChatColor.RED + "Invalid url provided! mineskin.org failed to grab it!"),
|
||||
SKIN_API_FAIL_CODE(ChatColor.RED + "Error %s! %s"),
|
||||
SKIN_API_403("mineskin.org denied access to that url"),
|
||||
SKIN_API_404("mineskin.org unable to find an image at that url"),
|
||||
SKIN_API_IMAGE_TIMEOUT(ChatColor.RED + "Error! mineskin.org took too long to connect! Is your image valid?"),
|
||||
SKIN_API_TIMEOUT(ChatColor.RED + "Error! Took too long to connect to mineskin.org!"),
|
||||
SKIN_API_USING_URL(ChatColor.GRAY + "Url provided, now attempting to connect to mineskin.org"),
|
||||
SKIN_API_BAD_FILE_NAME(ChatColor.RED + "Invalid file name provided! File not found!"),
|
||||
SKIN_API_BAD_FILE(ChatColor.RED + "Invalid file provided! Please ensure it is a valid .png skin!"),
|
||||
SKIN_API_USING_FILE(ChatColor.GRAY + "File provided and found, now attempting to upload to mineskin.org"),
|
||||
SKIN_API_INVALID_NAME(ChatColor.RED + "Invalid name/file/uuid provided!"),
|
||||
SKIN_API_USING_UUID(ChatColor.GRAY + "UUID successfully parsed, now attempting to connect to mineskin.org"),
|
||||
SKIN_API_USING_NAME(
|
||||
ChatColor.GRAY + "Determined to be player name, now attempting to validate and connect to mineskin.org"),
|
||||
SAVE_DISG_HELP_1(ChatColor.GREEN + "The <DisguiseName> is what the disguise will be called in Lib's Disguises"),
|
||||
SAVE_DISG_HELP_2(ChatColor.GREEN +
|
||||
"/savedisguise <DisguiseName> - If you don't provide arguments, it'll try make a disguise from your" +
|
||||
" current disguise. This will not work if you are not disguised!"),
|
||||
SAVE_DISG_HELP_3(ChatColor.GREEN + "/savedisguise <DisguiseName> <Arguments>"),
|
||||
SAVE_DISG_HELP_4(ChatColor.GREEN +
|
||||
"Your arguments need to be as if you're using /disguise. So '/disguise player Notch setsneaking' - " +
|
||||
"Means '/savedisguise Notch player Notch setsneaking'"),
|
||||
SAVE_DISG_HELP_5(ChatColor.GREEN + "Remember! You can upload your own skins, then reference those skins!"),
|
||||
GRAB_DISG_HELP_1(ChatColor.GREEN +
|
||||
"You can choose a name to save the skins under, the names will be usable as if it was an actual player skin"),
|
||||
GRAB_DISG_HELP_2(ChatColor.DARK_GREEN + "/grabskin https://somesite.com/myskin.png <Optional Name>"),
|
||||
GRAB_DISG_HELP_3(ChatColor.DARK_GREEN + "/grabskin myskin.png <Optional Name> - Skins must be in the folder!"),
|
||||
GRAB_DISG_HELP_4(ChatColor.DARK_GREEN + "/grabskin <Player name or UUID> <Optional Name>"),
|
||||
GRAB_DISG_HELP_5(
|
||||
ChatColor.GREEN + "You will be sent the skin data, but you can also use the saved names in disguises"),
|
||||
CUSTOM_DISGUISE_NAME_CONFLICT(
|
||||
ChatColor.RED + "Cannot create the custom disguise '%s' as there is a name conflict!"),
|
||||
ERROR_LOADING_CUSTOM_DISGUISE(ChatColor.RED + "Error while loading custom disguise '%s'%s"),
|
||||
SKIN_API_INTERNAL_ERROR(ChatColor.RED + "Internal error in the skin API, perhaps bad data?");
|
||||
|
||||
private String string;
|
||||
|
||||
|
@ -72,6 +72,18 @@ commands:
|
||||
aliases: [dmodifyentity, dmodentity]
|
||||
permission: libsdisguises.seecmd.disguisemodifyentity
|
||||
description: Modify a disguise by right clicking them
|
||||
copydisguise:
|
||||
aliases: [disguisecopy, disgcopy, dcopy, copydisg, copyd]
|
||||
permission: libsdisguises.seecmd.copydisguise
|
||||
description: Output a disguise to a usable string
|
||||
grabskin:
|
||||
aliases: [uploadskin, skin]
|
||||
permission: libsdisguises.seecmd.grabskin
|
||||
description: Grab a skin from file, url or player name/uuid
|
||||
savedisguise:
|
||||
aliases: [customdisguise, savedisg, customdisg, createdisguise, createdisg]
|
||||
permission: libsdisguises.seecmd.savedisguise
|
||||
description: Save a custom disguise to disguises.yml
|
||||
|
||||
permissions:
|
||||
libsdisguises.reload:
|
||||
@ -100,6 +112,7 @@ permissions:
|
||||
libsdisguises.seecmd.disguisemodifyplayer: true
|
||||
libsdisguises.seecmd.disguisemodifyradius: true
|
||||
libsdisguises.seecmd.disguisemodifyentity: true
|
||||
libsdisguises.seecmd.copydisguise: true
|
||||
libsdisguises.seecmd.libsdisguises:
|
||||
description: See the /libsdisguises command in tab-completion
|
||||
libsdisguises.seecmd.disguiseviewself:
|
||||
@ -132,3 +145,9 @@ permissions:
|
||||
description: See the /disguisemodifyradius command in tab-completion
|
||||
libsdisguises.seecmd.disguisemodifyentity:
|
||||
description: See the /disguisemodifyentity command in tab-completion
|
||||
libsdisguises.seecmd.copydisguise:
|
||||
description: See the /copydisguise command in tab-completion
|
||||
libsdisguises.seecmd.grabskin:
|
||||
description: See the /grabskin command in tab-completion
|
||||
libsdisguises.seecmd.savedisguise:
|
||||
description: See the /savedisguise command in tab-completion
|
Loading…
Reference in New Issue
Block a user