A lot of methods changed from accepting DataInputStream to DataInput,
which messed with the part that dynamically finds the "readPacket"
method. Changed to accepting any method whose signature contains a
parameter derived from DataInput.
In NetworkFieldInjector, we use a "inverted" packet class to undo the
data received counter when a packet has been cancelled.
Previously, we would generate a proxy class that inherits from the
class of the packet (Packet3Chat, etc.) along with its size() method
(which is called and added to the counter, cancelling the other packet),
but this doesn't work for packets that are dynamically sized such as
Packet255KickDisconnect. Instead, we now pass the actual instance to
the proxy class through a weak hash map.
All warnings and error messages will now be identified using fields in
the sender classes, to avoid depending on the format of the error or
warning messages directly. This decoupling will make it possible to
filter out certain irrelevant messages.
Earlier versions of ProtocolLib would in fact load at startup, but due
to an experimental change (ffd920e5b2) -
where ProtocolLib injected code into DedicatedServerConnectionThread in
order to intercept pending connections - the load order had to be
set to world.
This injection was later removed, but the load order was never
reinstated. This causes problems with plugins that load on startup,
but also depend on ProtocolLib as load order trumpts dependency.
This change reintroduces startup load order.
The original intent of catching throwable is to "sandbox" arbitrary
plugin logic and prevent it from ever accidentally killing threads on
the server. A LinkageError due to a missing or old dependency shouldn't
bring down the server, so we secure it by catching all exceptions around
plugin event handlers.
Trouble is, this also catches exceptions such as OutOfMemoryError or
ThreadDead, which assuredly should NOT be caught. The latter case has
even occured in the wild as seen by ticket 45 of TagAPI on BukkitDev.
Minecraft may terminate the reader and writer thread by calling stop(),
and this could occur within the event handler in a plugin. So we should
let ThreadDead go and propagate it to the appropriate handler in
Minecraft.
The original code attempted to parse the JavaScript as it went along,
counting open and close brackets. Unfortunately, this doesn't
take comments and string literals into consideration, so it would very
likely have failed with more complicated filters.
Instead, we'll let the JavaScript compiler handle all the complexity
and simply see if the code compiles. If it doesn't, but the error
occured in the last line, we assume it can be recovered by adding a
new line.
The filter command allows users with sufficient permission (or OPs) to
execute arbitrary JavaScript (no sandboxing). This is fine for a
debug and testing, but could potentially be exploited in a
production environment.
Instead, we disable this command by default and force users to enable it
specifically in the configuration file (not through commands). If
someone has access to the config.yml file, they probably also have
access to the plugins/ folder and thus the ability to install plugins
with arbitrary code execution as well.