Use translatable components like vanilla and cleanup type casts (#831)

* Use translatable components like vanilla and cleanup type casts

Just a few messages becoming dynamic using translatable components like vanilla instead of being hardcoded.

* Use checkerframework

* Readd disconnect string methods

* Do not make nullable
This commit is contained in:
Alex 2024-07-07 17:31:18 +02:00 committed by GitHub
parent 002754f3af
commit 2b2af7a424
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 80 additions and 89 deletions

View file

@ -1,5 +1,6 @@
package org.geysermc.mcprotocollib.network.example;
import net.kyori.adventure.text.Component;
import org.geysermc.mcprotocollib.network.Session;
import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent;
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
@ -14,23 +15,23 @@ public class ClientSessionListener extends SessionAdapter {
@Override
public void packetReceived(Session session, Packet packet) {
if (packet instanceof PingPacket) {
String id = ((PingPacket) packet).getPingId();
if (packet instanceof PingPacket pingPacket) {
String id = pingPacket.getPingId();
log.info("CLIENT Received: {}", id);
if (id.equals("hello")) {
session.send(new PingPacket("exit"));
} else if (id.equals("exit")) {
session.disconnect("Finished");
session.disconnect(Component.text("Finished"));
}
}
}
@Override
public void packetSent(Session session, Packet packet) {
if (packet instanceof PingPacket) {
log.info("CLIENT Sent: {}", ((PingPacket) packet).getPingId());
if (packet instanceof PingPacket pingPacket) {
log.info("CLIENT Sent: {}", pingPacket.getPingId());
}
}

View file

@ -14,16 +14,16 @@ public class ServerSessionListener extends SessionAdapter {
@Override
public void packetReceived(Session session, Packet packet) {
if (packet instanceof PingPacket) {
log.info("SERVER Received: {}", ((PingPacket) packet).getPingId());
if (packet instanceof PingPacket pingPacket) {
log.info("SERVER Received: {}", pingPacket.getPingId());
session.send(packet);
}
}
@Override
public void packetSent(Session session, Packet packet) {
if (packet instanceof PingPacket) {
log.info("SERVER Sent: {}", ((PingPacket) packet).getPingId());
if (packet instanceof PingPacket pingPacket) {
log.info("SERVER Sent: {}", pingPacket.getPingId());
}
}

View file

@ -112,9 +112,9 @@ public class MinecraftProtocolTest {
event.getSession().addListener(new SessionAdapter() {
@Override
public void packetReceived(Session session, Packet packet) {
if (packet instanceof ServerboundChatPacket) {
if (packet instanceof ServerboundChatPacket chatPacket) {
GameProfile profile = event.getSession().getFlag(MinecraftConstants.PROFILE_KEY);
log.info("{}: {}", profile.getName(), ((ServerboundChatPacket) packet).getMessage());
log.info("{}: {}", profile.getName(), chatPacket.getMessage());
Component msg = Component.text("Hello, ")
.color(NamedTextColor.GREEN)
@ -207,10 +207,10 @@ public class MinecraftProtocolTest {
public void packetReceived(Session session, Packet packet) {
if (packet instanceof ClientboundLoginPacket) {
session.send(new ServerboundChatPacket("Hello, this is a test of MCProtocolLib.", Instant.now().toEpochMilli(), 0L, null, 0, new BitSet()));
} else if (packet instanceof ClientboundSystemChatPacket) {
Component message = ((ClientboundSystemChatPacket) packet).getContent();
} else if (packet instanceof ClientboundSystemChatPacket systemChatPacket) {
Component message = systemChatPacket.getContent();
log.info("Received Message: {}", message);
session.disconnect("Finished");
session.disconnect(Component.text("Finished"));
}
}

View file

@ -1,5 +1,6 @@
package org.geysermc.mcprotocollib.network;
import net.kyori.adventure.text.Component;
import org.geysermc.mcprotocollib.network.event.server.ServerBoundEvent;
import org.geysermc.mcprotocollib.network.event.server.ServerClosedEvent;
import org.geysermc.mcprotocollib.network.event.server.ServerClosingEvent;
@ -119,7 +120,7 @@ public abstract class AbstractServer implements Server {
public void removeSession(Session session) {
this.sessions.remove(session);
if (session.isConnected()) {
session.disconnect("Connection closed.");
session.disconnect(Component.translatable("disconnect.endOfStream"));
}
this.callEvent(new SessionRemovedEvent(this, session));
@ -164,7 +165,7 @@ public abstract class AbstractServer implements Server {
this.callEvent(new ServerClosingEvent(this));
for (Session session : this.getSessions()) {
if (session.isConnected()) {
session.disconnect("Server closed.");
session.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
}
}

View file

@ -1,6 +1,7 @@
package org.geysermc.mcprotocollib.network;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
import org.geysermc.mcprotocollib.network.crypt.PacketEncryption;
@ -259,12 +260,39 @@ public interface Session {
*/
void send(Packet packet);
/**
* Disconnects the session.
* This method just wraps the reason into a {@link Component}.
* It is recommended to use Components instead as they provide more flexibility.
*
* @param reason Reason for disconnecting.
* @see #disconnect(String, Throwable)
*/
default void disconnect(@NonNull String reason) {
this.disconnect(reason, null);
}
/**
* Disconnects the session.
* This method just wraps the reason into a {@link Component}.
* It is recommended to use Components instead as they provide more flexibility.
*
* @param reason Reason for disconnecting.
* @param cause Throwable responsible for disconnecting.
* @see #disconnect(Component, Throwable)
*/
default void disconnect(@NonNull String reason, @Nullable Throwable cause) {
this.disconnect(Component.text(reason), cause);
}
/**
* Disconnects the session.
*
* @param reason Reason for disconnecting.
*/
void disconnect(@Nullable String reason);
default void disconnect(@NonNull Component reason) {
this.disconnect(reason, null);
}
/**
* Disconnects the session.
@ -272,20 +300,5 @@ public interface Session {
* @param reason Reason for disconnecting.
* @param cause Throwable responsible for disconnecting.
*/
void disconnect(@Nullable String reason, Throwable cause);
/**
* Disconnects the session.
*
* @param reason Reason for disconnecting.
*/
void disconnect(@Nullable Component reason);
/**
* Disconnects the session.
*
* @param reason Reason for disconnecting.
* @param cause Throwable responsible for disconnecting.
*/
void disconnect(@Nullable Component reason, Throwable cause);
void disconnect(@NonNull Component reason, @Nullable Throwable cause);
}

View file

@ -28,8 +28,8 @@ import io.netty.handler.proxy.Socks5ProxyHandler;
import io.netty.resolver.dns.DnsNameResolver;
import io.netty.resolver.dns.DnsNameResolverBuilder;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.geysermc.mcprotocollib.network.ProxyInfo;
import org.geysermc.mcprotocollib.network.BuiltinFlags;
import org.geysermc.mcprotocollib.network.ProxyInfo;
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
import org.geysermc.mcprotocollib.network.helper.TransportHelper;
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
@ -256,11 +256,6 @@ public class TcpClientSession extends TcpSession {
}
}
@Override
public void disconnect(String reason, Throwable cause) {
super.disconnect(reason, cause);
}
private static void createTcpEventLoopGroup() {
if (EVENT_LOOP_GROUP != null) {
return;

View file

@ -3,17 +3,15 @@ package org.geysermc.mcprotocollib.network.tcp;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ConnectTimeoutException;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.ReadTimeoutException;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutException;
import io.netty.handler.timeout.WriteTimeoutHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.mcprotocollib.network.Flag;
import org.geysermc.mcprotocollib.network.Session;
@ -27,7 +25,6 @@ import org.geysermc.mcprotocollib.network.event.session.SessionListener;
import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
import java.net.ConnectException;
import java.net.SocketAddress;
import java.util.Collections;
import java.util.HashMap;
@ -35,6 +32,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public abstract class TcpSession extends SimpleChannelInboundHandler<Packet> implements Session {
/**
@ -279,22 +277,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler<Packet> imp
}
@Override
public void disconnect(String reason) {
this.disconnect(Component.text(reason));
}
@Override
public void disconnect(String reason, Throwable cause) {
this.disconnect(Component.text(reason), cause);
}
@Override
public void disconnect(Component reason) {
this.disconnect(reason, null);
}
@Override
public void disconnect(final Component reason, final Throwable cause) {
public void disconnect(@NonNull Component reason, @Nullable Throwable cause) {
if (this.disconnected) {
return;
}
@ -303,11 +286,9 @@ public abstract class TcpSession extends SimpleChannelInboundHandler<Packet> imp
if (this.channel != null && this.channel.isOpen()) {
this.callEvent(new DisconnectingEvent(this, reason, cause));
this.channel.flush().close().addListener((ChannelFutureListener) future ->
callEvent(new DisconnectedEvent(TcpSession.this,
reason != null ? reason : Component.text("Connection closed."), cause)));
this.channel.flush().close().addListener((ChannelFutureListener) future -> callEvent(new DisconnectedEvent(TcpSession.this, reason, cause)));
} else {
this.callEvent(new DisconnectedEvent(this, reason != null ? reason : Component.text("Connection closed."), cause));
this.callEvent(new DisconnectedEvent(this, reason, cause));
}
}
@ -385,21 +366,17 @@ public abstract class TcpSession extends SimpleChannelInboundHandler<Packet> imp
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel() == this.channel) {
this.disconnect("Connection closed.");
this.disconnect(Component.translatable("disconnect.endOfStream"));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
String message;
if (cause instanceof ConnectTimeoutException || (cause instanceof ConnectException && cause.getMessage().contains("connection timed out"))) {
message = "Connection timed out.";
} else if (cause instanceof ReadTimeoutException) {
message = "Read timed out.";
} else if (cause instanceof WriteTimeoutException) {
message = "Write timed out.";
Component message;
if (cause instanceof TimeoutException) {
message = Component.translatable("disconnect.timeout");
} else {
message = cause.toString();
message = Component.translatable("disconnect.genericReason", Component.text("Internal Exception: " + cause));
}
this.disconnect(message, cause);

View file

@ -3,6 +3,7 @@ package org.geysermc.mcprotocollib.protocol;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.SneakyThrows;
import net.kyori.adventure.text.Component;
import org.geysermc.mcprotocollib.auth.GameProfile;
import org.geysermc.mcprotocollib.auth.SessionService;
import org.geysermc.mcprotocollib.network.Session;
@ -77,10 +78,12 @@ public class ClientListener extends SessionAdapter {
SessionService sessionService = session.getFlag(MinecraftConstants.SESSION_SERVICE_KEY, new SessionService());
String serverId = SessionService.getServerId(helloPacket.getServerId(), helloPacket.getPublicKey(), key);
// TODO: Add generic error, disabled multiplayer and banned from playing online errors
try {
sessionService.joinServer(profile, accessToken, serverId);
} catch (IOException e) {
session.disconnect("Login failed: Authentication error: " + e.getMessage(), e);
session.disconnect(Component.translatable("disconnect.loginFailedInfo", Component.text(e.getMessage())), e);
return;
}
@ -109,7 +112,7 @@ public class ClientListener extends SessionAdapter {
handler.handle(session, time);
}
session.disconnect("Finished");
session.disconnect(Component.translatable("multiplayer.status.finished"));
}
} else if (protocol.getState() == ProtocolState.GAME) {
if (packet instanceof ClientboundKeepAlivePacket keepAlivePacket && session.getFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, true)) {
@ -122,7 +125,7 @@ public class ClientListener extends SessionAdapter {
if (session.getFlag(MinecraftConstants.FOLLOW_TRANSFERS, true)) {
TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol());
newSession.setFlags(session.getFlags());
session.disconnect("Transferring");
session.disconnect(Component.translatable("disconnect.transfer"));
newSession.connect(true, true);
}
}
@ -137,7 +140,7 @@ public class ClientListener extends SessionAdapter {
if (session.getFlag(MinecraftConstants.FOLLOW_TRANSFERS, true)) {
TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol());
newSession.setFlags(session.getFlags());
session.disconnect("Transferring");
session.disconnect(Component.translatable("disconnect.transfer"));
newSession.connect(true, true);
}
}

View file

@ -98,15 +98,15 @@ public class ServerListener extends SessionAdapter {
case STATUS -> protocol.setState(ProtocolState.STATUS);
case TRANSFER -> {
if (!session.getFlag(MinecraftConstants.ACCEPT_TRANSFERS_KEY, false)) {
session.disconnect("Server does not accept transfers.");
session.disconnect(Component.translatable("multiplayer.disconnect.transfers_disabled"));
}
}
case LOGIN -> {
protocol.setState(ProtocolState.LOGIN);
if (intentionPacket.getProtocolVersion() > protocol.getCodec().getProtocolVersion()) {
session.disconnect("Outdated server! I'm still on " + protocol.getCodec().getMinecraftVersion() + ".");
session.disconnect(Component.translatable("multiplayer.disconnect.incompatible", Component.text(protocol.getCodec().getMinecraftVersion())));
} else if (intentionPacket.getProtocolVersion() < protocol.getCodec().getProtocolVersion()) {
session.disconnect("Outdated client! Please use " + protocol.getCodec().getMinecraftVersion() + ".");
session.disconnect(Component.translatable("multiplayer.disconnect.outdated_client", Component.text(protocol.getCodec().getMinecraftVersion())));
}
}
default -> throw new UnsupportedOperationException("Invalid client intent: " + intentionPacket.getIntent());
@ -125,8 +125,7 @@ public class ServerListener extends SessionAdapter {
PrivateKey privateKey = KEY_PAIR.getPrivate();
if (!Arrays.equals(this.challenge, keyPacket.getEncryptedChallenge(privateKey))) {
session.disconnect("Invalid challenge!");
return;
throw new IllegalStateException("Protocol error");
}
SecretKey key = keyPacket.getSecretKey(privateKey);
@ -183,6 +182,7 @@ public class ServerListener extends SessionAdapter {
protocol.setState(ProtocolState.CONFIGURATION);
} else if (packet instanceof ServerboundPingRequestPacket pingRequestPacket) {
session.send(new ClientboundPongResponsePacket(pingRequestPacket.getPingTime()));
session.disconnect(Component.translatable("multiplayer.status.request_handled"));
}
} else if (protocol.getState() == ProtocolState.CONFIGURATION) {
if (packet instanceof ServerboundFinishConfigurationPacket) {
@ -230,12 +230,13 @@ public class ServerListener extends SessionAdapter {
try {
profile = sessionService.getProfileByServer(username, SessionService.getServerId(SERVER_ID, KEY_PAIR.getPublic(), this.key));
} catch (IOException e) {
this.session.disconnect("Failed to make session service request.", e);
session.disconnect(Component.translatable("multiplayer.disconnect.authservers_down"), e);
return;
}
if (profile == null) {
this.session.disconnect("Failed to verify username.");
session.disconnect(Component.translatable("multiplayer.disconnect.unverified_username"));
return;
}
} else {
profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes()), username);

View file

@ -83,11 +83,11 @@ public class MinecraftProtocolTest {
session.addListener(new DisconnectListener());
session.connect();
handler.status.await(4, SECONDS);
assertTrue(handler.status.await(4, SECONDS), "Did not receive server info in time.");
assertNotNull(handler.info, "Failed to get server info.");
assertEquals(SERVER_INFO, handler.info, "Received incorrect server info.");
} finally {
session.disconnect("Status test complete.");
session.disconnect(Component.text("Status test complete."));
}
}
@ -100,11 +100,11 @@ public class MinecraftProtocolTest {
session.addListener(new DisconnectListener());
session.connect();
listener.login.await(4, SECONDS);
assertTrue(listener.login.await(4, SECONDS), "Did not receive login packet in time.");
assertNotNull(listener.packet, "Failed to log in.");
assertEquals(JOIN_GAME_PACKET, listener.packet, "Received incorrect join packet.");
} finally {
session.disconnect("Login test complete.");
session.disconnect(Component.text("Login test complete."));
}
}
@ -125,8 +125,8 @@ public class MinecraftProtocolTest {
@Override
public void packetReceived(Session session, Packet packet) {
if (packet instanceof ClientboundLoginPacket) {
this.packet = (ClientboundLoginPacket) packet;
if (packet instanceof ClientboundLoginPacket loginPacket) {
this.packet = loginPacket;
this.login.countDown();
}
}