Update the player instance on login (LOWEST), not HIGHEST.

Should ensure that packet listeners recieve the most up-to-date player
instance, regardless of whether or not the main thread is blocked in the
player listener. No more temporary players.
This commit is contained in:
Kristian Stangeland 2013-03-28 22:27:58 -04:00
parent b3322b35c1
commit 27da638a91
7 changed files with 135 additions and 4 deletions

View File

@ -696,6 +696,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
try { try {
// Let's clean up the other injection first. // Let's clean up the other injection first.
playerInjection.uninjectPlayer(event.getPlayer().getAddress()); playerInjection.uninjectPlayer(event.getPlayer().getAddress());
playerInjection.updatePlayer(event.getPlayer());
} catch (Exception e) { } catch (Exception e) {
reporter.reportDetailed(PacketFilterManager.this, "Unable to uninject net handler for player.", e, event); reporter.reportDetailed(PacketFilterManager.this, "Unable to uninject net handler for player.", e, event);
} }

View File

@ -129,6 +129,12 @@ public interface PlayerInjectionHandler {
public abstract void recieveClientPacket(Player player, Object mcPacket) public abstract void recieveClientPacket(Player player, Object mcPacket)
throws IllegalAccessException, InvocationTargetException; throws IllegalAccessException, InvocationTargetException;
/**
* Ensure that packet readers are informed of this player reference.
* @param player - the player to update.
*/
public abstract void updatePlayer(Player player);
/** /**
* Determine if the given listeners are valid. * Determine if the given listeners are valid.
* @param version - the current Minecraft version, or NULL if unknown. * @param version - the current Minecraft version, or NULL if unknown.

View File

@ -642,10 +642,7 @@ abstract class PlayerInjector implements SocketInjector {
// Do nothing // Do nothing
} }
/** @Override
* Set the real Bukkit player that we will use.
* @param updatedPlayer - the real Bukkit player.
*/
public void setUpdatedPlayer(Player updatedPlayer) { public void setUpdatedPlayer(Player updatedPlayer) {
this.updatedPlayer = updatedPlayer; this.updatedPlayer = updatedPlayer;
} }

View File

@ -42,6 +42,7 @@ import com.comphenix.protocol.injector.ListenerInvoker;
import com.comphenix.protocol.injector.PlayerLoggedOutException; import com.comphenix.protocol.injector.PlayerLoggedOutException;
import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks; import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks;
import com.comphenix.protocol.injector.server.AbstractInputStreamLookup; import com.comphenix.protocol.injector.server.AbstractInputStreamLookup;
import com.comphenix.protocol.injector.server.BukkitSocketInjector;
import com.comphenix.protocol.injector.server.InputStreamLookupBuilder; import com.comphenix.protocol.injector.server.InputStreamLookupBuilder;
import com.comphenix.protocol.injector.server.SocketInjector; import com.comphenix.protocol.injector.server.SocketInjector;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
@ -416,6 +417,18 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
} }
} }
@Override
public void updatePlayer(Player player) {
SocketInjector injector = inputStreamLookup.peekSocketInjector(player.getAddress());
if (injector != null) {
injector.setUpdatedPlayer(player);
} else {
inputStreamLookup.setSocketInjector(player.getAddress(),
new BukkitSocketInjector(player));
}
}
/** /**
* Unregisters the given player. * Unregisters the given player.
* @param player - player to unregister. * @param player - player to unregister.

View File

@ -0,0 +1,103 @@
package com.comphenix.protocol.injector.server;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.bukkit.entity.Player;
public class BukkitSocketInjector implements SocketInjector {
/**
* Represents a single send packet command.
* @author Kristian
*/
static class SendPacketCommand {
private final Object packet;
private final boolean filtered;
public SendPacketCommand(Object packet, boolean filtered) {
this.packet = packet;
this.filtered = filtered;
}
public Object getPacket() {
return packet;
}
public boolean isFiltered() {
return filtered;
}
}
private Player player;
// Queue of server packets
private List<SendPacketCommand> syncronizedQueue = Collections.synchronizedList(new ArrayList<SendPacketCommand>());
/**
* Represents a temporary socket injector.
* @param temporaryPlayer -
*/
public BukkitSocketInjector(Player player) {
if (player == null)
throw new IllegalArgumentException("Player cannot be NULL.");
this.player = player;
}
@Override
public Socket getSocket() throws IllegalAccessException {
throw new UnsupportedOperationException("Cannot get socket from Bukkit player.");
}
@Override
public SocketAddress getAddress() throws IllegalAccessException {
return player.getAddress();
}
@Override
public void disconnect(String message) throws InvocationTargetException {
player.kickPlayer(message);
}
@Override
public void sendServerPacket(Object packet, boolean filtered)
throws InvocationTargetException {
SendPacketCommand command = new SendPacketCommand(packet, filtered);
// Queue until we can find something better
syncronizedQueue.add(command);
}
@Override
public Player getPlayer() {
return player;
}
@Override
public Player getUpdatedPlayer() {
return player;
}
@Override
public void transferState(SocketInjector delegate) {
// Transmit all queued packets to a different injector.
try {
synchronized(syncronizedQueue) {
for (SendPacketCommand command : syncronizedQueue) {
delegate.sendServerPacket(command.getPacket(), command.isFiltered());
}
syncronizedQueue.clear();
}
} catch (InvocationTargetException e) {
throw new RuntimeException("Unable to transmit packets to " + delegate + " from old injector.", e);
}
}
@Override
public void setUpdatedPlayer(Player updatedPlayer) {
this.player = updatedPlayer;
}
}

View File

@ -58,4 +58,10 @@ public interface SocketInjector {
* @param delegate - the new injector. * @param delegate - the new injector.
*/ */
public abstract void transferState(SocketInjector delegate); public abstract void transferState(SocketInjector delegate);
/**
* Set the real Bukkit player that we will use.
* @param updatedPlayer - the real Bukkit player.
*/
public abstract void setUpdatedPlayer(Player updatedPlayer);
} }

View File

@ -119,4 +119,9 @@ class DummyPlayerHandler implements PlayerInjectionHandler {
public void postWorldLoaded() { public void postWorldLoaded() {
// Do nothing // Do nothing
} }
@Override
public void updatePlayer(Player player) {
// Do nothing
}
} }