This occurs whenever a listener is added or removed. A listener can
now specify whether or not it's listening for packets sent BEFORE
a player has logged in (every packet upto Packet1Login and a few more),
or AFTER. By default, listeners only receive notifcation of packets
sent and received after.
ProtocolLib will now only hook NetLoginHandler if there's a login
listener, and vice versa. Thus, the new login feature will only
tax the server if another plugin is using it. In addition, ProtocolLib
will not consume any resources when it's not serving any listeners.
This is achieved by injecting the NetLoginHandler when it's added
to the DedicatedServerConnectionThread's list of current login handlers.
PacketEvents during this phase uses "fake" Player objects that only
support a subset of methods. Consumers can expect the following methods
to be functional:
* getPlayer()
* getAddress()
* getServer()
* chat(String)
* sendMessage(String)
* sendMessage(String[])
* kickPlayer(String)
A "fake" Player object can be converted to its real counterpart by
calling getPlayer().
Threads can now increment a shared counter indicating that a packet
should not be transmitted after the default packet listener
processing. This can be useful if a packet listener needs information
from additional packets before it can complete.
Packet listeners that whish to use this method begin by calling
incrementPacketDelay(). It is then responsible for calling
signalPacketTransmission() when it's done waiting. All processing
on PacketEvents outside packet listeners must be synchronized
with getProcessingLock().
While it may seem better to use a Spout PacketListener, we can't
prevent other spout listeners from stopping the listener
chain. For instance, Orebfuscator does supports Spout, but does this
by cancelling every chunk packet and sending them to be processed and
sent by Orebfuscator only. This can never be made compatible with
other plugins.
So, we choose to add some overhead and inject our proxy onto Spout.
Fortunately, Spout injects the proxy using a player listener on LOWEST,
so we get to override Spout again with our HIGHEST. The proxy method
should be generic enough to handle most proxy types.
This would happen if the NetServerHandler is already a proxy, and
the injection method is unable to create an instance of the proxy
type.
It's best to fail instead of polluting (due to constructors with
side-effects) Minecraft with failed proxy objects.