diff --git a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java index 8513e8e30..abad7127d 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java @@ -43,4 +43,18 @@ public interface PendingConnection extends Connection * @return the UUID */ String getUUID(); + + /** + * Get this connection's online mode. + * + * @return the online mode + */ + boolean isOnlineMode(); + + /** + * Set this connection's online mode. + * + * @param onlineMode + */ + void setOnlineMode(boolean onlineMode); } diff --git a/api/src/main/java/net/md_5/bungee/api/event/PreLoginEvent.java b/api/src/main/java/net/md_5/bungee/api/event/PreLoginEvent.java new file mode 100644 index 000000000..3e148afd5 --- /dev/null +++ b/api/src/main/java/net/md_5/bungee/api/event/PreLoginEvent.java @@ -0,0 +1,37 @@ +package net.md_5.bungee.api.event; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import net.md_5.bungee.api.Callback; +import net.md_5.bungee.api.connection.PendingConnection; +import net.md_5.bungee.api.plugin.Cancellable; + +/** + * Event called to represent a player first making their presence and username + * known. + */ +@Data +@ToString(callSuper = false) +@EqualsAndHashCode(callSuper = false) +public class PreLoginEvent extends AsyncEvent implements Cancellable { + + /** + * Cancelled state. + */ + private boolean cancelled; + /** + * Message to use when kicking if this event is canceled. + */ + private String cancelReason; + /** + * Connection attempting to login. + */ + private final PendingConnection connection; + + public PreLoginEvent(PendingConnection connection, Callback done) + { + super( done ); + this.connection = connection; + } +} \ No newline at end of file diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 3dc87f357..75856108e 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -13,6 +13,7 @@ import javax.crypto.Cipher; import javax.crypto.SecretKey; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.Setter; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.EncryptionUtil; import net.md_5.bungee.UserConnection; @@ -44,6 +45,7 @@ import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.api.AbstractReconnectHandler; import net.md_5.bungee.api.event.PlayerHandshakeEvent; +import net.md_5.bungee.api.event.PreLoginEvent; import net.md_5.bungee.protocol.Protocol; import net.md_5.bungee.protocol.packet.LegacyPing; import net.md_5.bungee.protocol.packet.LoginRequest; @@ -251,14 +253,33 @@ public class InitialHandler extends PacketHandler implements PendingConnection // TODO: Nuuuu Mojang why u do this // unsafe().sendPacket( PacketConstants.I_AM_BUNGEE ); // unsafe().sendPacket( PacketConstants.FORGE_MOD_REQUEST ); - if ( this.onlineMode ) + Callback callback = new Callback() { - unsafe().sendPacket( request = EncryptionUtil.encryptRequest() ); - } else - { - finish(); - } - thisState = State.ENCRYPT; + + @Override + public void done(PreLoginEvent result, Throwable error) + { + if ( result.isCancelled() ) + { + disconnect( result.getCancelReason() ); + } + if ( ch.isClosed() ) + { + return; + } + if ( InitialHandler.this.onlineMode ) + { + unsafe().sendPacket( request = EncryptionUtil.encryptRequest() ); + } else + { + finish(); + } + thisState = State.ENCRYPT; + } + }; + + // fire pre login event + bungee.getPluginManager().callEvent( new PreLoginEvent( InitialHandler.this, callback ) ); } @Override @@ -417,9 +438,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection return unsafe; } + @Override public void setOnlineMode(boolean onlineMode) { - Preconditions.checkState( thisState == State.HANDSHAKE, "Can only set online mode status whilst handshaking" ); + Preconditions.checkState( thisState == State.USERNAME, "Can only set online mode status whilst state is username" ); this.onlineMode = onlineMode; }