Added a shallow clone method.

Removed the identity cloner, as it's no longer needed.
This commit is contained in:
Kristian S. Stangeland 2012-12-27 11:13:42 +01:00
parent dea725e1e3
commit 695a4f3b0e
4 changed files with 51 additions and 24 deletions

View File

@ -30,6 +30,8 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import javax.annotation.Nullable;
import org.bukkit.World;
import org.bukkit.WorldType;
import org.bukkit.entity.Entity;
@ -38,13 +40,19 @@ import org.bukkit.inventory.ItemStack;
import com.comphenix.protocol.injector.StructureCache;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.ObjectWriter;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.cloning.AggregateCloner;
import com.comphenix.protocol.reflect.cloning.Cloner;
import com.comphenix.protocol.reflect.cloning.FieldCloner;
import com.comphenix.protocol.reflect.cloning.AggregateCloner.BuilderParameters;
import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.BukkitConverters;
import com.comphenix.protocol.wrappers.ChunkPosition;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
/**
@ -69,6 +77,21 @@ public class PacketContainer implements Serializable {
private static ConcurrentMap<Class<?>, Method> writeMethods = Maps.newConcurrentMap();
private static ConcurrentMap<Class<?>, Method> readMethods = Maps.newConcurrentMap();
// Used to clone packets
private static final AggregateCloner DEEP_CLONER = AggregateCloner.DEFAULT;
private static final AggregateCloner SHALLOW_CLONER = AggregateCloner.newBuilder().
instanceProvider(DefaultInstances.DEFAULT).
andThen(new Function<BuilderParameters, Cloner>() {
@Override
public Cloner apply(@Nullable BuilderParameters param) {
return new FieldCloner(param.getAggregateCloner(), param.getInstanceProvider()) {{
// Use a default writer with no concept of cloning
writer = new ObjectWriter();
}};
}
}).
build();
/**
* Creates a packet container for a new packet.
* @param id - ID of the packet to create.
@ -364,12 +387,29 @@ public class PacketContainer implements Serializable {
return id;
}
/**
* Create a shallow copy of the current packet.
* <p>
* This merely writes the content of each field to the new class directly,
* without performing any expensive copies.
*
* @return A shallow copy of the current packet.
*/
public PacketContainer shallowClone() {
Object clonedPacket = SHALLOW_CLONER.clone(getHandle());
return new PacketContainer(getID(), clonedPacket);
}
/**
* Create a deep copy of the current packet.
* <p>
* This will perform a full copy of the entire object tree, only skipping
* known immutable objects and primitive types.
*
* @return A deep copy of the current packet.
*/
public PacketContainer deepClone() {
Object clonedPacket = AggregateCloner.DEFAULT.clone(getHandle());
Object clonedPacket = DEEP_CLONER.clone(getHandle());
return new PacketContainer(getID(), clonedPacket);
}

View File

@ -47,6 +47,11 @@ public class AggregateCloner implements Cloner {
}
}
/**
* Represents a builder for aggregate (combined) cloners.
*
* @author Kristian
*/
public static class Builder {
private List<Function<BuilderParameters, Cloner>> factories = Lists.newArrayList();
private BuilderParameters parameters;
@ -75,7 +80,7 @@ public class AggregateCloner implements Cloner {
*/
public Builder andThen(final Class<? extends Cloner> type) {
// Use reflection to generate a factory on the fly
return orCloner(new Function<BuilderParameters, Cloner>() {
return andThen(new Function<BuilderParameters, Cloner>() {
@Override
public Cloner apply(@Nullable BuilderParameters param) {
Object result = param.typeConstructor.create(type);
@ -97,7 +102,7 @@ public class AggregateCloner implements Cloner {
* @param factory - factory constructing the next cloner.
* @return This builder.
*/
public Builder orCloner(Function<BuilderParameters, Cloner> factory) {
public Builder andThen(Function<BuilderParameters, Cloner> factory) {
factories.add(factory);
return this;
}

View File

@ -10,11 +10,11 @@ import com.comphenix.protocol.reflect.instances.InstanceProvider;
* @author Kristian
*/
public class FieldCloner implements Cloner {
private final Cloner defaultCloner;
private final InstanceProvider instanceProvider;
protected Cloner defaultCloner;
protected InstanceProvider instanceProvider;
// Used to clone objects
private final ObjectWriter writer;
protected ObjectWriter writer;
/**
* Constructs a field cloner that copies objects by reading and writing the internal fields directly.

View File

@ -1,18 +0,0 @@
package com.comphenix.protocol.reflect.cloning;
/**
* Represents a cloner that simply returns the given object.
*
* @author Kristian
*/
public class IdentityCloner implements Cloner {
@Override
public boolean canClone(Object source) {
return true;
}
@Override
public Object clone(Object source) {
return source;
}
}