/*
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol.injector;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.injector.PacketConstructor.Unwrapper;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.google.common.primitives.Primitives;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
/**
* Represents an object capable of converting wrapped Bukkit objects into NMS objects.
*
* Typical conversions include:
*
*
org.bukkit.entity.Player to net.minecraft.server.EntityPlayer
*
org.bukkit.World to net.minecraft.server.WorldServer
*
*
* @author Kristian
*/
public class BukkitUnwrapper implements Unwrapper {
public static final ReportType REPORT_ILLEGAL_ARGUMENT = new ReportType("Illegal argument.");
public static final ReportType REPORT_SECURITY_LIMITATION = new ReportType("Security limitation.");
public static final ReportType REPORT_CANNOT_FIND_UNWRAP_METHOD = new ReportType("Cannot find method.");
public static final ReportType REPORT_CANNOT_READ_FIELD_HANDLE = new ReportType("Cannot read field 'handle'.");
private static final Map, Unwrapper> UNWRAPPER_CACHE = new ConcurrentHashMap, Unwrapper>();
private static BukkitUnwrapper DEFAULT;
// The current error reporter
private final ErrorReporter reporter;
/**
* Construct a new Bukkit unwrapper with ProtocolLib's default error reporter.
*/
public BukkitUnwrapper() {
this(ProtocolLibrary.getErrorReporter());
}
/**
* Construct a new Bukkit unwrapper with the given error reporter.
*
* @param reporter - the error reporter to use.
*/
public BukkitUnwrapper(ErrorReporter reporter) {
this.reporter = reporter;
}
/**
* Retrieve the default instance of the Bukkit unwrapper.
*
* @return The default instance.
*/
public static BukkitUnwrapper getInstance() {
ErrorReporter currentReporter = ProtocolLibrary.getErrorReporter();
// Also recreate the unwrapper if the error reporter has changed
if (DEFAULT == null || DEFAULT.reporter != currentReporter) {
DEFAULT = new BukkitUnwrapper(currentReporter);
}
return DEFAULT;
}
private static Class> checkClass(Class> input, Class> expected, Class> result) {
if (expected.isAssignableFrom(input)) {
return result;
}
return null;
}
@SuppressWarnings("unchecked")
@Override
public Object unwrapItem(Object wrappedObject) {
// Special case
if (wrappedObject == null) {
return null;
}
Class> currentClass = PacketConstructor.getClass(wrappedObject);
// No need to unwrap primitives
if (currentClass.isPrimitive() || currentClass.equals(String.class)) {
return null;
}
// Next, check for types that doesn't have a getHandle()
if (wrappedObject instanceof Collection) {
return handleCollection((Collection