Added support for at least Beta 1.8.
This involved a bunch of reflection magic, along with the removal of every Apache Commons reference, in addition to every internal Guava class.
Dieser Commit ist enthalten in:
Ursprung
f372b247f9
Commit
035277bdeb
@ -4,6 +4,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketListener;
|
import com.comphenix.protocol.events.PacketListener;
|
||||||
@ -19,20 +20,28 @@ public interface ProtocolManager {
|
|||||||
* Retrieves a list of every registered packet listener.
|
* Retrieves a list of every registered packet listener.
|
||||||
* @return Every registered packet listener.
|
* @return Every registered packet listener.
|
||||||
*/
|
*/
|
||||||
public abstract ImmutableSet<PacketListener> getPacketListeners();
|
public ImmutableSet<PacketListener> getPacketListeners();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a packet listener.
|
* Adds a packet listener.
|
||||||
* @param listener - new packet listener.
|
* @param listener - new packet listener.
|
||||||
*/
|
*/
|
||||||
public abstract void addPacketListener(PacketListener listener);
|
public void addPacketListener(PacketListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a given packet listener.
|
* Removes a given packet listener.
|
||||||
* @param listener - the packet listener to remove.
|
* @param listener - the packet listener to remove.
|
||||||
*/
|
*/
|
||||||
public abstract void removePacketListener(PacketListener listener);
|
public void removePacketListener(PacketListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes every listener associated with the given plugin.
|
||||||
|
* <p>
|
||||||
|
* Note that this only works for listeners that derive from PacketAdapter.
|
||||||
|
* @param plugin - the plugin to unload.
|
||||||
|
*/
|
||||||
|
public void removePacketAdapters(Plugin plugin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a packet to the given player.
|
* Send a packet to the given player.
|
||||||
* @param reciever - the reciever.
|
* @param reciever - the reciever.
|
||||||
|
@ -2,9 +2,9 @@ package com.comphenix.protocol.events;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,7 +14,7 @@ import com.google.common.collect.Sets;
|
|||||||
*/
|
*/
|
||||||
public abstract class PacketAdapter implements PacketListener {
|
public abstract class PacketAdapter implements PacketListener {
|
||||||
|
|
||||||
protected JavaPlugin plugin;
|
protected Plugin plugin;
|
||||||
protected Set<Integer> packetsID;
|
protected Set<Integer> packetsID;
|
||||||
protected ConnectionSide connectionSide;
|
protected ConnectionSide connectionSide;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ public abstract class PacketAdapter implements PacketListener {
|
|||||||
* @param connectionSide - the packet type the listener is looking for.
|
* @param connectionSide - the packet type the listener is looking for.
|
||||||
* @param packets - the packet IDs the listener is looking for.
|
* @param packets - the packet IDs the listener is looking for.
|
||||||
*/
|
*/
|
||||||
public PacketAdapter(JavaPlugin plugin, ConnectionSide connectionSide, Integer... packets) {
|
public PacketAdapter(Plugin plugin, ConnectionSide connectionSide, Integer... packets) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.connectionSide = connectionSide;
|
this.connectionSide = connectionSide;
|
||||||
this.packetsID = Sets.newHashSet(packets);
|
this.packetsID = Sets.newHashSet(packets);
|
||||||
@ -50,11 +50,28 @@ public abstract class PacketAdapter implements PacketListener {
|
|||||||
return packetsID;
|
return packetsID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the plugin associated with this listener.
|
||||||
|
* @return The associated plugin.
|
||||||
|
*/
|
||||||
|
public Plugin getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
String name = "";
|
||||||
|
|
||||||
|
// Try to get the plugin name
|
||||||
|
try {
|
||||||
|
name = plugin.getName();
|
||||||
|
} catch (NoSuchMethodError e) {
|
||||||
|
name = plugin.toString();
|
||||||
|
}
|
||||||
|
|
||||||
// This is used by the error reporter
|
// This is used by the error reporter
|
||||||
return String.format("PacketAdapter[plugin=%s, side=%s, packets=%s]",
|
return String.format("PacketAdapter[plugin=%s, side=%s, packets=%s]",
|
||||||
plugin.getName(), getConnectionSide().name(),
|
name, getConnectionSide().name(),
|
||||||
StringUtils.join(packetsID, ", "));
|
Joiner.on(", ").join(packetsID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.comphenix.protocol.events;
|
package com.comphenix.protocol.events;
|
||||||
|
|
||||||
import org.apache.commons.lang.NullArgumentException;
|
|
||||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
@ -48,7 +47,7 @@ public class PacketContainer {
|
|||||||
*/
|
*/
|
||||||
public PacketContainer(int id, Packet handle, StructureModifier<Object> structure) {
|
public PacketContainer(int id, Packet handle, StructureModifier<Object> structure) {
|
||||||
if (handle == null)
|
if (handle == null)
|
||||||
throw new NullArgumentException("handle");
|
throw new IllegalArgumentException("handle cannot be null.");
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
|
@ -4,12 +4,11 @@ import java.lang.reflect.Field;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang.ObjectUtils;
|
|
||||||
|
|
||||||
import net.minecraft.server.Packet;
|
import net.minecraft.server.Packet;
|
||||||
|
|
||||||
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.google.common.base.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static registries in Minecraft.
|
* Static registries in Minecraft.
|
||||||
@ -78,7 +77,7 @@ class MinecraftRegistry {
|
|||||||
|
|
||||||
// Will most likely not be used
|
// Will most likely not be used
|
||||||
for (Map.Entry<Class, Integer> entry : getPacketToID().entrySet()) {
|
for (Map.Entry<Class, Integer> entry : getPacketToID().entrySet()) {
|
||||||
if (ObjectUtils.equals(entry.getValue(), packetID)) {
|
if (Objects.equal(entry.getValue(), packetID)) {
|
||||||
return entry.getKey();
|
return entry.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.comphenix.protocol.injector;
|
|||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -11,8 +12,10 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.minecraft.server.Packet;
|
import net.minecraft.server.Packet;
|
||||||
|
import net.sf.cglib.proxy.Enhancer;
|
||||||
|
import net.sf.cglib.proxy.MethodInterceptor;
|
||||||
|
import net.sf.cglib.proxy.MethodProxy;
|
||||||
|
|
||||||
import org.apache.commons.lang.NullArgumentException;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
@ -24,9 +27,11 @@ import org.bukkit.plugin.PluginManager;
|
|||||||
|
|
||||||
import com.comphenix.protocol.ProtocolManager;
|
import com.comphenix.protocol.ProtocolManager;
|
||||||
import com.comphenix.protocol.events.ConnectionSide;
|
import com.comphenix.protocol.events.ConnectionSide;
|
||||||
|
import com.comphenix.protocol.events.PacketAdapter;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.events.PacketListener;
|
import com.comphenix.protocol.events.PacketListener;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
@ -47,6 +52,9 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
// Whether or not this class has been closed
|
// Whether or not this class has been closed
|
||||||
private boolean hasClosed;
|
private boolean hasClosed;
|
||||||
|
|
||||||
|
// The default class loader
|
||||||
|
private ClassLoader classLoader;
|
||||||
|
|
||||||
// Error logger
|
// Error logger
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
|
||||||
@ -55,12 +63,13 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
*/
|
*/
|
||||||
public PacketFilterManager(ClassLoader classLoader, Logger logger) {
|
public PacketFilterManager(ClassLoader classLoader, Logger logger) {
|
||||||
if (logger == null)
|
if (logger == null)
|
||||||
throw new NullArgumentException("logger");
|
throw new IllegalArgumentException("logger cannot be NULL.");
|
||||||
if (classLoader == null)
|
if (classLoader == null)
|
||||||
throw new NullArgumentException("classLoader");
|
throw new IllegalArgumentException("classLoader cannot be NULL.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Initialize values
|
// Initialize values
|
||||||
|
this.classLoader = classLoader;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.packetInjector = new PacketInjector(classLoader, this, connectionLookup);
|
this.packetInjector = new PacketInjector(classLoader, this, connectionLookup);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
@ -80,7 +89,7 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
@Override
|
@Override
|
||||||
public void addPacketListener(PacketListener listener) {
|
public void addPacketListener(PacketListener listener) {
|
||||||
if (listener == null)
|
if (listener == null)
|
||||||
throw new NullArgumentException("listener");
|
throw new IllegalArgumentException("listener cannot be NULL.");
|
||||||
|
|
||||||
packetListeners.add(listener);
|
packetListeners.add(listener);
|
||||||
enablePacketFilters(listener.getConnectionSide(),
|
enablePacketFilters(listener.getConnectionSide(),
|
||||||
@ -90,13 +99,29 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
@Override
|
@Override
|
||||||
public void removePacketListener(PacketListener listener) {
|
public void removePacketListener(PacketListener listener) {
|
||||||
if (listener == null)
|
if (listener == null)
|
||||||
throw new NullArgumentException("listener");
|
throw new IllegalArgumentException("listener cannot be NULL");
|
||||||
|
|
||||||
packetListeners.remove(listener);
|
packetListeners.remove(listener);
|
||||||
disablePacketFilters(listener.getConnectionSide(),
|
disablePacketFilters(listener.getConnectionSide(),
|
||||||
listener.getPacketsID());
|
listener.getPacketsID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePacketAdapters(Plugin plugin) {
|
||||||
|
|
||||||
|
// Iterate through every packet listener
|
||||||
|
for (Object listener : packetListeners.toArray()) {
|
||||||
|
if (listener instanceof PacketAdapter) {
|
||||||
|
PacketAdapter adapter = (PacketAdapter) listener;
|
||||||
|
|
||||||
|
// Remove the listener
|
||||||
|
if (adapter.getPlugin().equals(plugin)) {
|
||||||
|
packetListeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the given packet event for every registered listener.
|
* Invokes the given packet event for every registered listener.
|
||||||
* @param event - the packet event to invoke.
|
* @param event - the packet event to invoke.
|
||||||
@ -150,7 +175,7 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
*/
|
*/
|
||||||
private void enablePacketFilters(ConnectionSide side, Set<Integer> packets) {
|
private void enablePacketFilters(ConnectionSide side, Set<Integer> packets) {
|
||||||
if (side == null)
|
if (side == null)
|
||||||
throw new NullArgumentException("side");
|
throw new IllegalArgumentException("side cannot be NULL.");
|
||||||
|
|
||||||
for (int packetID : packets) {
|
for (int packetID : packets) {
|
||||||
if (side.isForServer())
|
if (side.isForServer())
|
||||||
@ -167,7 +192,7 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
*/
|
*/
|
||||||
private void disablePacketFilters(ConnectionSide side, Set<Integer> packets) {
|
private void disablePacketFilters(ConnectionSide side, Set<Integer> packets) {
|
||||||
if (side == null)
|
if (side == null)
|
||||||
throw new NullArgumentException("side");
|
throw new IllegalArgumentException("side cannot be NULL.");
|
||||||
|
|
||||||
for (int packetID : packets) {
|
for (int packetID : packets) {
|
||||||
if (side.isForServer())
|
if (side.isForServer())
|
||||||
@ -185,9 +210,9 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
@Override
|
@Override
|
||||||
public void sendServerPacket(Player reciever, PacketContainer packet, boolean filters) throws InvocationTargetException {
|
public void sendServerPacket(Player reciever, PacketContainer packet, boolean filters) throws InvocationTargetException {
|
||||||
if (reciever == null)
|
if (reciever == null)
|
||||||
throw new NullArgumentException("reciever");
|
throw new IllegalArgumentException("reciever cannot be NULL.");
|
||||||
if (packet == null)
|
if (packet == null)
|
||||||
throw new NullArgumentException("packet");
|
throw new IllegalArgumentException("packet cannot be NULL.");
|
||||||
|
|
||||||
getInjector(reciever).sendServerPacket(packet.getHandle(), filters);
|
getInjector(reciever).sendServerPacket(packet.getHandle(), filters);
|
||||||
}
|
}
|
||||||
@ -201,9 +226,9 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
public void recieveClientPacket(Player sender, PacketContainer packet, boolean filters) throws IllegalAccessException, InvocationTargetException {
|
public void recieveClientPacket(Player sender, PacketContainer packet, boolean filters) throws IllegalAccessException, InvocationTargetException {
|
||||||
|
|
||||||
if (sender == null)
|
if (sender == null)
|
||||||
throw new NullArgumentException("sender");
|
throw new IllegalArgumentException("sender cannot be NULL.");
|
||||||
if (packet == null)
|
if (packet == null)
|
||||||
throw new NullArgumentException("packet");
|
throw new IllegalArgumentException("packet cannot be NULL.");
|
||||||
|
|
||||||
PlayerInjector injector = getInjector(sender);
|
PlayerInjector injector = getInjector(sender);
|
||||||
Packet mcPacket = packet.getHandle();
|
Packet mcPacket = packet.getHandle();
|
||||||
@ -277,18 +302,90 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
* @param plugin - the parent plugin.
|
* @param plugin - the parent plugin.
|
||||||
*/
|
*/
|
||||||
public void registerEvents(PluginManager manager, Plugin plugin) {
|
public void registerEvents(PluginManager manager, Plugin plugin) {
|
||||||
manager.registerEvents(new Listener() {
|
|
||||||
|
try {
|
||||||
|
manager.registerEvents(new Listener() {
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
injectPlayer(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
uninjectPlayer(event.getPlayer());
|
||||||
|
}
|
||||||
|
}, plugin);
|
||||||
|
|
||||||
|
} catch (NoSuchMethodError e) {
|
||||||
|
// Oh wow! We're running on 1.0.0 or older.
|
||||||
|
registerOld(manager, plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yes, this is crazy.
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
private void registerOld(PluginManager manager, Plugin plugin) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ClassLoader loader = manager.getClass().getClassLoader();
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
// The different enums we are going to need
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
Class eventTypes = loader.loadClass("org.bukkit.event.Event$Type");
|
||||||
injectPlayer(event.getPlayer());
|
Class eventPriority = loader.loadClass("org.bukkit.event.Event$Priority");
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
// Get the priority
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
Object priorityNormal = Enum.valueOf(eventPriority, "Normal");
|
||||||
uninjectPlayer(event.getPlayer());
|
|
||||||
}
|
// Get event types
|
||||||
}, plugin);
|
Object playerJoinType = Enum.valueOf(eventTypes, "PLAYER_JOIN");
|
||||||
|
Object playerQuitType = Enum.valueOf(eventTypes, "PLAYER_QUIT");
|
||||||
|
|
||||||
|
// The player listener! Good times.
|
||||||
|
Class<?> playerListener = loader.loadClass("org.bukkit.event.player.PlayerListener");
|
||||||
|
|
||||||
|
// Find the register event method
|
||||||
|
Method registerEvent = FuzzyReflection.fromObject(manager).getMethodByParameters("registerEvent",
|
||||||
|
eventTypes, Listener.class, eventPriority, Plugin.class);
|
||||||
|
|
||||||
|
Enhancer ex = new Enhancer();
|
||||||
|
ex.setSuperclass(playerListener);
|
||||||
|
ex.setClassLoader(classLoader);
|
||||||
|
ex.setCallback(new MethodInterceptor() {
|
||||||
|
@Override
|
||||||
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
||||||
|
|
||||||
|
// Must have a parameter
|
||||||
|
if (args.length == 1) {
|
||||||
|
Object event = args[0];
|
||||||
|
|
||||||
|
// Check for the correct event
|
||||||
|
if (event instanceof PlayerJoinEvent)
|
||||||
|
injectPlayer(((PlayerJoinEvent) event).getPlayer());
|
||||||
|
else if (event instanceof PlayerQuitEvent)
|
||||||
|
injectPlayer(((PlayerQuitEvent) event).getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create our listener
|
||||||
|
Object proxy = ex.create();
|
||||||
|
|
||||||
|
registerEvent.invoke(manager, playerJoinType, proxy, priorityNormal, plugin);
|
||||||
|
registerEvent.invoke(manager, playerQuitType, proxy, priorityNormal, plugin);
|
||||||
|
|
||||||
|
// A lot can go wrong
|
||||||
|
} catch (ClassNotFoundException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uninjectPlayer(Player player) {
|
private void uninjectPlayer(Player player) {
|
||||||
|
@ -15,6 +15,7 @@ import net.sf.cglib.proxy.Enhancer;
|
|||||||
|
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
import com.comphenix.protocol.reflect.FieldUtils;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,10 +50,10 @@ class PacketInjector {
|
|||||||
private void initialize() throws IllegalAccessException {
|
private void initialize() throws IllegalAccessException {
|
||||||
if (intHashMap == null) {
|
if (intHashMap == null) {
|
||||||
// We're looking for the first static field with a Minecraft-object. This should be a IntHashMap.
|
// We're looking for the first static field with a Minecraft-object. This should be a IntHashMap.
|
||||||
Field intHashMapField = FuzzyReflection.fromClass(Packet.class).getFieldByType(FuzzyReflection.MINECRAFT_OBJECT);
|
Field intHashMapField = FuzzyReflection.fromClass(Packet.class, true).getFieldByType(FuzzyReflection.MINECRAFT_OBJECT);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
intHashMap = intHashMapField.get(null);
|
intHashMap = FieldUtils.readField(intHashMapField, (Object) null, true);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new RuntimeException("Minecraft is incompatible.", e);
|
throw new RuntimeException("Minecraft is incompatible.", e);
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,9 @@ package com.comphenix.protocol.injector;
|
|||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
|
||||||
|
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ class ReadPacketModifier implements MethodInterceptor {
|
|||||||
|
|
||||||
// Is this a readPacketData method?
|
// Is this a readPacketData method?
|
||||||
if (returnValue == null &&
|
if (returnValue == null &&
|
||||||
ArrayUtils.isEquals(method.getParameterTypes(), parameters)) {
|
Arrays.equals(method.getParameterTypes(), parameters)) {
|
||||||
|
|
||||||
// We need this in order to get the correct player
|
// We need this in order to get the correct player
|
||||||
DataInputStream input = (DataInputStream) args[0];
|
DataInputStream input = (DataInputStream) args[0];
|
||||||
|
@ -6,11 +6,9 @@ import java.util.*;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
|
||||||
|
|
||||||
import com.google.common.base.Defaults;
|
import com.google.common.base.Defaults;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.gson.internal.Primitives;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to construct default instances of any type.
|
* Used to construct default instances of any type.
|
||||||
@ -91,7 +89,7 @@ public class DefaultInstances {
|
|||||||
// Note that we don't allow recursive types - that is, types that
|
// Note that we don't allow recursive types - that is, types that
|
||||||
// require itself in the constructor.
|
// require itself in the constructor.
|
||||||
if (types.length < lastCount) {
|
if (types.length < lastCount) {
|
||||||
if (!ArrayUtils.contains(types, type)) {
|
if (!contains(types, type)) {
|
||||||
minimum = candidate;
|
minimum = candidate;
|
||||||
lastCount = types.length;
|
lastCount = types.length;
|
||||||
|
|
||||||
@ -124,6 +122,15 @@ public class DefaultInstances {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T> boolean contains(T[] elements, T elementToFind) {
|
||||||
|
// Search for the given element in the array
|
||||||
|
for (T element : elements) {
|
||||||
|
if (Objects.equal(elementToFind, element))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides constructors for primtive types, wrappers, arrays and strings.
|
* Provides constructors for primtive types, wrappers, arrays and strings.
|
||||||
* @author Kristian
|
* @author Kristian
|
||||||
@ -133,10 +140,10 @@ public class DefaultInstances {
|
|||||||
@Override
|
@Override
|
||||||
public Object apply(@Nullable Class<?> type) {
|
public Object apply(@Nullable Class<?> type) {
|
||||||
|
|
||||||
if (Primitives.isPrimitive(type)) {
|
if (PrimitiveUtils.isPrimitive(type)) {
|
||||||
return Defaults.defaultValue(type);
|
return Defaults.defaultValue(type);
|
||||||
} else if (Primitives.isWrapperType(type)) {
|
} else if (PrimitiveUtils.isWrapperType(type)) {
|
||||||
return Defaults.defaultValue(Primitives.unwrap(type));
|
return Defaults.defaultValue(PrimitiveUtils.unwrap(type));
|
||||||
} else if (type.isArray()) {
|
} else if (type.isArray()) {
|
||||||
Class<?> arrayType = type.getComponentType();
|
Class<?> arrayType = type.getComponentType();
|
||||||
return Array.newInstance(arrayType, 0);
|
return Array.newInstance(arrayType, 0);
|
||||||
|
@ -21,9 +21,9 @@ import java.lang.reflect.AccessibleObject;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import org.apache.commons.lang.ClassUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for working with fields by reflection. Adapted and refactored from
|
* Utilities for working with fields by reflection. Adapted and refactored from
|
||||||
@ -119,11 +119,11 @@ public class FieldUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check the public interface case. This must be manually searched for
|
// check the public interface case. This must be manually searched for
|
||||||
// incase there is a public supersuperclass field hidden by a
|
// in case there is a public supersuperclass field hidden by a
|
||||||
// private/package
|
// private/package
|
||||||
// superclass field.
|
// superclass field.
|
||||||
Field match = null;
|
Field match = null;
|
||||||
for (Iterator intf = ClassUtils.getAllInterfaces(cls).iterator(); intf.hasNext();) {
|
for (Iterator intf = getAllInterfaces(cls).iterator(); intf.hasNext();) {
|
||||||
try {
|
try {
|
||||||
Field test = ((Class) intf.next()).getField(fieldName);
|
Field test = ((Class) intf.next()).getField(fieldName);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
@ -138,6 +138,44 @@ public class FieldUtils {
|
|||||||
}
|
}
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Gets a <code>List</code> of all interfaces implemented by the given
|
||||||
|
* class and its superclasses.</p>
|
||||||
|
*
|
||||||
|
* <p>The order is determined by looking through each interface in turn as
|
||||||
|
* declared in the source file and following its hierarchy up. Then each
|
||||||
|
* superclass is considered in the same way. Later duplicates are ignored,
|
||||||
|
* so the order is maintained.</p>
|
||||||
|
*
|
||||||
|
* @param cls the class to look up, may be <code>null</code>
|
||||||
|
* @return the <code>List</code> of interfaces in order,
|
||||||
|
* <code>null</code> if null input
|
||||||
|
*/
|
||||||
|
private static List getAllInterfaces(Class cls) {
|
||||||
|
if (cls == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Class> list = new ArrayList<Class>();
|
||||||
|
|
||||||
|
while (cls != null) {
|
||||||
|
Class[] interfaces = cls.getInterfaces();
|
||||||
|
for (int i = 0; i < interfaces.length; i++) {
|
||||||
|
if (list.contains(interfaces[i]) == false) {
|
||||||
|
list.add(interfaces[i]);
|
||||||
|
}
|
||||||
|
List superInterfaces = getAllInterfaces(interfaces[i]);
|
||||||
|
for (Iterator it = superInterfaces.iterator(); it.hasNext();) {
|
||||||
|
Class intface = (Class) it.next();
|
||||||
|
if (list.contains(intface) == false) {
|
||||||
|
list.add(intface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cls = cls.getSuperclass();
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read an accessible static Field.
|
* Read an accessible static Field.
|
||||||
|
@ -2,12 +2,11 @@ package com.comphenix.protocol.reflect;
|
|||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves fields and methods by signature, not just name.
|
* Retrieves fields and methods by signature, not just name.
|
||||||
*
|
*
|
||||||
@ -106,7 +105,7 @@ public class FuzzyReflection {
|
|||||||
|
|
||||||
// Find the correct method to call
|
// Find the correct method to call
|
||||||
for (Method method : getMethods()) {
|
for (Method method : getMethods()) {
|
||||||
if (ArrayUtils.isEquals(method.getParameterTypes(), args)) {
|
if (Arrays.equals(method.getParameterTypes(), args)) {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
124
ProtocolLib/src/com/comphenix/protocol/reflect/PrimitiveUtils.java
Normale Datei
124
ProtocolLib/src/com/comphenix/protocol/reflect/PrimitiveUtils.java
Normale Datei
@ -0,0 +1,124 @@
|
|||||||
|
package com.comphenix.protocol.reflect;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains static utility methods pertaining to primitive types and their
|
||||||
|
* corresponding wrapper types.
|
||||||
|
*
|
||||||
|
* @author Kevin Bourrillion
|
||||||
|
*/
|
||||||
|
public final class PrimitiveUtils {
|
||||||
|
private PrimitiveUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A map from primitive types to their corresponding wrapper types. */
|
||||||
|
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;
|
||||||
|
|
||||||
|
/** A map from wrapper types to their corresponding primitive types. */
|
||||||
|
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
|
||||||
|
|
||||||
|
// Sad that we can't use a BiMap. :(
|
||||||
|
static {
|
||||||
|
Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
|
||||||
|
Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
|
||||||
|
|
||||||
|
add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
|
||||||
|
add(primToWrap, wrapToPrim, byte.class, Byte.class);
|
||||||
|
add(primToWrap, wrapToPrim, char.class, Character.class);
|
||||||
|
add(primToWrap, wrapToPrim, double.class, Double.class);
|
||||||
|
add(primToWrap, wrapToPrim, float.class, Float.class);
|
||||||
|
add(primToWrap, wrapToPrim, int.class, Integer.class);
|
||||||
|
add(primToWrap, wrapToPrim, long.class, Long.class);
|
||||||
|
add(primToWrap, wrapToPrim, short.class, Short.class);
|
||||||
|
add(primToWrap, wrapToPrim, void.class, Void.class);
|
||||||
|
|
||||||
|
PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
|
||||||
|
WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void add(Map<Class<?>, Class<?>> forward,
|
||||||
|
Map<Class<?>, Class<?>> backward, Class<?> key, Class<?> value) {
|
||||||
|
forward.put(key, value);
|
||||||
|
backward.put(value, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this type is a primitive.
|
||||||
|
*/
|
||||||
|
public static boolean isPrimitive(Type type) {
|
||||||
|
return PRIMITIVE_TO_WRAPPER_TYPE.containsKey(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if {@code type} is one of the nine primitive-wrapper
|
||||||
|
* types, such as {@link Integer}.
|
||||||
|
*
|
||||||
|
* @see Class#isPrimitive
|
||||||
|
*/
|
||||||
|
public static boolean isWrapperType(Type type) {
|
||||||
|
return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(checkNotNull(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the corresponding wrapper type of {@code type} if it is a
|
||||||
|
* primitive type; otherwise returns {@code type} itself. Idempotent.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* wrap(int.class) == Integer.class
|
||||||
|
* wrap(Integer.class) == Integer.class
|
||||||
|
* wrap(String.class) == String.class
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static <T> Class<T> wrap(Class<T> type) {
|
||||||
|
// cast is safe: long.class and Long.class are both of type Class<Long>
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE
|
||||||
|
.get(checkNotNull(type));
|
||||||
|
return (wrapped == null) ? type : wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the corresponding primitive type of {@code type} if it is a
|
||||||
|
* wrapper type; otherwise returns {@code type} itself. Idempotent.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* unwrap(Integer.class) == int.class
|
||||||
|
* unwrap(int.class) == int.class
|
||||||
|
* unwrap(String.class) == String.class
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static <T> Class<T> unwrap(Class<T> type) {
|
||||||
|
// cast is safe: long.class and Long.class are both of type Class<Long>
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<T> unwrapped = (Class<T>) WRAPPER_TO_PRIMITIVE_TYPE
|
||||||
|
.get(checkNotNull(type));
|
||||||
|
return (unwrapped == null) ? type : unwrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T checkNotNull(T obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.gson.internal.Primitives;
|
|
||||||
|
|
||||||
import net.minecraft.server.Packet;
|
import net.minecraft.server.Packet;
|
||||||
|
|
||||||
@ -287,7 +286,7 @@ public class StructureModifier<TField> {
|
|||||||
Class<?> type = field.getType();
|
Class<?> type = field.getType();
|
||||||
|
|
||||||
// First, ignore primitive fields
|
// First, ignore primitive fields
|
||||||
if (!Primitives.isPrimitive(type)) {
|
if (!PrimitiveUtils.isPrimitive(type)) {
|
||||||
// Next, see if we actually can generate a default value
|
// Next, see if we actually can generate a default value
|
||||||
if (DefaultInstances.getDefault(type) != null) {
|
if (DefaultInstances.getDefault(type) != null) {
|
||||||
// If so, require it
|
// If so, require it
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren