Don't copy inflated buffers - they won't be modified in any case.
Resulted in some pretty ugly factory code.
Dieser Commit ist enthalten in:
Ursprung
20ab2a71ac
Commit
0d34b82d72
@ -43,8 +43,11 @@ 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.BukkitCloner;
|
||||
import com.comphenix.protocol.reflect.cloning.Cloner;
|
||||
import com.comphenix.protocol.reflect.cloning.CollectionCloner;
|
||||
import com.comphenix.protocol.reflect.cloning.FieldCloner;
|
||||
import com.comphenix.protocol.reflect.cloning.ImmutableDetector;
|
||||
import com.comphenix.protocol.reflect.cloning.AggregateCloner.BuilderParameters;
|
||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
@ -78,7 +81,14 @@ public class PacketContainer implements Serializable {
|
||||
private static ConcurrentMap<Class<?>, Method> readMethods = Maps.newConcurrentMap();
|
||||
|
||||
// Used to clone packets
|
||||
private static final AggregateCloner DEEP_CLONER = AggregateCloner.DEFAULT;
|
||||
private static final AggregateCloner DEEP_CLONER = AggregateCloner.newBuilder().
|
||||
instanceProvider(DefaultInstances.DEFAULT).
|
||||
andThen(BukkitCloner.class).
|
||||
andThen(ImmutableDetector.class).
|
||||
andThen(CollectionCloner.class).
|
||||
andThen(getSpecializedDeepClonerFactory()).
|
||||
build();
|
||||
|
||||
private static final AggregateCloner SHALLOW_CLONER = AggregateCloner.newBuilder().
|
||||
instanceProvider(DefaultInstances.DEFAULT).
|
||||
andThen(new Function<BuilderParameters, Cloner>() {
|
||||
@ -405,6 +415,8 @@ public class PacketContainer implements Serializable {
|
||||
* <p>
|
||||
* This will perform a full copy of the entire object tree, only skipping
|
||||
* known immutable objects and primitive types.
|
||||
* <p>
|
||||
* Note that the inflated buffers in packet 51 and 56 will be copied directly to save memory.
|
||||
*
|
||||
* @return A deep copy of the current packet.
|
||||
*/
|
||||
@ -413,6 +425,28 @@ public class PacketContainer implements Serializable {
|
||||
return new PacketContainer(getID(), clonedPacket);
|
||||
}
|
||||
|
||||
// To save space, we'll skip copying the inflated buffers in packet 51 and 56
|
||||
private static Function<BuilderParameters, Cloner> getSpecializedDeepClonerFactory() {
|
||||
// Look at what you've made me do Java, look at it!!
|
||||
return new Function<BuilderParameters, Cloner>() {
|
||||
@Override
|
||||
public Cloner apply(@Nullable BuilderParameters param) {
|
||||
return new FieldCloner(param.getAggregateCloner(), param.getInstanceProvider()) {{
|
||||
this.writer = new ObjectWriter() {
|
||||
protected void transformField(StructureModifier<Object> modifierSource,
|
||||
StructureModifier<Object> modifierDest, int fieldIndex) {
|
||||
// No need to clone inflated buffers
|
||||
if (modifierSource.getField(fieldIndex).getName().startsWith("inflatedBuffer"))
|
||||
modifierDest.write(fieldIndex, modifierSource.read(fieldIndex));
|
||||
else
|
||||
defaultTransform(modifierSource, modifierDest, getDefaultCloner(), fieldIndex);
|
||||
};
|
||||
};
|
||||
}};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream output) throws IOException {
|
||||
// Default serialization
|
||||
output.defaultWriteObject();
|
||||
|
@ -35,6 +35,11 @@ import com.google.common.collect.Lists;
|
||||
* @author Kristian
|
||||
*/
|
||||
public class AggregateCloner implements Cloner {
|
||||
/**
|
||||
* Supplies the cloner factories with necessary parameters.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class BuilderParameters {
|
||||
// Can only be modified by the builder
|
||||
private InstanceProvider instanceProvider;
|
||||
|
@ -47,12 +47,25 @@ public class FieldCloner implements Cloner {
|
||||
@Override
|
||||
protected void transformField(StructureModifier<Object> modifierSource,
|
||||
StructureModifier<Object> modifierDest, int fieldIndex) {
|
||||
Object value = modifierSource.read(fieldIndex);
|
||||
modifierDest.write(fieldIndex, getDefaultCloner().clone(value));
|
||||
defaultTransform(modifierDest, modifierDest, getDefaultCloner(), fieldIndex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation of the field transform. Applies a clone operation before a field value is written.
|
||||
* @param modifierSource - modifier for the original object.
|
||||
* @param modifierDest - modifier for the new cloned object.
|
||||
* @param defaultCloner - cloner to use.
|
||||
* @param fieldIndex - the current field index.
|
||||
*/
|
||||
protected void defaultTransform(StructureModifier<Object> modifierSource,
|
||||
StructureModifier<Object> modifierDest, Cloner defaultCloner, int fieldIndex) {
|
||||
|
||||
Object value = modifierSource.read(fieldIndex);
|
||||
modifierDest.write(fieldIndex, defaultCloner.clone(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canClone(Object source) {
|
||||
if (source == null)
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren