4040import com .velocitypowered .proxy .protocol .StateRegistry ;
4141import com .velocitypowered .proxy .protocol .netty .MinecraftCompressDecoder ;
4242import com .velocitypowered .proxy .protocol .netty .MinecraftCompressorAndLengthEncoder ;
43+ import com .velocitypowered .proxy .protocol .netty .MinecraftDecoder ;
4344import com .velocitypowered .proxy .protocol .netty .MinecraftEncoder ;
4445import com .velocitypowered .proxy .protocol .netty .MinecraftVarintLengthEncoder ;
4546import edu .umd .cs .findbugs .annotations .SuppressFBWarnings ;
4950import java .io .File ;
5051import java .io .IOException ;
5152import java .io .InputStream ;
53+ import java .lang .invoke .MethodHandle ;
54+ import java .lang .invoke .MethodHandles ;
5255import java .nio .file .Path ;
5356import java .util .HashMap ;
5457import java .util .HashSet ;
@@ -137,6 +140,8 @@ public class LimboAPI implements LimboFactory {
137140
138141 public static final ConcurrentHashMap <Player , UUID > INITIAL_ID = new ConcurrentHashMap <>();
139142
143+ private static final MethodHandle STATE_FIELD ;
144+
140145 private final VelocityServer server ;
141146 private final Metrics .Factory metricsFactory ;
142147 private final File configFile ;
@@ -443,12 +448,14 @@ public void inject3rdParty(Player player, MinecraftConnection connection, Channe
443448 public void setState (MinecraftConnection connection , StateRegistry stateRegistry ) {
444449 connection .setState (stateRegistry );
445450 this .setEncoderState (connection , stateRegistry );
451+ this .fixDecoderState (connection , stateRegistry );
446452 }
447453
448454 public void setActiveSessionHandler (MinecraftConnection connection , StateRegistry stateRegistry ,
449455 MinecraftSessionHandler sessionHandler ) {
450456 connection .setActiveSessionHandler (stateRegistry , sessionHandler );
451457 this .setEncoderState (connection , stateRegistry );
458+ this .fixDecoderState (connection , stateRegistry );
452459 }
453460
454461 public void setEncoderState (MinecraftConnection connection , StateRegistry state ) {
@@ -474,6 +481,20 @@ public void setEncoderState(MinecraftConnection connection, StateRegistry state)
474481 }
475482 }
476483
484+ public void fixDecoderState (MinecraftConnection connection , StateRegistry state ) {
485+ if (state .name () == null ) { // custom state
486+ MinecraftDecoder decoder = connection .getChannel ().pipeline ().get (MinecraftDecoder .class );
487+ if (decoder != null ) {
488+ try {
489+ // Let decoder know what we're in PLAY state, or it will kick the player.
490+ STATE_FIELD .invokeExact (decoder , StateRegistry .PLAY );
491+ } catch (Throwable throwable ) {
492+ LimboAPI .getLogger ().error ("Failed to fixup decoder" , throwable );
493+ }
494+ }
495+ }
496+ }
497+
477498 public void deject3rdParty (ChannelPipeline pipeline ) {
478499 this .preparedPacketFactory .deject (pipeline );
479500 }
@@ -693,4 +714,13 @@ private static void setSerializer(Serializer serializer) {
693714 public static Serializer getSerializer () {
694715 return SERIALIZER ;
695716 }
717+
718+ static {
719+ try {
720+ STATE_FIELD = MethodHandles .privateLookupIn (MinecraftDecoder .class , MethodHandles .lookup ())
721+ .findSetter (MinecraftDecoder .class , "state" , StateRegistry .class );
722+ } catch (NoSuchFieldException | IllegalAccessException e ) {
723+ throw new RuntimeException (e );
724+ }
725+ }
696726}
0 commit comments