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.ObjectWriter;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
import com.comphenix.protocol.reflect.cloning.AggregateCloner;
|
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.Cloner;
|
||||||
|
import com.comphenix.protocol.reflect.cloning.CollectionCloner;
|
||||||
import com.comphenix.protocol.reflect.cloning.FieldCloner;
|
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.cloning.AggregateCloner.BuilderParameters;
|
||||||
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;
|
||||||
@ -78,7 +81,14 @@ public class PacketContainer implements Serializable {
|
|||||||
private static ConcurrentMap<Class<?>, Method> readMethods = Maps.newConcurrentMap();
|
private static ConcurrentMap<Class<?>, Method> readMethods = Maps.newConcurrentMap();
|
||||||
|
|
||||||
// Used to clone packets
|
// 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().
|
private static final AggregateCloner SHALLOW_CLONER = AggregateCloner.newBuilder().
|
||||||
instanceProvider(DefaultInstances.DEFAULT).
|
instanceProvider(DefaultInstances.DEFAULT).
|
||||||
andThen(new Function<BuilderParameters, Cloner>() {
|
andThen(new Function<BuilderParameters, Cloner>() {
|
||||||
@ -405,6 +415,8 @@ public class PacketContainer implements Serializable {
|
|||||||
* <p>
|
* <p>
|
||||||
* This will perform a full copy of the entire object tree, only skipping
|
* This will perform a full copy of the entire object tree, only skipping
|
||||||
* known immutable objects and primitive types.
|
* 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.
|
* @return A deep copy of the current packet.
|
||||||
*/
|
*/
|
||||||
@ -413,6 +425,28 @@ public class PacketContainer implements Serializable {
|
|||||||
return new PacketContainer(getID(), clonedPacket);
|
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 {
|
private void writeObject(ObjectOutputStream output) throws IOException {
|
||||||
// Default serialization
|
// Default serialization
|
||||||
output.defaultWriteObject();
|
output.defaultWriteObject();
|
||||||
|
@ -35,6 +35,11 @@ import com.google.common.collect.Lists;
|
|||||||
* @author Kristian
|
* @author Kristian
|
||||||
*/
|
*/
|
||||||
public class AggregateCloner implements Cloner {
|
public class AggregateCloner implements Cloner {
|
||||||
|
/**
|
||||||
|
* Supplies the cloner factories with necessary parameters.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
public static class BuilderParameters {
|
public static class BuilderParameters {
|
||||||
// Can only be modified by the builder
|
// Can only be modified by the builder
|
||||||
private InstanceProvider instanceProvider;
|
private InstanceProvider instanceProvider;
|
||||||
|
@ -47,12 +47,25 @@ public class FieldCloner implements Cloner {
|
|||||||
@Override
|
@Override
|
||||||
protected void transformField(StructureModifier<Object> modifierSource,
|
protected void transformField(StructureModifier<Object> modifierSource,
|
||||||
StructureModifier<Object> modifierDest, int fieldIndex) {
|
StructureModifier<Object> modifierDest, int fieldIndex) {
|
||||||
Object value = modifierSource.read(fieldIndex);
|
defaultTransform(modifierDest, modifierDest, getDefaultCloner(), fieldIndex);
|
||||||
modifierDest.write(fieldIndex, getDefaultCloner().clone(value));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
@Override
|
||||||
public boolean canClone(Object source) {
|
public boolean canClone(Object source) {
|
||||||
if (source == null)
|
if (source == null)
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren