Fixed the "moved too quickly" error that would cause players to
fall out into the void on 1.3.2.
Dieser Commit ist enthalten in:
Ursprung
0470b2335c
Commit
2fceaa803e
@ -7,6 +7,8 @@ import java.util.List;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import net.sf.cglib.proxy.Factory;
|
||||||
|
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
|
|
||||||
import com.comphenix.protocol.reflect.FieldUtils;
|
import com.comphenix.protocol.reflect.FieldUtils;
|
||||||
@ -134,18 +136,33 @@ class InjectedServerConnection {
|
|||||||
if (list instanceof ReplacedArrayList) {
|
if (list instanceof ReplacedArrayList) {
|
||||||
replacedLists.add((ReplacedArrayList<Object>) list);
|
replacedLists.add((ReplacedArrayList<Object>) list);
|
||||||
} else {
|
} else {
|
||||||
replacedLists.add(new ReplacedArrayList<Object>(list));
|
replacedLists.add(createReplacement(list));
|
||||||
listFieldRef.setValue(replacedLists.get(0));
|
listFieldRef.setValue(replacedLists.get(0));
|
||||||
listFields.add(listFieldRef);
|
listFields.add(listFieldRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hack to avoid the "moved to quickly" error
|
||||||
|
private ReplacedArrayList<Object> createReplacement(List<Object> list) {
|
||||||
|
return new ReplacedArrayList<Object>(list) {
|
||||||
|
@Override
|
||||||
|
protected void onReplacing(Object inserting, Object replacement) {
|
||||||
|
// Is this a normal Minecraft object?
|
||||||
|
if (!(inserting instanceof Factory)) {
|
||||||
|
// If so, copy the content of the old element to the new
|
||||||
|
ObjectCloner.copyTo(inserting, replacement, inserting.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace the server handler instance kept by the "keep alive" object.
|
* Replace the server handler instance kept by the "keep alive" object.
|
||||||
* @param oldHandler - old server handler.
|
* @param oldHandler - old server handler.
|
||||||
* @param newHandler - new, proxied server handler.
|
* @param newHandler - new, proxied server handler.
|
||||||
*/
|
*/
|
||||||
public void replaceServerHandler(Object oldHandler, Object newHandler) {
|
public void replaceServerHandler(Object oldHandler, Object newHandler) {
|
||||||
|
|
||||||
if (!hasAttempted) {
|
if (!hasAttempted) {
|
||||||
injectList();
|
injectList();
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,8 @@ import net.sf.cglib.proxy.MethodProxy;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import com.comphenix.protocol.events.PacketListener;
|
import com.comphenix.protocol.events.PacketListener;
|
||||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
|
||||||
import com.comphenix.protocol.reflect.FieldUtils;
|
import com.comphenix.protocol.reflect.FieldUtils;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
|
||||||
import com.comphenix.protocol.reflect.instances.CollectionGenerator;
|
import com.comphenix.protocol.reflect.instances.CollectionGenerator;
|
||||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||||
import com.comphenix.protocol.reflect.instances.ExistingGenerator;
|
import com.comphenix.protocol.reflect.instances.ExistingGenerator;
|
||||||
@ -30,8 +28,6 @@ import com.comphenix.protocol.reflect.instances.PrimitiveGenerator;
|
|||||||
public class NetworkServerInjector extends PlayerInjector {
|
public class NetworkServerInjector extends PlayerInjector {
|
||||||
|
|
||||||
private static Method sendPacketMethod;
|
private static Method sendPacketMethod;
|
||||||
|
|
||||||
private StructureModifier<Object> serverHandlerModifier;
|
|
||||||
private InjectedServerConnection serverInjection;
|
private InjectedServerConnection serverInjection;
|
||||||
|
|
||||||
public NetworkServerInjector(Player player, PacketFilterManager manager,
|
public NetworkServerInjector(Player player, PacketFilterManager manager,
|
||||||
@ -48,8 +44,6 @@ public class NetworkServerInjector extends PlayerInjector {
|
|||||||
if (hasInitialized) {
|
if (hasInitialized) {
|
||||||
if (sendPacketMethod == null)
|
if (sendPacketMethod == null)
|
||||||
sendPacketMethod = FuzzyReflection.fromObject(serverHandler).getMethodByName("sendPacket.*");
|
sendPacketMethod = FuzzyReflection.fromObject(serverHandler).getMethodByName("sendPacket.*");
|
||||||
if (serverHandlerModifier == null)
|
|
||||||
serverHandlerModifier = new StructureModifier<Object>(serverHandler.getClass(), null, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,41 +113,23 @@ public class NetworkServerInjector extends PlayerInjector {
|
|||||||
CollectionGenerator.INSTANCE);
|
CollectionGenerator.INSTANCE);
|
||||||
|
|
||||||
Object proxyObject = serverInstances.forEnhancer(ex).getDefault(serverClass);
|
Object proxyObject = serverInstances.forEnhancer(ex).getDefault(serverClass);
|
||||||
serverInjection.replaceServerHandler(serverHandler, proxyObject);
|
|
||||||
|
|
||||||
// Inject it now
|
// Inject it now
|
||||||
if (proxyObject != null) {
|
if (proxyObject != null) {
|
||||||
copyTo(serverHandler, proxyObject);
|
// This will be done by InjectedServerConnection instead
|
||||||
|
//copyTo(serverHandler, proxyObject);
|
||||||
|
serverInjection.replaceServerHandler(serverHandler, proxyObject);
|
||||||
serverHandlerRef.setValue(proxyObject);
|
serverHandlerRef.setValue(proxyObject);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Cannot hook player: Unable to find a valid constructor for the NetServerHandler object.");
|
"Cannot hook player: Unable to find a valid constructor for the NetServerHandler object.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy every field in server handler A to server handler B.
|
|
||||||
* @param source - fields to copy.
|
|
||||||
* @param destination - fields to copy to.
|
|
||||||
*/
|
|
||||||
private void copyTo(Object source, Object destination) {
|
|
||||||
StructureModifier<Object> modifierSource = serverHandlerModifier.withTarget(source);
|
|
||||||
StructureModifier<Object> modifierDest = serverHandlerModifier.withTarget(destination);
|
|
||||||
|
|
||||||
// Copy every field
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < modifierSource.size(); i++) {
|
|
||||||
modifierDest.write(i, modifierSource.read(i));
|
|
||||||
}
|
|
||||||
} catch (FieldAccessException e) {
|
|
||||||
throw new RuntimeException("Unable to copy fields from NetServerHandler.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cleanupAll() {
|
public void cleanupAll() {
|
||||||
if (serverHandlerRef != null && serverHandlerRef.isCurrentSet()) {
|
if (serverHandlerRef != null && serverHandlerRef.isCurrentSet()) {
|
||||||
copyTo(serverHandlerRef.getValue(), serverHandlerRef.getOldValue());
|
ObjectCloner.copyTo(serverHandlerRef.getValue(), serverHandlerRef.getOldValue(), serverHandler.getClass());
|
||||||
serverHandlerRef.revertValue();
|
serverHandlerRef.revertValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
ProtocolLib/src/com/comphenix/protocol/injector/ObjectCloner.java
Normale Datei
64
ProtocolLib/src/com/comphenix/protocol/injector/ObjectCloner.java
Normale Datei
@ -0,0 +1,64 @@
|
|||||||
|
package com.comphenix.protocol.injector;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||||
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can copy an object field by field.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
class ObjectCloner {
|
||||||
|
|
||||||
|
// Cache structure modifiers
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private static ConcurrentMap<Class, StructureModifier<Object>> cache =
|
||||||
|
new ConcurrentHashMap<Class, StructureModifier<Object>>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy every field in object A to object B.
|
||||||
|
* <p>
|
||||||
|
* The two objects must have the same number of fields of the same type.
|
||||||
|
* @param source - fields to copy.
|
||||||
|
* @param destination - fields to copy to.
|
||||||
|
* @param commonType - type containing each field to copy.
|
||||||
|
*/
|
||||||
|
public static void copyTo(Object source, Object destination, Class<?> commonType) {
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
throw new IllegalArgumentException("Source cannot be NULL");
|
||||||
|
if (destination == null)
|
||||||
|
throw new IllegalArgumentException("Destination cannot be NULL");
|
||||||
|
|
||||||
|
StructureModifier<Object> modifier = cache.get(commonType);
|
||||||
|
|
||||||
|
// Create the structure modifier if we haven't already
|
||||||
|
if (modifier == null) {
|
||||||
|
StructureModifier<Object> value = new StructureModifier<Object>(commonType, null, false);
|
||||||
|
modifier = cache.putIfAbsent(commonType, value);
|
||||||
|
|
||||||
|
if (modifier == null)
|
||||||
|
modifier = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add target
|
||||||
|
StructureModifier<Object> modifierSource = modifier.withTarget(source);
|
||||||
|
StructureModifier<Object> modifierDest = modifier.withTarget(destination);
|
||||||
|
|
||||||
|
// Copy every field
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < modifierSource.size(); i++) {
|
||||||
|
Object value = modifierSource.read(i);
|
||||||
|
modifierDest.write(i, value);
|
||||||
|
|
||||||
|
// System.out.println(String.format("Writing value %s to %s",
|
||||||
|
// value, modifier.getFields().get(i).getName()));
|
||||||
|
}
|
||||||
|
} catch (FieldAccessException e) {
|
||||||
|
throw new RuntimeException("Unable to copy fields from " + commonType.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,10 +24,21 @@ class ReplacedArrayList<TKey> extends ForwardingList<TKey> {
|
|||||||
this.underlyingList = underlyingList;
|
this.underlyingList = underlyingList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a element inserted is replaced.
|
||||||
|
* @param inserting - the element inserted.
|
||||||
|
* @param replacement - the element that it should replace.
|
||||||
|
*/
|
||||||
|
protected void onReplacing(TKey inserting, TKey replacement) {
|
||||||
|
// Default is to do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(TKey element) {
|
public boolean add(TKey element) {
|
||||||
if (replaceMap.containsKey(element)) {
|
if (replaceMap.containsKey(element)) {
|
||||||
return super.add(replaceMap.get(element));
|
TKey replacement = replaceMap.get(element);
|
||||||
|
onReplacing(element, replacement);
|
||||||
|
return super.add(replacement);
|
||||||
} else {
|
} else {
|
||||||
return super.add(element);
|
return super.add(element);
|
||||||
}
|
}
|
||||||
@ -36,7 +47,9 @@ class ReplacedArrayList<TKey> extends ForwardingList<TKey> {
|
|||||||
@Override
|
@Override
|
||||||
public void add(int index, TKey element) {
|
public void add(int index, TKey element) {
|
||||||
if (replaceMap.containsKey(element)) {
|
if (replaceMap.containsKey(element)) {
|
||||||
super.add(index, replaceMap.get(element));
|
TKey replacement = replaceMap.get(element);
|
||||||
|
onReplacing(element, replacement);
|
||||||
|
super.add(index, replacement);
|
||||||
} else {
|
} else {
|
||||||
super.add(index, element);
|
super.add(index, element);
|
||||||
}
|
}
|
||||||
@ -101,8 +114,10 @@ class ReplacedArrayList<TKey> extends ForwardingList<TKey> {
|
|||||||
*/
|
*/
|
||||||
public synchronized void replaceAll(TKey find, TKey replace) {
|
public synchronized void replaceAll(TKey find, TKey replace) {
|
||||||
for (int i = 0; i < underlyingList.size(); i++) {
|
for (int i = 0; i < underlyingList.size(); i++) {
|
||||||
if (Objects.equal(underlyingList.get(i), find))
|
if (Objects.equal(underlyingList.get(i), find)) {
|
||||||
|
onReplacing(find, replace);
|
||||||
underlyingList.set(i, replace);
|
underlyingList.set(i, replace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +136,9 @@ class ReplacedArrayList<TKey> extends ForwardingList<TKey> {
|
|||||||
TKey replaced = underlyingList.get(i);
|
TKey replaced = underlyingList.get(i);
|
||||||
|
|
||||||
if (inverse.containsKey(replaced)) {
|
if (inverse.containsKey(replaced)) {
|
||||||
underlyingList.set(i, inverse.get(replaced));
|
TKey original = inverse.get(replaced);
|
||||||
|
onReplacing(replaced, original);
|
||||||
|
underlyingList.set(i, original);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren