ProtocolLib/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java

163 lines
5.1 KiB
Java
Raw Normal View History

2012-10-15 00:31:55 +02:00
package com.comphenix.protocol.injector.player;
import java.io.DataInputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress;
2012-10-15 00:31:55 +02:00
import java.util.Set;
import org.bukkit.entity.Player;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.injector.GamePhase;
2012-10-15 00:31:55 +02:00
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;
}
2012-10-15 00:31:55 +02:00
/**
* Retrieves how the server packets are read.
* @return Injection method for reading server packets.
*/
public abstract PlayerInjectHooks getPlayerHook();
/**
* Retrieves how the server packets are read.
* @param phase - the current game phase.
* @return Injection method for reading server packets.
*/
public abstract PlayerInjectHooks getPlayerHook(GamePhase phase);
2012-10-15 00:31:55 +02:00
/**
* Sets how the server packets are read.
* @param playerHook - the new injection method for reading server packets.
*/
public abstract void setPlayerHook(PlayerInjectHooks playerHook);
/**
* Sets how the server packets are read.
* @param phase - the current game phase.
* @param playerHook - the new injection method for reading server packets.
*/
public abstract void setPlayerHook(GamePhase phase, PlayerInjectHooks playerHook);
2012-10-15 00:31:55 +02:00
/**
* Add an underlying packet handler of the given ID.
* @param packetID - packet ID to register.
*/
public abstract void addPacketHandler(int packetID);
2012-10-15 00:31:55 +02:00
/**
* Remove an underlying packet handler of ths ID.
* @param packetID - packet ID to unregister.
*/
public abstract void removePacketHandler(int packetID);
/**
* Retrieve a player by its DataInput connection.
* @param inputStream - the associated DataInput connection.
* @return The player.
* @throws InterruptedException If the thread was interrupted during the wait.
*/
public abstract Player getPlayerByConnection(DataInputStream inputStream)
throws InterruptedException;
2012-10-15 00:31:55 +02:00
/**
* Initialize a player hook, allowing us to read server packets.
* <p>
* This call will be ignored if there's no listener that can receive the given events.
2012-10-15 00:31:55 +02:00
* @param player - player to hook.
* @param strategy - how to handle injection conflicts.
2012-10-15 00:31:55 +02:00
*/
public abstract void injectPlayer(Player player, ConflictStrategy strategy);
/**
* Invoke special routines for handling disconnect before a player is uninjected.
* @param player - player to process.
*/
public abstract void handleDisconnect(Player player);
/**
* Unregisters the given player.
* @param player - player to unregister.
* @return TRUE if a player has been uninjected, FALSE otherwise.
*/
public abstract boolean uninjectPlayer(Player player);
/**
* Unregisters a player by the given address.
* <p>
* If the server handler has been created before we've gotten a chance to unject the player,
* the method will try a workaround to remove the injected hook in the NetServerHandler.
*
* @param address - address of the player to unregister.
* @return TRUE if a player has been uninjected, FALSE otherwise.
*/
public abstract boolean uninjectPlayer(InetSocketAddress address);
/**
* Send the given packet to the given reciever.
* @param reciever - the player receiver.
* @param packet - the packet to send.
* @param filters - whether or not to invoke the packet filters.
* @throws InvocationTargetException If an error occured during sending.
*/
public abstract void sendServerPacket(Player reciever, PacketContainer packet, boolean filters)
throws InvocationTargetException;
/**
* Process a packet as if it were sent by the given player.
* @param player - the sender.
* @param mcPacket - the packet to process.
* @throws IllegalAccessException If the reflection machinery failed.
* @throws InvocationTargetException If the underlying method caused an error.
*/
public abstract void recieveClientPacket(Player player, Object mcPacket)
throws IllegalAccessException, InvocationTargetException;
2012-10-15 00:31:55 +02:00
/**
* Determine if the given listeners are valid.
* @param version - the current Minecraft version, or NULL if unknown.
2012-10-15 00:31:55 +02:00
* @param listeners - listeners to check.
*/
public abstract void checkListener(Set<PacketListener> listeners);
2012-10-15 00:31:55 +02:00
/**
* Determine if a listener is valid or not.
* <p>
* If not, a warning will be printed to the console.
* @param version - the current Minecraft version, or NULL if unknown.
2012-10-15 00:31:55 +02:00
* @param listener - listener to check.
*/
public abstract void checkListener(PacketListener listener);
2012-10-15 00:31:55 +02:00
/**
* Retrieve the current list of registered sending listeners.
* @return List of the sending listeners's packet IDs.
*/
public abstract Set<Integer> getSendingFilters();
2012-10-15 00:31:55 +02:00
/**
* Close any lingering proxy injections.
*/
public abstract void close();
/**
Experimental: InputStream -> Socket lookup by intercepting accept(). Previously, we have used a BlockingHashMap to simply lock the packet read thread until we have had a chance to intercept the NetLoginHandler/PendingConnection and store InputStream -> PlayerInjector -> TemporaryPlayer. Problem is, this could potentially cause problems if, for some reason, a packet is intercepted after the player has logged out and the player injector has been removed from the lookup map. In that case, the read thread would wait until it reaches the default timeout of 2 seconds. Locking threads is fairly inefficient in general, and waiting for the server connection thread to update the NetLoginHandler list could take a while. Instead, ProtocolLib will now intercept any Socket accepted in the server's main ServerSocket, and record any calls to getInputStream(). That way, we can get a InputStream -> Socket mapping before the server thread ever creates the read and write threads in NetLoginHandler -> NetworkManager. Unfortunately, it's not trivial to swap out the ServerSocket in the DedicatedServerConnectionThread - we actually have to trigger the accept() thread and move through a cycle of the loop before our custom ServerSocket is used. To do this, we will actually connect to the server and read its MOTD manually, hopefully getting to it before any other players. This creates a slight overhead of a couple of threads per server start, but it's probably much better than locking the read thread. More testing is needed though before this can be confirmed.
2013-02-25 01:59:48 +01:00
* Perform any action that must be delayed until the world(s) has loaded.
*/
Experimental: InputStream -> Socket lookup by intercepting accept(). Previously, we have used a BlockingHashMap to simply lock the packet read thread until we have had a chance to intercept the NetLoginHandler/PendingConnection and store InputStream -> PlayerInjector -> TemporaryPlayer. Problem is, this could potentially cause problems if, for some reason, a packet is intercepted after the player has logged out and the player injector has been removed from the lookup map. In that case, the read thread would wait until it reaches the default timeout of 2 seconds. Locking threads is fairly inefficient in general, and waiting for the server connection thread to update the NetLoginHandler list could take a while. Instead, ProtocolLib will now intercept any Socket accepted in the server's main ServerSocket, and record any calls to getInputStream(). That way, we can get a InputStream -> Socket mapping before the server thread ever creates the read and write threads in NetLoginHandler -> NetworkManager. Unfortunately, it's not trivial to swap out the ServerSocket in the DedicatedServerConnectionThread - we actually have to trigger the accept() thread and move through a cycle of the loop before our custom ServerSocket is used. To do this, we will actually connect to the server and read its MOTD manually, hopefully getting to it before any other players. This creates a slight overhead of a couple of threads per server start, but it's probably much better than locking the read thread. More testing is needed though before this can be confirmed.
2013-02-25 01:59:48 +01:00
public abstract void postWorldLoaded();
}