Archiviert
13
0

Improve packet class lookup performance by mainaining a inverse map.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2013-07-04 01:12:39 +02:00
Ursprung 0ec2a705da
Commit 49eb39e45f
3 geänderte Dateien mit 464 neuen und 304 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,130 @@
package com.comphenix.protocol.injector.packet;
import java.lang.reflect.Field;
import java.util.Map;
import com.comphenix.protocol.reflect.FieldUtils;
import com.google.common.base.Predicate;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.ForwardingMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
public class InverseMaps {
private InverseMaps() {
// Not constructable
}
public static <K, V> Multimap<K, V> inverseMultimap(final Map<V, K> map, final Predicate<Map.Entry<V, K>> filter) {
final MapContainer container = new MapContainer(map);
return new ForwardingMultimap<K, V>() {
// The cached multimap
private Multimap<K, V> inverseMultimap;
@Override
protected Multimap<K, V> delegate() {
if (container.hasChanged()) {
inverseMultimap = HashMultimap.create();
// Construct the inverse map
for (Map.Entry<V, K> entry : map.entrySet()) {
if (filter.apply(entry)) {
inverseMultimap.put(entry.getValue(), entry.getKey());
}
}
container.setChanged(false);
}
return inverseMultimap;
}
};
}
public static <K, V> Map<K, V> inverseMap(final Map<V, K> map, final Predicate<Map.Entry<V, K>> filter) {
final MapContainer container = new MapContainer(map);
return new ForwardingMap<K, V>() {
// The cached map
private Map<K, V> inverseMap;
@Override
protected Map<K, V> delegate() {
if (container.hasChanged()) {
inverseMap = Maps.newHashMap();
// Construct the inverse map
for (Map.Entry<V, K> entry : map.entrySet()) {
if (filter.apply(entry)) {
inverseMap.put(entry.getValue(), entry.getKey());
}
}
container.setChanged(false);
}
return inverseMap;
}
};
}
/**
* Represents a class that can detect if a map has changed.
* @author Kristian
*/
private static class MapContainer {
// For detecting changes
private Field modCountField;
private int lastModCount;
// The object along with whether or not this is the initial run
private Object source;
private boolean changed;
public MapContainer(Object source) {
this.source = source;
this.changed = true;
this.modCountField = FieldUtils.getField(source.getClass(), "modCount", true);
}
/**
* Determine if the map has changed.
* @return TRUE if it has, FALSE otherwise.
*/
public boolean hasChanged() {
// Check if unchanged
checkChanged();
return changed;
}
/**
* Mark the map as changed or unchanged.
* @param changed - TRUE if the map has changed, FALSE otherwise.
*/
public void setChanged(boolean changed) {
this.changed = changed;
}
/**
* Check for modifications to the current map.
*/
protected void checkChanged() {
if (!changed) {
if (getModificationCount() != lastModCount) {
lastModCount = getModificationCount();
changed = true;
}
}
}
/**
* Retrieve the current modification count.
* @return The current count, or something different than lastModCount if not accessible.
*/
private int getModificationCount() {
try {
return modCountField != null ? modCountField.getInt(source) : lastModCount + 1;
} catch (Exception e) {
throw new RuntimeException("Unable to retrieve modCount.", e);
}
}
}
}

Datei anzeigen

@ -1,303 +1,333 @@
/* /*
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland * Copyright (C) 2012 Kristian S. Stangeland
* *
* This program is free software; you can redistribute it and/or modify it under the terms of the * 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 * GNU General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version. * 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; * 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. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * 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; * 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 * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA * 02111-1307 USA
*/ */
package com.comphenix.protocol.injector.packet; package com.comphenix.protocol.injector.packet;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import net.sf.cglib.proxy.Factory;
import javax.annotation.Nullable;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.error.Report; import net.sf.cglib.proxy.Factory;
import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.reflect.FieldAccessException; import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.reflect.FieldUtils; import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.reflect.fuzzy.FuzzyClassContract; import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract; import com.comphenix.protocol.reflect.FieldUtils;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.reflect.fuzzy.FuzzyClassContract;
import com.comphenix.protocol.wrappers.TroveWrapper; import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.google.common.base.Objects; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.google.common.collect.ImmutableSet; import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.TroveWrapper;
/** import com.google.common.base.Predicate;
* Static packet registry in Minecraft. import com.google.common.collect.ImmutableSet;
* import com.google.common.collect.Iterables;
* @author Kristian import com.google.common.collect.Multimap;
*/
@SuppressWarnings("rawtypes") /**
public class PacketRegistry { * Static packet registry in Minecraft.
public static final ReportType REPORT_CANNOT_CORRECT_TROVE_MAP = new ReportType("Unable to correct no entry value."); *
* @author Kristian
public static final ReportType REPORT_INSUFFICIENT_SERVER_PACKETS = new ReportType("Too few server packets detected: %s"); */
public static final ReportType REPORT_INSUFFICIENT_CLIENT_PACKETS = new ReportType("Too few client packets detected: %s"); @SuppressWarnings("rawtypes")
public class PacketRegistry {
private static final int MIN_SERVER_PACKETS = 5; public static final ReportType REPORT_CANNOT_CORRECT_TROVE_MAP = new ReportType("Unable to correct no entry value.");
private static final int MIN_CLIENT_PACKETS = 5;
public static final ReportType REPORT_INSUFFICIENT_SERVER_PACKETS = new ReportType("Too few server packets detected: %s");
// Fuzzy reflection public static final ReportType REPORT_INSUFFICIENT_CLIENT_PACKETS = new ReportType("Too few client packets detected: %s");
private static FuzzyReflection packetRegistry;
private static final int MIN_SERVER_PACKETS = 5;
// The packet class to packet ID translator private static final int MIN_CLIENT_PACKETS = 5;
private static Map<Class, Integer> packetToID;
// Fuzzy reflection
// Whether or not certain packets are sent by the client or the server private static FuzzyReflection packetRegistry;
private static ImmutableSet<Integer> serverPackets;
private static ImmutableSet<Integer> clientPackets; // The packet class to packet ID translator
private static Map<Class, Integer> packetToID;
// The underlying sets
private static Set<Integer> serverPacketsRef; // Packet IDs to classes, grouped by whether or not they're vanilla or custom defined
private static Set<Integer> clientPacketsRef; private static Multimap<Integer, Class> customIdToPacket;
private static Map<Integer, Class> vanillaIdToPacket;
// New proxy values
private static Map<Integer, Class> overwrittenPackets = new HashMap<Integer, Class>(); // Whether or not certain packets are sent by the client or the server
private static ImmutableSet<Integer> serverPackets;
// Vanilla packets private static ImmutableSet<Integer> clientPackets;
private static Map<Integer, Class> previousValues = new HashMap<Integer, Class>();
// The underlying sets
@SuppressWarnings({ "unchecked" }) private static Set<Integer> serverPacketsRef;
public static Map<Class, Integer> getPacketToID() { private static Set<Integer> clientPacketsRef;
// Initialize it, if we haven't already
if (packetToID == null) { // New proxy values
try { private static Map<Integer, Class> overwrittenPackets = new HashMap<Integer, Class>();
Field packetsField = getPacketRegistry().getFieldByType("packetsField", Map.class);
packetToID = (Map<Class, Integer>) FieldUtils.readStaticField(packetsField, true); // Vanilla packets
} catch (IllegalArgumentException e) { private static Map<Integer, Class> previousValues = new HashMap<Integer, Class>();
// Spigot 1.2.5 MCPC workaround
try { @SuppressWarnings({ "unchecked" })
packetToID = getSpigotWrapper(); public static Map<Class, Integer> getPacketToID() {
} catch (Exception e2) { // Initialize it, if we haven't already
// Very bad indeed if (packetToID == null) {
throw new IllegalArgumentException(e.getMessage() + "; Spigot workaround failed.", e2); try {
} Field packetsField = getPacketRegistry().getFieldByType("packetsField", Map.class);
packetToID = (Map<Class, Integer>) FieldUtils.readStaticField(packetsField, true);
} catch (IllegalAccessException e) { } catch (IllegalArgumentException e) {
throw new RuntimeException("Unable to retrieve the packetClassToIdMap", e); // Spigot 1.2.5 MCPC workaround
} try {
} packetToID = getSpigotWrapper();
} catch (Exception e2) {
return packetToID; // Very bad indeed
} throw new IllegalArgumentException(e.getMessage() + "; Spigot workaround failed.", e2);
}
private static Map<Class, Integer> getSpigotWrapper() throws IllegalAccessException {
// If it talks like a duck, etc. } catch (IllegalAccessException e) {
// Perhaps it would be nice to have a proper duck typing library as well throw new RuntimeException("Unable to retrieve the packetClassToIdMap", e);
FuzzyClassContract mapLike = FuzzyClassContract.newBuilder(). }
method(FuzzyMethodContract.newBuilder().
nameExact("size").returnTypeExact(int.class)). // Create the inverse maps
method(FuzzyMethodContract.newBuilder(). customIdToPacket = InverseMaps.inverseMultimap(packetToID, new Predicate<Map.Entry<Class, Integer>>() {
nameExact("put").parameterCount(2)). @Override
method(FuzzyMethodContract.newBuilder(). public boolean apply(@Nullable Entry<Class, Integer> entry) {
nameExact("get").parameterCount(1)). return !MinecraftReflection.isMinecraftClass(entry.getKey());
build(); }
});
Field packetsField = getPacketRegistry().getField(
FuzzyFieldContract.newBuilder().typeMatches(mapLike).build()); // And the vanilla pack - here we assume a unique ID to class mapping
Object troveMap = FieldUtils.readStaticField(packetsField, true); vanillaIdToPacket = InverseMaps.inverseMap(packetToID, new Predicate<Map.Entry<Class, Integer>>() {
@Override
// Check for stupid no_entry_values public boolean apply(@Nullable Entry<Class, Integer> entry) {
try { return MinecraftReflection.isMinecraftClass(entry.getKey());
Field field = FieldUtils.getField(troveMap.getClass(), "no_entry_value", true); }
Integer value = (Integer) FieldUtils.readField(field, troveMap, true); });
}
if (value >= 0 && value < 256) { return packetToID;
// Someone forgot to set the no entry value. Let's help them. }
FieldUtils.writeField(field, troveMap, -1);
} private static Map<Class, Integer> getSpigotWrapper() throws IllegalAccessException {
} catch (IllegalArgumentException e) { // If it talks like a duck, etc.
// Whatever // Perhaps it would be nice to have a proper duck typing library as well
ProtocolLibrary.getErrorReporter().reportWarning(PacketRegistry.class, FuzzyClassContract mapLike = FuzzyClassContract.newBuilder().
Report.newBuilder(REPORT_CANNOT_CORRECT_TROVE_MAP).error(e)); method(FuzzyMethodContract.newBuilder().
} nameExact("size").returnTypeExact(int.class)).
method(FuzzyMethodContract.newBuilder().
// We'll assume this a Trove map nameExact("put").parameterCount(2)).
return TroveWrapper.getDecoratedMap(troveMap); method(FuzzyMethodContract.newBuilder().
} nameExact("get").parameterCount(1)).
build();
/**
* Retrieve the cached fuzzy reflection instance allowing access to the packet registry. Field packetsField = getPacketRegistry().getField(
* @return Reflected packet registry. FuzzyFieldContract.newBuilder().typeMatches(mapLike).build());
*/ Object troveMap = FieldUtils.readStaticField(packetsField, true);
private static FuzzyReflection getPacketRegistry() {
if (packetRegistry == null) // Check for stupid no_entry_values
packetRegistry = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true); try {
return packetRegistry; Field field = FieldUtils.getField(troveMap.getClass(), "no_entry_value", true);
} Integer value = (Integer) FieldUtils.readField(field, troveMap, true);
/** if (value >= 0 && value < 256) {
* Retrieve the injected proxy classes handlig each packet ID. // Someone forgot to set the no entry value. Let's help them.
* @return Injected classes. FieldUtils.writeField(field, troveMap, -1);
*/ }
public static Map<Integer, Class> getOverwrittenPackets() { } catch (IllegalArgumentException e) {
return overwrittenPackets; // Whatever
} ProtocolLibrary.getErrorReporter().reportWarning(PacketRegistry.class,
Report.newBuilder(REPORT_CANNOT_CORRECT_TROVE_MAP).error(e));
/** }
* Retrieve the vanilla classes handling each packet ID.
* @return Vanilla classes. // We'll assume this a Trove map
*/ return TroveWrapper.getDecoratedMap(troveMap);
public static Map<Integer, Class> getPreviousPackets() { }
return previousValues;
} /**
* Retrieve the cached fuzzy reflection instance allowing access to the packet registry.
/** * @return Reflected packet registry.
* Retrieve every known and supported server packet. */
* @return An immutable set of every known server packet. private static FuzzyReflection getPacketRegistry() {
* @throws FieldAccessException If we're unable to retrieve the server packet data from Minecraft. if (packetRegistry == null)
*/ packetRegistry = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true);
public static Set<Integer> getServerPackets() throws FieldAccessException { return packetRegistry;
initializeSets(); }
// Sanity check. This is impossible! /**
if (serverPackets != null && serverPackets.size() < MIN_SERVER_PACKETS) * Retrieve the injected proxy classes handlig each packet ID.
throw new FieldAccessException("Server packet list is empty. Seems to be unsupported"); * @return Injected classes.
return serverPackets; */
} public static Map<Integer, Class> getOverwrittenPackets() {
return overwrittenPackets;
/** }
* Retrieve every known and supported client packet.
* @return An immutable set of every known client packet. /**
* @throws FieldAccessException If we're unable to retrieve the client packet data from Minecraft. * Retrieve the vanilla classes handling each packet ID.
*/ * @return Vanilla classes.
public static Set<Integer> getClientPackets() throws FieldAccessException { */
initializeSets(); public static Map<Integer, Class> getPreviousPackets() {
return previousValues;
// As above }
if (clientPackets != null && clientPackets.size() < MIN_CLIENT_PACKETS)
throw new FieldAccessException("Client packet list is empty. Seems to be unsupported"); /**
return clientPackets; * Retrieve every known and supported server packet.
} * @return An immutable set of every known server packet.
* @throws FieldAccessException If we're unable to retrieve the server packet data from Minecraft.
@SuppressWarnings("unchecked") */
private static void initializeSets() throws FieldAccessException { public static Set<Integer> getServerPackets() throws FieldAccessException {
if (serverPacketsRef == null || clientPacketsRef == null) { initializeSets();
List<Field> sets = getPacketRegistry().getFieldListByType(Set.class);
// Sanity check. This is impossible!
try { if (serverPackets != null && serverPackets.size() < MIN_SERVER_PACKETS)
if (sets.size() > 1) { throw new FieldAccessException("Server packet list is empty. Seems to be unsupported");
serverPacketsRef = (Set<Integer>) FieldUtils.readStaticField(sets.get(0), true); return serverPackets;
clientPacketsRef = (Set<Integer>) FieldUtils.readStaticField(sets.get(1), true); }
// Impossible /**
if (serverPacketsRef == null || clientPacketsRef == null) * Retrieve every known and supported client packet.
throw new FieldAccessException("Packet sets are in an illegal state."); * @return An immutable set of every known client packet.
* @throws FieldAccessException If we're unable to retrieve the client packet data from Minecraft.
// NEVER allow callers to modify the underlying sets */
serverPackets = ImmutableSet.copyOf(serverPacketsRef); public static Set<Integer> getClientPackets() throws FieldAccessException {
clientPackets = ImmutableSet.copyOf(clientPacketsRef); initializeSets();
// Check sizes // As above
if (serverPackets.size() < MIN_SERVER_PACKETS) if (clientPackets != null && clientPackets.size() < MIN_CLIENT_PACKETS)
ProtocolLibrary.getErrorReporter().reportWarning( throw new FieldAccessException("Client packet list is empty. Seems to be unsupported");
PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_SERVER_PACKETS).messageParam(serverPackets.size()) return clientPackets;
); }
if (clientPackets.size() < MIN_CLIENT_PACKETS)
ProtocolLibrary.getErrorReporter().reportWarning( @SuppressWarnings("unchecked")
PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_CLIENT_PACKETS).messageParam(clientPackets.size()) private static void initializeSets() throws FieldAccessException {
); if (serverPacketsRef == null || clientPacketsRef == null) {
List<Field> sets = getPacketRegistry().getFieldListByType(Set.class);
} else {
throw new FieldAccessException("Cannot retrieve packet client/server sets."); try {
} if (sets.size() > 1) {
serverPacketsRef = (Set<Integer>) FieldUtils.readStaticField(sets.get(0), true);
} catch (IllegalAccessException e) { clientPacketsRef = (Set<Integer>) FieldUtils.readStaticField(sets.get(1), true);
throw new FieldAccessException("Cannot access field.", e);
} // Impossible
if (serverPacketsRef == null || clientPacketsRef == null)
} else { throw new FieldAccessException("Packet sets are in an illegal state.");
// Copy over again if it has changed
if (serverPacketsRef != null && serverPacketsRef.size() != serverPackets.size()) // NEVER allow callers to modify the underlying sets
serverPackets = ImmutableSet.copyOf(serverPacketsRef); serverPackets = ImmutableSet.copyOf(serverPacketsRef);
if (clientPacketsRef != null && clientPacketsRef.size() != clientPackets.size()) clientPackets = ImmutableSet.copyOf(clientPacketsRef);
clientPackets = ImmutableSet.copyOf(clientPacketsRef);
} // Check sizes
} if (serverPackets.size() < MIN_SERVER_PACKETS)
ProtocolLibrary.getErrorReporter().reportWarning(
/** PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_SERVER_PACKETS).messageParam(serverPackets.size())
* Retrieves the correct packet class from a given packet ID. );
* @param packetID - the packet ID. if (clientPackets.size() < MIN_CLIENT_PACKETS)
* @return The associated class. ProtocolLibrary.getErrorReporter().reportWarning(
*/ PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_CLIENT_PACKETS).messageParam(clientPackets.size())
public static Class getPacketClassFromID(int packetID) { );
return getPacketClassFromID(packetID, false);
} } else {
throw new FieldAccessException("Cannot retrieve packet client/server sets.");
/** }
* Retrieves the correct packet class from a given packet ID.
* @param packetID - the packet ID. } catch (IllegalAccessException e) {
* @param forceVanilla - whether or not to look for vanilla classes, not injected classes. throw new FieldAccessException("Cannot access field.", e);
* @return The associated class. }
*/
public static Class getPacketClassFromID(int packetID, boolean forceVanilla) { } else {
// Copy over again if it has changed
Map<Integer, Class> lookup = forceVanilla ? previousValues : overwrittenPackets; if (serverPacketsRef != null && serverPacketsRef.size() != serverPackets.size())
serverPackets = ImmutableSet.copyOf(serverPacketsRef);
// Optimized lookup if (clientPacketsRef != null && clientPacketsRef.size() != clientPackets.size())
if (lookup.containsKey(packetID)) { clientPackets = ImmutableSet.copyOf(clientPacketsRef);
return removeEnhancer(lookup.get(packetID), forceVanilla); }
} }
// Will most likely not be used /**
for (Map.Entry<Class, Integer> entry : getPacketToID().entrySet()) { * Retrieves the correct packet class from a given packet ID.
if (Objects.equal(entry.getValue(), packetID)) { * @param packetID - the packet ID.
// Attempt to get the vanilla class here too * @return The associated class.
if (!forceVanilla || MinecraftReflection.isMinecraftClass(entry.getKey())) */
return removeEnhancer(entry.getKey(), forceVanilla); public static Class getPacketClassFromID(int packetID) {
} return getPacketClassFromID(packetID, false);
} }
throw new IllegalArgumentException("The packet ID " + packetID + " is not registered."); /**
} * Retrieves the correct packet class from a given packet ID.
* @param packetID - the packet ID.
/** * @param forceVanilla - whether or not to look for vanilla classes, not injected classes.
* Retrieve the packet ID of a given packet. * @return The associated class.
* @param packet - the type of packet to check. */
* @return The ID of the given packet. public static Class getPacketClassFromID(int packetID, boolean forceVanilla) {
* @throws IllegalArgumentException If this is not a valid packet. Map<Integer, Class> lookup = forceVanilla ? previousValues : overwrittenPackets;
*/ Class<?> result = null;
public static int getPacketID(Class<?> packet) {
if (packet == null) // Optimized lookup
throw new IllegalArgumentException("Packet type class cannot be NULL."); if (lookup.containsKey(packetID)) {
if (!MinecraftReflection.getPacketClass().isAssignableFrom(packet)) return removeEnhancer(lookup.get(packetID), forceVanilla);
throw new IllegalArgumentException("Type must be a packet."); }
// The registry contains both the overridden and original packets // Refresh lookup tables
return getPacketToID().get(packet); getPacketToID();
}
// See if we can look for non-vanilla classes
/** if (!forceVanilla) {
* Find the first superclass that is not a CBLib proxy object. result = Iterables.getFirst(customIdToPacket.get(packetID), null);
* @param clazz - the class whose hierachy we're going to search through. }
* @param remove - whether or not to skip enhanced (proxy) classes. if (result == null) {
* @return If remove is TRUE, the first superclass that is not a proxy. result = vanillaIdToPacket.get(packetID);
*/ }
private static Class removeEnhancer(Class clazz, boolean remove) {
if (remove) { // See if we got it
// Get the underlying vanilla class if (result != null)
while (Factory.class.isAssignableFrom(clazz) && !clazz.equals(Object.class)) { return result;
clazz = clazz.getSuperclass(); else
} throw new IllegalArgumentException("The packet ID " + packetID + " is not registered.");
} }
return clazz; /**
} * Retrieve the packet ID of a given packet.
} * @param packet - the type of packet to check.
* @return The ID of the given packet.
* @throws IllegalArgumentException If this is not a valid packet.
*/
public static int getPacketID(Class<?> packet) {
if (packet == null)
throw new IllegalArgumentException("Packet type class cannot be NULL.");
if (!MinecraftReflection.getPacketClass().isAssignableFrom(packet))
throw new IllegalArgumentException("Type must be a packet.");
// The registry contains both the overridden and original packets
return getPacketToID().get(packet);
}
/**
* Find the first superclass that is not a CBLib proxy object.
* @param clazz - the class whose hierachy we're going to search through.
* @param remove - whether or not to skip enhanced (proxy) classes.
* @return If remove is TRUE, the first superclass that is not a proxy.
*/
private static Class removeEnhancer(Class clazz, boolean remove) {
if (remove) {
// Get the underlying vanilla class
while (Factory.class.isAssignableFrom(clazz) && !clazz.equals(Object.class)) {
clazz = clazz.getSuperclass();
}
}
return clazz;
}
}

Datei anzeigen

@ -287,7 +287,7 @@ public class MinecraftReflection {
public static boolean isMinecraftClass(@Nonnull Class<?> clazz) { public static boolean isMinecraftClass(@Nonnull Class<?> clazz) {
if (clazz == null) if (clazz == null)
throw new IllegalArgumentException("Class cannot be NULL."); throw new IllegalArgumentException("Class cannot be NULL.");
return getMinecraftObjectMatcher().isMatch(clazz, null); return getMinecraftObjectMatcher().isMatch(clazz, null);
} }