diff --git a/ItemDisguise/.settings/org.eclipse.core.resources.prefs b/ItemDisguise/.settings/org.eclipse.core.resources.prefs index aa930803..1a9b29c0 100644 --- a/ItemDisguise/.settings/org.eclipse.core.resources.prefs +++ b/ItemDisguise/.settings/org.eclipse.core.resources.prefs @@ -1,3 +1,2 @@ eclipse.preferences.version=1 -encoding//src/main/java=cp1252 encoding/=cp1252 diff --git a/ItemDisguise/target/ItemDisguise-1.0.0.jar b/ItemDisguise/target/ItemDisguise-1.0.0.jar new file mode 100644 index 00000000..746a95b6 Binary files /dev/null and b/ItemDisguise/target/ItemDisguise-1.0.0.jar differ diff --git a/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener$1.class b/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener$1.class new file mode 100644 index 00000000..51854b70 Binary files /dev/null and b/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener$1.class differ diff --git a/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener$2.class b/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener$2.class new file mode 100644 index 00000000..04f3d524 Binary files /dev/null and b/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener$2.class differ diff --git a/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener.class b/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener.class new file mode 100644 index 00000000..a94e8801 Binary files /dev/null and b/ItemDisguise/target/classes/com/comphenix/itemdisguise/HideEnchantmentsListener.class differ diff --git a/ItemDisguise/target/classes/com/comphenix/itemdisguise/ItemDisguiseMod.class b/ItemDisguise/target/classes/com/comphenix/itemdisguise/ItemDisguiseMod.class new file mode 100644 index 00000000..62c11448 Binary files /dev/null and b/ItemDisguise/target/classes/com/comphenix/itemdisguise/ItemDisguiseMod.class differ diff --git a/ItemDisguise/target/classes/plugin.yml b/ItemDisguise/target/classes/plugin.yml new file mode 100644 index 00000000..7639f0b5 --- /dev/null +++ b/ItemDisguise/target/classes/plugin.yml @@ -0,0 +1,14 @@ +name: ItemDisguiseMod +version: 1.0.0 +description: Change the appearance of inventory items. +author: Comphenix +website: http://www.comphenix.net/ItemDisguise + +main: com.comphenix.itemdisguise.ItemDisguiseMod +depends: [ProtocolLib] +database: false + +commands: + explosion: + description: Creates a fake explosion around the caller. + usage: / \ No newline at end of file diff --git a/ItemDisguise/target/maven-archiver/pom.properties b/ItemDisguise/target/maven-archiver/pom.properties new file mode 100644 index 00000000..10155862 --- /dev/null +++ b/ItemDisguise/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Thu Oct 11 09:08:39 CEST 2012 +version=1.0.0 +groupId=com.comphenix.itemdisguise +artifactId=ItemDisguise diff --git a/ProtocolLib/.classpath b/ProtocolLib/.classpath index e842aee4..c5d993a4 100644 --- a/ProtocolLib/.classpath +++ b/ProtocolLib/.classpath @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ProtocolLib/.project b/ProtocolLib/.project index a1960c9e..d36fcbe8 100644 --- a/ProtocolLib/.project +++ b/ProtocolLib/.project @@ -11,12 +11,12 @@ - org.eclipse.m2e.core.maven2Builder + net.sourceforge.metrics.builder - net.sourceforge.metrics.builder + org.eclipse.m2e.core.maven2Builder diff --git a/ProtocolLib/pom.xml b/ProtocolLib/pom.xml index 0d7b1758..42862be5 100644 --- a/ProtocolLib/pom.xml +++ b/ProtocolLib/pom.xml @@ -214,7 +214,7 @@ org.bukkit craftbukkit - 1.5.1-R0.2-SNAPSHOT + 1.6.2-R0.1-SNAPSHOT provided diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java b/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java index bbbad165..b2d8ee28 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java @@ -35,6 +35,11 @@ public final class Packets { */ public static final int MAXIMUM_PACKET_ID = 255; + /** + * The maximum number of unique packet IDs. It's unlikely this will ever change. + */ + public static final int PACKET_COUNT = 256; + /** * List of packets sent only by the server. * @author Kristian diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/concurrency/IntegerSet.java b/ProtocolLib/src/main/java/com/comphenix/protocol/concurrency/IntegerSet.java index c99e18e1..a163cb0a 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/concurrency/IntegerSet.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/concurrency/IntegerSet.java @@ -43,6 +43,18 @@ public class IntegerSet { this.array = new boolean[maximumCount]; } + /** + * Initialize a lookup table with a given maximum and value list. + *

+ * The provided elements must be in the range [0, count). + * @param maximumCount - the maximum element value and count. + * @param values - the elements to add to the set. + */ + public IntegerSet(int maximumCount, Collection values) { + this.array = new boolean[maximumCount]; + addAll(values); + } + /** * Determine whether or not the given element exists in the set. * @param element - the element to check. Must be in the range [0, count). diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java b/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java index 46d5e7f2..22b3be8a 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java @@ -17,7 +17,9 @@ package com.comphenix.protocol.events; +import java.io.DataInput; import java.io.DataInputStream; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectInputStream; @@ -26,6 +28,7 @@ import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.ConcurrentMap; @@ -37,6 +40,8 @@ import org.bukkit.WorldType; import org.bukkit.entity.Entity; import org.bukkit.inventory.ItemStack; +import com.comphenix.protocol.Packets; +import com.comphenix.protocol.concurrency.IntegerSet; import com.comphenix.protocol.injector.StructureCache; import com.comphenix.protocol.reflect.EquivalentConverter; import com.comphenix.protocol.reflect.FuzzyReflection; @@ -48,7 +53,9 @@ 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.ReflectionCloner; import com.comphenix.protocol.reflect.cloning.AggregateCloner.BuilderParameters; +import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.instances.DefaultInstances; import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.StreamSerializer; @@ -107,6 +114,10 @@ public class PacketContainer implements Serializable { }). build(); + // Packets that cannot be cloned by our default deep cloner + private static final IntegerSet CLONING_UNSUPPORTED = new IntegerSet(Packets.PACKET_COUNT, + Arrays.asList(Packets.Server.UPDATE_ATTRIBUTES)); + /** * Creates a packet container for a new packet. * @param id - ID of the packet to create. @@ -421,10 +432,17 @@ public class PacketContainer implements Serializable { * @return A deep copy of the current packet. */ public PacketContainer deepClone() { - Object clonedPacket = DEEP_CLONER.clone(getHandle()); + Object clonedPacket = null; + + // Fall back on the alternative (but slower) method of reading and writing back the packet + if (CLONING_UNSUPPORTED.contains(id)) { + clonedPacket = ReflectionCloner.clone(this).getHandle(); + } else { + clonedPacket = DEEP_CLONER.clone(getHandle()); + } return new PacketContainer(getID(), clonedPacket); } - + // To save space, we'll skip copying the inflated buffers in packet 51 and 56 private static Function getSpecializedDeepClonerFactory() { // Look at what you've made me do Java, look at it!! @@ -456,7 +474,7 @@ public class PacketContainer implements Serializable { try { // Call the write-method - getMethodLazily(writeMethods, handle.getClass(), "write", DataOutputStream.class). + getMethodLazily(writeMethods, handle.getClass(), "write", DataOutput.class). invoke(handle, new DataOutputStream(output)); } catch (IllegalArgumentException e) { @@ -483,7 +501,7 @@ public class PacketContainer implements Serializable { // Call the read method try { - getMethodLazily(readMethods, handle.getClass(), "read", DataInputStream.class). + getMethodLazily(readMethods, handle.getClass(), "read", DataInput.class). invoke(handle, new DataInputStream(input)); } catch (IllegalArgumentException e) { @@ -513,7 +531,12 @@ public class PacketContainer implements Serializable { // Atomic operation if (method == null) { - Method initialized = FuzzyReflection.fromClass(handleClass).getMethodByParameters(methodName, parameterClass); + Method initialized = FuzzyReflection.fromClass(handleClass).getMethod( + FuzzyMethodContract.newBuilder(). + parameterCount(1). + parameterDerivedOf(parameterClass). + returnTypeVoid(). + build()); method = lookup.putIfAbsent(handleClass, initialized); // Use our version if we succeeded diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/MethodInfo.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/MethodInfo.java index 73fdea0b..fafe48de 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/MethodInfo.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/MethodInfo.java @@ -9,8 +9,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.apache.commons.lang.NotImplementedException; - import com.google.common.collect.Lists; /** @@ -186,7 +184,7 @@ public abstract class MethodInfo implements GenericDeclaration, Member { */ @Override public String toString() { - throw new NotImplementedException(); + throw new UnsupportedOperationException(); } /** diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/cloning/ReflectionCloner.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/cloning/ReflectionCloner.java new file mode 100644 index 00000000..2c4d3492 --- /dev/null +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/cloning/ReflectionCloner.java @@ -0,0 +1,47 @@ +package com.comphenix.protocol.reflect.cloning; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * Represents a cloner that can clone any class that implements Serializable. + * @author Kristian Stangeland + */ +public class ReflectionCloner implements Cloner { + + @Override + public boolean canClone(Object source) { + if (source == null) + return false; + return source instanceof Serializable; + } + + @Override + public Object clone(Object source) { + return clone(source); + } + + /** + * Clone the given object using serialization. + * @param obj - the object to clone. + * @return The cloned object. + * @throws RuntimeException If we were unable to clone the object. + */ + @SuppressWarnings("unchecked") + public static T clone(final T obj) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream oout = new ObjectOutputStream(out); + + oout.writeObject(obj); + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); + return (T) in.readObject(); + + } catch (Exception e) { + throw new RuntimeException("Unable to clone object " + obj, e); + } + } +} diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMethodContract.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMethodContract.java index 35b92d9a..c761554b 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMethodContract.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMethodContract.java @@ -7,8 +7,6 @@ import java.util.regex.Pattern; import javax.annotation.Nonnull; -import org.apache.commons.lang.NotImplementedException; - import com.comphenix.protocol.reflect.MethodInfo; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; @@ -65,7 +63,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember { @Override public boolean isMatch(Class[] value, Object parent) { - throw new NotImplementedException("Use the parameter match instead."); + throw new UnsupportedOperationException("Use the parameter match instead."); } @Override diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java index cd6af1d2..40fe3d58 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java @@ -18,7 +18,7 @@ package com.comphenix.protocol.utility; import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -219,6 +219,11 @@ public class MinecraftReflection { MINECRAFT_FULL_PACKAGE = minecraftPackage; CRAFTBUKKIT_PACKAGE = craftBukkitPackage; + // Make sure it exists + if (getMinecraftServerClass() == null) { + throw new IllegalArgumentException("Cannot find MinecraftServer for package " + minecraftPackage); + } + // Standard matcher setDynamicPackageMatcher(MINECRAFT_OBJECT); } @@ -792,7 +797,7 @@ public class MinecraftReflection { Method selected = FuzzyReflection.fromClass(getDataWatcherClass(), true). getMethod(FuzzyMethodContract.newBuilder(). requireModifier(Modifier.STATIC). - parameterSuperOf(DataOutputStream.class, 0). + parameterDerivedOf(DataOutput.class, 0). parameterMatches(getMinecraftObjectMatcher(), 1). build()); diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java index 2a441149..a1d6dda5 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java @@ -2,7 +2,9 @@ package com.comphenix.protocol.utility; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataInput; import java.io.DataInputStream; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.lang.reflect.Method; @@ -13,6 +15,7 @@ import org.bukkit.inventory.ItemStack; import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; import com.comphenix.protocol.reflect.FuzzyReflection; +import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; /** * Utility methods for reading and writing Minecraft objects to streams. @@ -37,11 +40,14 @@ public class StreamSerializer { public ItemStack deserializeItemStack(@Nonnull DataInputStream input) throws IOException { if (input == null) throw new IllegalArgumentException("Input stream cannot be NULL."); - if (readItemMethod == null) - readItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()). - getMethodByParameters("readPacket", - MinecraftReflection.getItemStackClass(), - new Class[] {DataInputStream.class}); + if (readItemMethod == null) { + readItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod( + FuzzyMethodContract.newBuilder(). + parameterCount(1). + parameterDerivedOf(DataInput.class). + returnDerivedOf(MinecraftReflection.getItemStackClass()). + build()); + } try { Object nmsItem = readItemMethod.invoke(null, input); @@ -88,10 +94,12 @@ public class StreamSerializer { Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack); if (writeItemMethod == null) - writeItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()). - getMethodByParameters("writePacket", new Class[] { - MinecraftReflection.getItemStackClass(), - DataOutputStream.class }); + writeItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod( + FuzzyMethodContract.newBuilder(). + parameterCount(2). + parameterDerivedOf(MinecraftReflection.getItemStackClass(), 0). + parameterDerivedOf(DataOutput.class, 1). + build()); try { writeItemMethod.invoke(null, nmsItem, output); } catch (Exception e) { diff --git a/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java b/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java index 39b6b55d..988ac692 100644 --- a/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java +++ b/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java @@ -4,10 +4,10 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import net.minecraft.server.v1_5_R2.StatisticList; +import net.minecraft.server.v1_6_R2.StatisticList; // Will have to be updated for every version though -import org.bukkit.craftbukkit.v1_5_R2.inventory.CraftItemFactory; +import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftItemFactory; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -63,6 +63,6 @@ public class BukkitInitialization { */ public static void initializePackage() { // Initialize reflection - MinecraftReflection.setMinecraftPackage("net.minecraft.server.v1_5_R2", "org.bukkit.craftbukkit.v1_5_R2"); + MinecraftReflection.setMinecraftPackage("net.minecraft.server.v1_6_R2", "org.bukkit.craftbukkit.v1_6_R2"); } } diff --git a/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java b/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java index d305adf4..c6e67b0c 100644 --- a/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java +++ b/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java @@ -20,9 +20,17 @@ package com.comphenix.protocol.events; import static org.junit.Assert.*; import java.lang.reflect.Array; import java.util.List; +import java.util.UUID; +import net.minecraft.server.v1_6_R2.AttributeModifier; +import net.minecraft.server.v1_6_R2.AttributeSnapshot; +import net.minecraft.server.v1_6_R2.Packet44UpdateAttributes; + +import org.apache.commons.lang.SerializationUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; // Will have to be updated for every version though -import org.bukkit.craftbukkit.v1_5_R2.inventory.CraftItemFactory; +import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftItemFactory; import org.bukkit.Material; import org.bukkit.WorldType; @@ -305,7 +313,40 @@ public class PacketContainerTest { watchableAccessor.write(0, list); assertEquals(list, watchableAccessor.read(0)); } + + @Test + public void testSerialization() { + PacketContainer chat = new PacketContainer(3); + chat.getStrings().write(0, "Test"); + + PacketContainer copy = (PacketContainer) SerializationUtils.clone(chat); + + assertEquals(3, copy.getID()); + assertEquals("Test", copy.getStrings().read(0)); + } + + @Test + public void testAttributeList() { + PacketContainer attribute = new PacketContainer(Packets.Server.UPDATE_ATTRIBUTES); + attribute.getIntegers().write(0, 123); // Entity ID + + // Initialize some test data + List modifiers = Lists.newArrayList( + new AttributeModifier(UUID.randomUUID(), "Unknown synced attribute modifier", 10, 0)); + AttributeSnapshot snapshot = new AttributeSnapshot( + (Packet44UpdateAttributes) attribute.getHandle(), "generic.Maxhealth", 20.0, modifiers); + + attribute.getSpecificModifier(List.class).write(0, Lists.newArrayList(snapshot)); + PacketContainer cloned = attribute.deepClone(); + AttributeSnapshot clonedSnapshot = (AttributeSnapshot) cloned.getSpecificModifier(List.class).read(0).get(0); + + assertEquals( + ToStringBuilder.reflectionToString(snapshot, ToStringStyle.SHORT_PREFIX_STYLE), + ToStringBuilder.reflectionToString(clonedSnapshot, ToStringStyle.SHORT_PREFIX_STYLE)); + } + + @Test public void testDeepClone() { // Try constructing all the packets diff --git a/ProtocolLib/src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java b/ProtocolLib/src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java new file mode 100644 index 00000000..0895023b --- /dev/null +++ b/ProtocolLib/src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java @@ -0,0 +1,36 @@ +package com.comphenix.protocol.utility; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftItemFactory; +import org.bukkit.inventory.ItemStack; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; + +import com.comphenix.protocol.BukkitInitialization; + +@RunWith(org.powermock.modules.junit4.PowerMockRunner.class) +@PrepareForTest(CraftItemFactory.class) +public class StreamSerializerTest { + @BeforeClass + public static void initializeBukkit() throws IllegalAccessException { + BukkitInitialization.initializeItemMeta(); + } + + @Test + public void testSerializer() throws IOException { + ItemStack before = new ItemStack(Material.GOLD_AXE); + + StreamSerializer serializer = new StreamSerializer(); + String data = serializer.serializeItemStack(before); + ItemStack after = serializer.deserializeItemStack(data); + + assertEquals(before.getType(), after.getType()); + assertEquals(before.getAmount(), after.getAmount()); + } +}