Update the player instance during PlayerLoginEvent as well.
This ensures that we at least have an OfflinePlayer when certain packets are intercepted, instead of the TemporaryPlayer created by ProtocolLib.
Dieser Commit ist enthalten in:
Ursprung
936e0f0e82
Commit
9d972b90ac
@ -42,6 +42,7 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.event.server.PluginDisableEvent;
|
import org.bukkit.event.server.PluginDisableEvent;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
@ -921,10 +922,13 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
try {
|
try {
|
||||||
manager.registerEvents(new Listener() {
|
manager.registerEvents(new Listener() {
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent event) {
|
||||||
|
PacketFilterManager.this.onPlayerLogin(event);
|
||||||
|
}
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onPrePlayerJoin(PlayerJoinEvent event) {
|
public void onPrePlayerJoin(PlayerJoinEvent event) {
|
||||||
PacketFilterManager.this.onPrePlayerJoin(event);
|
PacketFilterManager.this.onPrePlayerJoin(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
PacketFilterManager.this.onPlayerJoin(event);
|
PacketFilterManager.this.onPlayerJoin(event);
|
||||||
@ -946,6 +950,11 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onPlayerLogin(PlayerLoginEvent event) {
|
||||||
|
System.out.println("Address: " + event.getAddress());
|
||||||
|
playerInjection.updatePlayer(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
private void onPrePlayerJoin(PlayerJoinEvent event) {
|
private void onPrePlayerJoin(PlayerJoinEvent event) {
|
||||||
playerInjection.updatePlayer(event.getPlayer());
|
playerInjection.updatePlayer(event.getPlayer());
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import java.util.NoSuchElementException;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import net.minecraft.util.com.mojang.authlib.GameProfile;
|
||||||
import net.minecraft.util.io.netty.buffer.ByteBuf;
|
import net.minecraft.util.io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.util.io.netty.channel.Channel;
|
import net.minecraft.util.io.netty.channel.Channel;
|
||||||
import net.minecraft.util.io.netty.channel.ChannelHandler;
|
import net.minecraft.util.io.netty.channel.ChannelHandler;
|
||||||
@ -24,6 +25,7 @@ import net.sf.cglib.proxy.Factory;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType;
|
||||||
import com.comphenix.protocol.PacketType.Protocol;
|
import com.comphenix.protocol.PacketType.Protocol;
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.error.Report;
|
import com.comphenix.protocol.error.Report;
|
||||||
@ -44,6 +46,7 @@ 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.
|
||||||
@ -53,7 +56,12 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
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> cachedInjector = new MapMaker().weakKeys().makeMap();
|
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
|
||||||
|
private static Class<?> PACKET_LOGIN_CLIENT = null;
|
||||||
|
private static FieldAccessor LOGIN_GAME_PROFILE = null;
|
||||||
|
|
||||||
// Saved accessors
|
// Saved accessors
|
||||||
private static MethodAccessor DECODE_BUFFER;
|
private static MethodAccessor DECODE_BUFFER;
|
||||||
@ -124,7 +132,7 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
* @return A new injector, or an existing injector associated with this player.
|
* @return A new injector, or an existing injector associated with this player.
|
||||||
*/
|
*/
|
||||||
public static ChannelInjector fromPlayer(Player player, ChannelListener listener) {
|
public static ChannelInjector fromPlayer(Player player, ChannelListener listener) {
|
||||||
ChannelInjector injector = cachedInjector.get(player);
|
ChannelInjector injector = PLAYER_LOOKUP.get(player);
|
||||||
|
|
||||||
// Find a temporary injector as well
|
// Find a temporary injector as well
|
||||||
if (injector == null)
|
if (injector == null)
|
||||||
@ -133,6 +141,11 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
return injector;
|
return injector;
|
||||||
|
|
||||||
Object networkManager = MinecraftFields.getNetworkManager(player);
|
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);
|
Channel channel = FuzzyReflection.getFieldValue(networkManager, Channel.class, true);
|
||||||
|
|
||||||
// See if a channel has already been created
|
// See if a channel has already been created
|
||||||
@ -145,7 +158,8 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
injector = new ChannelInjector(player, networkManager, channel, listener);
|
injector = new ChannelInjector(player, networkManager, channel, listener);
|
||||||
}
|
}
|
||||||
// Cache injector and return
|
// Cache injector and return
|
||||||
cachedInjector.put(player, injector);
|
NAME_LOOKUP.put(player.getName(), injector);
|
||||||
|
PLAYER_LOOKUP.put(player, injector);
|
||||||
return injector;
|
return injector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,6 +177,24 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
return null;
|
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.player = player;
|
||||||
|
return injector;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Cannot inject temporary Bukkit player.");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new channel injector for the given channel.
|
* Construct a new channel injector for the given channel.
|
||||||
* @param channel - the channel.
|
* @param channel - the channel.
|
||||||
@ -199,7 +231,7 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
if (findChannelHandler(originalChannel, ChannelInjector.class) != null) {
|
if (findChannelHandler(originalChannel, ChannelInjector.class) != null) {
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
if (player != null)
|
if (player != null)
|
||||||
cachedInjector.remove(player);
|
PLAYER_LOOKUP.remove(player);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +319,9 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
// Ignore it - the player has logged out
|
// Ignore it - the player has logged out
|
||||||
}
|
}
|
||||||
|
// Clear cache
|
||||||
|
NAME_LOOKUP.remove(player.getName());
|
||||||
|
PLAYER_LOOKUP.remove(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,6 +402,9 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
Class<?> packetClass = input.getClass();
|
Class<?> packetClass = input.getClass();
|
||||||
NetworkMarker marker = null;
|
NetworkMarker marker = null;
|
||||||
|
|
||||||
|
// Special case!
|
||||||
|
handleLogin(packetClass, input);
|
||||||
|
|
||||||
if (channelListener.includeBuffer(packetClass)) {
|
if (channelListener.includeBuffer(packetClass)) {
|
||||||
byteBuffer.resetReaderIndex();
|
byteBuffer.resetReaderIndex();
|
||||||
marker = new NettyNetworkMarker(ConnectionSide.CLIENT_SIDE, getBytes(byteBuffer));
|
marker = new NettyNetworkMarker(ConnectionSide.CLIENT_SIDE, getBytes(byteBuffer));
|
||||||
@ -385,6 +423,27 @@ class ChannelInjector extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when we may need to handle the login packet.
|
||||||
|
* @param packetClass - the packet class.
|
||||||
|
* @param packet - the packet.
|
||||||
|
*/
|
||||||
|
protected void handleLogin(Class<?> packetClass, Object packet) {
|
||||||
|
// Initialize packet class
|
||||||
|
if (PACKET_LOGIN_CLIENT == null) {
|
||||||
|
PACKET_LOGIN_CLIENT = PacketType.Login.Client.START.getPacketClass();
|
||||||
|
LOGIN_GAME_PROFILE = Accessors.getFieldAccessor(PACKET_LOGIN_CLIENT, GameProfile.class, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we are dealing with the login packet
|
||||||
|
if (PACKET_LOGIN_CLIENT.equals(packetClass)) {
|
||||||
|
GameProfile profile = (GameProfile) LOGIN_GAME_PROFILE.get(packet);
|
||||||
|
|
||||||
|
// Save the channel injector
|
||||||
|
NAME_LOOKUP.put(profile.getName(), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||||
super.channelActive(ctx);
|
super.channelActive(ctx);
|
||||||
|
@ -22,7 +22,7 @@ public class MinecraftFields {
|
|||||||
/**
|
/**
|
||||||
* Retrieve the network mananger associated with a particular player.
|
* Retrieve the network mananger associated with a particular player.
|
||||||
* @param player - the player.
|
* @param player - the player.
|
||||||
* @return The network manager.
|
* @return The network manager, or NULL if no network manager has been asssociated yet.
|
||||||
*/
|
*/
|
||||||
public static Object getNetworkManager(Player player) {
|
public static Object getNetworkManager(Player player) {
|
||||||
Object nmsPlayer = BukkitUnwrapper.getInstance().unwrapItem(player);
|
Object nmsPlayer = BukkitUnwrapper.getInstance().unwrapItem(player);
|
||||||
@ -33,7 +33,11 @@ public class MinecraftFields {
|
|||||||
NETWORK_ACCESSOR = Accessors.getFieldAccessor(connectionClass, networkClass, true);
|
NETWORK_ACCESSOR = Accessors.getFieldAccessor(connectionClass, networkClass, true);
|
||||||
}
|
}
|
||||||
// Retrieve the network manager
|
// Retrieve the network manager
|
||||||
return NETWORK_ACCESSOR.get(getPlayerConnection(nmsPlayer));
|
final Object playerConnection = getPlayerConnection(nmsPlayer);
|
||||||
|
|
||||||
|
if (playerConnection != null)
|
||||||
|
return NETWORK_ACCESSOR.get(playerConnection);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren