Archiviert
13
0

Use the object wrappers when printing custom Minecraft objects.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2013-07-26 17:30:47 +02:00
Ursprung 34f5278605
Commit 5c2fc8684e
4 geänderte Dateien mit 684 neuen und 564 gelöschten Zeilen

Datei anzeigen

@ -44,10 +44,13 @@ import com.comphenix.protocol.events.ListeningWhitelist;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener; import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.injector.GamePhase; import com.comphenix.protocol.injector.GamePhase;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.FieldAccessException; import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.PrettyPrinter; import com.comphenix.protocol.reflect.PrettyPrinter;
import com.comphenix.protocol.reflect.PrettyPrinter.ObjectPrinter;
import com.comphenix.protocol.utility.ChatExtensions; import com.comphenix.protocol.utility.ChatExtensions;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.BukkitConverters;
import com.google.common.collect.DiscreteDomains; import com.google.common.collect.DiscreteDomains;
import com.google.common.collect.Range; import com.google.common.collect.Range;
import com.google.common.collect.Ranges; import com.google.common.collect.Ranges;
@ -432,7 +435,20 @@ class CommandPacket extends CommandBase {
} }
logger.info(shortDescription + ":\n" + logger.info(shortDescription + ":\n" +
PrettyPrinter.printObject(packet, clazz, MinecraftReflection.getPacketClass()) PrettyPrinter.printObject(packet, clazz, MinecraftReflection.getPacketClass(), PrettyPrinter.RECURSE_DEPTH, new ObjectPrinter() {
@Override
public boolean print(StringBuilder output, Object value) {
if (value != null) {
EquivalentConverter<Object> converter = BukkitConverters.getGenericConverters().get(value.getClass());
if (converter != null) {
output.append(converter.getSpecific(value));
return true;
}
}
return false;
}
})
); );
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {

Datei anzeigen

@ -33,6 +33,28 @@ import com.google.common.primitives.Primitives;
* @author Kristian * @author Kristian
*/ */
public class PrettyPrinter { public class PrettyPrinter {
/**
* Represents a generic object printer.
* @author Kristian
*/
public interface ObjectPrinter {
public static final ObjectPrinter DEFAULT = new ObjectPrinter() {
@Override
public boolean print(StringBuilder output, Object value) {
return false;
}
};
/**
* Print the content of the given object.
* <p>
* Return FALSE in order for let the default printer take over.
* @param output - where to print the output.
* @param value - the value to print, may be NULL.
* @return TRUE if we processed the value and added to the output, FALSE otherwise.
*/
public boolean print(StringBuilder output, Object value);
}
/** /**
* How far we will recurse. * How far we will recurse.
@ -74,6 +96,19 @@ public class PrettyPrinter {
* @throws IllegalAccessException * @throws IllegalAccessException
*/ */
public static String printObject(Object object, Class<?> start, Class<?> stop, int hierachyDepth) throws IllegalAccessException { public static String printObject(Object object, Class<?> start, Class<?> stop, int hierachyDepth) throws IllegalAccessException {
return printObject(object, start, stop, hierachyDepth, ObjectPrinter.DEFAULT);
}
/**
* Print the content of an object.
* @param object - the object to serialize.
* @param stop - superclass that will stop the process.
* @param hierachyDepth - maximum recursion level.
* @param transformer - a generic object printer.
* @return String representation of the class.
* @throws IllegalAccessException
*/
public static String printObject(Object object, Class<?> start, Class<?> stop, int hierachyDepth, ObjectPrinter printer) throws IllegalAccessException {
if (object == null) if (object == null)
throw new IllegalArgumentException("object cannot be NULL."); throw new IllegalArgumentException("object cannot be NULL.");
@ -82,7 +117,7 @@ public class PrettyPrinter {
// Start and stop // Start and stop
output.append("{ "); output.append("{ ");
printObject(output, object, start, stop, previous, hierachyDepth, true); printObject(output, object, start, stop, previous, hierachyDepth, true, printer);
output.append(" }"); output.append(" }");
return output.toString(); return output.toString();
@ -90,7 +125,7 @@ public class PrettyPrinter {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private static void printIterables(StringBuilder output, Iterable iterable, Class<?> current, Class<?> stop, private static void printIterables(StringBuilder output, Iterable iterable, Class<?> current, Class<?> stop,
Set<Object> previous, int hierachyIndex) throws IllegalAccessException { Set<Object> previous, int hierachyIndex, ObjectPrinter printer) throws IllegalAccessException {
boolean first = true; boolean first = true;
output.append("("); output.append("(");
@ -102,7 +137,7 @@ public class PrettyPrinter {
output.append(", "); output.append(", ");
// Print value // Print value
printValue(output, value, stop, previous, hierachyIndex - 1); printValue(output, value, stop, previous, hierachyIndex - 1, printer);
} }
output.append(")"); output.append(")");
@ -119,7 +154,7 @@ public class PrettyPrinter {
* @throws IllegalAccessException If any reflection went wrong. * @throws IllegalAccessException If any reflection went wrong.
*/ */
private static void printMap(StringBuilder output, Map<Object, Object> map, Class<?> current, Class<?> stop, private static void printMap(StringBuilder output, Map<Object, Object> map, Class<?> current, Class<?> stop,
Set<Object> previous, int hierachyIndex) throws IllegalAccessException { Set<Object> previous, int hierachyIndex, ObjectPrinter printer) throws IllegalAccessException {
boolean first = true; boolean first = true;
output.append("["); output.append("[");
@ -130,16 +165,16 @@ public class PrettyPrinter {
else else
output.append(", "); output.append(", ");
printValue(output, entry.getKey(), stop, previous, hierachyIndex - 1); printValue(output, entry.getKey(), stop, previous, hierachyIndex - 1, printer);
output.append(": "); output.append(": ");
printValue(output, entry.getValue(), stop, previous, hierachyIndex - 1); printValue(output, entry.getValue(), stop, previous, hierachyIndex - 1, printer);
} }
output.append("]"); output.append("]");
} }
private static void printArray(StringBuilder output, Object array, Class<?> current, Class<?> stop, private static void printArray(StringBuilder output, Object array, Class<?> current, Class<?> stop,
Set<Object> previous, int hierachyIndex) throws IllegalAccessException { Set<Object> previous, int hierachyIndex, ObjectPrinter printer) throws IllegalAccessException {
Class<?> component = current.getComponentType(); Class<?> component = current.getComponentType();
boolean first = true; boolean first = true;
@ -156,7 +191,7 @@ public class PrettyPrinter {
// Handle exceptions // Handle exceptions
try { try {
printValue(output, Array.get(array, i), component, stop, previous, hierachyIndex - 1); printValue(output, Array.get(array, i), component, stop, previous, hierachyIndex - 1, printer);
} catch (ArrayIndexOutOfBoundsException e) { } catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace(); e.printStackTrace();
break; break;
@ -171,7 +206,8 @@ public class PrettyPrinter {
// Internal recursion method // Internal recursion method
private static void printObject(StringBuilder output, Object object, Class<?> current, Class<?> stop, private static void printObject(StringBuilder output, Object object, Class<?> current, Class<?> stop,
Set<Object> previous, int hierachyIndex, boolean first) throws IllegalAccessException { Set<Object> previous, int hierachyIndex, boolean first,
ObjectPrinter printer) throws IllegalAccessException {
// See if we're supposed to skip this class // See if we're supposed to skip this class
if (current == Object.class || (stop != null && current.equals(stop))) { if (current == Object.class || (stop != null && current.equals(stop))) {
@ -203,42 +239,46 @@ public class PrettyPrinter {
output.append(field.getName()); output.append(field.getName());
output.append(" = "); output.append(" = ");
printValue(output, value, type, stop, previous, hierachyIndex - 1); printValue(output, value, type, stop, previous, hierachyIndex - 1, printer);
} }
} }
// Recurse // Recurse
printObject(output, object, current.getSuperclass(), stop, previous, hierachyIndex, first); printObject(output, object, current.getSuperclass(), stop, previous, hierachyIndex, first, printer);
} }
private static void printValue(StringBuilder output, Object value, Class<?> stop, private static void printValue(StringBuilder output, Object value, Class<?> stop,
Set<Object> previous, int hierachyIndex) throws IllegalAccessException { Set<Object> previous, int hierachyIndex, ObjectPrinter printer) throws IllegalAccessException {
// Handle the NULL case // Handle the NULL case
printValue(output, value, value != null ? value.getClass() : null, stop, previous, hierachyIndex); printValue(output, value, value != null ? value.getClass() : null, stop, previous, hierachyIndex, printer);
} }
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
private static void printValue(StringBuilder output, Object value, Class<?> type, private static void printValue(StringBuilder output, Object value, Class<?> type,
Class<?> stop, Set<Object> previous, int hierachyIndex) throws IllegalAccessException { Class<?> stop, Set<Object> previous, int hierachyIndex,
ObjectPrinter printer) throws IllegalAccessException {
// Just print primitive types // Just print primitive types
if (value == null) { if (printer.print(output, value)) {
return;
} else if (value == null) {
output.append("NULL"); output.append("NULL");
} else if (type.isPrimitive() || Primitives.isWrapperType(type)) { } else if (type.isPrimitive() || Primitives.isWrapperType(type)) {
output.append(value); output.append(value);
} else if (type == String.class || hierachyIndex <= 0) { } else if (type == String.class || hierachyIndex <= 0) {
output.append("\"" + value + "\""); output.append("\"" + value + "\"");
} else if (type.isArray()) { } else if (type.isArray()) {
printArray(output, value, type, stop, previous, hierachyIndex); printArray(output, value, type, stop, previous, hierachyIndex, printer);
} else if (Iterable.class.isAssignableFrom(type)) { } else if (Iterable.class.isAssignableFrom(type)) {
printIterables(output, (Iterable) value, type, stop, previous, hierachyIndex); printIterables(output, (Iterable) value, type, stop, previous, hierachyIndex, printer);
} else if (Map.class.isAssignableFrom(type)) { } else if (Map.class.isAssignableFrom(type)) {
printMap(output, (Map<Object, Object>) value, type, stop, previous, hierachyIndex); printMap(output, (Map<Object, Object>) value, type, stop, previous, hierachyIndex, printer);
} else if (ClassLoader.class.isAssignableFrom(type) || previous.contains(value)) { } else if (ClassLoader.class.isAssignableFrom(type) || previous.contains(value)) {
// Don't print previous objects // Don't print previous objects
output.append("\"" + value + "\""); output.append("\"" + value + "\"");
} else { } else {
output.append("{ "); output.append("{ ");
printObject(output, value, value.getClass(), stop, previous, hierachyIndex, true); printObject(output, value, value.getClass(), stop, previous, hierachyIndex, true, printer);
output.append(" }"); output.append(" }");
} }
} }

Datei anzeigen

@ -45,6 +45,8 @@ import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers; import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.wrappers.WrappedDataWatcher; import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
import com.comphenix.protocol.wrappers.nbt.NbtType;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
/** /**
@ -869,6 +871,21 @@ public class MinecraftReflection {
} }
} }
/**
* Retrieve the NBT Compound class.
* @return The NBT Compond class.
*/
public static Class<?> getNBTCompoundClass() {
try {
return getMinecraftClass("NBTTagCompound");
} catch (RuntimeException e) {
return setMinecraftClass(
"NBTTagCompound",
NbtFactory.ofWrapper(NbtType.TAG_COMPOUND, "Test").getHandle().getClass()
);
}
}
/** /**
* Retrieve the EntityTracker (NMS) class. * Retrieve the EntityTracker (NMS) class.
* @return EntityTracker class. * @return EntityTracker class.

Datei anzeigen

@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.WorldType; import org.bukkit.WorldType;
@ -35,8 +36,10 @@ import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.instances.DefaultInstances; import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.nbt.NbtBase; import com.comphenix.protocol.wrappers.nbt.NbtBase;
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
import com.comphenix.protocol.wrappers.nbt.NbtFactory; import com.comphenix.protocol.wrappers.nbt.NbtFactory;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
/** /**
* Contains several useful equivalent converters for normal Bukkit types. * Contains several useful equivalent converters for normal Bukkit types.
@ -47,6 +50,10 @@ public class BukkitConverters {
// Check whether or not certain classes exists // Check whether or not certain classes exists
private static boolean hasWorldType = false; private static boolean hasWorldType = false;
// The static maps
private static Map<Class<?>, EquivalentConverter<Object>> specificConverters;
private static Map<Class<?>, EquivalentConverter<Object>> genericConverters;
// Used to access the world type // Used to access the world type
private static Method worldTypeName; private static Method worldTypeName;
private static Method worldTypeGetType; private static Method worldTypeGetType;
@ -416,4 +423,44 @@ public class BukkitConverters {
} }
}; };
} }
/**
* Retrieve every converter that is associated with a specific class.
* @return Every converter with a unique specific class.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static Map<Class<?>, EquivalentConverter<Object>> getSpecificConverters() {
if (specificConverters == null) {
// Generics doesn't work, as usual
specificConverters = ImmutableMap.<Class<?>, EquivalentConverter<Object>>builder().
put(WrappedDataWatcher.class, (EquivalentConverter) getDataWatcherConverter()).
put(ItemStack.class, (EquivalentConverter) getItemStackConverter()).
put(NbtBase.class, (EquivalentConverter) getNbtConverter()).
put(NbtCompound.class, (EquivalentConverter) getNbtConverter()).
put(WrappedWatchableObject.class, (EquivalentConverter) getWatchableObjectConverter()).
put(WorldType.class, (EquivalentConverter) getWorldTypeConverter()).
build();
}
return specificConverters;
}
/**
* Retrieve every converter that is associated with a generic class.
* @return Every converter with a unique generic class.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static Map<Class<?>, EquivalentConverter<Object>> getGenericConverters() {
if (genericConverters == null) {
// Generics doesn't work, as usual
genericConverters = ImmutableMap.<Class<?>, EquivalentConverter<Object>>builder().
put(MinecraftReflection.getDataWatcherClass(), (EquivalentConverter) getDataWatcherConverter()).
put(MinecraftReflection.getItemStackClass(), (EquivalentConverter) getItemStackConverter()).
put(MinecraftReflection.getNBTBaseClass(), (EquivalentConverter) getNbtConverter()).
put(MinecraftReflection.getNBTCompoundClass(), (EquivalentConverter) getNbtConverter()).
put(MinecraftReflection.getWatchableObjectClass(), (EquivalentConverter) getWatchableObjectConverter()).
put(MinecraftReflection.getWorldTypeClass(), (EquivalentConverter) getWorldTypeConverter()).
build();
}
return genericConverters;
}
} }