BungeeCord - обнаружен аутентифицированный игрок в автономном режиме
В течение нескольких дней я пытался определить, является ли учетная запись игрока аутентифицированной Mojang, когда он находится в автономном режиме.
Почему я хочу это сделать?
В настоящее время у меня есть базовая система управления, которая состоит из проверки того, существует ли псевдоним игрока в базе данных mojang, если для setOnlineMode установлено значение true, в противном случае для него установлено значение false. Система позволяет отображать обложку игрока и его UUID, но проблема в том, что если игрок, рассматриваемый как офлайн, покупает премиум-аккаунт с тем же псевдонимом, у него нет обложки или его реального UUID, поскольку для setOnlineMode для false задано значение false. предотвратить потерю своего прогресса. Моя цель - создать систему, которая обнаружит, что офлайн-пользователь только что вошел в систему с аутентифицированной учетной записью Minecraft, чтобы сервер мог предложить ему автоматический перенос его прогресса в его новый аутентичный UUID.
Я провел некоторое исследование - попробуйте, например, здесь, я удалил условие онлайн-режима, чтобы разрешить проверку подлинности игрока, тогда здесь я удалил разъединение, если игрок был недействительным. Что дало мне чудесную ошибку.
13:13:31 [GRAVE] [Arbi13_] -> UpstreamBridge - обнаружено исключение io.netty.handler.codec.EncoderException: java.lang.IllegalArgumentException: невозможно получить идентификатор для класса пакета net.md_5.bungee.protocol.packet.SetCompression в фазе ИГРА с направлением TO_CLIENT на io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:125) на io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContecan.oContain.jt.dll) ij..invokeWriteAndFlush(AbstractChannelHandlerContext.java:801) при io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814) при io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794) при io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1066) в io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:305) в net.md_5.bungee.netty.ChannelWrapper.write(ChannelWrapper.java:60) net.md_5.bungee.UserConnection$1.sendPacket(UserConnection.java:148) в net.md_5.bungee.UserConnection.setCompressionThreshold(UserConnection.java:697) в net.md_5.bungee.connection.InitialHandler$6$1.run(InitialHandler.java:523) по адресу io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) по адресу io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.jnel:40ty at at.epoll.EpollEventLoop.run(EpollEventLoop.java:326) в io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897) в java.lang.Thread.run(Thread.java:748), вызванный: java.lang.IllegalArgumentException: не удается получить идентификатор для класса пакета net.md_5.bungee.protocol.packet.SetCompression в фазе GAME с направлением TO_CLIENT на com.google.common.base.Preconditions.checkArgument(Preconditions.java:399) в сети.md_5.bungee.protocol.Protocol$DirectionData.getId(Protocol.java:462) в net.md_5.bungee.protocol.MinecraftEncoder.encode(MinecraftEncoder.java:23) в net.md_5.bungee.protocol.MinecraftEncoder.encode(MinecraftEncoder.java:9) в io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107) 15 Больше
@Override
public void handle(LoginRequest loginRequest) throws Exception
{
Preconditions.checkState( thisState == State.USERNAME, "Not expecting USERNAME" );
this.loginRequest = loginRequest;
if ( getName().contains( "." ) )
{
disconnect( bungee.getTranslation( "name_invalid" ) );
return;
}
if ( getName().length() > 16 )
{
disconnect( bungee.getTranslation( "name_too_long" ) );
return;
}
int limit = BungeeCord.getInstance().config.getPlayerLimit();
if ( limit > 0 && bungee.getOnlineCount() > limit )
{
disconnect( bungee.getTranslation( "proxy_full" ) );
return;
}
// If offline mode and they are already on, don't allow connect
// We can just check by UUID here as names are based on UUID
if ( !isOnlineMode() && bungee.getPlayer( getUniqueId() ) != null )
{
disconnect( bungee.getTranslation( "already_connected_proxy" ) );
return;
}
Callback<PreLoginEvent> callback = new Callback<PreLoginEvent>()
{
@Override
public void done(PreLoginEvent result, Throwable error)
{
if ( result.isCancelled() )
{
disconnect( result.getCancelReasonComponents() );
return;
}
if ( ch.isClosed() )
{
return;
}
unsafe().sendPacket( request = EncryptionUtil.encryptRequest() );
thisState = State.ENCRYPT;
}
};
// fire pre login event
bungee.getPluginManager().callEvent( new PreLoginEvent( InitialHandler.this, callback ) );
}
@Override
public void handle(final EncryptionResponse encryptResponse) throws Exception
{
Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" );
SecretKey sharedKey = EncryptionUtil.getSecret( encryptResponse, request );
BungeeCipher decrypt = EncryptionUtil.getCipher( false, sharedKey );
ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
BungeeCipher encrypt = EncryptionUtil.getCipher( true, sharedKey );
ch.addBefore( PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" );
MessageDigest sha = MessageDigest.getInstance( "SHA-1" );
for ( byte[] bit : new byte[][]
{
request.getServerId().getBytes( "ISO_8859_1" ), sharedKey.getEncoded(), EncryptionUtil.keys.getPublic().getEncoded()
} )
{
sha.update( bit );
}
String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" );
String preventProxy = ( ( BungeeCord.getInstance().config.isPreventProxyConnections() ) ? "&ip=" + URLEncoder.encode( getAddress().getAddress().getHostAddress(), "UTF-8" ) : "" );
String authURL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" + encName + "&serverId=" + encodedHash + preventProxy;
Callback<String> handler = new Callback<String>()
{
@Override
public void done(String result, Throwable error)
{
if ( error == null )
{
LoginResult obj = BungeeCord.getInstance().gson.fromJson( result, LoginResult.class );
if ( obj != null && obj.getId() != null )
{
loginProfile = obj;
name = obj.getName();
uniqueId = Util.getUUID( obj.getId() );
authenticated = true;
finish();
return;
}
if(isOnlineMode()) {
disconnect(bungee.getTranslation("offline_mode_player"));
return;
}
finish();
return;
} else
{
disconnect( bungee.getTranslation( "mojang_fail" ) );
bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", error );
}
}
};
HttpClient.get( authURL, ch.getHandle().eventLoop(), handler );
}
2 ответа
Я не думаю, что это возможно из-за того, что Minecraft не обменивается данными сеанса. Я знаю серверы, на которых запущен второй прокси-сервер с включенным онлайн-режимом для премиум-пользователей, чтобы обрабатывать детали сеанса, ведущие к тем же серверам bukkit «позади».
Возможно, вы это ищете: https://www.spigotmc.org/resources/fastlogin.14153/
Пока не пользовался, но, судя по отзывам, в последней версии все еще работает.
Кроме того, это открытый исходный код, вы можете заглянуть в код и посмотреть, как это делается.