Rewrite BukkitCloner to be more dynamic, fix some NPEs

Fixes #66
This commit is contained in:
Dan Mulloy 2015-03-30 23:20:13 -04:00
parent 0abe72d72b
commit 992be51646

View File

@ -1,4 +1,4 @@
/*
/**
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland
*
@ -14,18 +14,19 @@
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol.reflect.cloning;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.BlockPosition;
import com.comphenix.protocol.wrappers.BukkitConverters;
import com.comphenix.protocol.wrappers.ChunkPosition;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
/**
* Represents an object that can clone a specific list of Bukkit- and Minecraft-related objects.
@ -34,35 +35,39 @@ import com.google.common.collect.Lists;
*/
public class BukkitCloner implements Cloner {
// List of classes we support
private Class<?>[] clonableClasses;
private final Map<Integer, Class<?>> clonableClasses = Maps.newConcurrentMap();
public BukkitCloner() {
List<Class<?>> classes = Lists.newArrayList();
classes.add(MinecraftReflection.getItemStackClass());
classes.add(MinecraftReflection.getDataWatcherClass());
addClass(0, MinecraftReflection.getItemStackClass());
addClass(1, MinecraftReflection.getDataWatcherClass());
// Try to add position classes
try {
classes.add(MinecraftReflection.getBlockPositionClass());
} catch (Throwable ex) { }
try {
classes.add(MinecraftReflection.getChunkPositionClass());
} catch (Throwable ex) { }
if (MinecraftReflection.isUsingNetty()) {
classes.add(MinecraftReflection.getServerPingClass());
addClass(2, MinecraftReflection.getBlockPositionClass());
} catch (Throwable ex) {
}
this.clonableClasses = classes.toArray(new Class<?>[0]);
try {
addClass(3, MinecraftReflection.getChunkPositionClass());
} catch (Throwable ex) {
}
if (MinecraftReflection.isUsingNetty()) {
addClass(4, MinecraftReflection.getServerPingClass());
}
}
private void addClass(int id, Class<?> clazz) {
if (clazz != null)
clonableClasses.put(id, clazz);
}
private int findMatchingClass(Class<?> type) {
// See if is a subclass of any of our supported superclasses
for (int i = 0; i < clonableClasses.length; i++) {
if (clonableClasses[i].isAssignableFrom(type))
return i;
for (Entry<Integer, Class<?>> entry : clonableClasses.entrySet()) {
if (entry.getValue().isAssignableFrom(type)) {
return entry.getKey();
}
}
return -1;
@ -86,14 +91,17 @@ public class BukkitCloner implements Cloner {
case 0:
return MinecraftReflection.getMinecraftItemStack(MinecraftReflection.getBukkitItemStack(source).clone());
case 1:
EquivalentConverter<ChunkPosition> chunkConverter = ChunkPosition.getConverter();
return chunkConverter.getGeneric(clonableClasses[1], chunkConverter.getSpecific(source));
case 2:
EquivalentConverter<WrappedDataWatcher> dataConverter = BukkitConverters.getDataWatcherConverter();
return dataConverter.getGeneric(clonableClasses[2], dataConverter.getSpecific(source).deepClone());
return dataConverter.getGeneric(clonableClasses.get(1), dataConverter.getSpecific(source).deepClone());
case 2:
EquivalentConverter<BlockPosition> blockConverter = BlockPosition.getConverter();
return blockConverter.getGeneric(clonableClasses.get(2), blockConverter.getSpecific(source));
case 3:
EquivalentConverter<ChunkPosition> chunkConverter = ChunkPosition.getConverter();
return chunkConverter.getGeneric(clonableClasses.get(3), chunkConverter.getSpecific(source));
case 4:
EquivalentConverter<WrappedServerPing> serverConverter = BukkitConverters.getWrappedServerPingConverter();
return serverConverter.getGeneric(clonableClasses[3], serverConverter.getSpecific(source).deepClone());
return serverConverter.getGeneric(clonableClasses.get(4), serverConverter.getSpecific(source).deepClone());
default:
throw new IllegalArgumentException("Cannot clone objects of type " + source.getClass());
}