Add mechanism to clone NonNullLists
Dieser Commit ist enthalten in:
Ursprung
684b687e42
Commit
7b61796506
@ -16,10 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.comphenix.protocol.reflect.cloning;
|
package com.comphenix.protocol.reflect.cloning;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||||
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.comphenix.protocol.wrappers.BlockPosition;
|
import com.comphenix.protocol.wrappers.BlockPosition;
|
||||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||||
@ -67,6 +71,11 @@ public class BukkitCloner implements Cloner {
|
|||||||
addClass(7, MinecraftReflection.getIBlockDataClass());
|
addClass(7, MinecraftReflection.getIBlockDataClass());
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
addClass(8, MinecraftReflection.getNonNullListClass());
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addClass(int id, Class<?> clazz) {
|
private void addClass(int id, Class<?> clazz) {
|
||||||
@ -122,8 +131,43 @@ public class BukkitCloner implements Cloner {
|
|||||||
case 7:
|
case 7:
|
||||||
EquivalentConverter<WrappedBlockData> blockDataConverter = BukkitConverters.getWrappedBlockDataConverter();
|
EquivalentConverter<WrappedBlockData> blockDataConverter = BukkitConverters.getWrappedBlockDataConverter();
|
||||||
return blockDataConverter.getGeneric(clonableClasses.get(7), blockDataConverter.getSpecific(source).deepClone());
|
return blockDataConverter.getGeneric(clonableClasses.get(7), blockDataConverter.getSpecific(source).deepClone());
|
||||||
|
case 8:
|
||||||
|
return nonNullListCloner().clone(source);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Cannot clone objects of type " + source.getClass());
|
throw new IllegalArgumentException("Cannot clone objects of type " + source.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Constructor<?> nonNullList = null;
|
||||||
|
|
||||||
|
private static final Cloner nonNullListCloner() {
|
||||||
|
return new Cloner() {
|
||||||
|
@Override
|
||||||
|
public boolean canClone(Object source) {
|
||||||
|
return MinecraftReflection.is(MinecraftReflection.getNonNullListClass(), source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone(Object source) {
|
||||||
|
StructureModifier<Object> modifier = new StructureModifier<>(source.getClass(), true).withTarget(source);
|
||||||
|
List<?> list = (List<?>) modifier.read(0);
|
||||||
|
Object empty = modifier.read(1);
|
||||||
|
|
||||||
|
if (nonNullList == null) {
|
||||||
|
try {
|
||||||
|
nonNullList = source.getClass().getDeclaredConstructor(List.class, Object.class);
|
||||||
|
nonNullList.setAccessible(true);
|
||||||
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
throw new RuntimeException("Could not find NonNullList constructor", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return nonNullList.newInstance(new ArrayList<>(list), empty);
|
||||||
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
throw new RuntimeException("Could not create new NonNullList", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1836,6 +1836,10 @@ public class MinecraftReflection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Class<?> getNonNullListClass() {
|
||||||
|
return getMinecraftClass("NonNullList");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a CraftItemStack from a given ItemStack.
|
* Retrieve a CraftItemStack from a given ItemStack.
|
||||||
* @param bukkitItemStack - the Bukkit ItemStack to convert.
|
* @param bukkitItemStack - the Bukkit ItemStack to convert.
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
package com.comphenix.protocol.reflect.cloning;
|
package com.comphenix.protocol.reflect.cloning;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_11_R1.ItemStack;
|
||||||
|
import net.minecraft.server.v1_11_R1.NonNullList;
|
||||||
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.comphenix.protocol.BukkitInitialization;
|
import com.comphenix.protocol.BukkitInitialization;
|
||||||
|
import com.comphenix.protocol.PacketType;
|
||||||
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
|
|
||||||
public class AggregateClonerTest {
|
public class AggregateClonerTest {
|
||||||
|
|
||||||
@ -22,4 +28,20 @@ public class AggregateClonerTest {
|
|||||||
List<Integer> input = Arrays.asList(1, 2, 3);
|
List<Integer> input = Arrays.asList(1, 2, 3);
|
||||||
assertEquals(input, AggregateCloner.DEFAULT.clone(input));
|
assertEquals(input, AggregateCloner.DEFAULT.clone(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonNullList() {
|
||||||
|
PacketContainer packet = new PacketContainer(PacketType.Play.Server.WINDOW_ITEMS);
|
||||||
|
|
||||||
|
NonNullList<ItemStack> list = NonNullList.a(16, ItemStack.a);
|
||||||
|
packet.getModifier().write(1, list);
|
||||||
|
|
||||||
|
PacketContainer cloned = packet.deepClone();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
NonNullList<ItemStack> list1 = (NonNullList<ItemStack>) cloned.getModifier().read(1);
|
||||||
|
|
||||||
|
assertEquals(list.size(), list1.size());
|
||||||
|
assertArrayEquals(list.toArray(), list1.toArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren