Handle plugin reloading properly, uninjecting all player channels.
This should prevent any crashes if the plugin is reloaded during a player login.
Dieser Commit ist enthalten in:
Ursprung
5805150d8c
Commit
6bd8bd2ca2
@ -951,7 +951,6 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onPlayerLogin(PlayerLoginEvent event) {
|
private void onPlayerLogin(PlayerLoginEvent event) {
|
||||||
System.out.println("Address: " + event.getAddress());
|
|
||||||
playerInjection.updatePlayer(event.getPlayer());
|
playerInjection.updatePlayer(event.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener;
|
|||||||
import net.minecraft.util.io.netty.util.internal.TypeParameterMatcher;
|
import net.minecraft.util.io.netty.util.internal.TypeParameterMatcher;
|
||||||
import net.sf.cglib.proxy.Factory;
|
import net.sf.cglib.proxy.Factory;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
import com.comphenix.protocol.PacketType;
|
||||||
@ -35,7 +34,6 @@ import com.comphenix.protocol.events.NetworkMarker;
|
|||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.events.PacketOutputHandler;
|
import com.comphenix.protocol.events.PacketOutputHandler;
|
||||||
import com.comphenix.protocol.injector.server.SocketInjector;
|
import com.comphenix.protocol.injector.server.SocketInjector;
|
||||||
import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
|
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.VolatileField;
|
import com.comphenix.protocol.reflect.VolatileField;
|
||||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||||
@ -46,19 +44,15 @@ import com.comphenix.protocol.utility.MinecraftMethods;
|
|||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a channel injector.
|
* Represents a channel injector.
|
||||||
* @author Kristian
|
* @author Kristian
|
||||||
*/
|
*/
|
||||||
class ChannelInjector extends ByteToMessageDecoder {
|
class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
||||||
public static final ReportType REPORT_CANNOT_INTERCEPT_SERVER_PACKET = new ReportType("Unable to intercept a written server packet.");
|
public static final ReportType REPORT_CANNOT_INTERCEPT_SERVER_PACKET = new ReportType("Unable to intercept a written server packet.");
|
||||||
public static final ReportType REPORT_CANNOT_INTERCEPT_CLIENT_PACKET = new ReportType("Unable to intercept a read client packet.");
|
public static final ReportType REPORT_CANNOT_INTERCEPT_CLIENT_PACKET = new ReportType("Unable to intercept a read client packet.");
|
||||||
|
|
||||||
private static final ConcurrentMap<Player, ChannelInjector> PLAYER_LOOKUP = Maps.newConcurrentMap();
|
|
||||||
private static final ConcurrentMap<String, ChannelInjector> NAME_LOOKUP = new MapMaker().weakValues().makeMap();
|
|
||||||
|
|
||||||
// The login packet
|
// The login packet
|
||||||
private static Class<?> PACKET_LOGIN_CLIENT = null;
|
private static Class<?> PACKET_LOGIN_CLIENT = null;
|
||||||
private static FieldAccessor LOGIN_GAME_PROFILE = null;
|
private static FieldAccessor LOGIN_GAME_PROFILE = null;
|
||||||
@ -71,6 +65,9 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
// For retrieving the protocol
|
// For retrieving the protocol
|
||||||
private static FieldAccessor PROTOCOL_ACCESSOR;
|
private static FieldAccessor PROTOCOL_ACCESSOR;
|
||||||
|
|
||||||
|
// The factory that created this injector
|
||||||
|
private InjectionFactory factory;
|
||||||
|
|
||||||
// The player, or temporary player
|
// The player, or temporary player
|
||||||
private Player player;
|
private Player player;
|
||||||
private Player updated;
|
private Player updated;
|
||||||
@ -112,12 +109,15 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
* @param player - the current player, or temporary player.
|
* @param player - the current player, or temporary player.
|
||||||
* @param networkManager - its network manager.
|
* @param networkManager - its network manager.
|
||||||
* @param channel - its channel.
|
* @param channel - its channel.
|
||||||
|
* @param channelListener - a listener.
|
||||||
|
* @param factory - the factory that created this injector
|
||||||
*/
|
*/
|
||||||
private ChannelInjector(Player player, Object networkManager, Channel channel, ChannelListener channelListener) {
|
public ChannelInjector(Player player, Object networkManager, Channel channel, ChannelListener channelListener, InjectionFactory factory) {
|
||||||
this.player = Preconditions.checkNotNull(player, "player cannot be NULL");
|
this.player = Preconditions.checkNotNull(player, "player cannot be NULL");
|
||||||
this.networkManager = Preconditions.checkNotNull(networkManager, "networkMananger cannot be NULL");
|
this.networkManager = Preconditions.checkNotNull(networkManager, "networkMananger cannot be NULL");
|
||||||
this.originalChannel = Preconditions.checkNotNull(channel, "channel cannot be NULL");
|
this.originalChannel = Preconditions.checkNotNull(channel, "channel cannot be NULL");
|
||||||
this.channelListener = Preconditions.checkNotNull(channelListener, "channelListener cannot be NULL");
|
this.channelListener = Preconditions.checkNotNull(channelListener, "channelListener cannot be NULL");
|
||||||
|
this.factory = Preconditions.checkNotNull(factory, "factory cannot be NULL");
|
||||||
|
|
||||||
// Get the channel field
|
// Get the channel field
|
||||||
this.channelField = new VolatileField(
|
this.channelField = new VolatileField(
|
||||||
@ -126,103 +126,12 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
networkManager, true);
|
networkManager, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Construct or retrieve a channel injector from an existing Bukkit player.
|
|
||||||
* @param player - the existing Bukkit player.
|
|
||||||
* @param channelListener - the listener.
|
|
||||||
* @return A new injector, or an existing injector associated with this player.
|
|
||||||
*/
|
|
||||||
public static ChannelInjector fromPlayer(Player player, ChannelListener listener) {
|
|
||||||
ChannelInjector injector = PLAYER_LOOKUP.get(player);
|
|
||||||
|
|
||||||
// Find a temporary injector as well
|
|
||||||
if (injector == null)
|
|
||||||
injector = getTemporaryInjector(player);
|
|
||||||
if (injector != null)
|
|
||||||
return injector;
|
|
||||||
|
|
||||||
Object networkManager = MinecraftFields.getNetworkManager(player);
|
|
||||||
|
|
||||||
// Must be a temporary Bukkit player
|
|
||||||
if (networkManager == null)
|
|
||||||
return fromName(player.getName(), player);
|
|
||||||
|
|
||||||
Channel channel = FuzzyReflection.getFieldValue(networkManager, Channel.class, true);
|
|
||||||
|
|
||||||
// See if a channel has already been created
|
|
||||||
injector = (ChannelInjector) findChannelHandler(channel, ChannelInjector.class);
|
|
||||||
|
|
||||||
if (injector != null) {
|
|
||||||
// Update the player instance
|
|
||||||
injector.player = player;
|
|
||||||
} else {
|
|
||||||
injector = new ChannelInjector(player, networkManager, channel, listener);
|
|
||||||
}
|
|
||||||
// Cache injector and return
|
|
||||||
NAME_LOOKUP.put(player.getName(), injector);
|
|
||||||
PLAYER_LOOKUP.put(player, injector);
|
|
||||||
return injector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the associated channel injector.
|
|
||||||
* @param player - the temporary player, or normal Bukkit player.
|
|
||||||
* @return The associated injector, or NULL if this is a Bukkit player.
|
|
||||||
*/
|
|
||||||
private static ChannelInjector getTemporaryInjector(Player player) {
|
|
||||||
SocketInjector injector = TemporaryPlayerFactory.getInjectorFromPlayer(player);
|
|
||||||
|
|
||||||
if (injector != null) {
|
|
||||||
return ((ChannelSocketInjector) injector).getChannelInjector();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a cached injector from a name.
|
|
||||||
* @param address - the name.
|
|
||||||
* @return The cached injector.
|
|
||||||
* @throws IllegalArgumentException If we cannot find the corresponding injector.
|
|
||||||
*/
|
|
||||||
private static ChannelInjector fromName(String name, Player player) {
|
|
||||||
ChannelInjector injector = NAME_LOOKUP.get(name);
|
|
||||||
|
|
||||||
// We can only retrieve cached injectors
|
|
||||||
if (injector != null) {
|
|
||||||
// Update instance
|
|
||||||
injector.updated = player;
|
|
||||||
return injector;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Cannot inject temporary Bukkit player.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new channel injector for the given channel.
|
|
||||||
* @param channel - the channel.
|
|
||||||
* @param playerFactory - a temporary player creator.
|
|
||||||
* @param channelListener - the listener.
|
|
||||||
* @param loader - the current (plugin) class loader.
|
|
||||||
* @return The channel injector.
|
|
||||||
*/
|
|
||||||
public static ChannelInjector fromChannel(Channel channel, ChannelListener listener, TemporaryPlayerFactory playerFactory) {
|
|
||||||
Object networkManager = findNetworkManager(channel);
|
|
||||||
Player temporaryPlayer = playerFactory.createTemporaryPlayer(Bukkit.getServer());
|
|
||||||
ChannelInjector injector = new ChannelInjector(temporaryPlayer, networkManager, channel, listener);
|
|
||||||
|
|
||||||
// Initialize temporary player
|
|
||||||
TemporaryPlayerFactory.setInjectorInPlayer(temporaryPlayer, new ChannelSocketInjector(injector));
|
|
||||||
return injector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject the current channel.
|
|
||||||
* <p>
|
|
||||||
* Note that only active channels can be injected.
|
|
||||||
* @return TRUE if we injected the channel, false if we could not inject or it was already injected.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public boolean inject() {
|
public boolean inject() {
|
||||||
synchronized (networkManager) {
|
synchronized (networkManager) {
|
||||||
|
if (closed)
|
||||||
|
return false;
|
||||||
if (originalChannel instanceof Factory)
|
if (originalChannel instanceof Factory)
|
||||||
return false;
|
return false;
|
||||||
if (!originalChannel.isActive())
|
if (!originalChannel.isActive())
|
||||||
@ -230,9 +139,6 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
|
|
||||||
// Don't inject the same channel twice
|
// Don't inject the same channel twice
|
||||||
if (findChannelHandler(originalChannel, ChannelInjector.class) != null) {
|
if (findChannelHandler(originalChannel, ChannelInjector.class) != null) {
|
||||||
// Invalidate cache
|
|
||||||
if (player != null)
|
|
||||||
PLAYER_LOOKUP.remove(player);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,29 +210,6 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
ENCODER_TYPE_MATCHER.set(encoder, TypeParameterMatcher.get(MinecraftReflection.getPacketClass()));
|
ENCODER_TYPE_MATCHER.set(encoder, TypeParameterMatcher.get(MinecraftReflection.getPacketClass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the current injector.
|
|
||||||
*/
|
|
||||||
public void close() {
|
|
||||||
if (!closed) {
|
|
||||||
closed = true;
|
|
||||||
|
|
||||||
if (injected) {
|
|
||||||
channelField.revertValue();
|
|
||||||
|
|
||||||
try {
|
|
||||||
originalChannel.pipeline().remove(this);
|
|
||||||
originalChannel.pipeline().remove(protocolEncoder);
|
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
// Ignore it - the player has logged out
|
|
||||||
}
|
|
||||||
// Clear cache
|
|
||||||
NAME_LOOKUP.remove(player.getName());
|
|
||||||
PLAYER_LOOKUP.remove(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode a packet to a byte buffer, taking over for the standard Minecraft encoder.
|
* Encode a packet to a byte buffer, taking over for the standard Minecraft encoder.
|
||||||
* @param ctx - the current context.
|
* @param ctx - the current context.
|
||||||
@ -441,7 +324,7 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
GameProfile profile = (GameProfile) LOGIN_GAME_PROFILE.get(packet);
|
GameProfile profile = (GameProfile) LOGIN_GAME_PROFILE.get(packet);
|
||||||
|
|
||||||
// Save the channel injector
|
// Save the channel injector
|
||||||
NAME_LOOKUP.put(profile.getName(), this);
|
factory.cacheInjector(profile.getName(), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,12 +369,7 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Send a packet to a player's client.
|
|
||||||
* @param packet - the packet to send.
|
|
||||||
* @param marker - the network marker.
|
|
||||||
* @param filtered - whether or not the packet is filtered.
|
|
||||||
*/
|
|
||||||
public void sendServerPacket(Object packet, NetworkMarker marker, boolean filtered) {
|
public void sendServerPacket(Object packet, NetworkMarker marker, boolean filtered) {
|
||||||
saveMarker(packet, marker);
|
saveMarker(packet, marker);
|
||||||
processedPackets.remove(packet);
|
processedPackets.remove(packet);
|
||||||
@ -522,12 +400,7 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Recieve a packet on the server.
|
|
||||||
* @param packet - the (NMS) packet to send.
|
|
||||||
* @param marker - the network marker.
|
|
||||||
* @param filtered - whether or not the packet is filtered.
|
|
||||||
*/
|
|
||||||
public void recieveClientPacket(Object packet, NetworkMarker marker, boolean filtered) {
|
public void recieveClientPacket(Object packet, NetworkMarker marker, boolean filtered) {
|
||||||
saveMarker(packet, marker);
|
saveMarker(packet, marker);
|
||||||
processedPackets.remove(packet);
|
processedPackets.remove(packet);
|
||||||
@ -545,10 +418,7 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Retrieve the current protocol state.
|
|
||||||
* @return The current protocol.
|
|
||||||
*/
|
|
||||||
public Protocol getCurrentProtocol() {
|
public Protocol getCurrentProtocol() {
|
||||||
if (PROTOCOL_ACCESSOR == null) {
|
if (PROTOCOL_ACCESSOR == null) {
|
||||||
PROTOCOL_ACCESSOR = Accessors.getFieldAccessor(
|
PROTOCOL_ACCESSOR = Accessors.getFieldAccessor(
|
||||||
@ -568,96 +438,57 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
return playerConnection;
|
return playerConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Undo the ignore status of a packet.
|
|
||||||
* @param packet - the packet.
|
|
||||||
* @return TRUE if the ignore status was undone, FALSE otherwise.
|
|
||||||
*/
|
|
||||||
public boolean unignorePacket(Object packet) {
|
public boolean unignorePacket(Object packet) {
|
||||||
return ignoredPackets.remove(packet);
|
return ignoredPackets.remove(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Ignore the given packet.
|
|
||||||
* @param packet - the packet to ignore.
|
|
||||||
* @return TRUE if it was ignored, FALSE if it already is ignored.
|
|
||||||
*/
|
|
||||||
public boolean ignorePacket(Object packet) {
|
public boolean ignorePacket(Object packet) {
|
||||||
return ignoredPackets.add(packet);
|
return ignoredPackets.add(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Retrieve the network marker associated with a given packet.
|
|
||||||
* @param packet - the packet.
|
|
||||||
* @return The network marker.
|
|
||||||
*/
|
|
||||||
public NetworkMarker getMarker(Object packet) {
|
public NetworkMarker getMarker(Object packet) {
|
||||||
return packetMarker.get(packet);
|
return packetMarker.get(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Associate a given network marker with a specific packet.
|
|
||||||
* @param packet - the NMS packet.
|
|
||||||
* @param marker - the associated marker.
|
|
||||||
*/
|
|
||||||
public void saveMarker(Object packet, NetworkMarker marker) {
|
public void saveMarker(Object packet, NetworkMarker marker) {
|
||||||
if (marker != null) {
|
if (marker != null) {
|
||||||
packetMarker.put(packet, marker);
|
packetMarker.put(packet, marker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Associate a given network marker with a packet event.
|
|
||||||
* @param marker - the marker.
|
|
||||||
* @param event - the packet event
|
|
||||||
*/
|
|
||||||
public void saveEvent(NetworkMarker marker, PacketEvent event) {
|
public void saveEvent(NetworkMarker marker, PacketEvent event) {
|
||||||
if (marker != null) {
|
if (marker != null) {
|
||||||
markerEvent.put(marker, event);
|
markerEvent.put(marker, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Find the network manager in a channel's pipeline.
|
|
||||||
* @param channel - the channel.
|
|
||||||
* @return The network manager.
|
|
||||||
*/
|
|
||||||
private static Object findNetworkManager(Channel channel) {
|
|
||||||
// Find the network manager
|
|
||||||
Object networkManager = findChannelHandler(channel, MinecraftReflection.getNetworkManagerClass());
|
|
||||||
|
|
||||||
if (networkManager != null)
|
|
||||||
return networkManager;
|
|
||||||
throw new IllegalArgumentException("Unable to find NetworkManager in " + channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the first channel handler that is assignable to a given type.
|
|
||||||
* @param channel - the channel.
|
|
||||||
* @param clazz - the type.
|
|
||||||
* @return The first handler, or NULL.
|
|
||||||
*/
|
|
||||||
private static ChannelHandler findChannelHandler(Channel channel, Class<?> clazz) {
|
|
||||||
for (Entry<String, ChannelHandler> entry : channel.pipeline()) {
|
|
||||||
if (clazz.isAssignableFrom(entry.getValue().getClass())) {
|
|
||||||
return entry.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the current player or temporary player associated with the injector.
|
|
||||||
* @return The current player.
|
|
||||||
*/
|
|
||||||
public Player getPlayer() {
|
public Player getPlayer() {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the channel has already been injected.
|
* Set the player instance.
|
||||||
* @return TRUE if it has, FALSE otherwise.
|
* @param player - current instance.
|
||||||
*/
|
*/
|
||||||
|
public void setPlayer(Player player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the updated player instance.
|
||||||
|
* @param updated - updated instance.
|
||||||
|
*/
|
||||||
|
public void setUpdatedPlayer(Player updated) {
|
||||||
|
this.updated = updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isInjected() {
|
public boolean isInjected() {
|
||||||
return injected;
|
return injected;
|
||||||
}
|
}
|
||||||
@ -666,10 +497,46 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
* Determine if this channel has been closed and cleaned up.
|
* Determine if this channel has been closed and cleaned up.
|
||||||
* @return TRUE if it has, FALSE otherwise.
|
* @return TRUE if it has, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return closed;
|
return closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (!closed) {
|
||||||
|
closed = true;
|
||||||
|
|
||||||
|
if (injected) {
|
||||||
|
channelField.revertValue();
|
||||||
|
|
||||||
|
try {
|
||||||
|
originalChannel.pipeline().remove(this);
|
||||||
|
originalChannel.pipeline().remove(protocolEncoder);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
// Ignore it - the player has logged out
|
||||||
|
}
|
||||||
|
// Clear cache
|
||||||
|
factory.invalidate(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the first channel handler that is assignable to a given type.
|
||||||
|
* @param channel - the channel.
|
||||||
|
* @param clazz - the type.
|
||||||
|
* @return The first handler, or NULL.
|
||||||
|
*/
|
||||||
|
public static ChannelHandler findChannelHandler(Channel channel, Class<?> clazz) {
|
||||||
|
for (Entry<String, ChannelHandler> entry : channel.pipeline()) {
|
||||||
|
if (clazz.isAssignableFrom(entry.getValue().getClass())) {
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a socket injector that foreards to the current channel injector.
|
* Represents a socket injector that foreards to the current channel injector.
|
||||||
* @author Kristian
|
* @author Kristian
|
||||||
|
@ -3,6 +3,7 @@ package com.comphenix.protocol.injector.netty;
|
|||||||
import com.comphenix.protocol.error.ErrorReporter;
|
import com.comphenix.protocol.error.ErrorReporter;
|
||||||
import com.comphenix.protocol.events.NetworkMarker;
|
import com.comphenix.protocol.events.NetworkMarker;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a listener for received or sent packets.
|
* Represents a listener for received or sent packets.
|
||||||
* @author Kristian
|
* @author Kristian
|
||||||
@ -17,7 +18,7 @@ interface ChannelListener {
|
|||||||
* @param marker - the associated network marker, if any.
|
* @param marker - the associated network marker, if any.
|
||||||
* @return The new packet, if it should be changed, or NULL to cancel.
|
* @return The new packet, if it should be changed, or NULL to cancel.
|
||||||
*/
|
*/
|
||||||
public Object onPacketSending(ChannelInjector injector, Object packet, NetworkMarker marker);
|
public Object onPacketSending(Injector injector, Object packet, NetworkMarker marker);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when a packet is being received from a client.
|
* Invoked when a packet is being received from a client.
|
||||||
@ -28,7 +29,7 @@ interface ChannelListener {
|
|||||||
* @param marker - the associated network marker, if any.
|
* @param marker - the associated network marker, if any.
|
||||||
* @return The new packet, if it should be changed, or NULL to cancel.
|
* @return The new packet, if it should be changed, or NULL to cancel.
|
||||||
*/
|
*/
|
||||||
public Object onPacketReceiving(ChannelInjector injector, Object packet, NetworkMarker marker);
|
public Object onPacketReceiving(Injector injector, Object packet, NetworkMarker marker);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if there is a packet listener for the given packet.
|
* Determine if there is a packet listener for the given packet.
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
package com.comphenix.protocol.injector.netty;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType.Protocol;
|
||||||
|
import com.comphenix.protocol.events.NetworkMarker;
|
||||||
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a closed injector.
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
class ClosedInjector implements Injector {
|
||||||
|
private Player player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new injector that is always closed.
|
||||||
|
* @param player - the associated player.
|
||||||
|
*/
|
||||||
|
public ClosedInjector(Player player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inject() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendServerPacket(Object packet, NetworkMarker marker, boolean filtered) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recieveClientPacket(Object packet, NetworkMarker marker, boolean filtered) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Protocol getCurrentProtocol() {
|
||||||
|
return Protocol.HANDSHAKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unignorePacket(Object packet) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean ignorePacket(Object packet) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NetworkMarker getMarker(Object packet) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveMarker(Object packet, NetworkMarker marker) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveEvent(NetworkMarker marker, PacketEvent event) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUpdatedPlayer(Player player) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlayer(Player player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInjected() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosed() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
package com.comphenix.protocol.injector.netty;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import net.minecraft.util.io.netty.channel.Channel;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.injector.netty.ChannelInjector.ChannelSocketInjector;
|
||||||
|
import com.comphenix.protocol.injector.server.SocketInjector;
|
||||||
|
import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
|
import com.comphenix.protocol.utility.MinecraftFields;
|
||||||
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
|
import com.google.common.collect.MapMaker;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an injector factory.
|
||||||
|
* <p>
|
||||||
|
* Note that the factory will return {@link ClosedInjector} when the factory is closed.
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
class InjectionFactory {
|
||||||
|
private final ConcurrentMap<Player, Injector> playerLookup = Maps.newConcurrentMap();
|
||||||
|
private final ConcurrentMap<String, Injector> nameLookup = new MapMaker().weakValues().makeMap();
|
||||||
|
|
||||||
|
// Whether or not the factory is closed
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct or retrieve a channel injector from an existing Bukkit player.
|
||||||
|
* @param player - the existing Bukkit player.
|
||||||
|
* @param channelListener - the listener.
|
||||||
|
* @return A new injector, an existing injector associated with this player, or a closed injector.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public Injector fromPlayer(Player player, ChannelListener listener) {
|
||||||
|
if (closed)
|
||||||
|
return new ClosedInjector(player);
|
||||||
|
Injector injector = playerLookup.get(player);
|
||||||
|
|
||||||
|
// Find a temporary injector as well
|
||||||
|
if (injector == null)
|
||||||
|
injector = getTemporaryInjector(player);
|
||||||
|
if (injector != null)
|
||||||
|
return injector;
|
||||||
|
|
||||||
|
Object networkManager = MinecraftFields.getNetworkManager(player);
|
||||||
|
|
||||||
|
// Must be a temporary Bukkit player
|
||||||
|
if (networkManager == null) {
|
||||||
|
return fromName(player.getName(), player);
|
||||||
|
}
|
||||||
|
Channel channel = FuzzyReflection.getFieldValue(networkManager, Channel.class, true);
|
||||||
|
|
||||||
|
// See if a channel has already been created
|
||||||
|
injector = (ChannelInjector) ChannelInjector.findChannelHandler(channel, ChannelInjector.class);
|
||||||
|
|
||||||
|
if (injector != null) {
|
||||||
|
// Update the player instance
|
||||||
|
playerLookup.remove(injector.getPlayer());
|
||||||
|
injector.setPlayer(player);
|
||||||
|
} else {
|
||||||
|
injector = new ChannelInjector(player, networkManager, channel, listener, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache injector and return
|
||||||
|
cacheInjector(player, injector);
|
||||||
|
return injector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a cached injector from a name.
|
||||||
|
* <p>
|
||||||
|
* The injector may be NULL if the plugin has been reloaded during a player login.
|
||||||
|
* @param address - the name.
|
||||||
|
* @return The cached injector, or a closed injector if it could not be found.
|
||||||
|
*/
|
||||||
|
public Injector fromName(String name, Player player) {
|
||||||
|
if (closed)
|
||||||
|
return new ClosedInjector(player);
|
||||||
|
Injector injector = nameLookup.get(name);
|
||||||
|
|
||||||
|
// We can only retrieve cached injectors
|
||||||
|
if (injector != null) {
|
||||||
|
// Update instance
|
||||||
|
injector.setUpdatedPlayer(player);
|
||||||
|
return injector;
|
||||||
|
}
|
||||||
|
return new ClosedInjector(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new channel injector for the given channel.
|
||||||
|
* @param channel - the channel.
|
||||||
|
* @param playerFactory - a temporary player creator.
|
||||||
|
* @param channelListener - the listener.
|
||||||
|
* @param loader - the current (plugin) class loader.
|
||||||
|
* @return The channel injector, or a closed injector.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public Injector fromChannel(Channel channel, ChannelListener listener, TemporaryPlayerFactory playerFactory) {
|
||||||
|
if (closed)
|
||||||
|
return new ClosedInjector(null);
|
||||||
|
|
||||||
|
Object networkManager = findNetworkManager(channel);
|
||||||
|
Player temporaryPlayer = playerFactory.createTemporaryPlayer(Bukkit.getServer());
|
||||||
|
ChannelInjector injector = new ChannelInjector(temporaryPlayer, networkManager, channel, listener, this);
|
||||||
|
|
||||||
|
// Initialize temporary player
|
||||||
|
TemporaryPlayerFactory.setInjectorInPlayer(temporaryPlayer, new ChannelSocketInjector(injector));
|
||||||
|
return injector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate a cached injector.
|
||||||
|
* @param player - the associated player.
|
||||||
|
* @return The cached injector, or NULL if nothing was cached.
|
||||||
|
*/
|
||||||
|
public Injector invalidate(Player player) {
|
||||||
|
Injector injector = playerLookup.remove(player);
|
||||||
|
|
||||||
|
nameLookup.remove(player.getName());
|
||||||
|
return injector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache an injector by player.
|
||||||
|
* @param player - the player.
|
||||||
|
* @param injector - the injector to cache.
|
||||||
|
* @return The previously cached injector.
|
||||||
|
*/
|
||||||
|
public Injector cacheInjector(Player player, Injector injector) {
|
||||||
|
nameLookup.put(player.getName(), injector);
|
||||||
|
return playerLookup.put(player, injector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache an injector by name alone.
|
||||||
|
* @param name - the name to lookup.
|
||||||
|
* @param injector - the injector.
|
||||||
|
* @return The cached injector.
|
||||||
|
*/
|
||||||
|
public Injector cacheInjector(String name, Injector injector) {
|
||||||
|
return nameLookup.put(name, injector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the associated channel injector.
|
||||||
|
* @param player - the temporary player, or normal Bukkit player.
|
||||||
|
* @return The associated injector, or NULL if this is a Bukkit player.
|
||||||
|
*/
|
||||||
|
private ChannelInjector getTemporaryInjector(Player player) {
|
||||||
|
SocketInjector injector = TemporaryPlayerFactory.getInjectorFromPlayer(player);
|
||||||
|
|
||||||
|
if (injector != null) {
|
||||||
|
return ((ChannelSocketInjector) injector).getChannelInjector();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the network manager in a channel's pipeline.
|
||||||
|
* @param channel - the channel.
|
||||||
|
* @return The network manager.
|
||||||
|
*/
|
||||||
|
private Object findNetworkManager(Channel channel) {
|
||||||
|
// Find the network manager
|
||||||
|
Object networkManager = ChannelInjector.findChannelHandler(channel, MinecraftReflection.getNetworkManagerClass());
|
||||||
|
|
||||||
|
if (networkManager != null)
|
||||||
|
return networkManager;
|
||||||
|
throw new IllegalArgumentException("Unable to find NetworkManager in " + channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the factory is closed.
|
||||||
|
* <p>
|
||||||
|
* If it is, all new injectors will be closed by default.
|
||||||
|
* @return TRUE if it is closed, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isClosed() {
|
||||||
|
return closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close all injectors created by this factory, and cease the creation of new injections.
|
||||||
|
*/
|
||||||
|
public synchronized void close() {
|
||||||
|
if (!closed) {
|
||||||
|
closed = true;
|
||||||
|
|
||||||
|
// Close everything
|
||||||
|
for (Injector injector : playerLookup.values())
|
||||||
|
injector.close();
|
||||||
|
for (Injector injector : nameLookup.values())
|
||||||
|
injector.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
package com.comphenix.protocol.injector.netty;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType.Protocol;
|
||||||
|
import com.comphenix.protocol.events.NetworkMarker;
|
||||||
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an injected client connection.
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
interface Injector {
|
||||||
|
/**
|
||||||
|
* Inject the current channel.
|
||||||
|
* <p>
|
||||||
|
* Note that only active channels can be injected.
|
||||||
|
* @return TRUE if we injected the channel, false if we could not inject or it was already injected.
|
||||||
|
*/
|
||||||
|
public abstract boolean inject();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the current injector.
|
||||||
|
*/
|
||||||
|
public abstract void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a packet to a player's client.
|
||||||
|
* @param packet - the packet to send.
|
||||||
|
* @param marker - the network marker.
|
||||||
|
* @param filtered - whether or not the packet is filtered.
|
||||||
|
*/
|
||||||
|
public abstract void sendServerPacket(Object packet, NetworkMarker marker, boolean filtered);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recieve a packet on the server.
|
||||||
|
* @param packet - the (NMS) packet to send.
|
||||||
|
* @param marker - the network marker.
|
||||||
|
* @param filtered - whether or not the packet is filtered.
|
||||||
|
*/
|
||||||
|
public abstract void recieveClientPacket(Object packet, NetworkMarker marker, boolean filtered);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the current protocol state.
|
||||||
|
* @return The current protocol.
|
||||||
|
*/
|
||||||
|
public abstract Protocol getCurrentProtocol();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo the ignore status of a packet.
|
||||||
|
* @param packet - the packet.
|
||||||
|
* @return TRUE if the ignore status was undone, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public abstract boolean unignorePacket(Object packet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignore the given packet.
|
||||||
|
* @param packet - the packet to ignore.
|
||||||
|
* @return TRUE if it was ignored, FALSE if it already is ignored.
|
||||||
|
*/
|
||||||
|
public abstract boolean ignorePacket(Object packet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the network marker associated with a given packet.
|
||||||
|
* @param packet - the packet.
|
||||||
|
* @return The network marker.
|
||||||
|
*/
|
||||||
|
public abstract NetworkMarker getMarker(Object packet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a given network marker with a specific packet.
|
||||||
|
* @param packet - the NMS packet.
|
||||||
|
* @param marker - the associated marker.
|
||||||
|
*/
|
||||||
|
public abstract void saveMarker(Object packet, NetworkMarker marker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a given network marker with a packet event.
|
||||||
|
* @param marker - the marker.
|
||||||
|
* @param event - the packet event
|
||||||
|
*/
|
||||||
|
public abstract void saveEvent(NetworkMarker marker, PacketEvent event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the current player or temporary player associated with the injector.
|
||||||
|
* @return The current player.
|
||||||
|
*/
|
||||||
|
public abstract Player getPlayer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current player instance.
|
||||||
|
* @param player - the current player.
|
||||||
|
*/
|
||||||
|
public abstract void setPlayer(Player player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the channel has already been injected.
|
||||||
|
* @return TRUE if it has, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public abstract boolean isInjected();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if this channel has been closed and cleaned up.
|
||||||
|
* @return TRUE if it has, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public abstract boolean isClosed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the updated player instance.
|
||||||
|
* <p>
|
||||||
|
* This will not replace the current instance, but it will allow PacketEvent to provide additional player information.
|
||||||
|
* @param player - the more up-to-date player.
|
||||||
|
*/
|
||||||
|
public abstract void setUpdatedPlayer(Player player);
|
||||||
|
}
|
@ -7,7 +7,6 @@ import java.lang.reflect.Method;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import net.minecraft.util.io.netty.channel.Channel;
|
import net.minecraft.util.io.netty.channel.Channel;
|
||||||
@ -23,11 +22,7 @@ import com.comphenix.protocol.concurrency.PacketTypeSet;
|
|||||||
import com.comphenix.protocol.error.ErrorReporter;
|
import com.comphenix.protocol.error.ErrorReporter;
|
||||||
import com.comphenix.protocol.error.Report;
|
import com.comphenix.protocol.error.Report;
|
||||||
import com.comphenix.protocol.error.ReportType;
|
import com.comphenix.protocol.error.ReportType;
|
||||||
import com.comphenix.protocol.events.ConnectionSide;
|
import com.comphenix.protocol.events.*;
|
||||||
import com.comphenix.protocol.events.ListenerOptions;
|
|
||||||
import com.comphenix.protocol.events.NetworkMarker;
|
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
|
||||||
import com.comphenix.protocol.injector.ListenerInvoker;
|
import com.comphenix.protocol.injector.ListenerInvoker;
|
||||||
import com.comphenix.protocol.injector.packet.PacketInjector;
|
import com.comphenix.protocol.injector.packet.PacketInjector;
|
||||||
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
||||||
@ -40,6 +35,7 @@ import com.comphenix.protocol.reflect.VolatileField;
|
|||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
|
||||||
public class NettyProtocolInjector implements ChannelListener {
|
public class NettyProtocolInjector implements ChannelListener {
|
||||||
public static final ReportType REPORT_CANNOT_INJECT_INCOMING_CHANNEL = new ReportType("Unable to to inject incoming channel %s.");
|
public static final ReportType REPORT_CANNOT_INJECT_INCOMING_CHANNEL = new ReportType("Unable to to inject incoming channel %s.");
|
||||||
|
|
||||||
@ -50,6 +46,9 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
private TemporaryPlayerFactory playerFactory = new TemporaryPlayerFactory();
|
private TemporaryPlayerFactory playerFactory = new TemporaryPlayerFactory();
|
||||||
private List<VolatileField> bootstrapFields = Lists.newArrayList();
|
private List<VolatileField> bootstrapFields = Lists.newArrayList();
|
||||||
|
|
||||||
|
// The channel injector factory
|
||||||
|
private InjectionFactory injectionFactory = new InjectionFactory();
|
||||||
|
|
||||||
// List of network managers
|
// List of network managers
|
||||||
private volatile List<Object> networkManagers;
|
private volatile List<Object> networkManagers;
|
||||||
|
|
||||||
@ -92,15 +91,9 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
@Override
|
@Override
|
||||||
protected void initChannel(Channel channel) throws Exception {
|
protected void initChannel(Channel channel) throws Exception {
|
||||||
try {
|
try {
|
||||||
// Check and see if the injector has closed
|
|
||||||
synchronized (this) {
|
|
||||||
if (closed)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can take a while, so we need to stop the main thread from interfering
|
// This can take a while, so we need to stop the main thread from interfering
|
||||||
synchronized (networkManagers) {
|
synchronized (networkManagers) {
|
||||||
ChannelInjector.fromChannel(channel, NettyProtocolInjector.this, playerFactory).inject();
|
injectionFactory.fromChannel(channel, NettyProtocolInjector.this, playerFactory).inject();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
reporter.reportDetailed(this, Report.newBuilder(REPORT_CANNOT_INJECT_INCOMING_CHANNEL).
|
reporter.reportDetailed(this, Report.newBuilder(REPORT_CANNOT_INJECT_INCOMING_CHANNEL).
|
||||||
@ -167,7 +160,7 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
* @param player
|
* @param player
|
||||||
*/
|
*/
|
||||||
public void injectPlayer(Player player) {
|
public void injectPlayer(Player player) {
|
||||||
ChannelInjector.fromPlayer(player, this).inject();
|
injectionFactory.fromPlayer(player, this).inject();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<VolatileField> getBootstrapFields(Object serverConnection) {
|
private List<VolatileField> getBootstrapFields(Object serverConnection) {
|
||||||
@ -203,16 +196,13 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
}
|
}
|
||||||
field.revertValue();
|
field.revertValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uninject all the players
|
// Uninject all the players
|
||||||
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
|
injectionFactory.close();
|
||||||
ChannelInjector.fromPlayer(player, this).close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object onPacketSending(ChannelInjector injector, Object packet, NetworkMarker marker) {
|
public Object onPacketSending(Injector injector, Object packet, NetworkMarker marker) {
|
||||||
Class<?> clazz = packet.getClass();
|
Class<?> clazz = packet.getClass();
|
||||||
|
|
||||||
if (sendingFilters.contains(clazz)) {
|
if (sendingFilters.contains(clazz)) {
|
||||||
@ -235,7 +225,7 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object onPacketReceiving(ChannelInjector injector, Object packet, NetworkMarker marker) {
|
public Object onPacketReceiving(Injector injector, Object packet, NetworkMarker marker) {
|
||||||
Class<?> clazz = packet.getClass();
|
Class<?> clazz = packet.getClass();
|
||||||
|
|
||||||
if (reveivedFilters.contains(clazz)) {
|
if (reveivedFilters.contains(clazz)) {
|
||||||
@ -295,12 +285,12 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updatePlayer(Player player) {
|
public void updatePlayer(Player player) {
|
||||||
ChannelInjector.fromPlayer(player, listener).inject();
|
injectionFactory.fromPlayer(player, listener).inject();
|
||||||
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void injectPlayer(Player player, ConflictStrategy strategy) {
|
public void injectPlayer(Player player, ConflictStrategy strategy) {
|
||||||
ChannelInjector.fromPlayer(player, listener).inject();
|
injectionFactory.fromPlayer(player, listener).inject();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -324,19 +314,19 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean uninjectPlayer(Player player) {
|
public boolean uninjectPlayer(Player player) {
|
||||||
ChannelInjector.fromPlayer(player, listener).close();
|
injectionFactory.fromPlayer(player, listener).close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendServerPacket(Player receiver, PacketContainer packet, NetworkMarker marker, boolean filters) throws InvocationTargetException {
|
public void sendServerPacket(Player receiver, PacketContainer packet, NetworkMarker marker, boolean filters) throws InvocationTargetException {
|
||||||
ChannelInjector.fromPlayer(receiver, listener).
|
injectionFactory.fromPlayer(receiver, listener).
|
||||||
sendServerPacket(packet.getHandle(), marker, filters);
|
sendServerPacket(packet.getHandle(), marker, filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void recieveClientPacket(Player player, Object mcPacket) throws IllegalAccessException, InvocationTargetException {
|
public void recieveClientPacket(Player player, Object mcPacket) throws IllegalAccessException, InvocationTargetException {
|
||||||
ChannelInjector.fromPlayer(player, listener).
|
injectionFactory.fromPlayer(player, listener).
|
||||||
recieveClientPacket(mcPacket, null, true);
|
recieveClientPacket(mcPacket, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +338,7 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleDisconnect(Player player) {
|
public void handleDisconnect(Player player) {
|
||||||
ChannelInjector.fromPlayer(player, listener).close();
|
injectionFactory.fromPlayer(player, listener).close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -363,7 +353,7 @@ public class NettyProtocolInjector implements ChannelListener {
|
|||||||
@Override
|
@Override
|
||||||
public PacketEvent packetRecieved(PacketContainer packet, Player client, byte[] buffered) {
|
public PacketEvent packetRecieved(PacketContainer packet, Player client, byte[] buffered) {
|
||||||
NetworkMarker marker = buffered != null ? new NettyNetworkMarker(ConnectionSide.CLIENT_SIDE, buffered) : null;
|
NetworkMarker marker = buffered != null ? new NettyNetworkMarker(ConnectionSide.CLIENT_SIDE, buffered) : null;
|
||||||
ChannelInjector.fromPlayer(client, NettyProtocolInjector.this).
|
injectionFactory.fromPlayer(client, NettyProtocolInjector.this).
|
||||||
saveMarker(packet.getHandle(), marker);
|
saveMarker(packet.getHandle(), marker);
|
||||||
return packetReceived(packet, client, marker);
|
return packetReceived(packet, client, marker);
|
||||||
}
|
}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren