diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/PacketType.java b/ProtocolLib/src/main/java/com/comphenix/protocol/PacketType.java new file mode 100644 index 00000000..e543dce6 --- /dev/null +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/PacketType.java @@ -0,0 +1,286 @@ +package com.comphenix.protocol; + +import java.io.Serializable; +import com.comphenix.protocol.reflect.ObjectEnum; +import com.google.common.base.Objects; + +/** + * Represents the type of a packet in a specific protocol. + *

+ * Note that vanilla Minecraft reuses packet IDs per protocol (ping, game, login), so you cannot + * rely on IDs alone. + * @author Kristian + */ +public class PacketType implements Serializable { + // Increment whenever the type changes + private static final long serialVersionUID = 1L; + + public static class Handshake { + public static final Protocol PROTOCOL = Protocol.HANDSHAKE; + + public static class Client extends ObjectEnum { + public final static Sender SENDER = Sender.CLIENT; + public final static Client INSTANCE = new Client(); + + public static final PacketType HANDSHAKE = new PacketType(PROTOCOL, SENDER, 0x00, 2); + } + } + + public static class Game { + public static final Protocol PROTOCOL = Protocol.GAME; + + public static class Server extends ObjectEnum { + public final static Sender SENDER = Sender.SERVER; + public final static Server INSTANCE = new Server(); + + public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x00, 0); + public static final PacketType LOGIN = new PacketType(PROTOCOL, SENDER, 0x01, 1); + public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x02, 3); + public static final PacketType UPDATE_TIME = new PacketType(PROTOCOL, SENDER, 0x03, 4); + public static final PacketType ENTITY_EQUIPMENT = new PacketType(PROTOCOL, SENDER, 0x04, 5); + public static final PacketType SPAWN_POSITION = new PacketType(PROTOCOL, SENDER, 0x05, 6); + public static final PacketType UPDATE_HEALTH = new PacketType(PROTOCOL, SENDER, 0x06, 8); + public static final PacketType RESPAWN = new PacketType(PROTOCOL, SENDER, 0x07, 9); + public static final PacketType PLAYER_LOOK_MOVE = new PacketType(PROTOCOL, SENDER, 0x08, 13); + public static final PacketType BLOCK_ITEM_SWITCH = new PacketType(PROTOCOL, SENDER, 0x09, 16); + public static final PacketType ENTITY_LOCATION_ACTION = new PacketType(PROTOCOL, SENDER, 0x0A, 17); + public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x0B, 18); + public static final PacketType NAMED_ENTITY_SPAWN = new PacketType(PROTOCOL, SENDER, 0x0C, 20); + public static final PacketType COLLECT = new PacketType(PROTOCOL, SENDER, 0x0D, 22); + public static final PacketType VEHICLE_SPAWN = new PacketType(PROTOCOL, SENDER, 0x0E, 23); + public static final PacketType MOB_SPAWN = new PacketType(PROTOCOL, SENDER, 0x0F, 24); + public static final PacketType ENTITY_PAINTING = new PacketType(PROTOCOL, SENDER, 0x10, 25); + public static final PacketType ADD_EXP_ORB = new PacketType(PROTOCOL, SENDER, 0x11, 26); + public static final PacketType ENTITY_VELOCITY = new PacketType(PROTOCOL, SENDER, 0x12, 28); + public static final PacketType DESTROY_ENTITY = new PacketType(PROTOCOL, SENDER, 0x13, 29); + public static final PacketType ENTITY = new PacketType(PROTOCOL, SENDER, 0x14, 30); + public static final PacketType REL_ENTITY_MOVE = new PacketType(PROTOCOL, SENDER, 0x15, 31); + public static final PacketType ENTITY_LOOK = new PacketType(PROTOCOL, SENDER, 0x16, 32); + public static final PacketType ENTITY_MOVE_LOOK = new PacketType(PROTOCOL, SENDER, 0x17, 33); + public static final PacketType ENTITY_TELEPORT = new PacketType(PROTOCOL, SENDER, 0x18, 34); + public static final PacketType ENTITY_HEAD_ROTATION = new PacketType(PROTOCOL, SENDER, 0x19, 35); + public static final PacketType ENTITY_STATUS = new PacketType(PROTOCOL, SENDER, 0x1A, 38); + public static final PacketType ATTACH_ENTITY = new PacketType(PROTOCOL, SENDER, 0x1B, 39); + public static final PacketType ENTITY_METADATA = new PacketType(PROTOCOL, SENDER, 0x1C, 40); + public static final PacketType MOB_EFFECT = new PacketType(PROTOCOL, SENDER, 0x1D, 41); + public static final PacketType REMOVE_MOB_EFFECT = new PacketType(PROTOCOL, SENDER, 0x1E, 42); + public static final PacketType SET_EXPERIENCE = new PacketType(PROTOCOL, SENDER, 0x1F, 43); + public static final PacketType UPDATE_ATTRIBUTES = new PacketType(PROTOCOL, SENDER, 0x20, 44); + public static final PacketType MAP_CHUNK = new PacketType(PROTOCOL, SENDER, 0x21, 51); + public static final PacketType MULTI_BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x22, 52); + public static final PacketType BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x23, 53); + public static final PacketType PLAY_NOTE_BLOCK = new PacketType(PROTOCOL, SENDER, 0x24, 54); + public static final PacketType BLOCK_BREAK_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x25, 55); + public static final PacketType MAP_CHUNK_BULK = new PacketType(PROTOCOL, SENDER, 0x26, 56); + public static final PacketType EXPLOSION = new PacketType(PROTOCOL, SENDER, 0x27, 60); + public static final PacketType WORLD_EVENT = new PacketType(PROTOCOL, SENDER, 0x28, 61); + public static final PacketType NAMED_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x29, 62); + public static final PacketType WORLD_PARTICLES = new PacketType(PROTOCOL, SENDER, 0x2A, 63); + public static final PacketType BED = new PacketType(PROTOCOL, SENDER, 0x2B, 70); + public static final PacketType WEATHER = new PacketType(PROTOCOL, SENDER, 0x2C, 71); + public static final PacketType OPEN_WINDOW = new PacketType(PROTOCOL, SENDER, 0x2D, 100); + public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x2E, 101); + public static final PacketType SET_SLOT = new PacketType(PROTOCOL, SENDER, 0x2F, 103); + public static final PacketType WINDOW_ITEMS = new PacketType(PROTOCOL, SENDER, 0x30, 104); + public static final PacketType CRAFT_PROGRESS_BAR = new PacketType(PROTOCOL, SENDER, 0x31, 105); + public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x32, 106); + public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x33, 130); + public static final PacketType ITEM_DATA = new PacketType(PROTOCOL, SENDER, 0x34, 131); + public static final PacketType TILE_ENTITY_DATA = new PacketType(PROTOCOL, SENDER, 0x35, 132); + public static final PacketType OPEN_TILE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x36, 133); + public static final PacketType STATISTICS = new PacketType(PROTOCOL, SENDER, 0x37, 200); + public static final PacketType PLAYER_INFO = new PacketType(PROTOCOL, SENDER, 0x38, 201); + public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x39, 202); + public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x3A, 203); + public static final PacketType SET_SCOREBOARD_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x3B, 206); + public static final PacketType SET_SCOREBOARD_SCORE = new PacketType(PROTOCOL, SENDER, 0x3C, 207); + public static final PacketType SET_SCOREBOARD_DISPLAY_OBJECTIVE = + new PacketType(PROTOCOL, SENDER, 0x3D, 208); + public static final PacketType SET_SCOREOARD_TEAM = new PacketType(PROTOCOL, SENDER, 0x3E, 209); + public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x3F, 250); + public static final PacketType KICK_DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x40, 255); + } + + public static class Client extends ObjectEnum { + public final static Sender SENDER = Sender.CLIENT; + public final static Client INSTANCE = new Client(); + + public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x00, 0); + public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x01, 3); + public static final PacketType USE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x02, 7); + public static final PacketType FLYING = new PacketType(PROTOCOL, SENDER, 0x03, 10); + public static final PacketType PLAYER_POSITION = new PacketType(PROTOCOL, SENDER, 0x04, 11); + public static final PacketType PLAYER_LOOK = new PacketType(PROTOCOL, SENDER, 0x05, 12); + public static final PacketType PLAYER_LOOK_MOVE = new PacketType(PROTOCOL, SENDER, 0x06, 13); + public static final PacketType BLOCK_DIG = new PacketType(PROTOCOL, SENDER, 0x07, 14); + public static final PacketType PLACE = new PacketType(PROTOCOL, SENDER, 0x08, 15); + public static final PacketType BLOCK_ITEM_SWITCH = new PacketType(PROTOCOL, SENDER, 0x09, 16); + public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x0A, 18); + public static final PacketType ENTITY_ACTION = new PacketType(PROTOCOL, SENDER, 0x0B, 19); + public static final PacketType PLAYER_INPUT = new PacketType(PROTOCOL, SENDER, 0x0C, 27); + public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x0D, 101); + public static final PacketType WINDOW_CLICK = new PacketType(PROTOCOL, SENDER, 0x0E, 102); + public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x0F, 106); + public static final PacketType CREATIVE_SLOT = new PacketType(PROTOCOL, SENDER, 0x10, 107); + public static final PacketType BUTTON_CLICK = new PacketType(PROTOCOL, SENDER, 0x11, 108); + public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x12, 130); + public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x13, 202); + public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x14, 203); + public static final PacketType LOCALE_AND_VIEW_DISTANCE = new PacketType(PROTOCOL, SENDER, 0x15, 204); + public static final PacketType CLIENT_COMMAND = new PacketType(PROTOCOL, SENDER, 0x16, 205); + public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x17, 250); + } + } + + public static class Status { + public static final Protocol PROTOCOL = Protocol.STATUS; + + public static class Server extends ObjectEnum { + public final static Sender SENDER = Sender.SERVER; + public final static Server INSTANCE = new Server(); + + public static final PacketType KICK_DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x00, 255); + @SuppressWarnings("deprecation") + public static final PacketType PING_TIME = new PacketType(PROTOCOL, SENDER, 0x00, Packets.Server.PING_TIME); + } + + public static class Client extends ObjectEnum { + public final static Sender SENDER = Sender.CLIENT; + public final static Client INSTANCE = new Client(); + + public static final PacketType STATUS_REQUEST = new PacketType(PROTOCOL, SENDER, 0x00, 254); + @SuppressWarnings("deprecation") + public static final PacketType PING_TIME = new PacketType(PROTOCOL, SENDER, 0x00, Packets.Client.PING_TIME); + } + } + + public static class Login { + public static final Protocol PROTOCOL = Protocol.LOGIN; + + public static class Server extends ObjectEnum { + public final static Sender SENDER = Sender.SERVER; + public final static Server INSTANCE = new Server(); + + public static final PacketType KICK_DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x00, 255); + public static final PacketType KEY_REQUEST = new PacketType(PROTOCOL, SENDER, 0x01, 253); + @SuppressWarnings("deprecation") + public static final PacketType LOGIN_SUCCESS = new PacketType(PROTOCOL, SENDER, 0x02, Packets.Server.LOGIN_SUCCESS); + } + + public static class Client extends ObjectEnum { + public final static Sender SENDER = Sender.CLIENT; + public final static Client INSTANCE = new Client(); + + @SuppressWarnings("deprecation") + public static final PacketType LOGIN_START = new PacketType(PROTOCOL, SENDER, 0x00, Packets.Client.LOGIN_START); + public static final PacketType KEY_RESPONSE = new PacketType(PROTOCOL, SENDER, 0x01, 252); + } + } + + /** + * Represents the different protocol or connection states. + * @author Kristian + */ + public enum Protocol { + HANDSHAKE, + GAME, + STATUS, + LOGIN + } + + /** + * Represens the sender of this packet type. + * @author Kristian + * + */ + public enum Sender { + /** + * Indicates that packets of this type will be sent by connected clients. + */ + CLIENT, + + /** + * Indicate that packets of this type will be sent by the current server. + */ + SERVER + } + + private final Protocol protocol; + private final Sender sender; + private final int currentId; + private final int legacyId; + + /** + * Construct a new packet type. + * @param protocol - the current protocol. + * @param target - the target - client or server. + * @param currentId - the current packet ID. + * @param legacyId - the legacy packet ID. + */ + public PacketType(Protocol protocol, Sender sender, int currentId, int legacyId) { + this.protocol = protocol; + this.sender = sender; + this.currentId = currentId; + this.legacyId = legacyId; + } + + /** + * Retrieve the protocol (the connection state) the packet type belongs. + * @return The protocol of this type. + */ + public Protocol getProtocol() { + return protocol; + } + + /** + * Retrieve which sender will transmit packets of this type. + * @return The sender of these packets. + */ + public Sender getSender() { + return sender; + } + + /** + * Retrieve the current protocol ID for this packet type. + *

+ * This is only unique within a specific protocol and target. + * @return The current ID. + */ + public int getCurrentId() { + return currentId; + } + + /** + * Retrieve the legacy (pre 1.7.2) protocol ID of the packet type. + *

+ * This ID is globally unique. + * @return The legacy ID. + */ + public int getLegacyId() { + return legacyId; + } + + @Override + public int hashCode() { + return Objects.hashCode(protocol, sender, legacyId, currentId); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + + if (obj instanceof PacketType) { + PacketType other = (PacketType) obj; + return protocol == other.protocol && + sender == other.sender && + currentId == other.currentId; + } + return false; + } + + @Override + public String toString() { + return "Packet [protocol=" + protocol + ", sender=" + sender + ", legacyId=" + legacyId + ", currentId=" + currentId + "]"; + } +} diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java b/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java index defd5419..7afc45b7 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/Packets.java @@ -42,8 +42,11 @@ public final class Packets { /** * List of packets sent only by the server. + *

+ * This has been superceded by PacketType. * @author Kristian */ + @Deprecated public static final class Server extends IntEnum { /** * The singleton instance. Can also be retrieved from the parent class. @@ -143,6 +146,16 @@ public final class Packets { public static final int KEY_REQUEST = 253; public static final int KICK_DISCONNECT = 255; + /** + * This packet was introduced in 1.7.2. + */ + public static final int PING_TIME = 230; + + /** + * This packet was introduced in 1.7.2. + */ + public static final int LOGIN_SUCCESS = 232; + /** * A registry that parses between names and packet IDs. * @return The current server registry. @@ -178,8 +191,11 @@ public final class Packets { /** * List of packets sent by the client. + *

+ * This has been superceded by PacketType. * @author Kristian */ + @Deprecated public static class Client extends IntEnum { /** * The singleton instance. Can also be retrieved from the parent class. @@ -223,6 +239,16 @@ public final class Packets { public static final int GET_INFO = 254; public static final int KICK_DISCONNECT = 255; + /** + * This packet was introduced in 1.7.2. + */ + public static final int PING_TIME = 230; + + /** + * This packet was introduced in 1.7.2. + */ + public static final int LOGIN_START = 231; + /** * A registry that parses between names and packet IDs. * @return The current client registry. @@ -260,6 +286,7 @@ public final class Packets { * A registry that parses between names and packet IDs. * @return The current client registry. */ + @Deprecated public static Server getServerRegistry() { return Server.getRegistry(); } @@ -268,6 +295,7 @@ public final class Packets { * A registry that parses between names and packet IDs. * @return The current server registry. */ + @Deprecated public static Client getClientRegistry() { return Client.INSTANCE; } @@ -277,6 +305,7 @@ public final class Packets { * @param name - name of packet to find. * @return The packet ID found. */ + @Deprecated public static int valueOf(String name) { Integer serverAttempt = Server.INSTANCE.valueOf(name); @@ -291,6 +320,7 @@ public final class Packets { * @param packetID - packet to retrieve name. * @return The name, or NULL if unable to find such a packet. */ + @Deprecated public static String getDeclaredName(int packetID) { String serverAttempt = Server.INSTANCE.getDeclaredName(packetID); diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/NettyProtocol.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/NettyProtocol.java new file mode 100644 index 00000000..87f309e9 --- /dev/null +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/NettyProtocol.java @@ -0,0 +1,28 @@ +package com.comphenix.protocol.injector.netty; + +import com.comphenix.protocol.utility.MinecraftReflection; + +/** + * Represents a way of accessing the new netty Protocol enum. + * @author Kristian + */ +public class NettyProtocol { + private Class enumProtocol; + + + + public NettyProtocol() { + enumProtocol = MinecraftReflection.getEnumProtocolClass(); + + + } + + /** + * Load the packet lookup tables in each protocol. + */ + private void initialize() { + for (Object protocol : enumProtocol.getEnumConstants()) { + + } + } +} diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/ObjectEnum.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/ObjectEnum.java new file mode 100644 index 00000000..9499454b --- /dev/null +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/ObjectEnum.java @@ -0,0 +1,109 @@ +/* + * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. + * Copyright (C) 2012 Kristian S. Stangeland + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ + +package com.comphenix.protocol.reflect; + +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +/** + * Represents a more modern object-based enum. + *

+ * This is useful if you want the flexibility of a modern Java enum, but don't + * want to prevent the creation of additional members dynamically. + * @author Kristian + */ +public class ObjectEnum { + // Used to convert between IDs and names + protected BiMap members = HashBiMap.create(); + + /** + * Registers every declared integer field. + */ + public ObjectEnum() { + registerAll(); + } + + /** + * Registers every public int field as a member. + */ + @SuppressWarnings("unchecked") + protected void registerAll() { + try { + // Register every int field + for (Field entry : this.getClass().getFields()) { + if (entry.getType().equals(int.class)) { + registerMember((T) entry.get(this), entry.getName()); + } + } + + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + /** + * Registers a member. + * @param instance - member instance. + * @param name - name of member. + */ + protected void registerMember(T instance, String name) { + members.put(instance, name); + + } + + /** + * Determines whether or not the given member has been registered to this enum. + * @param member - the member to check. + * @return TRUE if the given member has been registered, FALSE otherwise. + */ + public boolean hasMember(T member) { + return members.containsKey(member); + } + + /** + * Retrieve a member by name, + * @param name - name of member to retrieve. + * @return The member, or NULL if not found. + */ + public T valueOf(String name) { + return members.inverse().get(name); + } + + /** + * Retrieve the name of the given member. + * @param member - the member to retrieve. + * @return Declared name of the member, or NULL if not found. + */ + public String getDeclaredName(T member) { + return members.get(member); + } + + /** + * Retrieve every registered member. + * @return Enumeration of every value. + */ + public Set values() { + return new HashSet(members.keySet()); + } +} 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 fec2cd4b..4e9e6d59 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java @@ -584,6 +584,24 @@ public class MinecraftReflection { } } + /** + * Retrieve the EnumProtocol class in 1.7.2. + * @return The Enum protocol class. + */ + public static Class getEnumProtocolClass() { + try { + return getMinecraftClass("EnumProtocol"); + } catch (RuntimeException e) { + Method protocolMethod = FuzzyReflection.fromClass(getNetworkManagerClass()).getMethod( + FuzzyMethodContract.newBuilder(). + parameterCount(1). + parameterDerivedOf(Enum.class, 0). + build() + ); + return setMinecraftClass("EnumProtocol", protocolMethod.getParameterTypes()[0]); + } + } + /** * Retrieve the least derived class, except Object. * @return Least derived super class. @@ -599,7 +617,6 @@ public class MinecraftReflection { } } - /** * Retrieve the MinecraftServer class. * @return MinecraftServer class.