- Changed entire project to gradle
- Updated for 1.8.3 - No more errors, woo
This commit is contained in:
@@ -0,0 +1,736 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.AnimalColor;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MobDisguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.RabbitType;
|
||||
import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
public abstract class BaseDisguiseCommand implements CommandExecutor {
|
||||
|
||||
public class DisguiseParseException extends Exception {
|
||||
private static final long serialVersionUID = 1276971370793124510L;
|
||||
|
||||
public DisguiseParseException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DisguiseParseException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected ArrayList<String> getAllowedDisguises(HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> hashMap) {
|
||||
ArrayList<String> allowedDisguises = new ArrayList<String>();
|
||||
for (DisguiseType type : hashMap.keySet()) {
|
||||
allowedDisguises.add(type.toReadable().replace(" ", "_"));
|
||||
}
|
||||
Collections.sort(allowedDisguises, String.CASE_INSENSITIVE_ORDER);
|
||||
return allowedDisguises;
|
||||
}
|
||||
|
||||
protected HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> getPermissions(CommandSender sender) {
|
||||
return getPermissions(sender, "libsdisguises." + getClass().getSimpleName().replace("Command", "").toLowerCase() + ".");
|
||||
}
|
||||
|
||||
protected HashMap<String, Boolean> getDisguisePermission(CommandSender sender, DisguiseType type) {
|
||||
switch (type) {
|
||||
case PLAYER:
|
||||
case FALLING_BLOCK:
|
||||
case PAINTING:
|
||||
case SPLASH_POTION:
|
||||
case FISHING_HOOK:
|
||||
case DROPPED_ITEM:
|
||||
HashMap<String, Boolean> returns = new HashMap<String, Boolean>();
|
||||
String beginning = "libsdisguises.options." + getClass().getSimpleName().toLowerCase().replace("command", "") + ".";
|
||||
for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) {
|
||||
String lowerPerm = permission.getPermission().toLowerCase();
|
||||
if (lowerPerm.startsWith(beginning)) {
|
||||
String[] split = lowerPerm.substring(beginning.length()).split("\\.");
|
||||
if (split.length > 1) {
|
||||
if (split[0].replace("_", "").equals(type.name().toLowerCase().replace("_", ""))) {
|
||||
for (int i = 1; i < split.length; i++) {
|
||||
returns.put(split[i], permission.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returns;
|
||||
default:
|
||||
return new HashMap<String, Boolean>();
|
||||
}
|
||||
}
|
||||
|
||||
protected Method[] getDisguiseWatcherMethods(Class<? extends FlagWatcher> watcherClass) {
|
||||
Method[] methods = watcherClass.getMethods();
|
||||
methods = Arrays.copyOf(methods, methods.length + 4);
|
||||
int i = 4;
|
||||
for (String methodName : new String[] { "setViewSelfDisguise", "setHideHeldItemFromSelf", "setHideArmorFromSelf",
|
||||
"setHearSelfDisguise" }) {
|
||||
try {
|
||||
methods[methods.length - i--] = Disguise.class.getMethod(methodName, boolean.class);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get perms for the node. Returns a hashmap of allowed disguisetypes and their options
|
||||
*/
|
||||
protected HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> getPermissions(CommandSender sender,
|
||||
String permissionNode) {
|
||||
|
||||
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> singleDisguises = new HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>>();
|
||||
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> rangeDisguises = new HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>>();
|
||||
HashMap<String, Boolean> perms = new HashMap<String, Boolean>();
|
||||
|
||||
for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) {
|
||||
String perm = permission.getPermission().toLowerCase();
|
||||
if (perm.startsWith(permissionNode) && (!perms.containsKey(perm) || !permission.getValue())) {
|
||||
perms.put(perm, permission.getValue());
|
||||
}
|
||||
}
|
||||
if (!perms.containsKey(permissionNode + "*") && sender.hasPermission(permissionNode + "*")) {
|
||||
perms.put(permissionNode + "*", true);
|
||||
}
|
||||
if (!perms.containsKey(permissionNode + "*.*") && sender.hasPermission(permissionNode + "*.*")) {
|
||||
perms.put(permissionNode + "*.*", true);
|
||||
}
|
||||
|
||||
for (String perm : perms.keySet()) {
|
||||
if (perms.get(perm)) {
|
||||
perm = perm.substring(permissionNode.length());
|
||||
String disguiseType = perm.split("\\.")[0];
|
||||
DisguiseType dType = null;
|
||||
for (DisguiseType t : DisguiseType.values()) {
|
||||
if (t.name().replace("_", "").equalsIgnoreCase(disguiseType.replace("_", ""))) {
|
||||
dType = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dType != null) {
|
||||
HashMap<ArrayList<String>, Boolean> list;
|
||||
if (singleDisguises.containsKey(dType)) {
|
||||
list = singleDisguises.get(dType);
|
||||
} else {
|
||||
list = new HashMap<ArrayList<String>, Boolean>();
|
||||
singleDisguises.put(dType, list);
|
||||
}
|
||||
HashMap<ArrayList<String>, Boolean> map1 = getOptions(perm);
|
||||
list.put(map1.keySet().iterator().next(), map1.values().iterator().next());
|
||||
} else {
|
||||
for (DisguiseType type : DisguiseType.values()) {
|
||||
HashMap<ArrayList<String>, Boolean> options = null;
|
||||
Class entityClass = type.getEntityClass();
|
||||
if (disguiseType.equals("mob")) {
|
||||
if (type.isMob()) {
|
||||
options = getOptions(perm);
|
||||
}
|
||||
} else if (disguiseType.equals("animal") || disguiseType.equals("animals")) {
|
||||
if (Animals.class.isAssignableFrom(entityClass)) {
|
||||
options = getOptions(perm);
|
||||
}
|
||||
} else if (disguiseType.equals("monster") || disguiseType.equals("monsters")) {
|
||||
if (Monster.class.isAssignableFrom(entityClass)) {
|
||||
options = getOptions(perm);
|
||||
}
|
||||
} else if (disguiseType.equals("misc")) {
|
||||
if (type.isMisc()) {
|
||||
options = getOptions(perm);
|
||||
}
|
||||
} else if (disguiseType.equals("ageable")) {
|
||||
if (Ageable.class.isAssignableFrom(entityClass)) {
|
||||
options = getOptions(perm);
|
||||
}
|
||||
} else if (disguiseType.equals("*")) {
|
||||
options = getOptions(perm);
|
||||
}
|
||||
if (options != null) {
|
||||
HashMap<ArrayList<String>, Boolean> list;
|
||||
if (rangeDisguises.containsKey(type)) {
|
||||
list = rangeDisguises.get(type);
|
||||
} else {
|
||||
list = new HashMap<ArrayList<String>, Boolean>();
|
||||
rangeDisguises.put(type, list);
|
||||
}
|
||||
HashMap<ArrayList<String>, Boolean> map1 = getOptions(perm);
|
||||
list.put(map1.keySet().iterator().next(), map1.values().iterator().next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String perm : perms.keySet()) {
|
||||
if (!perms.get(perm)) {
|
||||
perm = perm.substring(permissionNode.length());
|
||||
String disguiseType = perm.split("\\.")[0];
|
||||
DisguiseType dType = null;
|
||||
for (DisguiseType t : DisguiseType.values()) {
|
||||
if (t.name().replace("_", "").equalsIgnoreCase(disguiseType.replace("_", ""))) {
|
||||
dType = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dType != null) {
|
||||
singleDisguises.remove(dType);
|
||||
rangeDisguises.remove(dType);
|
||||
} else {
|
||||
for (DisguiseType type : DisguiseType.values()) {
|
||||
boolean foundHim = false;
|
||||
Class entityClass = type.getEntityClass();
|
||||
if (disguiseType.equals("mob")) {
|
||||
if (type.isMob()) {
|
||||
foundHim = true;
|
||||
}
|
||||
} else if (disguiseType.equals("animal") || disguiseType.equals("animals")) {
|
||||
if (Animals.class.isAssignableFrom(entityClass)) {
|
||||
foundHim = true;
|
||||
}
|
||||
} else if (disguiseType.equals("monster") || disguiseType.equals("monsters")) {
|
||||
if (Monster.class.isAssignableFrom(entityClass)) {
|
||||
foundHim = true;
|
||||
}
|
||||
} else if (disguiseType.equals("misc")) {
|
||||
if (type.isMisc()) {
|
||||
foundHim = true;
|
||||
}
|
||||
} else if (disguiseType.equals("ageable")) {
|
||||
if (Ageable.class.isAssignableFrom(entityClass)) {
|
||||
foundHim = true;
|
||||
}
|
||||
} else if (disguiseType.equals("*")) {
|
||||
foundHim = true;
|
||||
}
|
||||
if (foundHim) {
|
||||
rangeDisguises.remove(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map = new HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>>();
|
||||
for (DisguiseType type : DisguiseType.values()) {
|
||||
HashMap<ArrayList<String>, Boolean> temp = new HashMap<ArrayList<String>, Boolean>();
|
||||
if (singleDisguises.containsKey(type)) {
|
||||
temp.putAll(singleDisguises.get(type));
|
||||
}
|
||||
if (rangeDisguises.containsKey(type)) {
|
||||
temp.putAll(rangeDisguises.get(type));
|
||||
}
|
||||
if (!temp.isEmpty()) {
|
||||
map.put(type, temp);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private HashMap<ArrayList<String>, Boolean> getOptions(String perm) {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
boolean isRemove = true;
|
||||
String[] split = perm.split("\\.");
|
||||
for (int i = 1; i < split.length; i++) {
|
||||
String option = split[i];
|
||||
boolean value = option.startsWith("-");
|
||||
if (value) {
|
||||
option = option.substring(1);
|
||||
isRemove = false;
|
||||
}
|
||||
if (option.equals("baby"))
|
||||
option = "setbaby";
|
||||
list.add(option);
|
||||
}
|
||||
HashMap<ArrayList<String>, Boolean> options = new HashMap<ArrayList<String>, Boolean>();
|
||||
options.put(list, isRemove);
|
||||
return options;
|
||||
}
|
||||
|
||||
protected boolean isDouble(String string) {
|
||||
try {
|
||||
Float.parseFloat(string);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isNumeric(String string) {
|
||||
try {
|
||||
Integer.parseInt(string);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the disguise if it all parsed correctly. Returns a exception with a complete message if it didn't. The
|
||||
* commandsender is purely used for checking permissions. Would defeat the purpose otherwise. To reach this point, the
|
||||
* disguise has been feed a proper disguisetype.
|
||||
*/
|
||||
protected Disguise parseDisguise(CommandSender sender, String[] args,
|
||||
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) throws DisguiseParseException,
|
||||
IllegalAccessException, InvocationTargetException {
|
||||
if (map.isEmpty()) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this command.");
|
||||
}
|
||||
if (args.length == 0) {
|
||||
sendCommandUsage(sender, map);
|
||||
throw new DisguiseParseException();
|
||||
}
|
||||
// How many args to skip due to the disugise being constructed
|
||||
// Time to start constructing the disguise.
|
||||
// We will need to check between all 3 kinds of disguises
|
||||
int toSkip = 1;
|
||||
ArrayList<String> usedOptions = new ArrayList<String>();
|
||||
Disguise disguise = null;
|
||||
HashMap<ArrayList<String>, Boolean> optionPermissions;
|
||||
if (args[0].startsWith("@")) {
|
||||
if (sender.hasPermission("libsdisguises.disguise.disguiseclone")) {
|
||||
disguise = DisguiseUtilities.getClonedDisguise(args[0].toLowerCase());
|
||||
if (disguise == null) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "Cannot find a disguise under the reference " + args[0]);
|
||||
}
|
||||
} else {
|
||||
throw new DisguiseParseException(ChatColor.RED + "You do not have perimssion to use disguise references!");
|
||||
}
|
||||
optionPermissions = (map.containsKey(disguise.getType()) ? map.get(disguise.getType())
|
||||
: new HashMap<ArrayList<String>, Boolean>());
|
||||
} else {
|
||||
DisguiseType disguiseType = null;
|
||||
if (args[0].equalsIgnoreCase("p")) {
|
||||
disguiseType = DisguiseType.PLAYER;
|
||||
} else {
|
||||
for (DisguiseType type : DisguiseType.values()) {
|
||||
if (args[0].equalsIgnoreCase(type.name()) || args[0].equalsIgnoreCase(type.name().replace("_", ""))) {
|
||||
disguiseType = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (disguiseType == null) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "Error! The disguise " + ChatColor.GREEN + args[0]
|
||||
+ ChatColor.RED + " doesn't exist!");
|
||||
}
|
||||
if (disguiseType.getEntityType() == null) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "Error! This version of minecraft does not have that disguise!");
|
||||
}
|
||||
if (!map.containsKey(disguiseType)) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this disguise.");
|
||||
}
|
||||
optionPermissions = map.get(disguiseType);
|
||||
HashMap<String, Boolean> disguiseOptions = this.getDisguisePermission(sender, disguiseType);
|
||||
if (disguiseType.isPlayer()) {// If he is doing a player disguise
|
||||
if (args.length == 1) {
|
||||
// He needs to give the player name
|
||||
throw new DisguiseParseException(ChatColor.RED + "Error! You need to give a player name!");
|
||||
} else {
|
||||
if (!disguiseOptions.isEmpty()
|
||||
&& (!disguiseOptions.containsKey(args[1].toLowerCase()) || !disguiseOptions
|
||||
.get(args[1].toLowerCase()))) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "Error! You don't have permission to use that name!");
|
||||
}
|
||||
// Construct the player disguise
|
||||
disguise = new PlayerDisguise(ChatColor.translateAlternateColorCodes('&', args[1]));
|
||||
toSkip++;
|
||||
}
|
||||
} else {
|
||||
if (disguiseType.isMob()) { // Its a mob, use the mob constructor
|
||||
boolean adult = true;
|
||||
if (args.length > 1) {
|
||||
if (args[1].equalsIgnoreCase("baby") || args[1].equalsIgnoreCase("adult")) {
|
||||
usedOptions.add("setbaby");
|
||||
doCheck(optionPermissions, usedOptions);
|
||||
adult = args[1].equalsIgnoreCase("adult");
|
||||
toSkip++;
|
||||
}
|
||||
}
|
||||
disguise = new MobDisguise(disguiseType, adult);
|
||||
} else if (disguiseType.isMisc()) {
|
||||
// Its a misc, we are going to use the MiscDisguise constructor.
|
||||
int miscId = -1;
|
||||
int miscData = -1;
|
||||
String secondArg = null;
|
||||
if (args.length > 1) {
|
||||
// They have defined more arguements!
|
||||
// If the first arg is a number
|
||||
if (args[1].contains(":")) {
|
||||
String[] split = args[1].split(":");
|
||||
if (isNumeric(split[1])) {
|
||||
secondArg = split[1];
|
||||
}
|
||||
args[1] = split[0];
|
||||
}
|
||||
if (isNumeric(args[1])) {
|
||||
miscId = Integer.parseInt(args[1]);
|
||||
} else {
|
||||
if (disguiseType == DisguiseType.FALLING_BLOCK || disguiseType == DisguiseType.DROPPED_ITEM) {
|
||||
for (Material mat : Material.values()) {
|
||||
if (mat.name().replace("_", "").equalsIgnoreCase(args[1].replace("_", ""))) {
|
||||
miscId = mat.getId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (miscId != -1) {
|
||||
switch (disguiseType) {
|
||||
case PAINTING:
|
||||
case FALLING_BLOCK:
|
||||
case SPLASH_POTION:
|
||||
case DROPPED_ITEM:
|
||||
case FISHING_HOOK:
|
||||
case ARROW:
|
||||
case SMALL_FIREBALL:
|
||||
case FIREBALL:
|
||||
case WITHER_SKULL:
|
||||
break;
|
||||
default:
|
||||
throw new DisguiseParseException(ChatColor.RED + "Error! " + disguiseType.toReadable()
|
||||
+ " doesn't know what to do with " + args[1] + "!");
|
||||
}
|
||||
toSkip++;
|
||||
// If they also defined a data value
|
||||
if (args.length > 2 && secondArg == null && isNumeric(args[2])) {
|
||||
secondArg = args[2];
|
||||
toSkip++;
|
||||
}
|
||||
if (secondArg != null) {
|
||||
if (disguiseType != DisguiseType.FALLING_BLOCK && disguiseType != DisguiseType.DROPPED_ITEM) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "Error! Only the disguises "
|
||||
+ DisguiseType.FALLING_BLOCK.toReadable() + " and "
|
||||
+ DisguiseType.DROPPED_ITEM.toReadable() + " uses a second number!");
|
||||
}
|
||||
miscData = Integer.parseInt(secondArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!disguiseOptions.isEmpty() && miscId != -1) {
|
||||
String toCheck = "" + miscId;
|
||||
if (miscData == 0 || miscData == -1) {
|
||||
if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) {
|
||||
toCheck += ":0";
|
||||
}
|
||||
} else {
|
||||
toCheck += ":" + miscData;
|
||||
}
|
||||
if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) {
|
||||
throw new DisguiseParseException(ChatColor.RED
|
||||
+ "Error! You do not have permission to use the parameter " + toCheck + " on the "
|
||||
+ disguiseType.toReadable() + " disguise!");
|
||||
}
|
||||
}
|
||||
if (miscId != -1) {
|
||||
if (disguiseType == DisguiseType.FALLING_BLOCK) {
|
||||
usedOptions.add("setblock");
|
||||
doCheck(optionPermissions, usedOptions);
|
||||
} else if (disguiseType == DisguiseType.PAINTING) {
|
||||
usedOptions.add("setpainting");
|
||||
doCheck(optionPermissions, usedOptions);
|
||||
} else if (disguiseType == DisguiseType.SPLASH_POTION) {
|
||||
usedOptions.add("setpotionid");
|
||||
doCheck(optionPermissions, usedOptions);
|
||||
}
|
||||
}
|
||||
// Construct the disguise
|
||||
disguise = new MiscDisguise(disguiseType, miscId, miscData);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copy strings to their new range
|
||||
String[] newArgs = new String[args.length - toSkip];
|
||||
System.arraycopy(args, toSkip, newArgs, 0, args.length - toSkip);
|
||||
args = newArgs;
|
||||
Method[] methods = this.getDisguiseWatcherMethods(disguise.getWatcher().getClass());
|
||||
for (int i = 0; i < args.length; i += 2) {
|
||||
String methodName = args[i];
|
||||
String valueString = (args.length - 1 == i ? null : args[i + 1]);
|
||||
Method methodToUse = null;
|
||||
Object value = null;
|
||||
DisguiseParseException storedEx = null;
|
||||
int c = 0;
|
||||
while (c < methods.length) {
|
||||
try {
|
||||
Entry<Method, Integer> entry = getMethod(methods, methodName, c);
|
||||
if (entry == null) {
|
||||
break;
|
||||
}
|
||||
methodToUse = entry.getKey();
|
||||
c = entry.getValue();
|
||||
methodName = methodToUse.getName();
|
||||
Class<?>[] types = methodToUse.getParameterTypes();
|
||||
Class param = types[0];
|
||||
if (valueString != null) {
|
||||
if (int.class == param) {
|
||||
// Parse to integer
|
||||
if (isNumeric(valueString)) {
|
||||
value = (int) Integer.parseInt(valueString);
|
||||
} else {
|
||||
throw parseToException("number", valueString, methodName);
|
||||
}
|
||||
} else if (float.class == param || double.class == param) {
|
||||
// Parse to number
|
||||
if (isDouble(valueString)) {
|
||||
float obj = Float.parseFloat(valueString);
|
||||
if (param == float.class) {
|
||||
value = (float) obj;
|
||||
} else if (param == double.class) {
|
||||
value = (double) obj;
|
||||
}
|
||||
} else {
|
||||
throw parseToException("number.0", valueString, methodName);
|
||||
}
|
||||
} else if (param == String.class) {
|
||||
// Parse to string
|
||||
value = ChatColor.translateAlternateColorCodes('&', valueString);
|
||||
} else if (param == AnimalColor.class) {
|
||||
// Parse to animal color
|
||||
try {
|
||||
value = AnimalColor.valueOf(valueString.toUpperCase());
|
||||
} catch (Exception ex) {
|
||||
throw parseToException("animal color", valueString, methodName);
|
||||
}
|
||||
} else if (param == ItemStack.class) {
|
||||
// Parse to itemstack
|
||||
try {
|
||||
value = parseToItemstack(valueString);
|
||||
} catch (Exception ex) {
|
||||
throw new DisguiseParseException(String.format(ex.getMessage(), methodName));
|
||||
}
|
||||
} else if (param == ItemStack[].class) {
|
||||
// Parse to itemstack array
|
||||
ItemStack[] items = new ItemStack[4];
|
||||
String[] split = valueString.split(",");
|
||||
if (split.length == 4) {
|
||||
for (int a = 0; a < 4; a++) {
|
||||
try {
|
||||
items[a] = parseToItemstack(split[a]);
|
||||
} catch (Exception ex) {
|
||||
throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN
|
||||
+ "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN
|
||||
+ "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName);
|
||||
}
|
||||
value = items;
|
||||
} else if (param.getSimpleName().equals("Color")) {
|
||||
// Parse to horse color
|
||||
value = callValueOf(param, valueString, methodName, "a horse color");
|
||||
} else if (param.getSimpleName().equals("Style")) {
|
||||
// Parse to horse style
|
||||
value = callValueOf(param, valueString, methodName, "a horse style");
|
||||
} else if (param.getSimpleName().equals("Profession")) {
|
||||
// Parse to villager profession
|
||||
value = callValueOf(param, valueString, methodName, "a villager profession");
|
||||
} else if (param.getSimpleName().equals("Art")) {
|
||||
// Parse to art type
|
||||
value = callValueOf(param, valueString, methodName, "a painting art");
|
||||
} else if (param.getSimpleName().equals("Type")) {
|
||||
// Parse to ocelot type
|
||||
value = callValueOf(param, valueString, methodName, "a ocelot type");
|
||||
} else if (param == PotionEffectType.class) {
|
||||
// Parse to potion effect
|
||||
try {
|
||||
PotionEffectType potionType = PotionEffectType.getByName(valueString.toUpperCase());
|
||||
if (potionType == null && isNumeric(valueString)) {
|
||||
potionType = PotionEffectType.getById(Integer.parseInt(valueString));
|
||||
}
|
||||
if (potionType == null)
|
||||
throw new DisguiseParseException();
|
||||
value = potionType;
|
||||
} catch (Exception ex) {
|
||||
throw parseToException("a potioneffect type", valueString, methodName);
|
||||
}
|
||||
} else if (param == int[].class) {
|
||||
String[] split = valueString.split(",");
|
||||
int[] values = new int[split.length];
|
||||
for (int b = 0; b < values.length; b++) {
|
||||
try {
|
||||
values[b] = Integer.parseInt(split[b]);
|
||||
} catch (NumberFormatException ex) {
|
||||
throw parseToException("Number,Number,Number...", valueString, methodName);
|
||||
}
|
||||
}
|
||||
value = values;
|
||||
} else if (param == BlockFace.class) {
|
||||
try {
|
||||
BlockFace face = BlockFace.valueOf(valueString.toUpperCase());
|
||||
if (face.ordinal() > 4)
|
||||
throw new DisguiseParseException();
|
||||
value = face;
|
||||
} catch (Exception ex) {
|
||||
throw parseToException("a direction (north, east, south, west, up)", valueString, methodName);
|
||||
}
|
||||
} else if (param == RabbitType.class) {
|
||||
try {
|
||||
for (RabbitType type : RabbitType.values()) {
|
||||
if (type.name().replace("_", "")
|
||||
.equalsIgnoreCase(valueString.replace("_", "").replace(" ", ""))) {
|
||||
value = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (value == null) {
|
||||
throw new Exception();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw parseToException("rabbit type (white, brown, patches...)", valueString, methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value == null && boolean.class == param) {
|
||||
if (valueString == null) {
|
||||
value = true;
|
||||
i--;
|
||||
} else if (valueString.equalsIgnoreCase("true")) {
|
||||
value = true;
|
||||
} else if (valueString.equalsIgnoreCase("false")) {
|
||||
value = false;
|
||||
} else {
|
||||
if (getMethod(methods, valueString, 0) == null) {
|
||||
throw parseToException("true/false", valueString, methodName);
|
||||
} else {
|
||||
value = true;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value != null) {
|
||||
break;
|
||||
}
|
||||
} catch (DisguiseParseException ex) {
|
||||
storedEx = ex;
|
||||
methodToUse = null;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
methodToUse = null;
|
||||
}
|
||||
}
|
||||
if (methodToUse == null) {
|
||||
if (storedEx != null) {
|
||||
throw storedEx;
|
||||
}
|
||||
throw new DisguiseParseException(ChatColor.RED + "Cannot find the option " + methodName);
|
||||
}
|
||||
if (value == null) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "No value was given for the option " + methodName);
|
||||
}
|
||||
if (!usedOptions.contains(methodName.toLowerCase())) {
|
||||
usedOptions.add(methodName.toLowerCase());
|
||||
}
|
||||
doCheck(optionPermissions, usedOptions);
|
||||
if (FlagWatcher.class.isAssignableFrom(methodToUse.getDeclaringClass()))
|
||||
methodToUse.invoke(disguise.getWatcher(), value);
|
||||
else
|
||||
methodToUse.invoke(disguise, value);
|
||||
}
|
||||
// Alright. We've constructed our disguise.
|
||||
return disguise;
|
||||
}
|
||||
|
||||
private Entry<Method, Integer> getMethod(Method[] methods, String methodName, int toStart) {
|
||||
for (int i = toStart; i < methods.length; i++) {
|
||||
Method method = methods[i];
|
||||
if (!method.getName().startsWith("get") && method.getName().equalsIgnoreCase(methodName)
|
||||
&& method.getAnnotation(Deprecated.class) == null && method.getParameterTypes().length == 1) {
|
||||
return new HashMap.SimpleEntry(method, ++i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object callValueOf(Class<?> param, String valueString, String methodName, String description)
|
||||
throws DisguiseParseException {
|
||||
Object value;
|
||||
try {
|
||||
value = param.getMethod("valueOf", String.class).invoke(null, valueString.toUpperCase());
|
||||
} catch (Exception ex) {
|
||||
throw parseToException(description, valueString, methodName);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean passesCheck(HashMap<ArrayList<String>, Boolean> map1, ArrayList<String> usedOptions) {
|
||||
boolean hasPermission = false;
|
||||
for (ArrayList<String> list : map1.keySet()) {
|
||||
boolean myPerms = true;
|
||||
for (String option : usedOptions) {
|
||||
if (!(map1.get(list) && list.contains("*")) && (list.contains(option) != map1.get(list))) {
|
||||
myPerms = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (myPerms) {
|
||||
hasPermission = true;
|
||||
}
|
||||
}
|
||||
return hasPermission;
|
||||
}
|
||||
|
||||
private void doCheck(HashMap<ArrayList<String>, Boolean> optionPermissions, ArrayList<String> usedOptions)
|
||||
throws DisguiseParseException {
|
||||
if (!passesCheck(optionPermissions, usedOptions)) {
|
||||
throw new DisguiseParseException(ChatColor.RED + "You do not have the permission to use the option "
|
||||
+ usedOptions.get(usedOptions.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private DisguiseParseException parseToException(String expectedValue, String receivedInstead, String methodName) {
|
||||
return new DisguiseParseException(ChatColor.RED + "Expected " + ChatColor.GREEN + expectedValue + ChatColor.RED
|
||||
+ ", received " + ChatColor.GREEN + receivedInstead + ChatColor.RED + " instead for " + ChatColor.GREEN
|
||||
+ methodName);
|
||||
}
|
||||
|
||||
private ItemStack parseToItemstack(String string) throws Exception {
|
||||
String[] split = string.split(":", -1);
|
||||
if (isNumeric(split[0])) {
|
||||
int itemId = Integer.parseInt(split[0]);
|
||||
short itemDura = 0;
|
||||
if (split.length > 1) {
|
||||
if (isNumeric(split[1])) {
|
||||
itemDura = Short.parseShort(split[1]);
|
||||
} else {
|
||||
throw parseToException("item ID:Durability combo", string, "%s");
|
||||
}
|
||||
}
|
||||
return new ItemStack(itemId, 1, itemDura);
|
||||
} else {
|
||||
if (split.length == 1) {
|
||||
throw parseToException("item ID", string, "%s");
|
||||
} else {
|
||||
throw parseToException("item ID:Durability combo", string, "%s");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map);
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.security.CodeSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* User: Austin Date: 4/22/13 Time: 11:47 PM (c) lazertester
|
||||
*/
|
||||
|
||||
// Code for this taken and slightly modified from
|
||||
// https://github.com/ddopson/java-class-enumerator
|
||||
public class ClassGetter {
|
||||
|
||||
public static ArrayList<Class<?>> getClassesForPackage(String pkgname) {
|
||||
ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
// String relPath = pkgname.replace('.', '/');
|
||||
|
||||
// Get a File object for the package
|
||||
CodeSource src = Entity.class.getProtectionDomain().getCodeSource();
|
||||
if (src != null) {
|
||||
URL resource = src.getLocation();
|
||||
resource.getPath();
|
||||
processJarfile(resource, pkgname, classes);
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static Class<?> loadClass(String className) {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Unexpected ClassNotFoundException loading class '" + className + "'");
|
||||
} catch (NoClassDefFoundError e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void processJarfile(URL resource, String pkgname, ArrayList<Class<?>> classes) {
|
||||
try {
|
||||
String relPath = pkgname.replace('.', '/');
|
||||
String resPath = URLDecoder.decode(resource.getPath(), "UTF-8");
|
||||
String jarPath = resPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", "");
|
||||
JarFile jarFile = new JarFile(jarPath);
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
String entryName = entry.getName();
|
||||
String className = null;
|
||||
if (entryName.endsWith(".class") && entryName.startsWith(relPath)
|
||||
&& entryName.length() > (relPath.length() + "/".length())) {
|
||||
className = entryName.replace('/', '.').replace('\\', '.').replace(".class", "");
|
||||
}
|
||||
if (className != null) {
|
||||
Class<?> c = loadClass(className);
|
||||
if (c != null)
|
||||
classes.add(c);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,230 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion;
|
||||
|
||||
import org.bukkit.Sound;
|
||||
|
||||
/**
|
||||
* Only living disguises go in here!
|
||||
*/
|
||||
public enum DisguiseSound {
|
||||
ARROW(null, null, null, null, "random.bowhit"),
|
||||
|
||||
BAT("mob.bat.hurt", null, "mob.bat.death", "mob.bat.idle", "damage.fallsmall", "mob.bat.loop", "damage.fallbig",
|
||||
"mob.bat.takeoff"),
|
||||
|
||||
BLAZE("mob.blaze.hit", null, "mob.blaze.death", "mob.blaze.breathe", "damage.fallsmall", "damage.fallbig"),
|
||||
|
||||
CAVE_SPIDER("mob.spider.say", "mob.spider.step", "mob.spider.death", "mob.spider.say"),
|
||||
|
||||
CHICKEN("mob.chicken.hurt", "mob.chicken.step", "mob.chicken.hurt", "mob.chicken.say", "damage.fallsmall",
|
||||
"mob.chicken.plop", "damage.fallbig"),
|
||||
|
||||
COW("mob.cow.hurt", "mob.cow.step", "mob.cow.hurt", "mob.cow.say"),
|
||||
|
||||
CREEPER("mob.creeper.say", "step.grass", "mob.creeper.death", null),
|
||||
|
||||
DONKEY("mob.horse.donkey.hit", "step.grass", "mob.horse.donkey.death", "mob.horse.donkey.idle", "mob.horse.gallop",
|
||||
"mob.horse.leather", "mob.horse.donkey.angry", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft",
|
||||
"mob.horse.land", "mob.horse.jump", "mob.horse.angry"),
|
||||
|
||||
ELDER_GUARDIAN("mob.guardian.elder.hit", null, "mob.guardian.elder.death", "mob.guardian.elder.death"),
|
||||
|
||||
ENDER_DRAGON("mob.enderdragon.hit", null, "mob.enderdragon.end", "mob.enderdragon.growl", "damage.fallsmall",
|
||||
"mob.enderdragon.wings", "damage.fallbig"),
|
||||
|
||||
ENDERMAN("mob.endermen.hit", "step.grass", "mob.endermen.death", "mob.endermen.idle", "mob.endermen.scream",
|
||||
"mob.endermen.portal", "mob.endermen.stare"),
|
||||
|
||||
ENDERMITE("mob.silverfish.hit", "mob.silverfish.step", "mob.silverfish.kill", "mob.silverfish.say"),
|
||||
|
||||
GHAST("mob.ghast.scream", null, "mob.ghast.death", "mob.ghast.moan", "damage.fallsmall", "mob.ghast.fireball",
|
||||
"damage.fallbig", "mob.ghast.affectionate_scream", "mob.ghast.charge"),
|
||||
|
||||
GIANT("damage.hit", "step.grass", null, null),
|
||||
|
||||
GUARDIAN("mob.guardian.hit", null, "mob.guardian.death", "mob.guardian.death"),
|
||||
|
||||
HORSE("mob.horse.hit", "step.grass", "mob.horse.death", "mob.horse.idle", "mob.horse.gallop", "mob.horse.leather",
|
||||
"mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump", "mob.horse.angry",
|
||||
"mob.horse.leather"),
|
||||
|
||||
IRON_GOLEM("mob.irongolem.hit", "mob.irongolem.walk", "mob.irongolem.death", "mob.irongolem.throw"),
|
||||
|
||||
MAGMA_CUBE("mob.slime.attack", "mob.slime.big", null, null, "mob.slime.small"),
|
||||
|
||||
MULE("mob.horse.donkey.hit", "step.grass", "mob.horse.donkey.death", "mob.horse.donkey.idle"),
|
||||
|
||||
MUSHROOM_COW("mob.cow.hurt", "mob.cow.step", "mob.cow.hurt", "mob.cow.say"),
|
||||
|
||||
OCELOT("mob.cat.hitt", "step.grass", "mob.cat.hitt", "mob.cat.meow", "mob.cat.purreow", "mob.cat.purr"),
|
||||
|
||||
PIG("mob.pig.say", "mob.pig.step", "mob.pig.death", "mob.pig.say"),
|
||||
|
||||
PIG_ZOMBIE("mob.zombiepig.zpighurt", null, "mob.zombiepig.zpigdeath", "mob.zombiepig.zpig", "mob.zombiepig.zpigangry"),
|
||||
|
||||
PLAYER("game.player.hurt", "step.grass", "game.player.hurt", null),
|
||||
|
||||
RABBIT("mob.rabbit.hurt", "mob.rabbit.hop", "mob.rabbit.death", "mob.rabbit.idle"),
|
||||
|
||||
SHEEP("mob.sheep.say", "mob.sheep.step", null, "mob.sheep.say", "mob.sheep.shear"),
|
||||
|
||||
SILVERFISH("mob.silverfish.hit", "mob.silverfish.step", "mob.silverfish.kill", "mob.silverfish.say"),
|
||||
|
||||
SKELETON("mob.skeleton.hurt", "mob.skeleton.step", "mob.skeleton.death", "mob.skeleton.say"),
|
||||
|
||||
SKELETON_HORSE("mob.horse.skeleton.hit", "step.grass", "mob.horse.skeleton.death", "mob.horse.skeleton.idle",
|
||||
"mob.horse.gallop", "mob.horse.leather", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land",
|
||||
"mob.horse.jump", "mob.horse.angry"),
|
||||
|
||||
SLIME("mob.slime.attack", "mob.slime.big", null, null, "mob.slime.small"),
|
||||
|
||||
SNOWMAN(),
|
||||
|
||||
SPIDER("mob.spider.say", "mob.spider.step", "mob.spider.death", "mob.spider.say"),
|
||||
|
||||
SQUID(),
|
||||
|
||||
UNDEAD_HORSE("mob.horse.zombie.hit", "step.grass", "mob.horse.zombie.death", "mob.horse.zombie.idle", "mob.horse.gallop",
|
||||
"mob.horse.leather", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump",
|
||||
"mob.horse.angry"),
|
||||
|
||||
VILLAGER("mob.villager.hit", null, "mob.villager.death", "mob.villager.idle", "mob.villager.haggle", "mob.villager.no",
|
||||
"mob.villager.yes"),
|
||||
|
||||
WITCH("mob.witch.hurt", null, "mob.witch.death", "mob.witch.idle"),
|
||||
|
||||
WITHER("mob.wither.hurt", null, "mob.wither.death", "mob.wither.idle", "damage.fallsmall", "mob.wither.spawn",
|
||||
"damage.fallbig", "mob.wither.shoot"),
|
||||
|
||||
WITHER_SKELETON("mob.skeleton.hurt", "mob.skeleton.step", "mob.skeleton.death", "mob.skeleton.say"),
|
||||
|
||||
WOLF("mob.wolf.hurt", "mob.wolf.step", "mob.wolf.death", "mob.wolf.bark", "mob.wolf.panting", "mob.wolf.whine",
|
||||
"mob.wolf.howl", "mob.wolf.growl", "mob.wolf.shake"),
|
||||
|
||||
ZOMBIE("mob.zombie.hurt", "mob.zombie.step", "mob.zombie.death", "mob.zombie.say", "mob.zombie.infect",
|
||||
"mob.zombie.woodbreak", "mob.zombie.metal", "mob.zombie.wood"),
|
||||
|
||||
ZOMBIE_VILLAGER("mob.zombie.hurt", "mob.zombie.step", "mob.zombie.death", "mob.zombie.say", "mob.zombie.infect",
|
||||
"mob.zombie.woodbreak", "mob.zombie.metal", "mob.zombie.wood");
|
||||
|
||||
public enum SoundType {
|
||||
CANCEL, DEATH, HURT, IDLE, STEP;
|
||||
}
|
||||
|
||||
public static DisguiseSound getType(String name) {
|
||||
try {
|
||||
return valueOf(name);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<String> cancelSounds = new HashSet<String>();
|
||||
private float damageSoundVolume = 1F;
|
||||
private HashMap<SoundType, String> disguiseSounds = new HashMap<SoundType, String>();
|
||||
|
||||
private DisguiseSound(Object... sounds) {
|
||||
for (int i = 0; i < sounds.length; i++) {
|
||||
Object obj = sounds[i];
|
||||
String s;
|
||||
if (obj == null)
|
||||
continue;
|
||||
else if (obj instanceof String) {
|
||||
s = (String) obj;
|
||||
} else if (obj instanceof Sound) {
|
||||
s = ReflectionManager.getCraftSound((Sound) obj);
|
||||
System.out.print("Warning! The sound " + obj + " needs to be converted to a string");
|
||||
} else {
|
||||
throw new RuntimeException("Was given a unknown object " + obj);
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
disguiseSounds.put(SoundType.HURT, s);
|
||||
break;
|
||||
case 1:
|
||||
disguiseSounds.put(SoundType.STEP, s);
|
||||
break;
|
||||
case 2:
|
||||
disguiseSounds.put(SoundType.DEATH, s);
|
||||
break;
|
||||
case 3:
|
||||
disguiseSounds.put(SoundType.IDLE, s);
|
||||
break;
|
||||
default:
|
||||
cancelSounds.add(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float getDamageAndIdleSoundVolume() {
|
||||
return damageSoundVolume;
|
||||
}
|
||||
|
||||
public String getSound(SoundType type) {
|
||||
if (type == null || !disguiseSounds.containsKey(type))
|
||||
return null;
|
||||
return disguiseSounds.get(type);
|
||||
}
|
||||
|
||||
public HashSet<String> getSoundsToCancel() {
|
||||
return cancelSounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if this sound name is owned by this disguise sound.
|
||||
*/
|
||||
public SoundType getType(String sound, boolean ignoreDamage) {
|
||||
if (isCancelSound(sound))
|
||||
return SoundType.CANCEL;
|
||||
if (disguiseSounds.containsKey(SoundType.STEP) && disguiseSounds.get(SoundType.STEP).startsWith("step.")
|
||||
&& sound.startsWith("step."))
|
||||
return SoundType.STEP;
|
||||
for (SoundType type : SoundType.values()) {
|
||||
if (!disguiseSounds.containsKey(type) || type == SoundType.DEATH || (ignoreDamage && type == SoundType.HURT))
|
||||
continue;
|
||||
String s = disguiseSounds.get(type);
|
||||
if (s != null) {
|
||||
if (s.equals(sound))
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isCancelSound(String sound) {
|
||||
return getSoundsToCancel().contains(sound);
|
||||
}
|
||||
|
||||
public void removeSound(SoundType type, Sound sound) {
|
||||
removeSound(type, ReflectionManager.getCraftSound(sound));
|
||||
}
|
||||
|
||||
public void removeSound(SoundType type, String sound) {
|
||||
if (type == SoundType.CANCEL)
|
||||
cancelSounds.remove(sound);
|
||||
else {
|
||||
disguiseSounds.remove(type);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDamageAndIdleSoundVolume(float strength) {
|
||||
this.damageSoundVolume = strength;
|
||||
}
|
||||
|
||||
public void setSound(SoundType type, Sound sound) {
|
||||
setSound(type, ReflectionManager.getCraftSound(sound));
|
||||
}
|
||||
|
||||
public void setSound(SoundType type, String sound) {
|
||||
if (type == SoundType.CANCEL)
|
||||
cancelSounds.add(sound);
|
||||
else {
|
||||
disguiseSounds.put(type, sound);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,990 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.DisguiseConfig;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Zombie;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
||||
|
||||
public class DisguiseUtilities {
|
||||
/**
|
||||
* This is a list of names which was called by other plugins. As such, don't remove from the gameProfiles as its the duty of
|
||||
* the plugin to do that.
|
||||
*/
|
||||
private static HashSet<String> addedByPlugins = new HashSet<String>();
|
||||
private static Object bedChunk;
|
||||
private static LinkedHashMap<String, Disguise> clonedDisguises = new LinkedHashMap<String, Disguise>();
|
||||
/**
|
||||
* A hashmap of the uuid's of entitys, alive and dead. And their disguises in use
|
||||
**/
|
||||
private static HashMap<UUID, HashSet<TargetedDisguise>> disguisesInUse = new HashMap<UUID, HashSet<TargetedDisguise>>();
|
||||
/**
|
||||
* Disguises which are stored ready for a entity to be seen by a player Preferably, disguises in this should only stay in for
|
||||
* a max of a second.
|
||||
*/
|
||||
private static HashMap<Integer, HashSet<TargetedDisguise>> futureDisguises = new HashMap<Integer, HashSet<TargetedDisguise>>();
|
||||
/**
|
||||
* A hashmap storing the uuid and skin of a playername
|
||||
*/
|
||||
private static HashMap<String, WrappedGameProfile> gameProfiles = new HashMap<String, WrappedGameProfile>();
|
||||
private static LibsDisguises libsDisguises;
|
||||
private static HashMap<String, ArrayList<Object>> runnables = new HashMap<String, ArrayList<Object>>();
|
||||
private static HashSet<UUID> selfDisguised = new HashSet<UUID>();
|
||||
private static Field xChunk, zChunk;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object server = ReflectionManager.getNmsMethod("MinecraftServer", "getServer").invoke(null);
|
||||
Object world = ((List) server.getClass().getField("worlds").get(server)).get(0);
|
||||
bedChunk = ReflectionManager.getNmsClass("Chunk")
|
||||
.getConstructor(ReflectionManager.getNmsClass("World"), int.class, int.class).newInstance(world, 0, 0);
|
||||
Field cSection = bedChunk.getClass().getDeclaredField("sections");
|
||||
cSection.setAccessible(true);
|
||||
Object chunkSection = ReflectionManager.getNmsClass("ChunkSection").getConstructor(int.class, boolean.class)
|
||||
.newInstance(0, true);
|
||||
Object block;
|
||||
try {
|
||||
block = ReflectionManager.getNmsClass("Block").getMethod("getById", int.class)
|
||||
.invoke(null, Material.BED_BLOCK.getId());
|
||||
} catch (Exception ex) {
|
||||
block = ((Object[]) ReflectionManager.getNmsField(ReflectionManager.getNmsClass("Block"), "byId").get(null))[Material.BED_BLOCK
|
||||
.getId()];
|
||||
}
|
||||
Method fromLegacyData = block.getClass().getMethod("fromLegacyData", int.class);
|
||||
Method setType = chunkSection.getClass().getMethod("setType", int.class, int.class, int.class,
|
||||
ReflectionManager.getNmsClass("IBlockData"));
|
||||
Method setSky = chunkSection.getClass().getMethod("a", int.class, int.class, int.class, int.class);
|
||||
Method setEmitted = chunkSection.getClass().getMethod("b", int.class, int.class, int.class, int.class);
|
||||
for (BlockFace face : new BlockFace[] { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH }) {
|
||||
setType.invoke(chunkSection, 1 + face.getModX(), 0, 1 + face.getModZ(), fromLegacyData.invoke(block, face.ordinal()));
|
||||
setSky.invoke(chunkSection, 1 + face.getModX(), 0, 1 + face.getModZ(), 0);
|
||||
setEmitted.invoke(chunkSection, 1 + face.getModX(), 0, 1 + face.getModZ(), 0);
|
||||
}
|
||||
|
||||
Object[] array = (Object[]) Array.newInstance(chunkSection.getClass(), 16);
|
||||
array[0] = chunkSection;
|
||||
cSection.set(bedChunk, array);
|
||||
xChunk = bedChunk.getClass().getField("locX");
|
||||
xChunk.setAccessible(true);
|
||||
zChunk = bedChunk.getClass().getField("locZ");
|
||||
zChunk.setAccessible(true);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean addClonedDisguise(String key, Disguise disguise) {
|
||||
if (DisguiseConfig.getMaxClonedDisguises() > 0) {
|
||||
if (clonedDisguises.containsKey(key)) {
|
||||
clonedDisguises.remove(key);
|
||||
} else if (DisguiseConfig.getMaxClonedDisguises() == clonedDisguises.size()) {
|
||||
clonedDisguises.remove(clonedDisguises.keySet().iterator().next());
|
||||
}
|
||||
if (DisguiseConfig.getMaxClonedDisguises() > clonedDisguises.size()) {
|
||||
clonedDisguises.put(key, disguise);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void addDisguise(UUID entityId, TargetedDisguise disguise) {
|
||||
if (!getDisguises().containsKey(entityId)) {
|
||||
getDisguises().put(entityId, new HashSet<TargetedDisguise>());
|
||||
}
|
||||
getDisguises().get(entityId).add(disguise);
|
||||
checkConflicts(disguise, null);
|
||||
if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS && disguise.isModifyBoundingBox()) {
|
||||
doBoundingBox(disguise);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addFutureDisguise(final int entityId, final TargetedDisguise disguise) {
|
||||
if (!futureDisguises.containsKey(entityId)) {
|
||||
futureDisguises.put(entityId, new HashSet<TargetedDisguise>());
|
||||
}
|
||||
futureDisguises.get(entityId).add(disguise);
|
||||
final BukkitRunnable runnable = new BukkitRunnable() {
|
||||
public void run() {
|
||||
if (futureDisguises.containsKey(entityId) && futureDisguises.get(entityId).contains(disguise)) {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Entity entity : world.getEntities()) {
|
||||
if (entity.getEntityId() == entityId) {
|
||||
UUID uniqueId = entity.getUniqueId();
|
||||
for (TargetedDisguise disguise : futureDisguises.remove(entityId)) {
|
||||
addDisguise(uniqueId, disguise);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
futureDisguises.get(entityId).remove(disguise);
|
||||
if (futureDisguises.get(entityId).isEmpty()) {
|
||||
futureDisguises.remove(entityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
runnable.runTaskLater(libsDisguises, 20);
|
||||
}
|
||||
|
||||
public static void addGameProfile(String string, WrappedGameProfile gameProfile) {
|
||||
getGameProfiles().put(string, gameProfile);
|
||||
getAddedByPlugins().add(string.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* If name isn't null. Make sure that the name doesn't see any other disguise. Else if name is null. Make sure that the
|
||||
* observers in the disguise don't see any other disguise.
|
||||
*/
|
||||
public static void checkConflicts(TargetedDisguise disguise, String name) {
|
||||
// If the disguise is being used.. Else we may accidentally undisguise something else
|
||||
if (DisguiseAPI.isDisguiseInUse(disguise)) {
|
||||
Iterator<TargetedDisguise> disguiseItel = getDisguises().get(disguise.getEntity().getUniqueId()).iterator();
|
||||
// Iterate through the disguises
|
||||
while (disguiseItel.hasNext()) {
|
||||
TargetedDisguise d = disguiseItel.next();
|
||||
// Make sure the disguise isn't the same thing
|
||||
if (d != disguise) {
|
||||
// If the loop'd disguise is hiding the disguise to everyone in its list
|
||||
if (d.getDisguiseTarget() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) {
|
||||
// If player is a observer in the loop
|
||||
if (disguise.getDisguiseTarget() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) {
|
||||
// If player is a observer in the disguise
|
||||
// Remove them from the loop
|
||||
if (name != null) {
|
||||
d.removePlayer(name);
|
||||
} else {
|
||||
for (String playername : disguise.getObservers()) {
|
||||
d.silentlyRemovePlayer(playername);
|
||||
}
|
||||
}
|
||||
} else if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
|
||||
// If player is not a observer in the loop
|
||||
if (name != null) {
|
||||
if (!disguise.getObservers().contains(name)) {
|
||||
d.removePlayer(name);
|
||||
}
|
||||
} else {
|
||||
for (String playername : new ArrayList<String>(d.getObservers())) {
|
||||
if (!disguise.getObservers().contains(playername)) {
|
||||
d.silentlyRemovePlayer(playername);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (d.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
|
||||
// Here you add it to the loop if they see the disguise
|
||||
if (disguise.getDisguiseTarget() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) {
|
||||
// Everyone who is in the disguise needs to be added to the loop
|
||||
if (name != null) {
|
||||
d.addPlayer(name);
|
||||
} else {
|
||||
for (String playername : disguise.getObservers()) {
|
||||
d.silentlyAddPlayer(playername);
|
||||
}
|
||||
}
|
||||
} else if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
|
||||
// This here is a paradox.
|
||||
// If fed a name. I can do this.
|
||||
// But the rest of the time.. Its going to conflict.
|
||||
// The below is debug output. Most people wouldn't care for it.
|
||||
|
||||
// System.out.print("Cannot set more than one " + TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS
|
||||
// + " on a entity. Removed the old disguise.");
|
||||
|
||||
disguiseItel.remove();
|
||||
d.removeDisguise();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends entity removal packets, as this disguise was removed
|
||||
*/
|
||||
public static void destroyEntity(TargetedDisguise disguise) {
|
||||
try {
|
||||
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
|
||||
if (entityTrackerEntry != null) {
|
||||
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
|
||||
entityTrackerEntry);
|
||||
HashSet cloned = (HashSet) trackedPlayers.clone();
|
||||
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
destroyPacket.getIntegerArrays().write(0, new int[] { disguise.getEntity().getEntityId() });
|
||||
for (Object p : cloned) {
|
||||
Player player = (Player) ReflectionManager.getBukkitEntity(p);
|
||||
if (player == disguise.getEntity() || disguise.canSee(player)) {
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, destroyPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void doBoundingBox(TargetedDisguise disguise) {
|
||||
// TODO Slimes
|
||||
Entity entity = disguise.getEntity();
|
||||
if (entity != null) {
|
||||
if (isDisguiseInUse(disguise)) {
|
||||
DisguiseValues disguiseValues = DisguiseValues.getDisguiseValues(disguise.getType());
|
||||
FakeBoundingBox disguiseBox = disguiseValues.getAdultBox();
|
||||
if (disguiseValues.getBabyBox() != null) {
|
||||
if ((disguise.getWatcher() instanceof AgeableWatcher && ((AgeableWatcher) disguise.getWatcher()).isBaby())
|
||||
|| (disguise.getWatcher() instanceof ZombieWatcher && ((ZombieWatcher) disguise.getWatcher())
|
||||
.isBaby())) {
|
||||
disguiseBox = disguiseValues.getBabyBox();
|
||||
}
|
||||
}
|
||||
ReflectionManager.setBoundingBox(entity, disguiseBox);
|
||||
} else {
|
||||
DisguiseValues entityValues = DisguiseValues.getDisguiseValues(DisguiseType.getType(entity.getType()));
|
||||
FakeBoundingBox entityBox = entityValues.getAdultBox();
|
||||
if (entityValues.getBabyBox() != null) {
|
||||
if ((entity instanceof Ageable && !((Ageable) entity).isAdult())
|
||||
|| (entity instanceof Zombie && ((Zombie) entity).isBaby())) {
|
||||
entityBox = entityValues.getBabyBox();
|
||||
}
|
||||
}
|
||||
ReflectionManager.setBoundingBox(entity, entityBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HashSet<String> getAddedByPlugins() {
|
||||
return addedByPlugins;
|
||||
}
|
||||
|
||||
public static PacketContainer[] getBedChunkPacket(Player player, Location newLoc, Location oldLoc) {
|
||||
int i = 0;
|
||||
PacketContainer[] packets = new PacketContainer[newLoc != null ? 2 + (oldLoc != null ? 1 : 0) : 1];
|
||||
for (Location loc : new Location[] { oldLoc, newLoc }) {
|
||||
if (loc == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
int chunkX = (int) Math.floor(loc.getX() / 16D) - 17, chunkZ = (int) Math.floor(loc.getZ() / 16D) - 17;
|
||||
chunkX -= chunkX % 8;
|
||||
chunkZ -= chunkZ % 8;
|
||||
xChunk.set(bedChunk, chunkX);
|
||||
zChunk.set(bedChunk, chunkZ);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
// Make unload packets
|
||||
try {
|
||||
packets[i] = ProtocolLibrary.getProtocolManager()
|
||||
.createPacketConstructor(PacketType.Play.Server.MAP_CHUNK, bedChunk, true, 0, 40)
|
||||
.createPacket(bedChunk, true, 0, 48);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
packets[i] = ProtocolLibrary.getProtocolManager()
|
||||
.createPacketConstructor(PacketType.Play.Server.MAP_CHUNK, bedChunk, true, 0)
|
||||
.createPacket(bedChunk, true, 0);
|
||||
}
|
||||
i++;
|
||||
// Make load packets
|
||||
if (oldLoc == null || i > 1) {
|
||||
packets[i] = ProtocolLibrary.getProtocolManager()
|
||||
.createPacketConstructor(PacketType.Play.Server.MAP_CHUNK_BULK, Arrays.asList(bedChunk))
|
||||
.createPacket(Arrays.asList(bedChunk));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return packets;
|
||||
}
|
||||
|
||||
public static PacketContainer[] getBedPackets(Player player, Location loc, Location playerLocation, PlayerDisguise disguise) {
|
||||
Entity entity = disguise.getEntity();
|
||||
PacketContainer setBed = new PacketContainer(PacketType.Play.Server.BED);
|
||||
StructureModifier<Integer> bedInts = setBed.getIntegers();
|
||||
bedInts.write(0, entity.getEntityId());
|
||||
PlayerWatcher watcher = disguise.getWatcher();
|
||||
int chunkX = (int) Math.floor(playerLocation.getX() / 16D) - 17, chunkZ = (int) Math
|
||||
.floor(playerLocation.getZ() / 16D) - 17;
|
||||
chunkX -= chunkX % 8;
|
||||
chunkZ -= chunkZ % 8;
|
||||
bedInts.write(1, (chunkX * 16) + 1 + watcher.getSleepingDirection().getModX());
|
||||
bedInts.write(3, (chunkZ * 16) + 1 + watcher.getSleepingDirection().getModZ());
|
||||
PacketContainer teleport = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
|
||||
StructureModifier<Integer> ints = teleport.getIntegers();
|
||||
ints.write(0, entity.getEntityId());
|
||||
ints.write(1, (int) Math.floor(loc.getX() * 32));
|
||||
ints.write(2, (int) Math.floor((PacketsManager.getYModifier(disguise.getEntity(), disguise) + loc.getY()) * 32));
|
||||
ints.write(3, (int) Math.floor(loc.getZ() * 32));
|
||||
return new PacketContainer[] { setBed, teleport };
|
||||
|
||||
}
|
||||
|
||||
public static Disguise getClonedDisguise(String key) {
|
||||
if (clonedDisguises.containsKey(key)) {
|
||||
return clonedDisguises.get(key).clone();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PacketContainer getDestroyPacket(int... ids) {
|
||||
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
destroyPacket.getIntegerArrays().write(0, ids);
|
||||
return destroyPacket;
|
||||
}
|
||||
|
||||
public static TargetedDisguise getDisguise(Player observer, Entity entity) {
|
||||
UUID entityId = entity.getUniqueId();
|
||||
if (futureDisguises.containsKey(entity.getEntityId())) {
|
||||
for (TargetedDisguise disguise : futureDisguises.remove(entity.getEntityId())) {
|
||||
addDisguise(entityId, disguise);
|
||||
}
|
||||
}
|
||||
if (getDisguises().containsKey(entityId)) {
|
||||
for (TargetedDisguise disguise : getDisguises().get(entityId)) {
|
||||
if (disguise.canSee(observer)) {
|
||||
return disguise;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HashMap<UUID, HashSet<TargetedDisguise>> getDisguises() {
|
||||
return disguisesInUse;
|
||||
}
|
||||
|
||||
public static TargetedDisguise[] getDisguises(UUID entityId) {
|
||||
if (getDisguises().containsKey(entityId)) {
|
||||
HashSet<TargetedDisguise> disguises = getDisguises().get(entityId);
|
||||
return disguises.toArray(new TargetedDisguise[disguises.size()]);
|
||||
}
|
||||
return new TargetedDisguise[0];
|
||||
}
|
||||
|
||||
public static HashMap<Integer, HashSet<TargetedDisguise>> getFutureDisguises() {
|
||||
return futureDisguises;
|
||||
}
|
||||
|
||||
public static WrappedGameProfile getGameProfile(String playerName) {
|
||||
return gameProfiles.get(playerName.toLowerCase());
|
||||
}
|
||||
|
||||
public static HashMap<String, WrappedGameProfile> getGameProfiles() {
|
||||
return gameProfiles;
|
||||
}
|
||||
|
||||
public static TargetedDisguise getMainDisguise(UUID entityId) {
|
||||
TargetedDisguise toReturn = null;
|
||||
if (getDisguises().containsKey(entityId)) {
|
||||
for (TargetedDisguise disguise : getDisguises().get(entityId)) {
|
||||
if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
|
||||
return disguise;
|
||||
}
|
||||
toReturn = disguise;
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all EntityPlayers who have this entity in their Entity Tracker And they are in the targetted disguise.
|
||||
*/
|
||||
public static ArrayList<Player> getPerverts(Disguise disguise) {
|
||||
ArrayList<Player> players = new ArrayList<Player>();
|
||||
try {
|
||||
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
|
||||
if (entityTrackerEntry != null) {
|
||||
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
|
||||
entityTrackerEntry);
|
||||
for (Object p : trackedPlayers) {
|
||||
Player player = (Player) ReflectionManager.getBukkitEntity(p);
|
||||
if (((TargetedDisguise) disguise).canSee(player)) {
|
||||
players.add(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
public static WrappedGameProfile getProfileFromMojang(final PlayerDisguise disguise) {
|
||||
final String nameToFetch = disguise.getSkin() != null ? disguise.getSkin() : disguise.getName();
|
||||
final boolean remove = getAddedByPlugins().contains(nameToFetch.toLowerCase());
|
||||
return getProfileFromMojang(nameToFetch, new LibsProfileLookup() {
|
||||
|
||||
@Override
|
||||
public void onLookup(WrappedGameProfile gameProfile) {
|
||||
if (remove) {
|
||||
getAddedByPlugins().remove(nameToFetch.toLowerCase());
|
||||
}
|
||||
if (DisguiseAPI.isDisguiseInUse(disguise)
|
||||
&& (!gameProfile.getName().equals(
|
||||
disguise.getSkin() != null ? disguise.getSkin() : disguise.getName())
|
||||
|| !gameProfile.getProperties().isEmpty())) {
|
||||
disguise.setGameProfile(gameProfile);
|
||||
DisguiseUtilities.refreshTrackers(disguise);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread safe to use. This returns a GameProfile. And if its GameProfile doesn't have a skin blob. Then it does a lookup
|
||||
* using schedulers. The runnable is run once the GameProfile has been successfully dealt with
|
||||
*/
|
||||
public static WrappedGameProfile getProfileFromMojang(String playerName, LibsProfileLookup runnableIfCantReturn) {
|
||||
return getProfileFromMojang(playerName, (Object) runnableIfCantReturn);
|
||||
}
|
||||
|
||||
private static WrappedGameProfile getProfileFromMojang(final String origName, final Object runnable) {
|
||||
final String playerName = origName.toLowerCase();
|
||||
if (gameProfiles.containsKey(playerName)) {
|
||||
if (gameProfiles.get(playerName) != null) {
|
||||
return gameProfiles.get(playerName);
|
||||
}
|
||||
} else if (Pattern.matches("([A-Za-z0-9_]){1,16}", origName)) {
|
||||
getAddedByPlugins().add(playerName);
|
||||
Player player = Bukkit.getPlayerExact(playerName);
|
||||
if (player != null) {
|
||||
WrappedGameProfile gameProfile = ReflectionManager.getGameProfile(player);
|
||||
if (!gameProfile.getProperties().isEmpty()) {
|
||||
gameProfiles.put(playerName, gameProfile);
|
||||
return gameProfile;
|
||||
}
|
||||
}
|
||||
// Add null so that if this is called again. I already know I'm doing something about it
|
||||
gameProfiles.put(playerName, null);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final WrappedGameProfile gameProfile = lookupGameProfile(origName);
|
||||
Bukkit.getScheduler().runTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
if (!gameProfile.getProperties().isEmpty()) {
|
||||
if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) {
|
||||
gameProfiles.put(playerName, gameProfile);
|
||||
}
|
||||
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) {
|
||||
if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) {
|
||||
gameProfiles.remove(playerName);
|
||||
getAddedByPlugins().remove(playerName);
|
||||
}
|
||||
System.out.print("[LibsDisguises] Error when fetching " + playerName + "'s uuid from mojang: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return ReflectionManager.getGameProfile(null, origName);
|
||||
}
|
||||
if (runnable != null) {
|
||||
if (!runnables.containsKey(playerName)) {
|
||||
runnables.put(playerName, new ArrayList<Object>());
|
||||
}
|
||||
runnables.get(playerName).add(runnable);
|
||||
}
|
||||
return ReflectionManager.getGameProfile(null, origName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread safe to use. This returns a GameProfile. And if its GameProfile doesn't have a skin blob. Then it does a lookup
|
||||
* using schedulers. The runnable is run once the GameProfile has been successfully dealt with
|
||||
*/
|
||||
public static WrappedGameProfile getProfileFromMojang(String playerName, Runnable runnableIfCantReturn) {
|
||||
return getProfileFromMojang(playerName, (Object) runnableIfCantReturn);
|
||||
}
|
||||
|
||||
public static HashSet<UUID> getSelfDisguised() {
|
||||
return selfDisguised;
|
||||
}
|
||||
|
||||
public static boolean hasGameProfile(String playerName) {
|
||||
return getGameProfile(playerName) != null;
|
||||
}
|
||||
|
||||
public static void init(LibsDisguises disguises) {
|
||||
libsDisguises = disguises;
|
||||
}
|
||||
|
||||
public static boolean isDisguiseInUse(Disguise disguise) {
|
||||
return disguise.getEntity() != null && getDisguises().containsKey(disguise.getEntity().getUniqueId())
|
||||
&& getDisguises().get(disguise.getEntity().getUniqueId()).contains(disguise);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called on a thread as it is thread blocking
|
||||
*/
|
||||
public static WrappedGameProfile lookupGameProfile(String playerName) {
|
||||
return ReflectionManager.getSkullBlob(ReflectionManager.grabProfileAddUUID(playerName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Please note that in the future when 'DualInt' and the like are removed. This should break.. However, that should be negated
|
||||
* in the future as I'd be able to set the watcher index's as per the spigot version. Instead of checking on the player's
|
||||
* version every single packet..
|
||||
*/
|
||||
public static List<WrappedWatchableObject> rebuildForVersion(Player player, FlagWatcher watcher,
|
||||
List<WrappedWatchableObject> list) {
|
||||
if (true) // Use for future protocol compatibility
|
||||
return list;
|
||||
ArrayList<WrappedWatchableObject> rebuiltList = new ArrayList<WrappedWatchableObject>();
|
||||
ArrayList<WrappedWatchableObject> backups = new ArrayList<WrappedWatchableObject>();
|
||||
for (WrappedWatchableObject obj : list) {
|
||||
if (obj.getValue().getClass().getName().startsWith("org.")) {
|
||||
backups.add(obj);
|
||||
continue;
|
||||
}
|
||||
switch (obj.getIndex()) {
|
||||
// TODO: Future version support
|
||||
}
|
||||
}
|
||||
Iterator<WrappedWatchableObject> itel = backups.iterator();
|
||||
while (itel.hasNext()) {
|
||||
int index = itel.next().getIndex();
|
||||
for (WrappedWatchableObject obj2 : rebuiltList) {
|
||||
if (index == obj2.getIndex()) {
|
||||
itel.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rebuiltList.addAll(backups);
|
||||
return rebuiltList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resends the entity to this specific player
|
||||
*/
|
||||
public static void refreshTracker(final TargetedDisguise disguise, String player) {
|
||||
if (disguise.getEntity() != null && disguise.getEntity().isValid()) {
|
||||
try {
|
||||
PacketContainer destroyPacket = getDestroyPacket(disguise.getEntity().getEntityId());
|
||||
if (disguise.isDisguiseInUse() && disguise.getEntity() instanceof Player
|
||||
&& ((Player) disguise.getEntity()).getName().equalsIgnoreCase(player)) {
|
||||
removeSelfDisguise((Player) disguise.getEntity());
|
||||
if (disguise.isSelfDisguiseVisible())
|
||||
selfDisguised.add(disguise.getEntity().getUniqueId());
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket((Player) disguise.getEntity(), destroyPacket);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
DisguiseUtilities.sendSelfDisguise((Player) disguise.getEntity(), disguise);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 2);
|
||||
} else {
|
||||
final Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
|
||||
if (entityTrackerEntry != null) {
|
||||
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers")
|
||||
.get(entityTrackerEntry);
|
||||
Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear",
|
||||
ReflectionManager.getNmsClass("EntityPlayer"));
|
||||
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
|
||||
ReflectionManager.getNmsClass("EntityPlayer"));
|
||||
HashSet cloned = (HashSet) trackedPlayers.clone();
|
||||
for (final Object p : cloned) {
|
||||
Player pl = (Player) ReflectionManager.getBukkitEntity(p);
|
||||
if (player.equalsIgnoreCase((pl).getName())) {
|
||||
clear.invoke(entityTrackerEntry, p);
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(pl, destroyPacket);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
updatePlayer.invoke(entityTrackerEntry, p);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for me to refresh trackers in other plugins
|
||||
*/
|
||||
public static void refreshTrackers(Entity entity) {
|
||||
if (entity.isValid()) {
|
||||
try {
|
||||
PacketContainer destroyPacket = getDestroyPacket(entity.getEntityId());
|
||||
final Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(entity);
|
||||
if (entityTrackerEntry != null) {
|
||||
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
|
||||
entityTrackerEntry);
|
||||
Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear",
|
||||
ReflectionManager.getNmsClass("EntityPlayer"));
|
||||
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
|
||||
ReflectionManager.getNmsClass("EntityPlayer"));
|
||||
HashSet cloned = (HashSet) trackedPlayers.clone();
|
||||
for (final Object p : cloned) {
|
||||
Player player = (Player) ReflectionManager.getBukkitEntity(p);
|
||||
if (player != entity) {
|
||||
clear.invoke(entityTrackerEntry, p);
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, destroyPacket);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
updatePlayer.invoke(entityTrackerEntry, p);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resends the entity to all the watching players, which is where the magic begins
|
||||
*/
|
||||
public static void refreshTrackers(final TargetedDisguise disguise) {
|
||||
if (disguise.getEntity().isValid()) {
|
||||
PacketContainer destroyPacket = getDestroyPacket(disguise.getEntity().getEntityId());
|
||||
try {
|
||||
if (selfDisguised.contains(disguise.getEntity().getUniqueId()) && disguise.isDisguiseInUse()) {
|
||||
removeSelfDisguise((Player) disguise.getEntity());
|
||||
selfDisguised.add(disguise.getEntity().getUniqueId());
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket((Player) disguise.getEntity(), destroyPacket);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
DisguiseUtilities.sendSelfDisguise((Player) disguise.getEntity(), disguise);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 2);
|
||||
}
|
||||
final Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
|
||||
if (entityTrackerEntry != null) {
|
||||
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
|
||||
entityTrackerEntry);
|
||||
Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear",
|
||||
ReflectionManager.getNmsClass("EntityPlayer"));
|
||||
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
|
||||
ReflectionManager.getNmsClass("EntityPlayer"));
|
||||
HashSet cloned = (HashSet) trackedPlayers.clone();
|
||||
for (final Object p : cloned) {
|
||||
Player player = (Player) ReflectionManager.getBukkitEntity(p);
|
||||
if (disguise.getEntity() != player && disguise.canSee(player)) {
|
||||
clear.invoke(entityTrackerEntry, p);
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, destroyPacket);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
updatePlayer.invoke(entityTrackerEntry, p);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean removeDisguise(TargetedDisguise disguise) {
|
||||
UUID entityId = disguise.getEntity().getUniqueId();
|
||||
if (getDisguises().containsKey(entityId) && getDisguises().get(entityId).remove(disguise)) {
|
||||
if (getDisguises().get(entityId).isEmpty()) {
|
||||
getDisguises().remove(entityId);
|
||||
}
|
||||
if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS && disguise.isModifyBoundingBox()) {
|
||||
doBoundingBox(disguise);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void removeGameprofile(String string) {
|
||||
removeGameProfile(string);
|
||||
}
|
||||
|
||||
public static void removeGameProfile(String string) {
|
||||
gameProfiles.remove(string.toLowerCase());
|
||||
}
|
||||
|
||||
public static void removeSelfDisguise(Player player) {
|
||||
if (selfDisguised.contains(player.getUniqueId())) {
|
||||
// Send a packet to destroy the fake entity
|
||||
PacketContainer packet = getDestroyPacket(DisguiseAPI.getSelfDisguiseId());
|
||||
try {
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
// Remove the fake entity ID from the disguise bin
|
||||
selfDisguised.remove(player.getUniqueId());
|
||||
// Get the entity tracker
|
||||
try {
|
||||
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(player);
|
||||
if (entityTrackerEntry != null) {
|
||||
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
|
||||
entityTrackerEntry);
|
||||
// If the tracker exists. Remove himself from his tracker
|
||||
trackedPlayers.remove(ReflectionManager.getNmsEntity(player));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
// Resend entity metadata else he will be invisible to himself until its resent
|
||||
try {
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(
|
||||
player,
|
||||
ProtocolLibrary
|
||||
.getProtocolManager()
|
||||
.createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, player.getEntityId(),
|
||||
WrappedDataWatcher.getEntityWatcher(player), true)
|
||||
.createPacket(player.getEntityId(), WrappedDataWatcher.getEntityWatcher(player), true));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the self disguise to the player
|
||||
*/
|
||||
public static void sendSelfDisguise(final Player player, final TargetedDisguise disguise) {
|
||||
try {
|
||||
if (!disguise.isDisguiseInUse() || !player.isValid() || !player.isOnline() || !disguise.isSelfDisguiseVisible()
|
||||
|| !disguise.canSee(player)) {
|
||||
return;
|
||||
}
|
||||
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(player);
|
||||
if (entityTrackerEntry == null) {
|
||||
// A check incase the tracker is null.
|
||||
// If it is, then this method will be run again in one tick. Which is when it should be constructed.
|
||||
// Else its going to run in a infinite loop hue hue hue..
|
||||
// At least until this disguise is discarded
|
||||
Bukkit.getScheduler().runTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
if (DisguiseAPI.getDisguise(player, player) == disguise) {
|
||||
sendSelfDisguise(player, disguise);
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Add himself to his own entity tracker
|
||||
((HashSet<Object>) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry))
|
||||
.add(ReflectionManager.getNmsEntity(player));
|
||||
ProtocolManager manager = ProtocolLibrary.getProtocolManager();
|
||||
// Send the player a packet with himself being spawned
|
||||
manager.sendServerPacket(player, manager.createPacketConstructor(PacketType.Play.Server.NAMED_ENTITY_SPAWN, player)
|
||||
.createPacket(player));
|
||||
WrappedDataWatcher dataWatcher = WrappedDataWatcher.getEntityWatcher(player);
|
||||
sendSelfPacket(
|
||||
player,
|
||||
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, player.getEntityId(), dataWatcher,
|
||||
true).createPacket(player.getEntityId(), dataWatcher, true));
|
||||
|
||||
boolean isMoving = false;
|
||||
try {
|
||||
Field field = ReflectionManager.getNmsClass("EntityTrackerEntry").getDeclaredField("isMoving");
|
||||
field.setAccessible(true);
|
||||
isMoving = field.getBoolean(entityTrackerEntry);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
// Send the velocity packets
|
||||
if (isMoving) {
|
||||
Vector velocity = player.getVelocity();
|
||||
sendSelfPacket(
|
||||
player,
|
||||
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_VELOCITY, player.getEntityId(),
|
||||
velocity.getX(), velocity.getY(), velocity.getZ()).createPacket(player.getEntityId(),
|
||||
velocity.getX(), velocity.getY(), velocity.getZ()));
|
||||
}
|
||||
|
||||
// Why the hell would he even need this. Meh.
|
||||
if (player.getVehicle() != null && player.getEntityId() > player.getVehicle().getEntityId()) {
|
||||
sendSelfPacket(player,
|
||||
manager.createPacketConstructor(PacketType.Play.Server.ATTACH_ENTITY, 0, player, player.getVehicle())
|
||||
.createPacket(0, player, player.getVehicle()));
|
||||
} else if (player.getPassenger() != null && player.getEntityId() > player.getPassenger().getEntityId()) {
|
||||
sendSelfPacket(player,
|
||||
manager.createPacketConstructor(PacketType.Play.Server.ATTACH_ENTITY, 0, player.getPassenger(), player)
|
||||
.createPacket(0, player.getPassenger(), player));
|
||||
}
|
||||
|
||||
// Resend the armor
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ItemStack item;
|
||||
if (i == 0) {
|
||||
item = player.getItemInHand();
|
||||
} else {
|
||||
item = player.getInventory().getArmorContents()[i - 1];
|
||||
}
|
||||
|
||||
if (item != null && item.getType() != Material.AIR) {
|
||||
sendSelfPacket(
|
||||
player,
|
||||
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_EQUIPMENT, player.getEntityId(), i,
|
||||
item).createPacket(player.getEntityId(), i, item));
|
||||
}
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
// If the disguised is sleeping for w/e reason
|
||||
if (player.isSleeping()) {
|
||||
sendSelfPacket(
|
||||
player,
|
||||
manager.createPacketConstructor(PacketType.Play.Server.BED, player, loc.getBlockX(), loc.getBlockY(),
|
||||
loc.getBlockZ()).createPacket(player, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
|
||||
// Resend any active potion effects
|
||||
for (PotionEffect potionEffect : player.getActivePotionEffects()) {
|
||||
Object mobEffect = ReflectionManager.createMobEffect(potionEffect);
|
||||
sendSelfPacket(player,
|
||||
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_EFFECT, player.getEntityId(), mobEffect)
|
||||
.createPacket(player.getEntityId(), mobEffect));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a packet to the self disguise, translate his entity ID to the fake id.
|
||||
*/
|
||||
private static void sendSelfPacket(final Player player, PacketContainer packet) {
|
||||
PacketContainer[][] transformed = PacketsManager.transformPacket(packet, player, player);
|
||||
PacketContainer[] packets = transformed == null ? null : transformed[0];
|
||||
final PacketContainer[] delayed = transformed == null ? null : transformed[1];
|
||||
try {
|
||||
if (packets == null) {
|
||||
packets = new PacketContainer[] { packet };
|
||||
}
|
||||
for (PacketContainer p : packets) {
|
||||
p = p.deepClone();
|
||||
p.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId());
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, p, false);
|
||||
}
|
||||
if (delayed != null && delayed.length > 0) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
for (PacketContainer packet : delayed) {
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false);
|
||||
}
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup it so he can see himself when disguised
|
||||
*/
|
||||
public static void setupFakeDisguise(final Disguise disguise) {
|
||||
Entity e = disguise.getEntity();
|
||||
// If the disguises entity is null, or the disguised entity isn't a player return
|
||||
if (e == null || !(e instanceof Player) || !getDisguises().containsKey(e.getUniqueId())
|
||||
|| !getDisguises().get(e.getUniqueId()).contains(disguise)) {
|
||||
return;
|
||||
}
|
||||
Player player = (Player) e;
|
||||
// Check if he can even see this..
|
||||
if (!((TargetedDisguise) disguise).canSee(player)) {
|
||||
return;
|
||||
}
|
||||
// Remove the old disguise, else we have weird disguises around the place
|
||||
DisguiseUtilities.removeSelfDisguise(player);
|
||||
// If the disguised player can't see himself. Return
|
||||
if (!disguise.isSelfDisguiseVisible() || !PacketsManager.isViewDisguisesListenerEnabled() || player.getVehicle() != null) {
|
||||
return;
|
||||
}
|
||||
selfDisguised.add(player.getUniqueId());
|
||||
sendSelfDisguise(player, (TargetedDisguise) disguise);
|
||||
if (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf()) {
|
||||
if (PacketsManager.isInventoryListenerEnabled()) {
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
|
||||
public class DisguiseValues {
|
||||
|
||||
private static HashMap<DisguiseType, DisguiseValues> values = new HashMap<DisguiseType, DisguiseValues>();
|
||||
|
||||
public static DisguiseValues getDisguiseValues(DisguiseType type) {
|
||||
switch (type) {
|
||||
case DONKEY:
|
||||
case MULE:
|
||||
case UNDEAD_HORSE:
|
||||
case SKELETON_HORSE:
|
||||
type = DisguiseType.HORSE;
|
||||
break;
|
||||
case MINECART_CHEST:
|
||||
case MINECART_COMMAND:
|
||||
case MINECART_FURNACE:
|
||||
case MINECART_HOPPER:
|
||||
case MINECART_TNT:
|
||||
case MINECART_MOB_SPAWNER:
|
||||
type = DisguiseType.MINECART;
|
||||
break;
|
||||
case WITHER_SKELETON:
|
||||
type = DisguiseType.SKELETON;
|
||||
break;
|
||||
case ZOMBIE_VILLAGER:
|
||||
type = DisguiseType.ZOMBIE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return values.get(type);
|
||||
}
|
||||
|
||||
public static HashMap<Integer, Object> getMetaValues(DisguiseType type) {
|
||||
return getDisguiseValues(type).getMetaValues();
|
||||
}
|
||||
|
||||
public static Class getNmsEntityClass(DisguiseType type) {
|
||||
return getDisguiseValues(type).getNmsEntityClass();
|
||||
}
|
||||
|
||||
private FakeBoundingBox adultBox;
|
||||
private FakeBoundingBox babyBox;
|
||||
private float[] entitySize;
|
||||
private int enumEntitySize;
|
||||
private double maxHealth;
|
||||
private HashMap<Integer, Object> metaValues = new HashMap<Integer, Object>();
|
||||
private Class nmsEntityClass;
|
||||
|
||||
public DisguiseValues(DisguiseType type, Class classType, int entitySize, double maxHealth) {
|
||||
values.put(type, this);
|
||||
enumEntitySize = entitySize;
|
||||
nmsEntityClass = classType;
|
||||
this.maxHealth = maxHealth;
|
||||
}
|
||||
|
||||
public FakeBoundingBox getAdultBox() {
|
||||
return adultBox;
|
||||
}
|
||||
|
||||
public FakeBoundingBox getBabyBox() {
|
||||
return babyBox;
|
||||
}
|
||||
|
||||
public float[] getEntitySize() {
|
||||
return entitySize;
|
||||
}
|
||||
|
||||
public int getEntitySize(double paramDouble) {
|
||||
double d = paramDouble - (((int) Math.floor(paramDouble)) + 0.5D);
|
||||
|
||||
switch (enumEntitySize) {
|
||||
case 1:
|
||||
if (d < 0.0D ? d < -0.3125D : d < 0.3125D) {
|
||||
return (int) Math.ceil(paramDouble * 32.0D);
|
||||
}
|
||||
|
||||
return (int) Math.floor(paramDouble * 32.0D);
|
||||
case 2:
|
||||
if (d < 0.0D ? d < -0.3125D : d < 0.3125D) {
|
||||
return (int) Math.floor(paramDouble * 32.0D);
|
||||
}
|
||||
|
||||
return (int) Math.ceil(paramDouble * 32.0D);
|
||||
case 3:
|
||||
if (d > 0.0D) {
|
||||
return (int) Math.floor(paramDouble * 32.0D);
|
||||
}
|
||||
|
||||
return (int) Math.ceil(paramDouble * 32.0D);
|
||||
case 4:
|
||||
if (d < 0.0D ? d < -0.1875D : d < 0.1875D) {
|
||||
return (int) Math.ceil(paramDouble * 32.0D);
|
||||
}
|
||||
|
||||
return (int) Math.floor(paramDouble * 32.0D);
|
||||
case 5:
|
||||
if (d < 0.0D ? d < -0.1875D : d < 0.1875D) {
|
||||
return (int) Math.floor(paramDouble * 32.0D);
|
||||
}
|
||||
|
||||
return (int) Math.ceil(paramDouble * 32.0D);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (d > 0.0D) {
|
||||
return (int) Math.ceil(paramDouble * 32.0D);
|
||||
}
|
||||
|
||||
return (int) Math.floor(paramDouble * 32.0D);
|
||||
}
|
||||
|
||||
public double getMaxHealth() {
|
||||
return maxHealth;
|
||||
}
|
||||
|
||||
public HashMap<Integer, Object> getMetaValues() {
|
||||
return metaValues;
|
||||
}
|
||||
|
||||
public Class getNmsEntityClass() {
|
||||
return nmsEntityClass;
|
||||
}
|
||||
|
||||
public void setAdultBox(FakeBoundingBox newBox) {
|
||||
adultBox = newBox;
|
||||
}
|
||||
|
||||
public void setBabyBox(FakeBoundingBox newBox) {
|
||||
babyBox = newBox;
|
||||
}
|
||||
|
||||
public void setEntitySize(float[] size) {
|
||||
this.entitySize = size;
|
||||
}
|
||||
|
||||
public void setMetaValue(int no, Object value) {
|
||||
metaValues.put(no, value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
public class FakeBoundingBox {
|
||||
private double xMod;
|
||||
private double yMod;
|
||||
private double zMod;
|
||||
|
||||
public FakeBoundingBox(double xMod, double yMod, double zMod) {
|
||||
this.xMod = xMod;
|
||||
this.yMod = yMod;
|
||||
this.zMod = zMod;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return xMod / 2;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return yMod;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return zMod / 2;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
|
||||
public interface LibsProfileLookup {
|
||||
public void onLookup(WrappedGameProfile gameProfile);
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.ProfileLookupCallback;
|
||||
|
||||
public class LibsProfileLookupCaller implements ProfileLookupCallback {
|
||||
private WrappedGameProfile gameProfile;
|
||||
|
||||
public WrappedGameProfile getGameProfile() {
|
||||
return gameProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProfileLookupFailed(GameProfile gameProfile, Exception arg1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProfileLookupSucceeded(GameProfile profile) {
|
||||
gameProfile = WrappedGameProfile.fromHandle(profile);
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,633 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.bukkit.Art;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
public class ReflectionManager {
|
||||
|
||||
public enum LibVersion {
|
||||
V1_8;
|
||||
private static LibVersion currentVersion;
|
||||
static {
|
||||
//String mcVersion = Bukkit.getVersion().split("MC: ")[1].replace(")", "");
|
||||
currentVersion = V1_8;
|
||||
}
|
||||
|
||||
public static LibVersion getGameVersion() {
|
||||
return currentVersion;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String bukkitVersion = Bukkit.getServer().getClass().getName().split("\\.")[3];
|
||||
private static final Class<?> craftItemClass;
|
||||
private static Method damageAndIdleSoundMethod;
|
||||
private static final Field entitiesField;
|
||||
private static final Constructor<?> boundingBoxConstructor;
|
||||
private static final Method setBoundingBoxMethod;
|
||||
/**
|
||||
* Map of mc-dev simple class name to fully qualified Forge class name.
|
||||
*/
|
||||
private static Map<String, String> ForgeClassMappings;
|
||||
/**
|
||||
* Map of Forge fully qualified class names to a map from mc-dev field names to Forge field names.
|
||||
*/
|
||||
private static Map<String, Map<String, String>> ForgeFieldMappings;
|
||||
|
||||
/**
|
||||
* Map of Forge fully qualified class names to a map from mc-dev method names to a map from method signatures to Forge method
|
||||
* names.
|
||||
*/
|
||||
private static Map<String, Map<String, Map<String, String>>> ForgeMethodMappings;
|
||||
private static final Method ihmGet;
|
||||
private static final boolean isForge = Bukkit.getServer().getName().contains("Cauldron")
|
||||
|| Bukkit.getServer().getName().contains("MCPC-Plus");
|
||||
private static final Field pingField;
|
||||
private static Map<Class<?>, String> primitiveTypes;
|
||||
private static final Field trackerField;
|
||||
|
||||
/*
|
||||
* This portion of code is originally Copyright (C) 2014-2014 Kane York.
|
||||
*
|
||||
* In addition to the implicit license granted to libraryaddict to redistribuite the code, the
|
||||
* code is also licensed to the public under the BSD 2-clause license.
|
||||
*
|
||||
* The publicly licensed version may be viewed here: https://gist.github.com/riking/2f330f831c30e2276df7
|
||||
*/
|
||||
static {
|
||||
final String nameseg_class = "a-zA-Z0-9$_";
|
||||
final String fqn_class = nameseg_class + "/";
|
||||
|
||||
primitiveTypes = ImmutableMap.<Class<?>, String> builder().put(boolean.class, "Z").put(byte.class, "B")
|
||||
.put(char.class, "C").put(short.class, "S").put(int.class, "I").put(long.class, "J").put(float.class, "F")
|
||||
.put(double.class, "D").put(void.class, "V").build();
|
||||
|
||||
if (isForge) {
|
||||
// Initialize the maps by reading the srg file
|
||||
ForgeClassMappings = new HashMap<String, String>();
|
||||
ForgeFieldMappings = new HashMap<String, Map<String, String>>();
|
||||
ForgeMethodMappings = new HashMap<String, Map<String, Map<String, String>>>();
|
||||
try {
|
||||
InputStream stream = Class.forName("net.minecraftforge.common.MinecraftForge").getClassLoader()
|
||||
.getResourceAsStream("mappings/" + getBukkitVersion() + "/cb2numpkg.srg");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||
|
||||
// 1: cb-simpleName
|
||||
// 2: forge-fullName (Needs dir2fqn())
|
||||
Pattern classPattern = Pattern.compile("^CL: net/minecraft/server/([" + nameseg_class + "]+) ([" + fqn_class
|
||||
+ "]+)$");
|
||||
// 1: cb-simpleName
|
||||
// 2: cb-fieldName
|
||||
// 3: forge-fullName (Needs dir2fqn())
|
||||
// 4: forge-fieldName
|
||||
Pattern fieldPattern = Pattern.compile("^FD: net/minecraft/server/([" + nameseg_class + "]+)/([" + nameseg_class
|
||||
+ "]+) ([" + fqn_class + "]+)/([" + nameseg_class + "]+)$");
|
||||
// 1: cb-simpleName
|
||||
// 2: cb-methodName
|
||||
// 3: cb-signature-args
|
||||
// 4: cb-signature-ret
|
||||
// 5: forge-fullName (Needs dir2fqn())
|
||||
// 6: forge-methodName
|
||||
// 7: forge-signature-args
|
||||
// 8: forge-signature-ret
|
||||
Pattern methodPattern = Pattern.compile("^MD: net/minecraft/server/([" + fqn_class + "]+)/([" + nameseg_class
|
||||
+ "]+) \\(([;\\[" + fqn_class + "]*)\\)([;\\[" + fqn_class + "]+) " + "([" + fqn_class + "]+)/(["
|
||||
+ nameseg_class + "]+) \\(([;\\[" + fqn_class + "]*)\\)([;\\[" + fqn_class + "]+)$");
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
Matcher classMatcher = classPattern.matcher(line);
|
||||
if (classMatcher.matches()) {
|
||||
// by CB class name
|
||||
ForgeClassMappings.put(classMatcher.group(1), dir2fqn(classMatcher.group(2)));
|
||||
continue;
|
||||
}
|
||||
Matcher fieldMatcher = fieldPattern.matcher(line);
|
||||
if (fieldMatcher.matches()) {
|
||||
// by CB class name
|
||||
Map<String, String> innerMap = ForgeFieldMappings.get(dir2fqn(fieldMatcher.group(3)));
|
||||
if (innerMap == null) {
|
||||
innerMap = new HashMap<String, String>();
|
||||
ForgeFieldMappings.put(dir2fqn(fieldMatcher.group(3)), innerMap);
|
||||
}
|
||||
// by CB field name to Forge field name
|
||||
innerMap.put(fieldMatcher.group(2), fieldMatcher.group(4));
|
||||
continue;
|
||||
}
|
||||
Matcher methodMatcher = methodPattern.matcher(line);
|
||||
if (methodMatcher.matches()) {
|
||||
// get by CB class name
|
||||
Map<String, Map<String, String>> middleMap = ForgeMethodMappings.get(dir2fqn(methodMatcher.group(5)));
|
||||
if (middleMap == null) {
|
||||
middleMap = new HashMap<String, Map<String, String>>();
|
||||
ForgeMethodMappings.put(dir2fqn(methodMatcher.group(5)), middleMap);
|
||||
}
|
||||
// get by CB method name
|
||||
Map<String, String> innerMap = middleMap.get(methodMatcher.group(2));
|
||||
if (innerMap == null) {
|
||||
innerMap = new HashMap<String, String>();
|
||||
middleMap.put(methodMatcher.group(2), innerMap);
|
||||
}
|
||||
// store the parameter strings
|
||||
innerMap.put(methodMatcher.group(3), methodMatcher.group(6));
|
||||
innerMap.put(methodMatcher.group(7), methodMatcher.group(6));
|
||||
}
|
||||
}
|
||||
System.out.println("[LibsDisguises] Loaded in Cauldron/Forge mode");
|
||||
System.out.println("[LibsDisguises] Loaded " + ForgeClassMappings.size() + " Cauldron class mappings");
|
||||
System.out.println("[LibsDisguises] Loaded " + ForgeFieldMappings.size() + " Cauldron field mappings");
|
||||
System.out.println("[LibsDisguises] Loaded " + ForgeMethodMappings.size() + " Cauldron method mappings");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
System.err
|
||||
.println("Warning: Running on Cauldron server, but couldn't load mappings file. LibsDisguises will likely crash!");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.err
|
||||
.println("Warning: Running on Cauldron server, but couldn't load mappings file. LibsDisguises will likely crash!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
for (Method method : getNmsClass("EntityLiving").getDeclaredMethods()) {
|
||||
try {
|
||||
if (method.getReturnType() == float.class && Modifier.isProtected(method.getModifiers())
|
||||
&& method.getParameterTypes().length == 0) {
|
||||
Object entity = createEntityInstance("Cow");
|
||||
method.setAccessible(true);
|
||||
float value = (Float) method.invoke(entity);
|
||||
if (value == 0.4F) {
|
||||
damageAndIdleSoundMethod = method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
craftItemClass = getCraftClass("inventory.CraftItemStack");
|
||||
pingField = getNmsField("EntityPlayer", "ping");
|
||||
trackerField = getNmsField("WorldServer", "tracker");
|
||||
entitiesField = getNmsField("EntityTracker", "trackedEntities");
|
||||
ihmGet = getNmsMethod("IntHashMap", "get", int.class);
|
||||
boundingBoxConstructor = getNmsConstructor("AxisAlignedBB",double.class, double.class, double.class,
|
||||
double.class, double.class, double.class);
|
||||
setBoundingBoxMethod = getNmsMethod("Entity", "a", getNmsClass("AxisAlignedBB"));
|
||||
}
|
||||
|
||||
public static Object createEntityInstance(String entityName) {
|
||||
try {
|
||||
Class<?> entityClass = getNmsClass("Entity" + entityName);
|
||||
Object entityObject;
|
||||
Object world = getWorld(Bukkit.getWorlds().get(0));
|
||||
if (entityName.equals("Player")) {
|
||||
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
|
||||
Object playerinteractmanager = getNmsClass("PlayerInteractManager").getConstructor(getNmsClass("World"))
|
||||
.newInstance(world);
|
||||
WrappedGameProfile gameProfile = getGameProfile(null, "LibsDisguises");
|
||||
entityObject = entityClass.getConstructor(getNmsClass("MinecraftServer"), getNmsClass("WorldServer"),
|
||||
gameProfile.getHandleType(), playerinteractmanager.getClass()).newInstance(minecraftServer, world,
|
||||
gameProfile.getHandle(), playerinteractmanager);
|
||||
} else if (entityName.equals("EnderPearl")) {
|
||||
entityObject = entityClass.getConstructor(getNmsClass("World"), getNmsClass("EntityLiving"))
|
||||
.newInstance(world, createEntityInstance("Cow"));
|
||||
} else {
|
||||
entityObject = entityClass.getConstructor(getNmsClass("World")).newInstance(world);
|
||||
}
|
||||
return entityObject;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object createMobEffect(int id, int duration, int amplification, boolean ambient, boolean particles) {
|
||||
try {
|
||||
return getNmsClass("MobEffect").getConstructor(int.class, int.class, int.class, boolean.class, boolean.class)
|
||||
.newInstance(id, duration, amplification, ambient, particles);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object createMobEffect(PotionEffect effect) {
|
||||
return createMobEffect(effect.getType().getId(), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles());
|
||||
}
|
||||
|
||||
private static String dir2fqn(String s) {
|
||||
return s.replaceAll("/", ".");
|
||||
}
|
||||
|
||||
public static FakeBoundingBox getBoundingBox(Entity entity) {
|
||||
try {
|
||||
Object boundingBox = getNmsMethod("Entity", "getBoundingBox").invoke(getNmsEntity(entity));
|
||||
double x = 0, y = 0, z = 0;
|
||||
int stage = 0;
|
||||
for (Field field : boundingBox.getClass().getFields()) {
|
||||
if (field.getType().getSimpleName().equals("double")) {
|
||||
stage++;
|
||||
switch (stage) {
|
||||
case 1:
|
||||
x -= field.getDouble(boundingBox);
|
||||
break;
|
||||
case 2:
|
||||
y -= field.getDouble(boundingBox);
|
||||
break;
|
||||
case 3:
|
||||
z -= field.getDouble(boundingBox);
|
||||
break;
|
||||
case 4:
|
||||
x += field.getDouble(boundingBox);
|
||||
break;
|
||||
case 5:
|
||||
y += field.getDouble(boundingBox);
|
||||
break;
|
||||
case 6:
|
||||
z += field.getDouble(boundingBox);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Error while setting the bounding box, more doubles than I thought??");
|
||||
}
|
||||
}
|
||||
}
|
||||
return new FakeBoundingBox(x, y, z);
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Entity getBukkitEntity(Object nmsEntity) {
|
||||
try {
|
||||
return (Entity) getNmsMethod("Entity", "getBukkitEntity").invoke(nmsEntity);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ItemStack getBukkitItem(Object nmsItem) {
|
||||
try {
|
||||
return (ItemStack) craftItemClass.getMethod("asBukkitCopy", getNmsClass("ItemStack")).invoke(null, nmsItem);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getBukkitVersion() {
|
||||
return bukkitVersion;
|
||||
}
|
||||
|
||||
public static Class<?> getCraftClass(String className) {
|
||||
try {
|
||||
return Class.forName("org.bukkit.craftbukkit." + getBukkitVersion() + "." + className);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getCraftSound(Sound sound) {
|
||||
try {
|
||||
return (String) getCraftClass("CraftSound").getMethod("getSound", Sound.class).invoke(null, sound);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getEntityTrackerEntry(Entity target) throws Exception {
|
||||
Object world = getWorld(target.getWorld());
|
||||
Object tracker = trackerField.get(world);
|
||||
Object trackedEntities = entitiesField.get(tracker);
|
||||
return ihmGet.invoke(trackedEntities, target.getEntityId());
|
||||
}
|
||||
|
||||
public static String getEnumArt(Art art) {
|
||||
try {
|
||||
Object enumArt = getCraftClass("CraftArt").getMethod("BukkitToNotch", Art.class).invoke(null, art);
|
||||
for (Field field : enumArt.getClass().getFields()) {
|
||||
if (field.getType() == String.class) {
|
||||
return (String) field.get(enumArt);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getBlockPosition(int x, int y, int z) {
|
||||
try {
|
||||
return getNmsClass("BlockPosition").getConstructor(int.class, int.class, int.class).newInstance(x, y, z);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Enum getEnumDirection(int direction) {
|
||||
try {
|
||||
return (Enum) getNmsMethod("EnumDirection", "fromType2", int.class).invoke(null, direction);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Enum getEnumPlayerInfoAction(int action) {
|
||||
try {
|
||||
return (Enum) getNmsClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction").getEnumConstants()[action];
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getPlayerInfoData(Object playerInfoPacket, WrappedGameProfile gameProfile) {
|
||||
try {
|
||||
Object playerListName = getNmsClass("ChatComponentText").getConstructor(String.class)
|
||||
.newInstance(gameProfile.getName());
|
||||
return getNmsClass("PacketPlayOutPlayerInfo$PlayerInfoData").getConstructor(getNmsClass("PacketPlayOutPlayerInfo"),
|
||||
gameProfile.getHandleType(), int.class, getNmsClass("WorldSettings$EnumGamemode"), getNmsClass("IChatBaseComponent"))
|
||||
.newInstance(playerInfoPacket, gameProfile.getHandle(), 0,
|
||||
getNmsClass("WorldSettings$EnumGamemode").getEnumConstants()[1], playerListName);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static WrappedGameProfile getGameProfile(Player player) {
|
||||
return WrappedGameProfile.fromPlayer(player);
|
||||
}
|
||||
|
||||
public static WrappedGameProfile getGameProfile(UUID uuid, String playerName) {
|
||||
try {
|
||||
return new WrappedGameProfile(uuid != null ? uuid : UUID.randomUUID(), playerName);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static WrappedGameProfile getGameProfileWithThisSkin(UUID uuid, String playerName, WrappedGameProfile profileWithSkin) {
|
||||
try {
|
||||
WrappedGameProfile gameProfile = new WrappedGameProfile(uuid != null ? uuid : UUID.randomUUID(), playerName);
|
||||
gameProfile.getProperties().putAll(profileWithSkin.getProperties());
|
||||
return gameProfile;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class getNmsClass(String className) {
|
||||
if (isForge) {
|
||||
String forgeName = ForgeClassMappings.get(className);
|
||||
if (forgeName != null) {
|
||||
try {
|
||||
return Class.forName(forgeName);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
} else {
|
||||
// Throw, because the default cannot possibly work
|
||||
throw new RuntimeException("Missing Forge mapping for " + className);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return Class.forName("net.minecraft.server." + getBukkitVersion() + "." + className);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Constructor getNmsConstructor(Class clazz, Class<?>... parameters) {
|
||||
try {
|
||||
return clazz.getConstructor(parameters);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Constructor getNmsConstructor(String className, Class<?>... parameters) {
|
||||
return getNmsConstructor(getNmsClass(className), parameters);
|
||||
}
|
||||
|
||||
public static Object getNmsEntity(Entity entity) {
|
||||
try {
|
||||
return getCraftClass("entity.CraftEntity").getMethod("getHandle").invoke(entity);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Field getNmsField(Class clazz, String fieldName) {
|
||||
if (isForge) {
|
||||
try {
|
||||
return clazz.getField(ForgeFieldMappings.get(clazz.getName()).get(fieldName));
|
||||
} catch (NoSuchFieldException ex) {
|
||||
ex.printStackTrace();
|
||||
} catch (NullPointerException ignored) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
return clazz.getField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Field getNmsField(String className, String fieldName) {
|
||||
return getNmsField(getNmsClass(className), fieldName);
|
||||
}
|
||||
|
||||
public static Object getNmsItem(ItemStack itemstack) {
|
||||
try {
|
||||
return craftItemClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemstack);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Method getNmsMethod(Class<?> clazz, String methodName, Class<?>... parameters) {
|
||||
if (isForge) {
|
||||
try {
|
||||
Map<String, String> innerMap = ForgeMethodMappings.get(clazz.getName()).get(methodName);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Class<?> cl : parameters) {
|
||||
sb.append(methodSignaturePart(cl));
|
||||
}
|
||||
return clazz.getMethod(innerMap.get(sb.toString()), parameters);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NullPointerException ignored) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
return clazz.getMethod(methodName, parameters);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Method getNmsMethod(String className, String methodName, Class<?>... parameters) {
|
||||
return getNmsMethod(getNmsClass(className), methodName, parameters);
|
||||
}
|
||||
|
||||
public static double getPing(Player player) {
|
||||
try {
|
||||
return (double) pingField.getInt(ReflectionManager.getNmsEntity(player));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return 0D;
|
||||
}
|
||||
|
||||
public static float[] getSize(Entity entity) {
|
||||
try {
|
||||
float length = getNmsField("Entity", "length").getFloat(getNmsEntity(entity));
|
||||
float width = getNmsField("Entity", "width").getFloat(getNmsEntity(entity));
|
||||
float height = (Float) getNmsMethod("Entity", "getHeadHeight").invoke(getNmsEntity(entity));
|
||||
return new float[] { length, width, height };
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static WrappedGameProfile getSkullBlob(WrappedGameProfile gameProfile) {
|
||||
try {
|
||||
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
|
||||
for (Method method : getNmsClass("MinecraftServer").getMethods()) {
|
||||
if (method.getReturnType().getSimpleName().equals("MinecraftSessionService")) {
|
||||
Object session = method.invoke(minecraftServer);
|
||||
return WrappedGameProfile.fromHandle(session.getClass()
|
||||
.getMethod("fillProfileProperties", gameProfile.getHandleType(), boolean.class)
|
||||
.invoke(session, gameProfile.getHandle(), true));
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Float getSoundModifier(Object entity) {
|
||||
try {
|
||||
damageAndIdleSoundMethod.setAccessible(true);
|
||||
return (Float) damageAndIdleSoundMethod.invoke(entity);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getWorld(World world) {
|
||||
try {
|
||||
return getCraftClass("CraftWorld").getMethod("getHandle").invoke(world);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static WrappedGameProfile grabProfileAddUUID(String playername) {
|
||||
try {
|
||||
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
|
||||
for (Method method : getNmsClass("MinecraftServer").getMethods()) {
|
||||
if (method.getReturnType().getSimpleName().equals("GameProfileRepository")) {
|
||||
Object profileRepo = method.invoke(minecraftServer);
|
||||
Object agent = Class.forName("com.mojang.authlib.Agent").getField("MINECRAFT").get(null);
|
||||
LibsProfileLookupCaller callback = new LibsProfileLookupCaller();
|
||||
profileRepo
|
||||
.getClass()
|
||||
.getMethod("findProfilesByNames", String[].class, agent.getClass(),
|
||||
Class.forName("com.mojang.authlib.ProfileLookupCallback"))
|
||||
.invoke(profileRepo, new String[] { playername }, agent, callback);
|
||||
if (callback.getGameProfile() != null) {
|
||||
return callback.getGameProfile();
|
||||
}
|
||||
return getGameProfile(null, playername);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isForge() {
|
||||
return isForge;
|
||||
}
|
||||
|
||||
private static String methodSignaturePart(Class<?> param) {
|
||||
if (param.isArray()) {
|
||||
return "[" + methodSignaturePart(param.getComponentType());
|
||||
} else if (param.isPrimitive()) {
|
||||
return primitiveTypes.get(param);
|
||||
} else {
|
||||
return "L" + param.getName().replaceAll("\\.", "/") + ";";
|
||||
}
|
||||
}
|
||||
|
||||
public static void removePlayer(Player player) {
|
||||
|
||||
}
|
||||
|
||||
public static void setAllowSleep(Player player) {
|
||||
try {
|
||||
Object nmsEntity = getNmsEntity(player);
|
||||
Object connection = getNmsField(nmsEntity.getClass(), "playerConnection").get(nmsEntity);
|
||||
Field check = getNmsField(connection.getClass(), "checkMovement");
|
||||
check.setBoolean(connection, true);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setBoundingBox(Entity entity, FakeBoundingBox newBox) {
|
||||
try {
|
||||
Location loc = entity.getLocation();
|
||||
Object boundingBox = boundingBoxConstructor.newInstance(loc.getX() - newBox.getX(), loc.getY() - newBox.getY(),
|
||||
loc.getZ() - newBox.getZ(), loc.getX() + newBox.getX(), loc.getY() + newBox.getY(), loc.getZ() + newBox.getZ());
|
||||
setBoundingBoxMethod.invoke(getNmsEntity(entity), boundingBox);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class UpdateChecker {
|
||||
private String latestVersion;
|
||||
|
||||
private boolean checkHigher(String currentVersion, String newVersion) {
|
||||
String current = toReadable(currentVersion);
|
||||
String newVers = toReadable(newVersion);
|
||||
return current.compareTo(newVers) < 0;
|
||||
}
|
||||
|
||||
public void checkUpdate(String currentVersion) {
|
||||
String version = getSpigotVersion();
|
||||
if (version != null) {
|
||||
if (checkHigher(currentVersion, version)) {
|
||||
latestVersion = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getLatestVersion() {
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks spigot for the version
|
||||
*/
|
||||
private String getSpigotVersion() {
|
||||
try {
|
||||
HttpURLConnection con = (HttpURLConnection) new URL("http://www.spigotmc.org/api/general.php").openConnection();
|
||||
con.setDoOutput(true);
|
||||
con.setRequestMethod("POST");
|
||||
con.getOutputStream().write(
|
||||
("key=98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4&resource=81").getBytes("UTF-8"));
|
||||
String version = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine();
|
||||
if (version.length() <= 7) {
|
||||
return version;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out.print("[LibsDisguises] Failed to check for a update on spigot. Now checking bukkit..");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String toReadable(String version) {
|
||||
String[] split = Pattern.compile(".", Pattern.LITERAL).split(version.replace("v", ""));
|
||||
version = "";
|
||||
for (String s : split)
|
||||
version += String.format("%4s", s);
|
||||
return version;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user