Don't overwrite an existing player injector in net login.

This commit is contained in:
Kristian S. Stangeland 2013-03-04 16:54:54 +01:00
parent b1b6e9ec20
commit 9f6b4b60e3
5 changed files with 41 additions and 12 deletions

View File

@ -56,6 +56,7 @@ import com.comphenix.protocol.injector.packet.PacketInjectorBuilder;
import com.comphenix.protocol.injector.packet.PacketRegistry;
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
import com.comphenix.protocol.injector.player.PlayerInjectorBuilder;
import com.comphenix.protocol.injector.player.PlayerInjectionHandler.ConflictStrategy;
import com.comphenix.protocol.injector.spigot.SpigotPacketInjector;
import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.FuzzyReflection;
@ -620,7 +621,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
*/
public void initializePlayers(Player[] players) {
for (Player player : players)
playerInjection.injectPlayer(player);
playerInjection.injectPlayer(player, ConflictStrategy.OVERRIDE);
}
/**
@ -680,7 +681,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
private void onPlayerJoin(PlayerJoinEvent event) {
try {
// This call will be ignored if no listeners are registered
playerInjection.injectPlayer(event.getPlayer());
playerInjection.injectPlayer(event.getPlayer(), ConflictStrategy.OVERRIDE);
} catch (Exception e) {
reporter.reportDetailed(PacketFilterManager.this, "Unable to inject player.", e, event);
}

View File

@ -24,6 +24,7 @@ import org.bukkit.entity.Player;
import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.injector.GamePhase;
import com.comphenix.protocol.injector.player.PlayerInjectionHandler.ConflictStrategy;
import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.google.common.collect.Maps;
@ -64,7 +65,9 @@ class NetLoginInjector {
return inserting;
Player temporary = playerFactory.createTemporaryPlayer(server);
PlayerInjector injector = injectionHandler.injectPlayer(temporary, inserting, GamePhase.LOGIN);
// Note that we bail out if there's an existing player injector
PlayerInjector injector = injectionHandler.injectPlayer(
temporary, inserting, ConflictStrategy.BAIL_OUT, GamePhase.LOGIN);
if (injector != null) {
// Update injector as well

View File

@ -12,6 +12,23 @@ import com.comphenix.protocol.injector.GamePhase;
import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks;
public interface PlayerInjectionHandler {
/**
* How to handle a previously existing player injection.
*
* @author Kristian
*/
public enum ConflictStrategy {
/**
* Override it.
*/
OVERRIDE,
/**
* Immediately exit.
*/
BAIL_OUT;
}
/**
* Retrieves how the server packets are read.
* @return Injection method for reading server packets.
@ -64,8 +81,9 @@ public interface PlayerInjectionHandler {
* <p>
* This call will be ignored if there's no listener that can receive the given events.
* @param player - player to hook.
* @param strategy - how to handle injection conflicts.
*/
public abstract void injectPlayer(Player player);
public abstract void injectPlayer(Player player, ConflictStrategy strategy);
/**
* Invoke special routines for handling disconnect before a player is uninjected.

View File

@ -253,12 +253,13 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
* <p>
* This call will be ignored if there's no listener that can receive the given events.
* @param player - player to hook.
* @param strategy - how to handle previous player injections.
*/
@Override
public void injectPlayer(Player player) {
public void injectPlayer(Player player, ConflictStrategy strategy) {
// Inject using the player instance itself
if (isInjectionNecessary(GamePhase.PLAYING)) {
injectPlayer(player, player, GamePhase.PLAYING);
injectPlayer(player, player, strategy, GamePhase.PLAYING);
}
}
@ -281,7 +282,7 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
* @param phase - the current game phase.
* @return The resulting player injector, or NULL if the injection failed.
*/
PlayerInjector injectPlayer(Player player, Object injectionPoint, GamePhase phase) {
PlayerInjector injectPlayer(Player player, Object injectionPoint, ConflictStrategy stategy, GamePhase phase) {
if (player == null)
throw new IllegalArgumentException("Player cannot be NULL.");
if (injectionPoint == null)
@ -291,12 +292,12 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
// Unfortunately, due to NetLoginHandler, multiple threads may potentially call this method.
synchronized (player) {
return injectPlayerInternal(player, injectionPoint, phase);
return injectPlayerInternal(player, injectionPoint, stategy, phase);
}
}
// Unsafe variant of the above
private PlayerInjector injectPlayerInternal(Player player, Object injectionPoint, GamePhase phase) {
private PlayerInjector injectPlayerInternal(Player player, Object injectionPoint, ConflictStrategy stategy, GamePhase phase) {
PlayerInjector injector = playerInjection.get(player);
PlayerInjectHooks tempHook = getPlayerHook(phase);
PlayerInjectHooks permanentHook = tempHook;
@ -328,9 +329,14 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
// Close any previously associated hooks before we proceed
if (previous != null && !(player instanceof Factory)) {
uninjectPlayer(previous.getPlayer(), true);
switch (stategy) {
case OVERRIDE:
uninjectPlayer(previous.getPlayer(), true);
break;
case BAIL_OUT:
return null;
}
}
injector.injectManager();
// Save injector

View File

@ -79,7 +79,8 @@ class DummyPlayerHandler implements PlayerInjectionHandler {
}
@Override
public void injectPlayer(Player player) {
public void injectPlayer(Player player, ConflictStrategy strategy) {
// We don't care about strategy
injector.injectPlayer(player);
}