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:
libraryaddict 2020-01-02 17:10:36 +13:00
parent da6f98a3d7
commit c073af37e8
17 changed files with 1355 additions and 57 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,55 +743,57 @@ public class DisguiseUtilities {
}
}
if (contactMojang && !runnables.containsKey(playerName)) {
Bukkit.getScheduler().runTaskAsynchronously(LibsDisguises.getInstance(), new Runnable() {
@Override
public void run() {
try {
final WrappedGameProfile gameProfile = lookupGameProfile(origName);
synchronized (runnables) {
if (contactMojang && !runnables.containsKey(playerName)) {
runnables.put(playerName, new ArrayList<>());
Bukkit.getScheduler().runTask(LibsDisguises.getInstance(), new Runnable() {
@Override
public void run() {
if (gameProfile.getProperties().isEmpty()) {
return;
}
if (runnable != null) {
runnables.get(playerName).add(runnable);
}
if (DisguiseConfig.isSaveGameProfiles()) {
addGameProfile(playerName, gameProfile);
}
Bukkit.getScheduler().runTaskAsynchronously(LibsDisguises.getInstance(), new Runnable() {
@Override
public void run() {
try {
final WrappedGameProfile gameProfile = lookupGameProfile(origName);
if (runnables.containsKey(playerName)) {
for (Object obj : runnables.remove(playerName)) {
if (obj instanceof Runnable) {
((Runnable) obj).run();
} else if (obj instanceof LibsProfileLookup) {
((LibsProfileLookup) obj).onLookup(gameProfile);
Bukkit.getScheduler().runTask(LibsDisguises.getInstance(), new Runnable() {
@Override
public void run() {
if (DisguiseConfig.isSaveGameProfiles()) {
addGameProfile(playerName, gameProfile);
}
synchronized (runnables) {
if (runnables.containsKey(playerName)) {
for (Object obj : runnables.remove(playerName)) {
if (obj instanceof Runnable) {
((Runnable) obj).run();
} else if (obj instanceof LibsProfileLookup) {
((LibsProfileLookup) obj).onLookup(gameProfile);
}
}
}
}
}
});
}
catch (Exception e) {
synchronized (runnables) {
runnables.remove(playerName);
}
});
getLogger().severe("Error when fetching " + playerName + "'s uuid from mojang: " +
e.getMessage());
}
}
catch (Exception e) {
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 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

View 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);
}
}
}
}

View File

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

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

View File

@ -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,10 +160,25 @@ public class DisguiseParser {
ourValue = null;
}
// If its the same as default, continue
if (!m.isAnnotationPresent(RandomDefaultValue.class) &&
Objects.deepEquals(entry.getValue(), ourValue)) {
continue;
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";
}

View File

@ -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 + "", "&");
}
}

View File

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

View File

@ -39,7 +39,30 @@ public class ParamInfoItemStackArray extends ParamInfoItemStack {
@Override
public String toString(Object object) {
return DisguiseUtilities.getGson().toJson(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

View File

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

View File

@ -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:
@ -131,4 +144,10 @@ permissions:
libsdisguises.seecmd.disguisemodifyradius:
description: See the /disguisemodifyradius command in tab-completion
libsdisguises.seecmd.disguisemodifyentity:
description: See the /disguisemodifyentity command in tab-completion
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